aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes/UVideo.pas
diff options
context:
space:
mode:
Diffstat (limited to 'Game/Code/Classes/UVideo.pas')
-rw-r--r--Game/Code/Classes/UVideo.pas625
1 files changed, 358 insertions, 267 deletions
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 <jaybinks@gmail.com>)
- @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.