From 8c923b5b76bb17e00132a0b2b2b96de34265fc63 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Tue, 16 Oct 2007 11:27:23 +0000 Subject: modified ffmpeg usage, to use interface same as bass... still needs some tidy up, but its working. :) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@515 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 625 +++++++++++++++++++++++++------------------ 1 file changed, 358 insertions(+), 267 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index ed1e5fe3..6e16a7a3 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -22,6 +22,14 @@ interface {$MODE DELPHI} {$ENDIF} +(* + + look into + av_read_play + +*) + +implementation uses SDL, UGraphicClasses, @@ -37,56 +45,69 @@ uses SDL, dialogs, {$endif} {$ENDIF} - UIni; + UIni, + UMusic; -procedure Init; -procedure FFmpegOpenFile(FileName: pAnsiChar); -procedure FFmpegClose; -procedure FFmpegGetFrame(Time: Extended); -procedure FFmpegDrawGL(Screen: integer); -procedure FFmpegTogglePause; -procedure FFmpegSkip(Time: Single); -{ - @author(Jay Binks ) - @created(2007-10-09) - @lastmod(2007-10-09) +var + singleton_VideoFFMpeg : IVideoPlayback; - @param(aFormatCtx is a PAVFormatContext returned from av_open_input_file ) - @param(aFirstVideoStream is an OUT value of type integer, this is the index of the video stream) - @param(aFirstAudioStream is an OUT value of type integer, this is the index of the audio stream) - @returns(@true on success, @false otherwise) +type + TVideoPlayback_ffmpeg = class( TInterfacedObject, IVideoPlayback ) + private + fVideoOpened , + fVideoPaused : Boolean; - translated from "Setting Up the Audio" section at - http://www.dranger.com/ffmpeg/ffmpegtutorial_all.html - } -function find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean; + fVideoTex : glUint; + fVideoSkipTime : Single; + + fTexData : array of Byte; + + VideoFormatContext: PAVFormatContext; + + VideoStreamIndex , + AudioStreamIndex : Integer; + VideoCodecContext: PAVCodecContext; + VideoCodec: PAVCodec; + AVFrame: PAVFrame; + AVFrameRGB: PAVFrame; + myBuffer: pByte; + + TexX, TexY, dataX, dataY: Cardinal; + + ScaledVideoWidth, ScaledVideoHeight: Real; + VideoAspect: Real; + VideoTextureU, VideoTextureV: Real; + VideoTimeBase, VideoTime, LastFrameTime, TimeDifference: Extended; + + + WantedAudioCodecContext, + AudioCodecContext : PSDL_AudioSpec; + aCodecCtx : PAVCodecContext; + + + function find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean; + public + constructor create(); + function GetName: String; + + procedure init(); + + function Open( aFileName : string): boolean; // true if succeed + procedure Close; + + procedure Play; + procedure Pause; + procedure Stop; + + procedure MoveTo(Time: real); + function getPosition: real; + + procedure FFmpegGetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC + procedure FFmpegDrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC + + end; -var - VideoOpened, VideoPaused: Boolean; - VideoFormatContext: PAVFormatContext; - VideoStreamIndex , - AudioStreamIndex : Integer; - VideoCodecContext: PAVCodecContext; - VideoCodec: PAVCodec; - AVFrame: PAVFrame; - AVFrameRGB: PAVFrame; - myBuffer: pByte; - VideoTex: glUint; - TexX, TexY, dataX, dataY: Cardinal; - TexData: array of Byte; - ScaledVideoWidth, ScaledVideoHeight: Real; - VideoAspect: Real; - VideoTextureU, VideoTextureV: Real; - VideoTimeBase, VideoTime, LastFrameTime, TimeDifference: Extended; - VideoSkipTime: Single; - - - WantedAudioCodecContext, - AudioCodecContext : PSDL_AudioSpec; - aCodecCtx : PAVCodecContext; - -implementation {$ifdef DebugDisplay} //{$ifNdef win32} @@ -102,15 +123,10 @@ end; { ------------------------------------------------------------------------------ asdf ------------------------------------------------------------------------------ } -procedure Init; -begin - av_register_all; - VideoOpened:=False; - VideoPaused:=False; - - glGenTextures(1, PglUint(@VideoTex)); - SetLength(TexData,0); +function TVideoPlayback_ffmpeg.GetName: String; +begin + result := 'FFMpeg'; end; { @@ -126,7 +142,7 @@ end; translated from "Setting Up the Audio" section at http://www.dranger.com/ffmpeg/ffmpegtutorial_all.html } -function find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean; +function TVideoPlayback_ffmpeg.find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean; var i : integer; st : pAVStream; @@ -164,202 +180,10 @@ begin (aFirstVideoStream > -1) ; // Didn't find a video stream end; -procedure FFmpegOpenFile(FileName: pAnsiChar); -var errnum, i, x,y: Integer; - lStreamsCount : Integer; - -begin - VideoOpened := False; - VideoPaused := False; - VideoTimeBase := 0; - VideoTime := 0; - LastFrameTime := 0; - TimeDifference := 0; - VideoFormatContext := 0; - - writeln( Filename ); - - errnum := av_open_input_file(VideoFormatContext, FileName, Nil, 0, Nil); - writeln( 'Errnum : ' +inttostr( errnum )); - if(errnum <> 0) then - begin -{$ifdef DebugDisplay} - case errnum of - AVERROR_UNKNOWN: showmessage('failed to open file '+Filename+#13#10+'AVERROR_UNKNOWN'); - AVERROR_IO: showmessage('failed to open file '+Filename+#13#10+'AVERROR_IO'); - AVERROR_NUMEXPECTED: showmessage('failed to open file '+Filename+#13#10+'AVERROR_NUMEXPECTED'); - AVERROR_INVALIDDATA: showmessage('failed to open file '+Filename+#13#10+'AVERROR_INVALIDDATA'); - AVERROR_NOMEM: showmessage('failed to open file '+Filename+#13#10+'AVERROR_NOMEM'); - AVERROR_NOFMT: showmessage('failed to open file '+Filename+#13#10+'AVERROR_NOFMT'); - AVERROR_NOTSUPP: showmessage('failed to open file '+Filename+#13#10+'AVERROR_NOTSUPP'); - else showmessage('failed to open file '+Filename+#13#10+'Error number: '+inttostr(Errnum)); - end; -{$ENDIF} - Exit; - end - else - begin - VideoStreamIndex := -1; - AudioStreamIndex := -1; - - // Find which stream contains the video - if( av_find_stream_info(VideoFormatContext) >= 0 ) then - begin - find_stream_ids( VideoFormatContext, VideoStreamIndex, AudioStreamIndex ); - - writeln( 'VideoStreamIndex : ' + inttostr(VideoStreamIndex) ); - writeln( 'AudioStreamIndex : ' + inttostr(AudioStreamIndex) ); - end; - aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; - - WantedAudioCodecContext.freq := aCodecCtx^.sample_rate; - WantedAudioCodecContext.format := AUDIO_S16SYS; - WantedAudioCodecContext.channels := aCodecCtx^.channels; - WantedAudioCodecContext.silence := 0; - WantedAudioCodecContext.samples := 1024;//SDL_AUDIO_BUFFER_SIZE; -// WantedAudioCodecContext.callback := audio_callback; - WantedAudioCodecContext.userdata := aCodecCtx; - - -(* - if(SDL_OpenAudio(WantedAudioCodecContext, AudioCodecContext) < 0) then - begin - writeln( 'Could not do SDL_OpenAudio' ); - exit; - end; -*) - - if(VideoStreamIndex >= 0) then - begin - VideoCodecContext:=VideoFormatContext^.streams[VideoStreamIndex]^.codec; - VideoCodec:=avcodec_find_decoder(VideoCodecContext^.codec_id); - end - else - begin -{$ifdef DebugDisplay} - showmessage('found no video stream'); -{$ENDIF} - av_close_input_file(VideoFormatContext); - Exit; - end; - - - if(VideoCodec<>Nil) then - begin - errnum:=avcodec_open(VideoCodecContext, VideoCodec); - end else begin -{$ifdef DebugDisplay} - showmessage('no matching codec found'); -{$ENDIF} - avcodec_close(VideoCodecContext); - av_close_input_file(VideoFormatContext); - Exit; - end; - if(errnum >=0) then - begin -{$ifdef DebugDisplay} - showmessage('Found a matching Codec: '+ VideoCodecContext^.Codec.Name +#13#10#13#10+ - ' Width = '+inttostr(VideoCodecContext^.width)+ ', Height='+inttostr(VideoCodecContext^.height)+#13#10+ - ' Aspect : '+inttostr(VideoCodecContext^.sample_aspect_ratio.num)+'/'+inttostr(VideoCodecContext^.sample_aspect_ratio.den)+#13#10+ - ' Framerate : '+inttostr(VideoCodecContext^.time_base.num)+'/'+inttostr(VideoCodecContext^.time_base.den)); -{$endif} - // allocate space for decoded frame and rgb frame - AVFrame:=avcodec_alloc_frame; - AVFrameRGB:=avcodec_alloc_frame; - end; - myBuffer:=Nil; - if(AVFrame <> Nil) and (AVFrameRGB <> Nil) then - begin - myBuffer:=av_malloc(avpicture_get_size(PIX_FMT_RGB24, VideoCodecContext^.width, - VideoCodecContext^.height)); - end; - if myBuffer <> Nil then errnum:=avpicture_fill(PAVPicture(AVFrameRGB), myBuffer, PIX_FMT_RGB24, - VideoCodecContext^.width, VideoCodecContext^.height) - else begin -{$ifdef DebugDisplay} - showmessage('failed to allocate video buffer'); -{$endif} - av_free(AVFrameRGB); - av_free(AVFrame); - avcodec_close(VideoCodecContext); - av_close_input_file(VideoFormatContext); - Exit; - end; - if errnum >=0 then - begin - VideoOpened:=True; - - TexX := VideoCodecContext^.width; - TexY := VideoCodecContext^.height; - dataX := Round(Power(2, Ceil(Log2(TexX)))); - dataY := Round(Power(2, Ceil(Log2(TexY)))); - SetLength(TexData,dataX*dataY*3); - // calculate some information for video display - VideoAspect:=VideoCodecContext^.sample_aspect_ratio.num/VideoCodecContext^.sample_aspect_ratio.den; - if (VideoAspect = 0) then - VideoAspect:=VideoCodecContext^.width/VideoCodecContext^.height - else - VideoAspect:=VideoAspect*VideoCodecContext^.width/VideoCodecContext^.height; - if VideoAspect >= 4/3 then - begin - ScaledVideoWidth:=800.0; - ScaledVideoHeight:=800.0/VideoAspect; - end else - begin - ScaledVideoHeight:=600.0; - ScaledVideoWidth:=600.0*VideoAspect; - end; - VideoTimeBase:=VideoCodecContext^.time_base.num/VideoCodecContext^.time_base.den; - // hack to get reasonable timebase for divx -{$ifdef DebugDisplay} - showmessage('framerate: '+inttostr(floor(1/videotimebase))+'fps'); -{$endif} - if VideoTimeBase < 0.02 then // 0.02 <-> 50 fps - begin - VideoTimeBase:=VideoCodecContext^.time_base.den/VideoCodecContext^.time_base.num; - while VideoTimeBase > 50 do VideoTimeBase:=VideoTimeBase/10; - VideoTimeBase:=1/VideoTimeBase; - end; -{$ifdef DebugDisplay} - showmessage('corrected framerate: '+inttostr(floor(1/videotimebase))+'fps'); - - if ((VideoAspect*VideoCodecContext^.width*VideoCodecContext^.height)>200000) then - showmessage('you are trying to play a rather large video'+#13#10+ - 'be prepared to experience some timing problems'); -{$endif} - end; - end; -end; - -procedure FFmpegClose; -begin - if VideoOpened then begin - av_free(myBuffer); - av_free(AVFrameRGB); - av_free(AVFrame); - avcodec_close(VideoCodecContext); - av_close_input_file(VideoFormatContext); - SetLength(TexData,0); - VideoOpened:=False; - end; -end; -procedure FFmpegTogglePause; -begin - if VideoPaused then VideoPaused:=False - else VideoPaused:=True; -end; -procedure FFmpegSkip(Time: Single); -begin - VideoSkiptime:=Time; - if VideoSkipTime > 0 then begin - av_seek_frame(VideoFormatContext,-1,Floor((VideoSkipTime)*1500000),0); - VideoTime:=VideoSkipTime; - end; -end; -procedure FFmpegGetFrame(Time: Extended); +procedure TVideoPlayback_ffmpeg.FFmpegGetFrame(Time: Extended); var FrameFinished: Integer; AVPacket: TAVPacket; @@ -372,13 +196,13 @@ var const FRAMEDROPCOUNT=3; begin - if not VideoOpened then Exit; + if not fVideoOpened then Exit; - if VideoPaused then Exit; - - myTime:=Time+VideoSkipTime; - TimeDifference:=myTime-VideoTime; - DropFrame:=False; + if fVideoPaused then Exit; + + myTime := Time + fVideoSkipTime; + TimeDifference := myTime - VideoTime; + DropFrame := False; {$IFDEF DebugDisplay} showmessage('Time: '+inttostr(floor(Time*1000))+#13#10+ @@ -404,7 +228,8 @@ begin Exit;// we don't need a new frame now end; - + + VideoTime:=VideoTime+VideoTimeBase; TimeDifference:=myTime-VideoTime; if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then // skip frames @@ -415,37 +240,52 @@ begin {$endif} {$IFDEF DebugDisplay} + showmessage('skipping frames'+#13#10+ 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ 'TimeDiff: '+inttostr(floor(TimeDifference*1000))+#13#10+ 'Time2Skip: '+inttostr(floor((Time-LastFrameTime)*1000))); + {$endif} -// av_seek_frame(VideoFormatContext,VideoStreamIndex,Floor(Time*VideoTimeBase),0); +// av_seek_frame(VideoFormatContext.,VideoStreamIndex,Floor(Time*VideoTimeBase),0); { av_seek_frame(VideoFormatContext,-1,Floor((myTime+VideoTimeBase)*1500000),0); VideoTime:=floor(myTime/VideoTimeBase)*VideoTimeBase;} VideoTime:=VideoTime+FRAMEDROPCOUNT*VideoTimeBase; DropFrame:=True; end; + // av_init_packet(@AVPacket); + AVPacket.data := nil; av_init_packet( AVPacket ); // JB-ffmpeg - + + FrameFinished:=0; // read packets until we have a finished frame (or there are no more packets) // while (FrameFinished=0) and (av_read_frame(VideoFormatContext, @AVPacket)>=0) do while (FrameFinished=0) and (av_read_frame(VideoFormatContext, AVPacket)>=0) do // JB-ffmpeg begin + + // if we got a packet from the video stream, then decode it if (AVPacket.stream_index=VideoStreamIndex) then // errnum:=avcodec_decode_video(VideoCodecContext, AVFrame, @frameFinished , AVPacket.data, AVPacket.size); errnum := avcodec_decode_video(VideoCodecContext, AVFrame, frameFinished , AVPacket.data, AVPacket.size); // JB-ffmpeg - + // release internal packet structure created by av_read_frame // av_free_packet(PAVPacket(@AVPacket)); - av_free_packet( AVPacket ); // JB-ffmpeg + + try + if AVPacket.data <> nil then + av_free_packet( AVPacket ); // JB-ffmpeg + except + // TODO : JB_FFMpeg ... why does this now AV sometimes ( or always !! ) + end; + end; - + + if DropFrame then for droppedFrames:=1 to FRAMEDROPCOUNT do begin FrameFinished:=0; @@ -485,12 +325,12 @@ begin linesize := AVFrameRGB^.linesize[0]; for y:=0 to TexY-1 do begin - System.Move(FrameDataPtr[y*linesize],TexData[3*y*dataX],linesize); + System.Move(FrameDataPtr[y*linesize],fTexData[3*y*dataX],linesize); end; // generate opengl texture out of whatever we got - glBindTexture(GL_TEXTURE_2D, VideoTex); - glTexImage2D(GL_TEXTURE_2D, 0, 3, dataX, dataY, 0, GL_RGB, GL_UNSIGNED_BYTE, TexData); + glBindTexture(GL_TEXTURE_2D, fVideoTex); + glTexImage2D(GL_TEXTURE_2D, 0, 3, dataX, dataY, 0, GL_RGB, GL_UNSIGNED_BYTE, fTexData); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); {$ifdef DebugFrames} @@ -501,20 +341,21 @@ begin end; end; -procedure FFmpegDrawGL(Screen: integer); +procedure TVideoPlayback_ffmpeg.FFmpegDrawGL(Screen: integer); begin // have a nice black background to draw on (even if there were errors opening the vid) - if Screen=1 then begin + if Screen=1 then + begin glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); end; // exit if there's nothing to draw - if not VideoOpened then Exit; + if not fVideoOpened then Exit; glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glColor4f(1, 1, 1, 1); - glBindTexture(GL_TEXTURE_2D, VideoTex); + glBindTexture(GL_TEXTURE_2D, fVideoTex); glbegin(gl_quads); glTexCoord2f( 0, 0); glVertex2f(400-ScaledVideoWidth/2, 300-ScaledVideoHeight/2); glTexCoord2f( 0, TexY/dataY); glVertex2f(400-ScaledVideoWidth/2, 300+ScaledVideoHeight/2); @@ -525,7 +366,8 @@ begin glDisable(GL_BLEND); {$ifdef Info} - if VideoSkipTime+VideoTime+VideoTimeBase < 0 then begin + if VideoSkipTime+VideoTime+VideoTimeBase < 0 then + begin glColor4f(0.7, 1, 0.3, 1); SetFontStyle (1); SetFontItalic(False); @@ -558,4 +400,253 @@ begin {$endif} end; +constructor TVideoPlayback_ffmpeg.create(); +begin + writeln( 'UVideo_FFMpeg - TVideoPlayback_ffmpeg.create()' ); + + writeln( 'UVideo_FFMpeg - av_register_all' ); + av_register_all; + + fVideoOpened := False; + fVideoPaused := False; + +end; + +procedure TVideoPlayback_ffmpeg.init(); +begin + writeln( 'UVideo_FFMpeg - glGenTextures(1, PglUint(@fVideoTex))' ); + glGenTextures(1, PglUint(@fVideoTex)); + + writeln( 'UVideo_FFMpeg - SetLength(fTexData,0)' ); + SetLength(fTexData,0); +end; + + +function TVideoPlayback_ffmpeg.Open( aFileName : string): boolean; // true if succeed +var + errnum, i, x,y: Integer; + lStreamsCount : Integer; + +begin + fVideoOpened := False; + fVideoPaused := False; + VideoTimeBase := 0; + VideoTime := 0; + LastFrameTime := 0; + TimeDifference := 0; + VideoFormatContext := 0; + + writeln( aFileName ); + + errnum := av_open_input_file(VideoFormatContext, pchar( aFileName ), Nil, 0, Nil); + writeln( 'Errnum : ' +inttostr( errnum )); + if(errnum <> 0) then + begin +{$ifdef DebugDisplay} + case errnum of + AVERROR_UNKNOWN: showmessage('failed to open file '+aFileName+#13#10+'AVERROR_UNKNOWN'); + AVERROR_IO: showmessage('failed to open file '+aFileName+#13#10+'AVERROR_IO'); + AVERROR_NUMEXPECTED: showmessage('failed to open file '+aFileName+#13#10+'AVERROR_NUMEXPECTED'); + AVERROR_INVALIDDATA: showmessage('failed to open file '+aFileName+#13#10+'AVERROR_INVALIDDATA'); + AVERROR_NOMEM: showmessage('failed to open file '+aFileName+#13#10+'AVERROR_NOMEM'); + AVERROR_NOFMT: showmessage('failed to open file '+aFileName+#13#10+'AVERROR_NOFMT'); + AVERROR_NOTSUPP: showmessage('failed to open file '+aFileName+#13#10+'AVERROR_NOTSUPP'); + else showmessage('failed to open file '+aFileName+#13#10+'Error number: '+inttostr(Errnum)); + end; +{$ENDIF} + Exit; + end + else + begin + VideoStreamIndex := -1; + AudioStreamIndex := -1; + + // Find which stream contains the video + if( av_find_stream_info(VideoFormatContext) >= 0 ) then + begin + find_stream_ids( VideoFormatContext, VideoStreamIndex, AudioStreamIndex ); + + writeln( 'VideoStreamIndex : ' + inttostr(VideoStreamIndex) ); + writeln( 'AudioStreamIndex : ' + inttostr(AudioStreamIndex) ); + end; + aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; + +(* + WantedAudioCodecContext.freq := aCodecCtx^.sample_rate; + WantedAudioCodecContext.format := AUDIO_S16SYS; + WantedAudioCodecContext.channels := aCodecCtx^.channels; + WantedAudioCodecContext.silence := 0; + WantedAudioCodecContext.samples := 1024;//SDL_AUDIO_BUFFER_SIZE; +// WantedAudioCodecContext.callback := audio_callback; + WantedAudioCodecContext.userdata := aCodecCtx; +*) + +(* + if(SDL_OpenAudio(WantedAudioCodecContext, AudioCodecContext) < 0) then + begin + writeln( 'Could not do SDL_OpenAudio' ); + exit; + end; +*) + + if(VideoStreamIndex >= 0) then + begin + VideoCodecContext:=VideoFormatContext^.streams[VideoStreamIndex]^.codec; + VideoCodec:=avcodec_find_decoder(VideoCodecContext^.codec_id); + end + else + begin +{$ifdef DebugDisplay} + showmessage('found no video stream'); +{$ENDIF} + av_close_input_file(VideoFormatContext); + Exit; + end; + + + if(VideoCodec<>Nil) then + begin + errnum:=avcodec_open(VideoCodecContext, VideoCodec); + end else begin +{$ifdef DebugDisplay} + showmessage('no matching codec found'); +{$ENDIF} + avcodec_close(VideoCodecContext); + av_close_input_file(VideoFormatContext); + Exit; + end; + if(errnum >=0) then + begin +{$ifdef DebugDisplay} + showmessage('Found a matching Codec: '+ VideoCodecContext^.Codec.Name +#13#10#13#10+ + ' Width = '+inttostr(VideoCodecContext^.width)+ ', Height='+inttostr(VideoCodecContext^.height)+#13#10+ + ' Aspect : '+inttostr(VideoCodecContext^.sample_aspect_ratio.num)+'/'+inttostr(VideoCodecContext^.sample_aspect_ratio.den)+#13#10+ + ' Framerate : '+inttostr(VideoCodecContext^.time_base.num)+'/'+inttostr(VideoCodecContext^.time_base.den)); +{$endif} + // allocate space for decoded frame and rgb frame + AVFrame:=avcodec_alloc_frame; + AVFrameRGB:=avcodec_alloc_frame; + end; + myBuffer:=Nil; + if(AVFrame <> Nil) and (AVFrameRGB <> Nil) then + begin + myBuffer:=av_malloc(avpicture_get_size(PIX_FMT_RGB24, VideoCodecContext^.width, + VideoCodecContext^.height)); + end; + if myBuffer <> Nil then errnum:=avpicture_fill(PAVPicture(AVFrameRGB), myBuffer, PIX_FMT_RGB24, + VideoCodecContext^.width, VideoCodecContext^.height) + else begin +{$ifdef DebugDisplay} + showmessage('failed to allocate video buffer'); +{$endif} + av_free(AVFrameRGB); + av_free(AVFrame); + avcodec_close(VideoCodecContext); + av_close_input_file(VideoFormatContext); + Exit; + end; + if errnum >=0 then + begin + fVideoOpened:=True; + + TexX := VideoCodecContext^.width; + TexY := VideoCodecContext^.height; + dataX := Round(Power(2, Ceil(Log2(TexX)))); + dataY := Round(Power(2, Ceil(Log2(TexY)))); + SetLength(fTexData,dataX*dataY*3); + // calculate some information for video display + VideoAspect:=VideoCodecContext^.sample_aspect_ratio.num/VideoCodecContext^.sample_aspect_ratio.den; + if (VideoAspect = 0) then + VideoAspect:=VideoCodecContext^.width/VideoCodecContext^.height + else + VideoAspect:=VideoAspect*VideoCodecContext^.width/VideoCodecContext^.height; + if VideoAspect >= 4/3 then + begin + ScaledVideoWidth:=800.0; + ScaledVideoHeight:=800.0/VideoAspect; + end else + begin + ScaledVideoHeight:=600.0; + ScaledVideoWidth:=600.0*VideoAspect; + end; + VideoTimeBase:=VideoCodecContext^.time_base.num/VideoCodecContext^.time_base.den; + // hack to get reasonable timebase for divx +{$ifdef DebugDisplay} + showmessage('framerate: '+inttostr(floor(1/videotimebase))+'fps'); +{$endif} + if VideoTimeBase < 0.02 then // 0.02 <-> 50 fps + begin + VideoTimeBase:=VideoCodecContext^.time_base.den/VideoCodecContext^.time_base.num; + while VideoTimeBase > 50 do VideoTimeBase:=VideoTimeBase/10; + VideoTimeBase:=1/VideoTimeBase; + end; +{$ifdef DebugDisplay} + showmessage('corrected framerate: '+inttostr(floor(1/videotimebase))+'fps'); + + if ((VideoAspect*VideoCodecContext^.width*VideoCodecContext^.height)>200000) then + showmessage('you are trying to play a rather large video'+#13#10+ + 'be prepared to experience some timing problems'); +{$endif} + end; + end; +end; + +procedure TVideoPlayback_ffmpeg.Close; +begin + if fVideoOpened then + begin + av_free(myBuffer); + av_free(AVFrameRGB); + av_free(AVFrame); + + avcodec_close(VideoCodecContext); + av_close_input_file(VideoFormatContext); + + SetLength(fTexData,0); + + fVideoOpened:=False; + end; +end; + +procedure TVideoPlayback_ffmpeg.Play; +begin +end; + +procedure TVideoPlayback_ffmpeg.Pause; +begin + fVideoPaused := not fVideoPaused; +end; + +procedure TVideoPlayback_ffmpeg.Stop; +begin +end; + +procedure TVideoPlayback_ffmpeg.MoveTo(Time: real); +begin + fVideoSkipTime := Time; + + if fVideoSkipTime > 0 then + begin + av_seek_frame(VideoFormatContext,-1,Floor((fVideoSkipTime)*1500000),0); + + VideoTime := fVideoSkipTime; + end; +end; + +function TVideoPlayback_ffmpeg.getPosition: real; +begin + result := 0; +end; + +initialization + singleton_VideoFFMpeg := TVideoPlayback_ffmpeg.create(); + + writeln( 'UVideo_FFMpeg - Register Playback' ); + AudioManager.add( IVideoPlayback( singleton_VideoFFMpeg ) ); + + +finalization + AudioManager.Remove( IVideoPlayback( singleton_VideoFFMpeg ) ); + + end. -- cgit v1.2.3