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/UMain.pas | 16 ++- Game/Code/Classes/UTime.pas | 142 +++++++++++++----------- Game/Code/Classes/UVideo.pas | 258 ++++++++++++++++++++++++++++++------------- 3 files changed, 273 insertions(+), 143 deletions(-) (limited to 'Game/Code/Classes') diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas index aa4bc639..41676bf3 100644 --- a/Game/Code/Classes/UMain.pas +++ b/Game/Code/Classes/UMain.pas @@ -139,7 +139,11 @@ procedure MainLoop; var Delay: integer; begin + Delay := 0; SDL_EnableKeyRepeat(125, 125); + + + CountSkipTime(); // JB - for some reason this seems to be needed when we use the SDL Timer functions. While not Done do Begin // joypad @@ -158,16 +162,26 @@ begin // delay CountMidTime; + + {$IFDEF DebugDisplay} + Writeln( 'TimeMid : '+ inttostr(trunc(TimeMid)) ); + {$ENDIF} + // if 1000*TimeMid > 100 then beep; Delay := Floor(1000 / 100 - 1000 * TimeMid); + {$IFDEF DebugDisplay} + Writeln( 'Delay ms : '+ inttostr(Delay) ); + {$ENDIF} + if Delay >= 1 then SDL_Delay(Delay); // dynamic, maximum is 100 fps CountSkipTime; // reinitialization of graphics - if Restart then begin + if Restart then + begin Reinitialize3D; Restart := false; end; diff --git a/Game/Code/Classes/UTime.pas b/Game/Code/Classes/UTime.pas index c197a70f..edd65b7e 100644 --- a/Game/Code/Classes/UTime.pas +++ b/Game/Code/Classes/UTime.pas @@ -6,6 +6,9 @@ interface {$MODE Delphi} {$ENDIF} +{$DEFINE SDLTimer} +{$UNDEF DebugDisplay} + type TTime = class constructor Create; @@ -15,7 +18,6 @@ type procedure CountSkipTimeSet; procedure CountSkipTime; procedure CountMidTime; -procedure TimeSleep(ms: real); var USTime: TTime; @@ -36,21 +38,22 @@ uses libc, time, {$ENDIF} + sysutils, + {$IFDEF SDLTimer} + sdl, + {$ENDIF} ucommon; - - -// -- ON Linux it MAY Be better to use ... clock_gettime() instead of CurrentSec100OfDay -// who knows how fast or slow that function is ! -// but this gets a compile for now .. :) + +const + cSDLCorrectionRatio = 1000; (* -msec( ) -{ - struct timeval tv; - gettimeofday( &tv, NULL ); - return (int64_t)tv.tv_sec * (int64_t)1000000 + (int64_t)tv.tv_usec; -} +BEST Option now ( after discussion with whiteshark ) seems to be to use SDL +timer functions... +SDL_delay +SDL_GetTicks +http://www.gamedev.net/community/forums/topic.asp?topic_id=466145&whichpage=1%EE%8D%B7 *) @@ -59,86 +62,99 @@ begin CountSkipTimeSet; end; + procedure CountSkipTimeSet; begin - {$IFDEF win32} - QueryPerformanceFrequency(TimeFreq); - QueryPerformanceCounter(TimeNew); + {$IFDEF SDLTimer} + TimeNew := SDL_GetTicks(); // / cSDLCorrectionRatio + TimeFreq := 0; {$ELSE} - TimeNew := CurrentSec100OfDay(); // TODO - JB_Linux will prob need looking at - TimeFreq := 0; + {$IFDEF win32} + QueryPerformanceFrequency(TimeFreq); + QueryPerformanceCounter(TimeNew); + {$ELSE} + TimeNew := CurrentSec100OfDay(); // TODO - JB_Linux will prob need looking at + TimeFreq := 0; + {$ENDIF} + {$ENDIF} + + {$IFDEF DebugDisplay} + Writeln( 'CountSkipTimeSet : ' + inttostr(trunc(TimeNew)) ); {$ENDIF} end; + procedure CountSkipTime; begin TimeOld := TimeNew; - {$IFDEF win32} - QueryPerformanceCounter(TimeNew); + {$IFDEF SDLTimer} + TimeNew := SDL_GetTicks(); + TimeSkip := (TimeNew-TimeOld) / cSDLCorrectionRatio; {$ELSE} - TimeNew := CurrentSec100OfDay(); // TODO - JB_Linux will prob need looking at + {$IFDEF win32} + QueryPerformanceCounter(TimeNew); + + if ( TimeNew-TimeOld > 0 ) AND + ( TimeFreq > 0 ) THEN + begin + TimeSkip := (TimeNew-TimeOld)/TimeFreq; + end; + + {$ELSE} + TimeNew := CurrentSec100OfDay(); // TODO - JB_Linux will prob need looking at + TimeSkip := (TimeNew-TimeOld); + {$ENDIF} {$ENDIF} - - if ( TimeNew-TimeOld > 0 ) AND - ( TimeFreq > 0 ) THEN - begin - TimeSkip := (TimeNew-TimeOld)/TimeFreq; - end; -end; -procedure CountMidTime; -begin - {$IFDEF win32} - QueryPerformanceCounter(TimeMidTemp); - TimeMid := (TimeMidTemp-TimeNew)/TimeFreq; - {$ELSE} - TimeMidTemp := CurrentSec100OfDay(); - TimeMid := (TimeMidTemp-TimeNew); // TODO - JB_Linux will prob need looking at + {$IFDEF DebugDisplay} + Writeln( 'TimeNew : ' + inttostr(trunc(TimeNew)) ); + Writeln( 'CountSkipTime : ' + inttostr(trunc(TimeSkip)) ); {$ENDIF} end; -procedure TimeSleep(ms: real); -var - TimeStart: int64; - TimeHalf: int64; - Time: real; - Stop: boolean; + +procedure CountMidTime; begin - {$IFDEF win32} - QueryPerformanceCounter(TimeStart); + {$IFDEF SDLTimer} + TimeMidTemp := SDL_GetTicks(); + TimeMid := (TimeMidTemp - TimeNew) / cSDLCorrectionRatio; {$ELSE} - TimeStart := CurrentSec100OfDay(); // TODO - JB_Linux will prob need looking at - {$ENDIF} - - - Stop := false; - while (not Stop) do - begin {$IFDEF win32} - QueryPerformanceCounter(TimeHalf); - Time := 1000 * (TimeHalf-TimeStart)/TimeFreq; + QueryPerformanceCounter(TimeMidTemp); + TimeMid := (TimeMidTemp-TimeNew)/TimeFreq; {$ELSE} - TimeHalf := CurrentSec100OfDay(); - Time := 1000 * (TimeHalf-TimeStart); // TODO - JB_Linux will prob need looking at + TimeMidTemp := CurrentSec100OfDay(); + TimeMid := (TimeMidTemp-TimeNew); // TODO - JB_Linux will prob need looking at {$ENDIF} + {$ENDIF} - if Time > ms then - Stop := true; - end; - + {$IFDEF DebugDisplay} + Writeln( 'TimeNew : ' + inttostr(trunc(TimeNew)) ); + Writeln( 'CountMidTime : ' + inttostr(trunc(TimeMid)) ); + {$ENDIF} end; + function TTime.GetTime: real; var TimeTemp: int64; begin - {$IFDEF win32} - QueryPerformanceCounter(TimeTemp); - Result := TimeTemp / TimeFreq; + {$IFDEF SDLTimer} + TimeTemp := SDL_GetTicks(); + Result := TimeTemp / cSDLCorrectionRatio; // TODO - JB_Linux will prob need looking at {$ELSE} - TimeTemp := CurrentSec100OfDay(); - Result := TimeTemp; // TODO - JB_Linux will prob need looking at + {$IFDEF win32} + QueryPerformanceCounter(TimeTemp); + Result := TimeTemp / TimeFreq; + {$ELSE} + TimeTemp := CurrentSec100OfDay(); + Result := TimeTemp; // TODO - JB_Linux will prob need looking at + {$ENDIF} + {$ENDIF} + + {$IFDEF DebugDisplay} + Writeln( 'GetTime : ' + inttostr(trunc(Result)) ); {$ENDIF} end; 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