From 247cbdca4eb8af228fa1753f1185e85077b5befa Mon Sep 17 00:00:00 2001 From: b1indy Date: Fri, 7 Sep 2007 21:09:02 +0000 Subject: UScreenSing.pas, UScreenSingModi.pas: removed Uffmpeg and USmpeg, added UVideo UGraphic.pas: prepared for possible loading animation UGraphicClasses.pas, ULCD.pas, ULight.pas, UMain.pas, USkins.pas, UDisplay.pas, UMenuButton.pas, UMenuSelect.pas, UMenuSelectSlide.pas, UMenuStatic.pas, UScreenCredits.pas, UScreenEditSub.pas, UScreenOpen.pas, UScreenPopup.pas: some fixes to get rid of some compiler infos/warnings git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@374 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 378 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 Game/Code/Classes/UVideo.pas (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas new file mode 100644 index 00000000..8e2fc446 --- /dev/null +++ b/Game/Code/Classes/UVideo.pas @@ -0,0 +1,378 @@ +{############################################################################ +# FFmpeg support for UltraStar deluxe # +# # +# Created by b1indy # +# based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) # +#############################################################################} + +//{$define DebugDisplay} // uncomment if u want to see the debug stuff +{$define DebugFrames} +{$define Info} + + +unit UVideo; + +interface +uses SDL, UGraphicClasses, textgl, avcodec, avformat, avutil, math, OpenGL12, SysUtils, UIni, dialogs; + +procedure Init; +procedure FFmpegOpenFile(FileName: pAnsiChar); +procedure FFmpegClose; +procedure FFmpegGetFrame(Time: Extended); +procedure FFmpegDrawGL(Screen: integer); +procedure FFmpegTogglePause; +procedure FFmpegSkip(Time: Single); + +var + VideoOpened, VideoPaused: Boolean; + VideoFormatContext: PAVFormatContext; + VideoStreamIndex: 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; + +implementation + +procedure Init; +begin + av_register_all; + VideoOpened:=False; + VideoPaused:=False; + glGenTextures(1, PglUint(@VideoTex)); + SetLength(TexData,0); +end; + +procedure FFmpegOpenFile(FileName: pAnsiChar); +var errnum, i, x,y: Integer; +begin + VideoOpened:=False; + VideoPaused:=False; + VideoTimeBase:=0; + VideoTime:=0; + LastFrameTime:=0; + TimeDifference:=0; + errnum:=av_open_input_file(VideoFormatContext, FileName, Nil, 0, Nil); + if(errnum <> 0) + then begin + 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; + Exit; + end + else begin + VideoStreamIndex:=-1; + if(av_find_stream_info(VideoFormatContext)>=0) then + begin + for i:=0 to VideoFormatContext^.nb_streams-1 do + if(VideoFormatContext^.streams[i]^.codec^.codec_type=CODEC_TYPE_VIDEO) then begin + VideoStreamIndex:=i; + end else + end; + if(VideoStreamIndex >= 0) then + begin + VideoCodecContext:=VideoFormatContext^.streams[VideoStreamIndex]^.codec; + VideoCodec:=avcodec_find_decoder(VideoCodecContext^.codec_id); + end else begin + showmessage('found no video stream'); + av_close_input_file(VideoFormatContext); + Exit; + end; + if(VideoCodec<>Nil) then + begin + errnum:=avcodec_open(VideoCodecContext, VideoCodec); + end else begin + showmessage('no matching codec found'); + avcodec_close(VideoCodecContext); + av_close_input_file(VideoFormatContext); + Exit; + end; + if(errnum >=0) then + begin +{$ifdef DebugDisplay} + showmessage('Found a matching Codec:'+#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 + showmessage('failed to allocate video buffer'); + 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); +var + FrameFinished: Integer; + AVPacket: TAVPacket; + errnum, x, y: Integer; + FrameDataPtr: PByteArray; + linesize: integer; + myTime: Extended; + DropFrame: Boolean; + droppedFrames: Integer; +const + FRAMEDROPCOUNT=3; +begin + if not VideoOpened then Exit; + if VideoPaused then Exit; + myTime:=Time+VideoSkipTime; + TimeDifference:=myTime-VideoTime; + DropFrame:=False; +{ showmessage('Time: '+inttostr(floor(Time*1000))+#13#10+ + 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ + 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ + 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); +} + if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin +{$ifdef DebugFrames} + // frame delay debug display + GoldenRec.Spawn(200,15,1,16,0,-1,ColoredStar,$00ff00); +{$endif} +{ showmessage('not getting new frame'+#13#10+ + 'Time: '+inttostr(floor(Time*1000))+#13#10+ + 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ + 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ + 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); +} + Exit;// we don't need a new frame now + end; + VideoTime:=VideoTime+VideoTimeBase; + TimeDifference:=myTime-VideoTime; + if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then begin // skip frames +{$ifdef DebugFrames} + //frame drop debug display + GoldenRec.Spawn(200,55,1,16,0,-1,ColoredStar,$ff0000); +{$endif} +// 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))); +// 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); + 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 + 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); + // release internal packet structure created by av_read_frame + av_free_packet(PAVPacket(@AVPacket)); + end; + if DropFrame then + for droppedFrames:=1 to FRAMEDROPCOUNT do begin + 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 + 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); + // release internal packet structure created by av_read_frame + av_free_packet(PAVPacket(@AVPacket)); + end; + end; + + // if we did not get an new frame, there's nothing more to do + if Framefinished=0 then begin + GoldenRec.Spawn(220,15,1,16,0,-1,ColoredStar,$0000ff); + Exit; + end; + // otherwise we convert the pixeldata from YUV to RGB + errnum:=img_convert(PAVPicture(AVFrameRGB), PIX_FMT_RGB24, + PAVPicture(AVFrame), VideoCodecContext^.pix_fmt, + VideoCodecContext^.width, VideoCodecContext^.height); +//errnum:=1; + if errnum >=0 then begin + // copy RGB pixeldata to our TextureBuffer + // (line by line) + FrameDataPtr:=AVFrameRGB^.data[0]; + linesize:=AVFrameRGB^.linesize[0]; + for y:=0 to TexY-1 do begin + System.Move(FrameDataPtr[y*linesize],TexData[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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +{$ifdef DebugFrames} + //frame decode debug display + GoldenRec.Spawn(200,35,1,16,0,-1,ColoredStar,$ffff00); +{$endif} + + end; +end; + +procedure 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 + 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; + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glColor4f(1, 1, 1, 1); + glBindTexture(GL_TEXTURE_2D, VideoTex); + glbegin(gl_quads); + glTexCoord2f( 0, 0); glVertex2f(400-ScaledVideoWidth/2, 300-ScaledVideoHeight/2); + glTexCoord2f( 0, TexY/dataY); glVertex2f(400-ScaledVideoWidth/2, 300+ScaledVideoHeight/2); + glTexCoord2f(TexX/dataX, TexY/dataY); glVertex2f(400+ScaledVideoWidth/2, 300+ScaledVideoHeight/2); + glTexCoord2f(TexX/dataX, 0); glVertex2f(400+ScaledVideoWidth/2, 300-ScaledVideoHeight/2); + glEnd; + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + +{$ifdef Info} + if VideoSkipTime+VideoTime+VideoTimeBase < 0 then begin + glColor4f(0.7, 1, 0.3, 1); + SetFontStyle (1); + SetFontItalic(False); + SetFontSize(9); + SetFontPos (300, 0); + glPrint('Delay due to negative VideoGap'); + glColor4f(1, 1, 1, 1); + end; +{$endif} + +{$ifdef DebugFrames} + glColor4f(0, 0, 0, 0.2); + glbegin(gl_quads); + glVertex2f(0, 0); + glVertex2f(0, 70); + glVertex2f(250, 70); + glVertex2f(250, 0); + glEnd; + + glColor4f(1,1,1,1); + SetFontStyle (1); + SetFontItalic(False); + SetFontSize(9); + SetFontPos (5, 0); + glPrint('delaying frame'); + SetFontPos (5, 20); + glPrint('fetching frame'); + SetFontPos (5, 40); + glPrint('dropping frame'); +{$endif} +end; + +end. -- cgit v1.2.3 From 433a1b7339e2bf96f3b0bb4c98b8c799c6540027 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Tue, 18 Sep 2007 13:19:20 +0000 Subject: changes in order to compile in lazarus... minor tidy ups and removal of big old comment blocks.. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@394 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 8e2fc446..c97057ac 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -5,6 +5,10 @@ # based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) # #############################################################################} +{$IFDEF FPC} + {$MODE DELPHI} +{$ENDIF} + //{$define DebugDisplay} // uncomment if u want to see the debug stuff {$define DebugFrames} {$define Info} @@ -13,7 +17,20 @@ unit UVideo; interface -uses SDL, UGraphicClasses, textgl, avcodec, avformat, avutil, math, OpenGL12, SysUtils, UIni, dialogs; + +uses SDL, + UGraphicClasses, + textgl, + avcodec, + avformat, + avutil, + math, + OpenGL12, + SysUtils, + {$ifdef DebugDisplay} + dialogs, + {$ENDIF} + UIni; procedure Init; procedure FFmpegOpenFile(FileName: pAnsiChar); @@ -64,6 +81,7 @@ begin errnum:=av_open_input_file(VideoFormatContext, FileName, Nil, 0, Nil); 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'); @@ -74,6 +92,7 @@ begin 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 @@ -90,7 +109,9 @@ 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; @@ -98,7 +119,9 @@ begin 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; @@ -125,7 +148,9 @@ begin 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); -- cgit v1.2.3 From 62c82114318ed04ce42617fa9ce2e179834dbda4 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Wed, 19 Sep 2007 11:44:10 +0000 Subject: added UCommon ( in classes ) for lazarus... common functions needed for lazarus ( and others ) can be put in here. also this now compiles on lazarus.. ( dosnt link yet... but I dont get any critical compiler errors ) tested to compile in my delphi, and basic functionality is fine. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@395 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index c97057ac..4c8a4076 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -5,10 +5,6 @@ # based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) # #############################################################################} -{$IFDEF FPC} - {$MODE DELPHI} -{$ENDIF} - //{$define DebugDisplay} // uncomment if u want to see the debug stuff {$define DebugFrames} {$define Info} @@ -18,6 +14,11 @@ unit UVideo; interface +{$IFDEF FPC} + {$MODE DELPHI} +{$ENDIF} + + uses SDL, UGraphicClasses, textgl, -- cgit v1.2.3 From f26a2364e41b95665d9e55593eb0c0e8f4cf646b Mon Sep 17 00:00:00 2001 From: mogguh Date: Fri, 21 Sep 2007 11:20:41 +0000 Subject: ScoreScreen, still working on some minor things like simplifying the src (messy joes), color stuff, overlay for the bars, 2 screen fix and when the bars should be drawn (regarding to the playercount) - other skin stuff will follow soon git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@426 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 4c8a4076..290db271 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -6,8 +6,8 @@ #############################################################################} //{$define DebugDisplay} // uncomment if u want to see the debug stuff -{$define DebugFrames} -{$define Info} +//{$define DebugFrames} +//{$define Info} unit UVideo; -- cgit v1.2.3 From 979d59410f1625a4943a8a84e0f204465800453f Mon Sep 17 00:00:00 2001 From: jaybinks Date: Mon, 8 Oct 2007 00:19:58 +0000 Subject: fixed some stuff for linux build... now its getting close to the look of the windows build... YAY ! see http://www.flickr.com/photos/31428768@N00/sets/72157602234125005/ git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@468 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 866 +++++++++++++++++++++++-------------------- 1 file changed, 462 insertions(+), 404 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 290db271..b2ba01dc 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -1,404 +1,462 @@ -{############################################################################ -# FFmpeg support for UltraStar deluxe # -# # -# Created by b1indy # -# based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) # -#############################################################################} - -//{$define DebugDisplay} // uncomment if u want to see the debug stuff -//{$define DebugFrames} -//{$define Info} - - -unit UVideo; - -interface - -{$IFDEF FPC} - {$MODE DELPHI} -{$ENDIF} - - -uses SDL, - UGraphicClasses, - textgl, - avcodec, - avformat, - avutil, - math, - OpenGL12, - SysUtils, - {$ifdef DebugDisplay} - dialogs, - {$ENDIF} - UIni; - -procedure Init; -procedure FFmpegOpenFile(FileName: pAnsiChar); -procedure FFmpegClose; -procedure FFmpegGetFrame(Time: Extended); -procedure FFmpegDrawGL(Screen: integer); -procedure FFmpegTogglePause; -procedure FFmpegSkip(Time: Single); - -var - VideoOpened, VideoPaused: Boolean; - VideoFormatContext: PAVFormatContext; - VideoStreamIndex: 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; - -implementation - -procedure Init; -begin - av_register_all; - VideoOpened:=False; - VideoPaused:=False; - glGenTextures(1, PglUint(@VideoTex)); - SetLength(TexData,0); -end; - -procedure FFmpegOpenFile(FileName: pAnsiChar); -var errnum, i, x,y: Integer; -begin - VideoOpened:=False; - VideoPaused:=False; - VideoTimeBase:=0; - VideoTime:=0; - LastFrameTime:=0; - TimeDifference:=0; - errnum:=av_open_input_file(VideoFormatContext, FileName, Nil, 0, Nil); - 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; - if(av_find_stream_info(VideoFormatContext)>=0) then - begin - for i:=0 to VideoFormatContext^.nb_streams-1 do - if(VideoFormatContext^.streams[i]^.codec^.codec_type=CODEC_TYPE_VIDEO) then begin - VideoStreamIndex:=i; - end else - 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:'+#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); -var - FrameFinished: Integer; - AVPacket: TAVPacket; - errnum, x, y: Integer; - FrameDataPtr: PByteArray; - linesize: integer; - myTime: Extended; - DropFrame: Boolean; - droppedFrames: Integer; -const - FRAMEDROPCOUNT=3; -begin - if not VideoOpened then Exit; - if VideoPaused then Exit; - myTime:=Time+VideoSkipTime; - TimeDifference:=myTime-VideoTime; - DropFrame:=False; -{ showmessage('Time: '+inttostr(floor(Time*1000))+#13#10+ - 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ - 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ - 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); -} - if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin -{$ifdef DebugFrames} - // frame delay debug display - GoldenRec.Spawn(200,15,1,16,0,-1,ColoredStar,$00ff00); -{$endif} -{ showmessage('not getting new frame'+#13#10+ - 'Time: '+inttostr(floor(Time*1000))+#13#10+ - 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ - 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ - 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); -} - Exit;// we don't need a new frame now - end; - VideoTime:=VideoTime+VideoTimeBase; - TimeDifference:=myTime-VideoTime; - if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then begin // skip frames -{$ifdef DebugFrames} - //frame drop debug display - GoldenRec.Spawn(200,55,1,16,0,-1,ColoredStar,$ff0000); -{$endif} -// 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))); -// 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); - 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 - 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); - // release internal packet structure created by av_read_frame - av_free_packet(PAVPacket(@AVPacket)); - end; - if DropFrame then - for droppedFrames:=1 to FRAMEDROPCOUNT do begin - 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 - 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); - // release internal packet structure created by av_read_frame - av_free_packet(PAVPacket(@AVPacket)); - end; - end; - - // if we did not get an new frame, there's nothing more to do - if Framefinished=0 then begin - GoldenRec.Spawn(220,15,1,16,0,-1,ColoredStar,$0000ff); - Exit; - end; - // otherwise we convert the pixeldata from YUV to RGB - errnum:=img_convert(PAVPicture(AVFrameRGB), PIX_FMT_RGB24, - PAVPicture(AVFrame), VideoCodecContext^.pix_fmt, - VideoCodecContext^.width, VideoCodecContext^.height); -//errnum:=1; - if errnum >=0 then begin - // copy RGB pixeldata to our TextureBuffer - // (line by line) - FrameDataPtr:=AVFrameRGB^.data[0]; - linesize:=AVFrameRGB^.linesize[0]; - for y:=0 to TexY-1 do begin - System.Move(FrameDataPtr[y*linesize],TexData[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); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -{$ifdef DebugFrames} - //frame decode debug display - GoldenRec.Spawn(200,35,1,16,0,-1,ColoredStar,$ffff00); -{$endif} - - end; -end; - -procedure 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 - 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; - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glColor4f(1, 1, 1, 1); - glBindTexture(GL_TEXTURE_2D, VideoTex); - glbegin(gl_quads); - glTexCoord2f( 0, 0); glVertex2f(400-ScaledVideoWidth/2, 300-ScaledVideoHeight/2); - glTexCoord2f( 0, TexY/dataY); glVertex2f(400-ScaledVideoWidth/2, 300+ScaledVideoHeight/2); - glTexCoord2f(TexX/dataX, TexY/dataY); glVertex2f(400+ScaledVideoWidth/2, 300+ScaledVideoHeight/2); - glTexCoord2f(TexX/dataX, 0); glVertex2f(400+ScaledVideoWidth/2, 300-ScaledVideoHeight/2); - glEnd; - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - -{$ifdef Info} - if VideoSkipTime+VideoTime+VideoTimeBase < 0 then begin - glColor4f(0.7, 1, 0.3, 1); - SetFontStyle (1); - SetFontItalic(False); - SetFontSize(9); - SetFontPos (300, 0); - glPrint('Delay due to negative VideoGap'); - glColor4f(1, 1, 1, 1); - end; -{$endif} - -{$ifdef DebugFrames} - glColor4f(0, 0, 0, 0.2); - glbegin(gl_quads); - glVertex2f(0, 0); - glVertex2f(0, 70); - glVertex2f(250, 70); - glVertex2f(250, 0); - glEnd; - - glColor4f(1,1,1,1); - SetFontStyle (1); - SetFontItalic(False); - SetFontSize(9); - SetFontPos (5, 0); - glPrint('delaying frame'); - SetFontPos (5, 20); - glPrint('fetching frame'); - SetFontPos (5, 40); - glPrint('dropping frame'); -{$endif} -end; - -end. +{############################################################################ +# FFmpeg support for UltraStar deluxe # +# # +# Created by b1indy # +# based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) # +#############################################################################} + +//{$define DebugDisplay} // uncomment if u want to see the debug stuff +//{$define DebugFrames} +//{$define Info} + + +unit UVideo; + +interface + +{$IFDEF FPC} + {$MODE DELPHI} +{$ENDIF} + + +uses SDL, + UGraphicClasses, + textgl, + avcodec, + avformat, + avutil, + math, + OpenGL12, + SysUtils, + {$ifdef DebugDisplay} + {$ifdef win32} + dialogs, + {$endif} + {$ENDIF} + UIni; + +procedure Init; +procedure FFmpegOpenFile(FileName: pAnsiChar); +procedure FFmpegClose; +procedure FFmpegGetFrame(Time: Extended); +procedure FFmpegDrawGL(Screen: integer); +procedure FFmpegTogglePause; +procedure FFmpegSkip(Time: Single); + +var + VideoOpened, VideoPaused: Boolean; + VideoFormatContext: PAVFormatContext; + VideoStreamIndex: 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; + +implementation + +{$ifdef DebugDisplay} +{$ifNdef win32} + +procedure showmessage( aMessage : String ); +begin + writeln( aMessage ); +end; + +{$endif} +{$ENDIF} + +procedure Init; +begin + av_register_all; + {$ifdef DebugDisplay} + showmessage( 'AV_Register_ALL' ); + {$endif} + + VideoOpened:=False; + VideoPaused:=False; + + glGenTextures(1, PglUint(@VideoTex)); + SetLength(TexData,0); +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; + + errnum := av_open_input_file(VideoFormatContext, FileName, Nil, 0, Nil); + + 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; + + // Find which stream contains the video + if(av_find_stream_info(VideoFormatContext) >= 0) then + begin + {$ifdef DebugDisplay} + writeln( 'FFMPEG debug... VideoFormatContext^.nb_streams : '+ inttostr( VideoFormatContext^.nb_streams ) ); + {$endif} + for i:= 0 to MAX_STREAMS-1 do + begin + {$ifdef DebugDisplay} + writeln( 'FFMPEG debug... found stream '+ inttostr(i) + ' stream val ' + inttostr( integer(VideoFormatContext^.streams[i] ) ) ); + {$endif} + try + if assigned( VideoFormatContext ) AND + assigned( VideoFormatContext^.streams[i] ) AND + assigned( VideoFormatContext^.streams[i]^.codec ) THEN + begin + {$ifdef DebugDisplay} + writeln( 'FFMPEG debug... found stream '+ inttostr(i) + ' code val ' + inttostr( integer(VideoFormatContext^.streams[i].codec ) ) ); + writeln( 'FFMPEG debug... found stream '+ inttostr(i) + ' code Type ' + inttostr( integer(VideoFormatContext^.streams[i].codec^.codec_type ) ) ); + {$endif} + if(VideoFormatContext^.streams[i]^.codec^.codec_type=CODEC_TYPE_VIDEO) then + begin + {$ifdef DebugDisplay} + writeln( 'FFMPEG debug, found CODEC_TYPE_VIDEO stream' ); + {$endif} + VideoStreamIndex:=i; + end + else + end; + except + // TODO : JB_Linux ... this is excepting at line 108... ( Was 111 previously.. so its prob todo with streams[i]^.codec .. + {$ifdef DebugDisplay} + writeln( 'FFMPEG error, finding video stream' ); + {$endif} + end; + + end; + 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:'+#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); +var + FrameFinished: Integer; + AVPacket: TAVPacket; + errnum, x, y: Integer; + FrameDataPtr: PByteArray; + linesize: integer; + myTime: Extended; + DropFrame: Boolean; + droppedFrames: Integer; +const + FRAMEDROPCOUNT=3; +begin + if not VideoOpened then Exit; + if VideoPaused then Exit; + myTime:=Time+VideoSkipTime; + TimeDifference:=myTime-VideoTime; + DropFrame:=False; +{ showmessage('Time: '+inttostr(floor(Time*1000))+#13#10+ + 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ + 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ + 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); +} + if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin +{$ifdef DebugFrames} + // frame delay debug display + GoldenRec.Spawn(200,15,1,16,0,-1,ColoredStar,$00ff00); +{$endif} +{ showmessage('not getting new frame'+#13#10+ + 'Time: '+inttostr(floor(Time*1000))+#13#10+ + 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ + 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ + 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); +} + Exit;// we don't need a new frame now + end; + VideoTime:=VideoTime+VideoTimeBase; + TimeDifference:=myTime-VideoTime; + if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then begin // skip frames +{$ifdef DebugFrames} + //frame drop debug display + GoldenRec.Spawn(200,55,1,16,0,-1,ColoredStar,$ff0000); +{$endif} +// 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))); +// 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); + 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 + 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); + // release internal packet structure created by av_read_frame + av_free_packet(PAVPacket(@AVPacket)); + end; + if DropFrame then + for droppedFrames:=1 to FRAMEDROPCOUNT do begin + 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 + 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); + // release internal packet structure created by av_read_frame + av_free_packet(PAVPacket(@AVPacket)); + end; + end; + + // if we did not get an new frame, there's nothing more to do + if Framefinished=0 then begin + GoldenRec.Spawn(220,15,1,16,0,-1,ColoredStar,$0000ff); + Exit; + end; + // otherwise we convert the pixeldata from YUV to RGB + errnum:=img_convert(PAVPicture(AVFrameRGB), PIX_FMT_RGB24, + PAVPicture(AVFrame), VideoCodecContext^.pix_fmt, + VideoCodecContext^.width, VideoCodecContext^.height); +//errnum:=1; + if errnum >=0 then begin + // copy RGB pixeldata to our TextureBuffer + // (line by line) + FrameDataPtr:=AVFrameRGB^.data[0]; + linesize:=AVFrameRGB^.linesize[0]; + for y:=0 to TexY-1 do begin + System.Move(FrameDataPtr[y*linesize],TexData[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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +{$ifdef DebugFrames} + //frame decode debug display + GoldenRec.Spawn(200,35,1,16,0,-1,ColoredStar,$ffff00); +{$endif} + + end; +end; + +procedure 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 + 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; + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glColor4f(1, 1, 1, 1); + glBindTexture(GL_TEXTURE_2D, VideoTex); + glbegin(gl_quads); + glTexCoord2f( 0, 0); glVertex2f(400-ScaledVideoWidth/2, 300-ScaledVideoHeight/2); + glTexCoord2f( 0, TexY/dataY); glVertex2f(400-ScaledVideoWidth/2, 300+ScaledVideoHeight/2); + glTexCoord2f(TexX/dataX, TexY/dataY); glVertex2f(400+ScaledVideoWidth/2, 300+ScaledVideoHeight/2); + glTexCoord2f(TexX/dataX, 0); glVertex2f(400+ScaledVideoWidth/2, 300-ScaledVideoHeight/2); + glEnd; + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + +{$ifdef Info} + if VideoSkipTime+VideoTime+VideoTimeBase < 0 then begin + glColor4f(0.7, 1, 0.3, 1); + SetFontStyle (1); + SetFontItalic(False); + SetFontSize(9); + SetFontPos (300, 0); + glPrint('Delay due to negative VideoGap'); + glColor4f(1, 1, 1, 1); + end; +{$endif} + +{$ifdef DebugFrames} + glColor4f(0, 0, 0, 0.2); + glbegin(gl_quads); + glVertex2f(0, 0); + glVertex2f(0, 70); + glVertex2f(250, 70); + glVertex2f(250, 0); + glEnd; + + glColor4f(1,1,1,1); + SetFontStyle (1); + SetFontItalic(False); + SetFontSize(9); + SetFontPos (5, 0); + glPrint('delaying frame'); + SetFontPos (5, 20); + glPrint('fetching frame'); + SetFontPos (5, 40); + glPrint('dropping frame'); +{$endif} +end; + +end. -- cgit v1.2.3 From d123263213fba448d5695df35660f7de4cbed433 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 11 Oct 2007 08:11:47 +0000 Subject: modified UTime to utilise SDL timer... this allows for reliable cross platform timers. Tested working on linux. Modified UVideo and screens to get Video playback working on linux currently only video stream... no audio.. but I Will be working towards this, for all audio playback ( at least for linux ) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@501 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 258 ++++++++++++++++++++++++++++++------------- 1 file changed, 179 insertions(+), 79 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index b2ba01dc..d3cd4ac7 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -1,17 +1,21 @@ -{############################################################################ -# FFmpeg support for UltraStar deluxe # -# # -# Created by b1indy # -# based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) # -#############################################################################} - -//{$define DebugDisplay} // uncomment if u want to see the debug stuff +unit UVideo; +{< ############################################################################# +# FFmpeg support for UltraStar deluxe # +# # +# Created by b1indy # +# based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/) # +# # +# http://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg09949.html # +# http://www.nabble.com/file/p11795857/mpegpas01.zip # +# # +############################################################################## } + +{$define DebugDisplay} // uncomment if u want to see the debug stuff //{$define DebugFrames} //{$define Info} +{} -unit UVideo; - interface {$IFDEF FPC} @@ -43,10 +47,26 @@ procedure FFmpegDrawGL(Screen: integer); procedure FFmpegTogglePause; procedure FFmpegSkip(Time: Single); +{ + @author(Jay Binks ) + @created(2007-10-09) + @lastmod(2007-10-09) + + @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) + + 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; + var VideoOpened, VideoPaused: Boolean; VideoFormatContext: PAVFormatContext; - VideoStreamIndex: Integer; + VideoStreamIndex , + AudioStreamIndex : Integer; VideoCodecContext: PAVCodecContext; VideoCodec: PAVCodec; AVFrame: PAVFrame; @@ -61,6 +81,11 @@ var VideoTimeBase, VideoTime, LastFrameTime, TimeDifference: Extended; VideoSkipTime: Single; + + WantedAudioCodecContext, + AudioCodecContext : PSDL_AudioSpec; + aCodecCtx : PAVCodecContext; + implementation {$ifdef DebugDisplay} @@ -74,13 +99,13 @@ end; {$endif} {$ENDIF} +{ ------------------------------------------------------------------------------ +asdf +------------------------------------------------------------------------------ } procedure Init; begin av_register_all; - {$ifdef DebugDisplay} - showmessage( 'AV_Register_ALL' ); - {$endif} - + VideoOpened:=False; VideoPaused:=False; @@ -88,9 +113,61 @@ begin SetLength(TexData,0); end; +{ + @author(Jay Binks ) + @created(2007-10-09) + @lastmod(2007-10-09) + + @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) + + 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; +var + i : integer; + st : pAVStream; +begin + // Find the first video stream + aFirstAudioStream := -1; + aFirstVideoStream := -1; + + writeln( ' aFormatCtx.nb_streams : ' + inttostr( aFormatCtx.nb_streams ) ); + writeln( ' length( aFormatCtx.streams ) : ' + inttostr( length(aFormatCtx.streams) ) ); + + i := 0; + while ( i < aFormatCtx.nb_streams ) do +// while ( i < length(aFormatCtx.streams)-1 ) do + begin + writeln( ' aFormatCtx.streams[i] : ' + inttostr( i ) ); + st := aFormatCtx.streams[i]; + + if(st.codec.codec_type = CODEC_TYPE_VIDEO ) AND + (aFirstVideoStream < 0) THEN + begin + aFirstVideoStream := i; + end; + + if ( st.codec.codec_type = CODEC_TYPE_AUDIO ) AND + ( aFirstAudioStream < 0) THEN + begin + aFirstAudioStream := i; + end; + + inc( i ); + end; // while + + result := (aFirstAudioStream > -1) OR + (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; @@ -98,9 +175,12 @@ begin 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} @@ -119,46 +199,36 @@ begin end else begin - VideoStreamIndex:=-1; + VideoStreamIndex := -1; + AudioStreamIndex := -1; // Find which stream contains the video - if(av_find_stream_info(VideoFormatContext) >= 0) then + if( av_find_stream_info(VideoFormatContext) >= 0 ) then begin - {$ifdef DebugDisplay} - writeln( 'FFMPEG debug... VideoFormatContext^.nb_streams : '+ inttostr( VideoFormatContext^.nb_streams ) ); - {$endif} - for i:= 0 to MAX_STREAMS-1 do - begin - {$ifdef DebugDisplay} - writeln( 'FFMPEG debug... found stream '+ inttostr(i) + ' stream val ' + inttostr( integer(VideoFormatContext^.streams[i] ) ) ); - {$endif} - try - if assigned( VideoFormatContext ) AND - assigned( VideoFormatContext^.streams[i] ) AND - assigned( VideoFormatContext^.streams[i]^.codec ) THEN - begin - {$ifdef DebugDisplay} - writeln( 'FFMPEG debug... found stream '+ inttostr(i) + ' code val ' + inttostr( integer(VideoFormatContext^.streams[i].codec ) ) ); - writeln( 'FFMPEG debug... found stream '+ inttostr(i) + ' code Type ' + inttostr( integer(VideoFormatContext^.streams[i].codec^.codec_type ) ) ); - {$endif} - if(VideoFormatContext^.streams[i]^.codec^.codec_type=CODEC_TYPE_VIDEO) then - begin - {$ifdef DebugDisplay} - writeln( 'FFMPEG debug, found CODEC_TYPE_VIDEO stream' ); - {$endif} - VideoStreamIndex:=i; - end - else - end; - except - // TODO : JB_Linux ... this is excepting at line 108... ( Was 111 previously.. so its prob todo with streams[i]^.codec .. - {$ifdef DebugDisplay} - writeln( 'FFMPEG error, finding video stream' ); - {$endif} - end; + find_stream_ids( VideoFormatContext, VideoStreamIndex, AudioStreamIndex ); + + writeln( 'VideoStreamIndex : ' + inttostr(VideoStreamIndex) ); + writeln( 'AudioStreamIndex : ' + inttostr(AudioStreamIndex) ); + end; +(* + aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; - end; + 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 @@ -173,6 +243,7 @@ begin av_close_input_file(VideoFormatContext); Exit; end; + if(VideoCodec<>Nil) then begin @@ -188,11 +259,10 @@ begin if(errnum >=0) then begin {$ifdef DebugDisplay} - showmessage('Found a matching Codec:'+#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)); + 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; @@ -253,6 +323,7 @@ begin 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'); @@ -303,39 +374,53 @@ const FRAMEDROPCOUNT=3; begin if not VideoOpened then Exit; + if VideoPaused then Exit; + myTime:=Time+VideoSkipTime; TimeDifference:=myTime-VideoTime; DropFrame:=False; -{ showmessage('Time: '+inttostr(floor(Time*1000))+#13#10+ + +{$IFDEF DebugDisplay} + showmessage('Time: '+inttostr(floor(Time*1000))+#13#10+ 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); -} - if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin +{$endif} + + if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then + begin {$ifdef DebugFrames} // frame delay debug display GoldenRec.Spawn(200,15,1,16,0,-1,ColoredStar,$00ff00); {$endif} -{ showmessage('not getting new frame'+#13#10+ + +{$IFDEF DebugDisplay} + showmessage('not getting new frame'+#13#10+ 'Time: '+inttostr(floor(Time*1000))+#13#10+ 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); -} +{$endif} + Exit;// we don't need a new frame now end; + VideoTime:=VideoTime+VideoTimeBase; TimeDifference:=myTime-VideoTime; - if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then begin // skip frames + if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then // skip frames + begin {$ifdef DebugFrames} //frame drop debug display GoldenRec.Spawn(200,55,1,16,0,-1,ColoredStar,$ff0000); {$endif} -// 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))); + +{$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,-1,Floor((myTime+VideoTimeBase)*1500000),0); VideoTime:=floor(myTime/VideoTimeBase)*VideoTimeBase;} @@ -343,30 +428,41 @@ begin DropFrame:=True; end; - av_init_packet(@AVPacket); +// av_init_packet(@AVPacket); + 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 + 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); + 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(PAVPacket(@AVPacket)); + av_free_packet( AVPacket ); // JB-ffmpeg end; + if DropFrame then for droppedFrames:=1 to FRAMEDROPCOUNT do begin 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 + 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); + 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(PAVPacket(@AVPacket)); // JB-ffmpeg + av_free_packet( AVPacket ); end; end; @@ -380,12 +476,16 @@ begin PAVPicture(AVFrame), VideoCodecContext^.pix_fmt, VideoCodecContext^.width, VideoCodecContext^.height); //errnum:=1; - if errnum >=0 then begin + + if errnum >=0 then + begin // copy RGB pixeldata to our TextureBuffer // (line by line) - FrameDataPtr:=AVFrameRGB^.data[0]; - linesize:=AVFrameRGB^.linesize[0]; - for y:=0 to TexY-1 do begin + + FrameDataPtr := pointer( AVFrameRGB^.data[0] ); + linesize := AVFrameRGB^.linesize[0]; + for y:=0 to TexY-1 do + begin System.Move(FrameDataPtr[y*linesize],TexData[3*y*dataX],linesize); end; -- cgit v1.2.3 From 0d997f8433e982584a0ab67a6d630d12f4314759 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 11 Oct 2007 10:50:01 +0000 Subject: fixes so codebase builds in delphi now, after major FFMpeg changse for linux. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@503 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index d3cd4ac7..2dd745fd 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -89,14 +89,14 @@ var implementation {$ifdef DebugDisplay} -{$ifNdef win32} +//{$ifNdef win32} procedure showmessage( aMessage : String ); begin writeln( aMessage ); end; -{$endif} +//{$endif} {$ENDIF} { ------------------------------------------------------------------------------ -- cgit v1.2.3 From 44554c7908f7e2405a249331f00a35703f5939c2 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 11 Oct 2007 12:02:20 +0000 Subject: Added IAudioPlayback Interface and implementation for BASS. Created "AudioPlayback" Global Singleton, which removed the need for the "Music" Global variable. This was done because global singleton objects are a recognized better "design pattern" achieving the same thing as global variables, but in a nicer way. I will be working to a) separate IAudioPlayback in to separate "Playback" and "Input" Interfaces b) build a FFMpeg class that implements IAudioPlayback git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@504 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 2dd745fd..ed1e5fe3 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -210,7 +210,6 @@ begin writeln( 'VideoStreamIndex : ' + inttostr(VideoStreamIndex) ); writeln( 'AudioStreamIndex : ' + inttostr(AudioStreamIndex) ); end; -(* aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; WantedAudioCodecContext.freq := aCodecCtx^.sample_rate; @@ -222,7 +221,7 @@ begin WantedAudioCodecContext.userdata := aCodecCtx; - +(* if(SDL_OpenAudio(WantedAudioCodecContext, AudioCodecContext) < 0) then begin writeln( 'Could not do SDL_OpenAudio' ); -- cgit v1.2.3 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 From 59074886c5609310cbafcbae19b0a847a1c2bd0e Mon Sep 17 00:00:00 2001 From: jaybinks Date: Wed, 24 Oct 2007 12:05:05 +0000 Subject: comment this.. oops git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@524 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 6e16a7a3..05496fbc 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -83,7 +83,7 @@ type WantedAudioCodecContext, AudioCodecContext : PSDL_AudioSpec; - aCodecCtx : PAVCodecContext; + aCodecCtx : PAVCodecContext; function find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean; @@ -471,16 +471,19 @@ begin end; aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; -(* + if aCodecCtx <> nil then + begin + WantedAudioCodecContext.freq := aCodecCtx^.sample_rate; - WantedAudioCodecContext.format := AUDIO_S16SYS; - WantedAudioCodecContext.channels := aCodecCtx^.channels; - WantedAudioCodecContext.silence := 0; +// 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; *) + end; (* if(SDL_OpenAudio(WantedAudioCodecContext, AudioCodecContext) < 0) then begin -- cgit v1.2.3 From 9a144f3cc3b9fbed5b07ffc3a05c5449d638d3ae Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 25 Oct 2007 06:59:28 +0000 Subject: minor changes and fixes for USDX on linux. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@526 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 05496fbc..4c27867d 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -94,9 +94,9 @@ type procedure init(); function Open( aFileName : string): boolean; // true if succeed - procedure Close; - - procedure Play; + procedure Close; + + procedure Play; procedure Pause; procedure Stop; @@ -126,7 +126,7 @@ asdf function TVideoPlayback_ffmpeg.GetName: String; begin - result := 'FFMpeg'; + result := 'FFMpeg'; end; { @@ -281,7 +281,7 @@ begin av_free_packet( AVPacket ); // JB-ffmpeg except // TODO : JB_FFMpeg ... why does this now AV sometimes ( or always !! ) - end; + end; end; @@ -402,29 +402,29 @@ end; constructor TVideoPlayback_ffmpeg.create(); begin - writeln( 'UVideo_FFMpeg - TVideoPlayback_ffmpeg.create()' ); - - writeln( 'UVideo_FFMpeg - av_register_all' ); - av_register_all; + writeln( 'UVideo_FFMpeg - TVideoPlayback_ffmpeg.create()' ); + + writeln( 'UVideo_FFMpeg - av_register_all' ); + av_register_all; fVideoOpened := False; fVideoPaused := False; -end; - -procedure TVideoPlayback_ffmpeg.init(); +end; + +procedure TVideoPlayback_ffmpeg.init(); begin - writeln( 'UVideo_FFMpeg - glGenTextures(1, PglUint(@fVideoTex))' ); + 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; +end; + + +function TVideoPlayback_ffmpeg.Open( aFileName : string): boolean; // true if succeed +var + errnum, i, x,y: Integer; lStreamsCount : Integer; begin @@ -474,7 +474,7 @@ begin if aCodecCtx <> nil then begin - WantedAudioCodecContext.freq := aCodecCtx^.sample_rate; +// WantedAudioCodecContext.freq := aCodecCtx^.sample_rate; // WantedAudioCodecContext.format := AUDIO_S16SYS; // WantedAudioCodecContext.channels := aCodecCtx^.channels; (* WantedAudioCodecContext.silence := 0; @@ -591,10 +591,10 @@ begin 'be prepared to experience some timing problems'); {$endif} end; - end; -end; - -procedure TVideoPlayback_ffmpeg.Close; + end; +end; + +procedure TVideoPlayback_ffmpeg.Close; begin if fVideoOpened then begin @@ -610,8 +610,8 @@ begin fVideoOpened:=False; end; end; - -procedure TVideoPlayback_ffmpeg.Play; + +procedure TVideoPlayback_ffmpeg.Play; begin end; @@ -638,7 +638,7 @@ end; function TVideoPlayback_ffmpeg.getPosition: real; begin - result := 0; + result := 0; end; initialization @@ -648,8 +648,8 @@ initialization AudioManager.add( IVideoPlayback( singleton_VideoFFMpeg ) ); -finalization - AudioManager.Remove( IVideoPlayback( singleton_VideoFFMpeg ) ); +finalization + AudioManager.Remove( IVideoPlayback( singleton_VideoFFMpeg ) ); end. -- cgit v1.2.3 From 8cca9e3e6f591c35d35d132a9d3f93ffc7cdfee8 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Sat, 27 Oct 2007 06:31:04 +0000 Subject: made some major progress with ffmpeg audio playback !!! YAY !!! still a little choppy, so I suspect incorrect buffer sizes or something like that. also made some mods to support Unicode song file iteration on windows, this is no worse than what we had before, but is not complete.. oh this code only supports win 2000 and up .. no Win 98... git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@533 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 85 +++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 25 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 4c27867d..154cd04c 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -10,9 +10,11 @@ unit UVideo; # # ############################################################################## } -{$define DebugDisplay} // uncomment if u want to see the debug stuff +//{$define DebugDisplay} // uncomment if u want to see the debug stuff //{$define DebugFrames} //{$define Info} + +//{$define FFMpegAudio} {} @@ -45,6 +47,9 @@ uses SDL, dialogs, {$endif} {$ENDIF} + {$ifdef FFMpegAudio} + UAudio_FFMpeg, + {$endif} UIni, UMusic; @@ -108,7 +113,9 @@ type end; - + const + SDL_AUDIO_BUFFER_SIZE = 1024; + {$ifdef DebugDisplay} //{$ifNdef win32} @@ -262,19 +269,23 @@ begin 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 + 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); + begin 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)); + {$ifdef FFMpegAudio} + end + else + if (AVPacket.stream_index = AudioStreamIndex ) then + begin + UAudio_FFMpeg.packet_queue_put(UAudio_FFMpeg.audioq, AVPacket); + {$endif} + end; try if AVPacket.data <> nil then @@ -427,6 +438,10 @@ var errnum, i, x,y: Integer; lStreamsCount : Integer; + wanted_spec , + spec : TSDL_AudioSpec; + aCodec : pAVCodec; + begin fVideoOpened := False; fVideoPaused := False; @@ -471,27 +486,47 @@ begin end; aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; + {$ifdef FFMpegAudio} + // This is the audio ffmpeg audio support Jay is working on. if aCodecCtx <> nil then begin + wanted_spec.freq := aCodecCtx.sample_rate; + wanted_spec.format := AUDIO_S16SYS; + wanted_spec.channels := aCodecCtx.channels; + wanted_spec.silence := 0; + wanted_spec.samples := SDL_AUDIO_BUFFER_SIZE; + wanted_spec.callback := UAudio_FFMpeg.audio_callback; + wanted_spec.userdata := aCodecCtx; -// 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(@wanted_spec, @spec) < 0) then + begin + writeln('SDL_OpenAudio: '+SDL_GetError()); + exit; + end; + + writeln( 'SDL opened audio device' ); + + aCodec := avcodec_find_decoder(aCodecCtx.codec_id); + if (aCodec = nil) then + begin + writeln('Unsupported codec!'); + exit; + end; + + avcodec_open(aCodecCtx, aCodec); + + writeln( 'Opened the codec' ); + + packet_queue_init( audioq ); + SDL_PauseAudio(0); + + writeln( 'SDL_PauseAudio' ); + end; -(* - if(SDL_OpenAudio(WantedAudioCodecContext, AudioCodecContext) < 0) then - begin - writeln( 'Could not do SDL_OpenAudio' ); - exit; - end; -*) - + {$endif} + if(VideoStreamIndex >= 0) then begin VideoCodecContext:=VideoFormatContext^.streams[VideoStreamIndex]^.codec; -- cgit v1.2.3 From 391d30716d48dc709f6444b19c008e82311623b9 Mon Sep 17 00:00:00 2001 From: eddie-0815 Date: Thu, 1 Nov 2007 19:34:40 +0000 Subject: Mac OS X version compiles and links. I hope I didn't break too many files on windows/linux. Added switches.inc to all files. Changed many IFDEFs. For Windows-only code please use MSWINDOWS instead of WIN32 now. WIN32 is also used by the Mac port. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@546 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 154cd04c..c18eea6c 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -20,9 +20,7 @@ unit UVideo; interface -{$IFDEF FPC} - {$MODE DELPHI} -{$ENDIF} +{$I switches.inc} (* -- cgit v1.2.3 From 99955c78f63d1cb0d8bec666bc33953590a74c8a Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 1 Nov 2007 23:22:01 +0000 Subject: fixed failed builds build:USDX-LAZLIN-75 build:USDX-LAZLIN-76 for some reason we can not use {$MODE Delphi} in an included file. ( Probably because of the way the compier scopes this switch to each pas file ) ive had to revert this part of eddies changes. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@548 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index c18eea6c..65dbc0a2 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -14,12 +14,16 @@ unit UVideo; //{$define DebugFrames} //{$define Info} -//{$define FFMpegAudio} +// {$define FFMpegAudio} {} interface +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + {$I switches.inc} (* @@ -281,6 +285,7 @@ begin else if (AVPacket.stream_index = AudioStreamIndex ) then begin + writeln('Encue Audio packet'); UAudio_FFMpeg.packet_queue_put(UAudio_FFMpeg.audioq, AVPacket); {$endif} end; -- cgit v1.2.3 From dcbfb30a62776ffa128f620235a8bacf6137e0d5 Mon Sep 17 00:00:00 2001 From: tobigun Date: Wed, 5 Dec 2007 21:52:18 +0000 Subject: - bugfix: tried to access array element -1 if video contained no audio-stream git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@670 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 65dbc0a2..6c9458f9 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -487,7 +487,11 @@ begin writeln( 'VideoStreamIndex : ' + inttostr(VideoStreamIndex) ); writeln( 'AudioStreamIndex : ' + inttostr(AudioStreamIndex) ); end; - aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; + // FIXME: AudioStreamIndex is -1 if video has no sound -> memory access error + // Just a temporary workaround for now + aCodecCtx := nil; + if( AudioStreamIndex >= 0) then + aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; {$ifdef FFMpegAudio} // This is the audio ffmpeg audio support Jay is working on. @@ -683,11 +687,11 @@ initialization singleton_VideoFFMpeg := TVideoPlayback_ffmpeg.create(); writeln( 'UVideo_FFMpeg - Register Playback' ); - AudioManager.add( IVideoPlayback( singleton_VideoFFMpeg ) ); + AudioManager.add( singleton_VideoFFMpeg ); finalization - AudioManager.Remove( IVideoPlayback( singleton_VideoFFMpeg ) ); + AudioManager.Remove( singleton_VideoFFMpeg ); end. -- cgit v1.2.3 From 486ad8796acc5883ef83f3a78cd615f6711d77f0 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 6 Dec 2007 09:39:49 +0000 Subject: conformed projectM to IVideoPlayback still needs a little work. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@678 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 6c9458f9..c2e42224 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -110,8 +110,8 @@ type 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 + procedure GetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC + procedure DrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC end; @@ -192,7 +192,7 @@ end; -procedure TVideoPlayback_ffmpeg.FFmpegGetFrame(Time: Extended); +procedure TVideoPlayback_ffmpeg.GetFrame(Time: Extended); var FrameFinished: Integer; AVPacket: TAVPacket; @@ -355,7 +355,7 @@ begin end; end; -procedure TVideoPlayback_ffmpeg.FFmpegDrawGL(Screen: integer); +procedure TVideoPlayback_ffmpeg.DrawGL(Screen: integer); begin // have a nice black background to draw on (even if there were errors opening the vid) if Screen=1 then -- cgit v1.2.3 From 553ee1ad981964a3689e6510d5813dbff0f2119c Mon Sep 17 00:00:00 2001 From: jaybinks Date: Thu, 6 Dec 2007 10:46:53 +0000 Subject: added "V" key to sing screen to start Visualization... git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@681 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index c2e42224..62351e2d 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -96,22 +96,21 @@ type function find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean; public constructor create(); - function GetName: String; + function GetName: String; + procedure init(); - procedure init(); + function Open( aFileName : string): boolean; // true if succeed + procedure Close; - function Open( aFileName : string): boolean; // true if succeed - procedure Close; + procedure Play; + procedure Pause; + procedure Stop; - procedure Play; - procedure Pause; - procedure Stop; + procedure MoveTo(Time: real); + function getPosition: real; - procedure MoveTo(Time: real); - function getPosition: real; - - procedure GetFrame(Time: Extended); // WANT TO RENAME THESE TO BE MORE GENERIC - procedure DrawGL(Screen: integer); // WANT TO RENAME THESE TO BE MORE GENERIC + procedure GetFrame(Time: Extended); + procedure DrawGL(Screen: integer); end; -- cgit v1.2.3 From 425ff834dbc3933475ee8f783eea6167e92ec174 Mon Sep 17 00:00:00 2001 From: jaybinks Date: Fri, 7 Dec 2007 04:32:38 +0000 Subject: little bit of tidy up.. added command line switch, to see what media interfaces are being used. moved RandomPCM Data generation to Visualizer class. added Visualization preset change, on new line ( may be a little to much... maybe we should do ever 4 or 16 bars or something ?) git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@697 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 62351e2d..644c62a8 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -161,7 +161,7 @@ begin writeln( ' aFormatCtx.nb_streams : ' + inttostr( aFormatCtx.nb_streams ) ); writeln( ' length( aFormatCtx.streams ) : ' + inttostr( length(aFormatCtx.streams) ) ); - + i := 0; while ( i < aFormatCtx.nb_streams ) do // while ( i < length(aFormatCtx.streams)-1 ) do @@ -415,22 +415,15 @@ 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; @@ -453,10 +446,10 @@ begin TimeDifference := 0; VideoFormatContext := 0; - writeln( aFileName ); - +// writeln( aFileName ); + errnum := av_open_input_file(VideoFormatContext, pchar( aFileName ), Nil, 0, Nil); - writeln( 'Errnum : ' +inttostr( errnum )); +// writeln( 'Errnum : ' +inttostr( errnum )); if(errnum <> 0) then begin {$ifdef DebugDisplay} @@ -684,11 +677,8 @@ end; initialization singleton_VideoFFMpeg := TVideoPlayback_ffmpeg.create(); - - writeln( 'UVideo_FFMpeg - Register Playback' ); AudioManager.add( singleton_VideoFFMpeg ); - finalization AudioManager.Remove( singleton_VideoFFMpeg ); -- cgit v1.2.3 From 549fd3677bd451169bb45a97ae2da3ee5514622b Mon Sep 17 00:00:00 2001 From: tobigun Date: Mon, 17 Dec 2007 11:24:51 +0000 Subject: disabled the FFMPEG_AUDIO stuff for the moment git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@709 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 644c62a8..94c8d7ab 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -14,9 +14,6 @@ unit UVideo; //{$define DebugFrames} //{$define Info} -// {$define FFMpegAudio} -{} - interface @@ -49,7 +46,7 @@ uses SDL, dialogs, {$endif} {$ENDIF} - {$ifdef FFMpegAudio} + {$ifdef UseFFMpegAudio} UAudio_FFMpeg, {$endif} UIni, @@ -279,14 +276,16 @@ begin if (AVPacket.stream_index=VideoStreamIndex) then begin errnum := avcodec_decode_video(VideoCodecContext, AVFrame, frameFinished , AVPacket.data, AVPacket.size); // JB-ffmpeg - {$ifdef FFMpegAudio} + (* FIXME + {$ifdef UseFFMpegAudio} end else if (AVPacket.stream_index = AudioStreamIndex ) then begin writeln('Encue Audio packet'); - UAudio_FFMpeg.packet_queue_put(UAudio_FFMpeg.audioq, AVPacket); + audioq.put(AVPacket); {$endif} + *) end; try @@ -485,7 +484,8 @@ begin if( AudioStreamIndex >= 0) then aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec; - {$ifdef FFMpegAudio} + (* FIXME + {$ifdef UseFFMpegAudio} // This is the audio ffmpeg audio support Jay is working on. if aCodecCtx <> nil then begin @@ -516,15 +516,16 @@ begin avcodec_open(aCodecCtx, aCodec); writeln( 'Opened the codec' ); - + packet_queue_init( audioq ); SDL_PauseAudio(0); - + writeln( 'SDL_PauseAudio' ); - + end; {$endif} + *) if(VideoStreamIndex >= 0) then begin -- cgit v1.2.3 From 96407b5adf8eb1b9ff5e3838a70158d7d3aa29fd Mon Sep 17 00:00:00 2001 From: b1indy Date: Mon, 17 Dec 2007 17:52:42 +0000 Subject: swscale experiment was not satisfying (bad performance), but made clear, that there was unnecessary copying done in GetFrame. UVideo.pas will need some more cleanup but should work better than before. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@717 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 81 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 16 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 94c8d7ab..42971daf 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -14,7 +14,6 @@ unit UVideo; //{$define DebugFrames} //{$define Info} - interface {$IFDEF FPC} @@ -38,6 +37,7 @@ uses SDL, avcodec, avformat, avutil, +// swscale, math, OpenGL12, SysUtils, @@ -50,7 +50,8 @@ uses SDL, UAudio_FFMpeg, {$endif} UIni, - UMusic; + UMusic, + UGraphic; var @@ -65,6 +66,7 @@ type fVideoTex : glUint; fVideoSkipTime : Single; + //remove fTexData : array of Byte; VideoFormatContext: PAVFormatContext; @@ -77,6 +79,8 @@ type AVFrameRGB: PAVFrame; myBuffer: pByte; +// SoftwareScaleContext: PSwsContext; + TexX, TexY, dataX, dataY: Cardinal; ScaledVideoWidth, ScaledVideoHeight: Real; @@ -107,13 +111,13 @@ type function getPosition: real; procedure GetFrame(Time: Extended); - procedure DrawGL(Screen: integer); + procedure DrawGL(Screen: integer); end; const SDL_AUDIO_BUFFER_SIZE = 1024; - + {$ifdef DebugDisplay} //{$ifNdef win32} @@ -165,7 +169,7 @@ begin begin writeln( ' aFormatCtx.streams[i] : ' + inttostr( i ) ); st := aFormatCtx.streams[i]; - + if(st.codec.codec_type = CODEC_TYPE_VIDEO ) AND (aFirstVideoStream < 0) THEN begin @@ -177,10 +181,10 @@ begin begin aFirstAudioStream := i; end; - + inc( i ); end; // while - + result := (aFirstAudioStream > -1) OR (aFirstVideoStream > -1) ; // Didn't find a video stream end; @@ -327,10 +331,22 @@ begin PAVPicture(AVFrame), VideoCodecContext^.pix_fmt, VideoCodecContext^.width, VideoCodecContext^.height); //errnum:=1; - +{ + writeln('swscontext->srcH='+inttostr(SoftwareScaleContext^.srcH)); + writeln('swscontext->dstH='+inttostr(SoftwareScaleContext^.dstH)); + writeln('swscontext->slicedir='+inttostr(SoftwareScaleContext^.slicedir)); + errnum:=sws_scale(SoftwareScaleContext,@(AVFrame.data),@(AVFrame.linesize), + 0,VideoCodecContext^.Height, + @(AVFrameRGB.data),@(AVFrameRGB.linesize)); + writeln('errnum='+inttostr(errnum)); +} if errnum >=0 then begin - // copy RGB pixeldata to our TextureBuffer + glBindTexture(GL_TEXTURE_2D, fVideoTex); + glTexImage2D(GL_TEXTURE_2D, 0, 3, dataX, dataY, 0, GL_RGB, GL_UNSIGNED_BYTE, AVFrameRGB^.data[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +(* // copy RGB pixeldata to our TextureBuffer // (line by line) FrameDataPtr := pointer( AVFrameRGB^.data[0] ); @@ -345,6 +361,7 @@ begin 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} //frame decode debug display GoldenRec.Spawn(200,35,1,16,0,-1,ColoredStar,$ffff00); @@ -436,6 +453,8 @@ var spec : TSDL_AudioSpec; aCodec : pAVCodec; + sws_dst_w, sws_dst_h: Integer; + begin fVideoOpened := False; fVideoPaused := False; @@ -474,7 +493,7 @@ begin if( av_find_stream_info(VideoFormatContext) >= 0 ) then begin find_stream_ids( VideoFormatContext, VideoStreamIndex, AudioStreamIndex ); - + writeln( 'VideoStreamIndex : ' + inttostr(VideoStreamIndex) ); writeln( 'AudioStreamIndex : ' + inttostr(AudioStreamIndex) ); end; @@ -541,7 +560,7 @@ begin Exit; end; - + if(VideoCodec<>Nil) then begin errnum:=avcodec_open(VideoCodecContext, VideoCodec); @@ -555,6 +574,13 @@ begin end; if(errnum >=0) then begin + if (VideoCodecContext^.width >1024) or (VideoCodecContext^.height >1024) then + begin + ScreenPopupError.ShowPopup('Video dimensions\nmust not exceed\n1024 pixels\n\nvideo disabled'); //show error message + avcodec_close(VideoCodecContext); + av_close_input_file(VideoFormatContext); + Exit; + end; {$ifdef DebugDisplay} showmessage('Found a matching Codec: '+ VideoCodecContext^.Codec.Name +#13#10#13#10+ ' Width = '+inttostr(VideoCodecContext^.width)+ ', Height='+inttostr(VideoCodecContext^.height)+#13#10+ @@ -565,24 +591,47 @@ begin AVFrame:=avcodec_alloc_frame; AVFrameRGB:=avcodec_alloc_frame; end; + + dataX := Round(Power(2, Ceil(Log2(VideoCodecContext^.width)))); + dataY := Round(Power(2, Ceil(Log2(VideoCodecContext^.height)))); myBuffer:=Nil; if(AVFrame <> Nil) and (AVFrameRGB <> Nil) then begin - myBuffer:=av_malloc(avpicture_get_size(PIX_FMT_RGB24, VideoCodecContext^.width, - VideoCodecContext^.height)); + myBuffer:=av_malloc(avpicture_get_size(PIX_FMT_RGB24, dataX, dataY)); +// 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) +// VideoCodecContext^.width, VideoCodecContext^.height) + dataX, dataY) else begin -{$ifdef DebugDisplay} + {$ifdef DebugDisplay} showmessage('failed to allocate video buffer'); -{$endif} + {$endif} av_free(AVFrameRGB); av_free(AVFrame); avcodec_close(VideoCodecContext); av_close_input_file(VideoFormatContext); Exit; end; +{ + writeln('trying to get sws context: '+inttostr(VideoCodecContext^.width)+'x'+ + inttostr(VideoCodecContext^.height)+' -> '+inttostr(dataX)+'x'+inttostr(dataY)); + SoftwareScaleContext:=Nil; + SoftwareScaleContext:=sws_getContext(VideoCodecContext^.width,VideoCodecContext^.height,integer(VideoCodecContext^.pix_fmt), + dataX, dataY, integer(PIX_FMT_RGB24), + SWS_FAST_BILINEAR, 0, 0, 0); + if SoftwareScaleContext <> Nil then + writeln('got swscale context') + else begin + writeln('ERROR: didnīt get swscale context'); + av_free(AVFrameRGB); + av_free(AVFrame); + avcodec_close(VideoCodecContext); + av_close_input_file(VideoFormatContext); + Exit; + end; +} + // this is the errnum from avpicture_fill if errnum >=0 then begin fVideoOpened:=True; -- cgit v1.2.3 From ff85cdbd66a19dd80ed4d09b8cca7b0bf3ebf77b Mon Sep 17 00:00:00 2001 From: b1indy Date: Tue, 18 Dec 2007 15:49:16 +0000 Subject: incorporated some improvements (video scaling to full width, seeking for videogap) from 1.0.1 cleanup in UVideo.pas git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@728 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 148 ++++++++++--------------------------------- 1 file changed, 33 insertions(+), 115 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 42971daf..4f6b566a 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -37,7 +37,6 @@ uses SDL, avcodec, avformat, avutil, -// swscale, math, OpenGL12, SysUtils, @@ -66,9 +65,6 @@ type fVideoTex : glUint; fVideoSkipTime : Single; - //remove - fTexData : array of Byte; - VideoFormatContext: PAVFormatContext; VideoStreamIndex , @@ -79,8 +75,6 @@ type AVFrameRGB: PAVFrame; myBuffer: pByte; -// SoftwareScaleContext: PSwsContext; - TexX, TexY, dataX, dataY: Cardinal; ScaledVideoWidth, ScaledVideoHeight: Real; @@ -93,8 +87,8 @@ type AudioCodecContext : PSDL_AudioSpec; aCodecCtx : PAVCodecContext; - function find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean; + public constructor create(); function GetName: String; @@ -215,9 +209,9 @@ begin {$IFDEF DebugDisplay} showmessage('Time: '+inttostr(floor(Time*1000))+#13#10+ - 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ - 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ - 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); + 'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+ + 'TimeBase: '+inttostr(floor(VideoTimeBase*1000))+#13#10+ + 'TimeDiff: '+inttostr(floor(TimeDifference*1000))); {$endif} if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then @@ -238,7 +232,6 @@ 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 @@ -247,35 +240,25 @@ begin //frame drop debug display GoldenRec.Spawn(200,55,1,16,0,-1,ColoredStar,$ff0000); {$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,-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 // JB-ffmpeg + while ( FrameFinished = 0 ) do begin - - + if ( av_read_frame(VideoFormatContext, AVPacket) < 0 ) then + break; // if we got a packet from the video stream, then decode it if (AVPacket.stream_index=VideoStreamIndex) then begin @@ -293,7 +276,7 @@ begin end; try - if AVPacket.data <> nil then +// if AVPacket.data <> nil then av_free_packet( AVPacket ); // JB-ffmpeg except // TODO : JB_FFMpeg ... why does this now AV sometimes ( or always !! ) @@ -301,72 +284,46 @@ begin end; - if DropFrame then for droppedFrames:=1 to FRAMEDROPCOUNT do begin 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 + while (FrameFinished=0) do begin + if (av_read_frame(VideoFormatContext, AVPacket)<0) then + Break; // 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)); // JB-ffmpeg - av_free_packet( AVPacket ); + 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; end; // if we did not get an new frame, there's nothing more to do if Framefinished=0 then begin - GoldenRec.Spawn(220,15,1,16,0,-1,ColoredStar,$0000ff); Exit; end; // otherwise we convert the pixeldata from YUV to RGB errnum:=img_convert(PAVPicture(AVFrameRGB), PIX_FMT_RGB24, PAVPicture(AVFrame), VideoCodecContext^.pix_fmt, VideoCodecContext^.width, VideoCodecContext^.height); -//errnum:=1; -{ - writeln('swscontext->srcH='+inttostr(SoftwareScaleContext^.srcH)); - writeln('swscontext->dstH='+inttostr(SoftwareScaleContext^.dstH)); - writeln('swscontext->slicedir='+inttostr(SoftwareScaleContext^.slicedir)); - errnum:=sws_scale(SoftwareScaleContext,@(AVFrame.data),@(AVFrame.linesize), - 0,VideoCodecContext^.Height, - @(AVFrameRGB.data),@(AVFrameRGB.linesize)); - writeln('errnum='+inttostr(errnum)); -} if errnum >=0 then begin glBindTexture(GL_TEXTURE_2D, fVideoTex); glTexImage2D(GL_TEXTURE_2D, 0, 3, dataX, dataY, 0, GL_RGB, GL_UNSIGNED_BYTE, AVFrameRGB^.data[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -(* // copy RGB pixeldata to our TextureBuffer - // (line by line) - - FrameDataPtr := pointer( AVFrameRGB^.data[0] ); - linesize := AVFrameRGB^.linesize[0]; - for y:=0 to TexY-1 do - begin - System.Move(FrameDataPtr[y*linesize],fTexData[3*y*dataX],linesize); - end; - - // generate opengl texture out of whatever we got - 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} //frame decode debug display GoldenRec.Spawn(200,35,1,16,0,-1,ColoredStar,$ffff00); {$endif} - end; end; @@ -440,7 +397,6 @@ end; procedure TVideoPlayback_ffmpeg.init(); begin glGenTextures(1, PglUint(@fVideoTex)); - SetLength(fTexData,0); end; @@ -560,7 +516,6 @@ begin Exit; end; - if(VideoCodec<>Nil) then begin errnum:=avcodec_open(VideoCodecContext, VideoCodec); @@ -598,10 +553,8 @@ begin if(AVFrame <> Nil) and (AVFrameRGB <> Nil) then begin myBuffer:=av_malloc(avpicture_get_size(PIX_FMT_RGB24, dataX, dataY)); -// 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) dataX, dataY) else begin {$ifdef DebugDisplay} @@ -613,24 +566,6 @@ begin av_close_input_file(VideoFormatContext); Exit; end; -{ - writeln('trying to get sws context: '+inttostr(VideoCodecContext^.width)+'x'+ - inttostr(VideoCodecContext^.height)+' -> '+inttostr(dataX)+'x'+inttostr(dataY)); - SoftwareScaleContext:=Nil; - SoftwareScaleContext:=sws_getContext(VideoCodecContext^.width,VideoCodecContext^.height,integer(VideoCodecContext^.pix_fmt), - dataX, dataY, integer(PIX_FMT_RGB24), - SWS_FAST_BILINEAR, 0, 0, 0); - if SoftwareScaleContext <> Nil then - writeln('got swscale context') - else begin - writeln('ERROR: didnīt get swscale context'); - av_free(AVFrameRGB); - av_free(AVFrame); - avcodec_close(VideoCodecContext); - av_close_input_file(VideoFormatContext); - Exit; - end; -} // this is the errnum from avpicture_fill if errnum >=0 then begin @@ -640,41 +575,26 @@ begin 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; + VideoTimeBase:=VideoFormatContext^.streams[VideoStreamIndex]^.r_frame_rate.den/VideoFormatContext^.streams[VideoStreamIndex]^.r_frame_rate.num; +{$ifdef DebugDisplay} + showmessage('framerate: '+inttostr(floor(1/videotimebase))+'fps'); +{$endif} + // hack to get reasonable timebase (for divx and others) + if VideoTimeBase < 0.02 then // 0.02 <-> 50 fps + begin + VideoTimeBase:=VideoFormatContext^.streams[VideoStreamIndex]^.r_frame_rate.num/VideoFormatContext^.streams[VideoStreamIndex]^.r_frame_rate.den; + while VideoTimeBase > 50 do VideoTimeBase:=VideoTimeBase/10; + VideoTimeBase:=1/VideoTimeBase; + end; + end; end; end; @@ -689,8 +609,6 @@ begin avcodec_close(VideoCodecContext); av_close_input_file(VideoFormatContext); - SetLength(fTexData,0); - fVideoOpened:=False; end; end; @@ -711,18 +629,19 @@ end; procedure TVideoPlayback_ffmpeg.MoveTo(Time: real); begin fVideoSkipTime := Time; - + if fVideoSkipTime > 0 then begin - av_seek_frame(VideoFormatContext,-1,Floor((fVideoSkipTime)*1500000),0); + av_seek_frame(VideoFormatContext,VideoStreamIndex,Floor(Time/VideoTimeBase),AVSEEK_FLAG_ANY); VideoTime := fVideoSkipTime; end; end; +// what is this supposed to do? return VideoTime? function TVideoPlayback_ffmpeg.getPosition: real; begin - result := 0; + result := 0; end; initialization @@ -732,5 +651,4 @@ initialization finalization AudioManager.Remove( singleton_VideoFFMpeg ); - end. -- cgit v1.2.3 From ff1dc556936cef441e105a19aa9d1d3b9e0cc833 Mon Sep 17 00:00:00 2001 From: tobigun Date: Fri, 11 Jan 2008 13:52:44 +0000 Subject: changed from ffmpeg-free (audio) to ffmpeg-enabled (if turned on in switches.inc) version. BASS is used by default. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@786 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index 4f6b566a..bbd03d84 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -45,9 +45,11 @@ uses SDL, dialogs, {$endif} {$ENDIF} + (* FIXME {$ifdef UseFFMpegAudio} - UAudio_FFMpeg, + UAudioDecoder_FFMpeg, {$endif} + *) UIni, UMusic, UGraphic; @@ -101,8 +103,8 @@ type procedure Pause; procedure Stop; - procedure MoveTo(Time: real); - function getPosition: real; + procedure SetPosition(Time: real); + function GetPosition: real; procedure GetFrame(Time: Extended); procedure DrawGL(Screen: integer); @@ -626,7 +628,7 @@ procedure TVideoPlayback_ffmpeg.Stop; begin end; -procedure TVideoPlayback_ffmpeg.MoveTo(Time: real); +procedure TVideoPlayback_ffmpeg.SetPosition(Time: real); begin fVideoSkipTime := Time; @@ -639,7 +641,7 @@ begin end; // what is this supposed to do? return VideoTime? -function TVideoPlayback_ffmpeg.getPosition: real; +function TVideoPlayback_ffmpeg.GetPosition: real; begin result := 0; end; -- cgit v1.2.3 From e95f320dd030e9def8174e8b173e3631f11dba25 Mon Sep 17 00:00:00 2001 From: tobigun Date: Fri, 18 Jan 2008 16:30:06 +0000 Subject: added blindy's swscale support. It can be enabled with {$DEFINE UseSWScale}. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@795 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index bbd03d84..c30b271e 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -37,6 +37,9 @@ uses SDL, avcodec, avformat, avutil, + {$IFDEF UseSWScale} + swscale, + {$ENDIF} math, OpenGL12, SysUtils, @@ -77,6 +80,10 @@ type AVFrameRGB: PAVFrame; myBuffer: pByte; + {$IFDEF UseSWScale} + SoftwareScaleContext: PSwsContext; + {$ENDIF} + TexX, TexY, dataX, dataY: Cardinal; ScaledVideoWidth, ScaledVideoHeight: Real; @@ -312,10 +319,18 @@ begin if Framefinished=0 then begin Exit; end; + // otherwise we convert the pixeldata from YUV to RGB + {$IFDEF UseSWScale} + errnum:=sws_scale(SoftwareScaleContext,@(AVFrame.data),@(AVFrame.linesize), + 0,VideoCodecContext^.Height, + @(AVFrameRGB.data),@(AVFrameRGB.linesize)); + {$ELSE} errnum:=img_convert(PAVPicture(AVFrameRGB), PIX_FMT_RGB24, PAVPicture(AVFrame), VideoCodecContext^.pix_fmt, VideoCodecContext^.width, VideoCodecContext^.height); + {$ENDIF} + if errnum >=0 then begin glBindTexture(GL_TEXTURE_2D, fVideoTex); @@ -568,6 +583,23 @@ begin av_close_input_file(VideoFormatContext); Exit; end; + + {$IFDEF UseSWScale} + SoftwareScaleContext:=sws_getContext(VideoCodecContext^.width,VideoCodecContext^.height,integer(VideoCodecContext^.pix_fmt), + dataX, dataY, integer(PIX_FMT_RGB24), + SWS_FAST_BILINEAR, 0, 0, 0); + if SoftwareScaleContext <> Nil then + writeln('got swscale context') + else begin + writeln('ERROR: didnīt get swscale context'); + av_free(AVFrameRGB); + av_free(AVFrame); + avcodec_close(VideoCodecContext); + av_close_input_file(VideoFormatContext); + Exit; + end; + {$ENDIF} + // this is the errnum from avpicture_fill if errnum >=0 then begin -- cgit v1.2.3 From 89ac41a2ccb85d6dfccb501ff4877231cab72094 Mon Sep 17 00:00:00 2001 From: tobigun Date: Tue, 5 Feb 2008 13:43:38 +0000 Subject: Update of the ffmpeg headers to their current trunk versions. IMPORTANT: parameter of av_free_packet is a pointer now procedure av_free_packet (pkt: PAVPacket); as it is with av_free() and av_freep() git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@814 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index c30b271e..db7e3ffd 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -286,7 +286,7 @@ begin try // if AVPacket.data <> nil then - av_free_packet( AVPacket ); // JB-ffmpeg + av_free_packet( @AVPacket ); // JB-ffmpeg except // TODO : JB_FFMpeg ... why does this now AV sometimes ( or always !! ) end; @@ -308,7 +308,7 @@ begin // release internal packet structure created by av_read_frame try // if AVPacket.data <> nil then - av_free_packet( AVPacket ); // JB-ffmpeg + av_free_packet( @AVPacket ); // JB-ffmpeg except // TODO : JB_FFMpeg ... why does this now AV sometimes ( or always !! ) end; -- cgit v1.2.3 From c09529e6ab6ecbf2d5ba2ac8f29713ba0101e55a Mon Sep 17 00:00:00 2001 From: tobigun Date: Tue, 5 Feb 2008 13:57:27 +0000 Subject: Removed the "use nil instead of 0" warnings git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@815 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UVideo.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Game/Code/Classes/UVideo.pas') diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index db7e3ffd..66c0c8e6 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -435,7 +435,7 @@ begin VideoTime := 0; LastFrameTime := 0; TimeDifference := 0; - VideoFormatContext := 0; + VideoFormatContext := nil; // writeln( aFileName ); @@ -587,7 +587,7 @@ begin {$IFDEF UseSWScale} SoftwareScaleContext:=sws_getContext(VideoCodecContext^.width,VideoCodecContext^.height,integer(VideoCodecContext^.pix_fmt), dataX, dataY, integer(PIX_FMT_RGB24), - SWS_FAST_BILINEAR, 0, 0, 0); + SWS_FAST_BILINEAR, nil, nil, nil); if SoftwareScaleContext <> Nil then writeln('got swscale context') else begin -- cgit v1.2.3