aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes/UVideo.pas
diff options
context:
space:
mode:
authorjaybinks <jaybinks@b956fd51-792f-4845-bead-9b4dfca2ff2c>2007-10-11 08:11:47 +0000
committerjaybinks <jaybinks@b956fd51-792f-4845-bead-9b4dfca2ff2c>2007-10-11 08:11:47 +0000
commitd123263213fba448d5695df35660f7de4cbed433 (patch)
treeef0bb01727be4b38a44a84ef6bef8224ee38d9b2 /Game/Code/Classes/UVideo.pas
parent48676faa6c0da1eb77999512322896840ea13cb1 (diff)
downloadusdx-d123263213fba448d5695df35660f7de4cbed433.tar.gz
usdx-d123263213fba448d5695df35660f7de4cbed433.tar.xz
usdx-d123263213fba448d5695df35660f7de4cbed433.zip
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
Diffstat (limited to 'Game/Code/Classes/UVideo.pas')
-rw-r--r--Game/Code/Classes/UVideo.pas258
1 files changed, 179 insertions, 79 deletions
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 <jaybinks@gmail.com>)
+ @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 <jaybinks@gmail.com>)
+ @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;