diff options
-rw-r--r-- | Game/Code/Classes/UIni.pas | 2 | ||||
-rw-r--r-- | Game/Code/Classes/UVideo.pas | 503 | ||||
-rw-r--r-- | Game/Code/Screens/UScreenSing.pas | 2 |
3 files changed, 223 insertions, 284 deletions
diff --git a/Game/Code/Classes/UIni.pas b/Game/Code/Classes/UIni.pas index 6ea24653..682016b8 100644 --- a/Game/Code/Classes/UIni.pas +++ b/Game/Code/Classes/UIni.pas @@ -400,7 +400,7 @@ begin if Tekst = IAspectCorrect[Pet] then Ini.AspectCorrect := Pet;
// PerformanceMode
- Tekst := IniFile.ReadString('Graphics', 'PerformanceMode', IPerformanceMode[1]);
+ Tekst := IniFile.ReadString('Graphics', 'PerformanceMode', IPerformanceMode[0]);
for Pet := 0 to High(IPerformanceMode) do
if Tekst = IPerformanceMode[Pet] then Ini.PerformanceMode := Pet;
diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index d54ca5c7..b89f5cc0 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -9,6 +9,7 @@ //{$define Info} + unit UVideo; interface @@ -28,15 +29,13 @@ uses SDL, glu, glext, SysUtils, - SyncObjs, {$ifdef DebugDisplay} {$ifdef win32} dialogs, {$endif} {$ENDIF} UIni, - UTime, - windows; + UTime; type TAspectCorrection = (acoStretch, acoCrop, acoLetterBox); //from 1.1 @@ -51,37 +50,20 @@ type ZoomFaktor: real;
end; - TFrameThread = class(TThread) - private
- Time: Extended;
- Gap: Single;
- Start: Single;
- - iSkip: Boolean;
- iDecode: Boolean;
-
- procedure DoDecode;
- procedure DoSkip;
- protected
- constructor Create;
- procedure Execute; override;
- public
- procedure Update();
- end; - procedure Init; procedure acOpenFile(FileName: pAnsiChar); procedure acClose; procedure acGetFrame(Time: Extended); +function acSearch(Time: Extended): integer; procedure acDrawGL(Screen: integer; DoDraw: boolean); procedure acDrawGLi(Screen: integer; Window: TRectCoords; Blend: real; DoDraw: boolean); procedure acTogglePause; +procedure acSkip(Gap: Single; Start: Single); procedure acSkip2(Gap: Single; Start: Single); procedure ToggleAspectCorrection; procedure GetVideoRect(var ScreenRect, TexRect: TRectCoords; Window: TRectCoords); procedure SetAspectCorrection(aspect: TAspectCorrection); procedure ResetAspectCorrection; -procedure UploadNewFrame; Const MIN_FPS = 40; @@ -136,16 +118,6 @@ var EnableVideoDraw: boolean; - FrameData: Pointer; - NewFrame: boolean; - SetTime: Extended; - SetGap: Single; - SetStart: Single; - SetSkip: boolean; - - FrameThread: TFrameThread; - - EventDecode: TEvent; implementation @@ -161,7 +133,7 @@ end; function seek_proc(sender: Pointer; pos: int64; whence: integer): int64; cdecl;
begin
- result := fs.Seek(pos, TSeekOrigin(whence));
+ result := fs.Seek(pos, TSeekOrigin(whence))
end; procedure Init; @@ -189,19 +161,6 @@ begin PIXEL_FORMAT := GL_RGBA;
EnableVideoDraw := true;
-
- SetTime := 0;
- if(FrameData<>nil) then
- FreeMem(FrameData);
- FrameData := nil;
-
- if (FrameThread<>nil) then
- begin
- FrameThread.Terminate;
- FrameThread.WaitFor;
- FrameThread.Free;
- FrameThread := nil;
- end;
end; procedure acOpenFile(FileName: pAnsiChar); @@ -209,7 +168,6 @@ var I: integer; begin - acClose; VideoPaused := False;
VideoTimeBase := 0;
@@ -217,6 +175,7 @@ begin LastFrameTime := 0;
TimeDifference := 0; Counter := 0; + acClose; if not FileExists(FileName) then Exit; //TODO: error.log
@@ -275,8 +234,6 @@ begin dataX := Round(Power(2, Ceil(Log2(TexX))));
dataY := Round(Power(2, Ceil(Log2(TexY))));
- GetMem(FrameData, numBytes*TexX*TexY);
-
// calculate some information for video display
VideoAspect:=videodecoder^.stream_info.additional_info.video_info.pixel_aspect;
if (VideoAspect = 0) then
@@ -311,42 +268,11 @@ begin end; mmfps := (MAX_FPS-MIN_FPS)/2;
-
- SetTime := 0;
- NewFrame := false;
- SetSkip := false;
-
- if (EventDecode = nil) then
- EventDecode := TEvent.Create(nil, false, false, '');
-
- if (FrameThread = nil) then
- FrameThread := TFrameThread.Create();
-
- FrameThread.Resume;
end; procedure acClose; begin - if VideoOpened then - begin - if (FrameThread<>nil) then - begin - FrameThread.Suspend; - //Framethread.WaitFor; - end; - - {if (FrameThread<>nil) then - begin
- FrameThread.Terminate;
- FrameThread.WaitFor;
- FrameThread.Free;
- FrameThread := nil;
- end; - - FreeAndNil(EventDecode);} - - NewFrame := false; - SetSkip := false; + if VideoOpened then begin if videodecoder <> nil then ac_free_decoder(videodecoder);
@@ -360,10 +286,6 @@ begin VideoOpened:=False; fName := ''; - - if(FrameData<>nil) then - FreeMem(FrameData);
- FrameData := nil; end; end; @@ -375,22 +297,117 @@ end; procedure acSkip2(Gap: Single; Start: Single); begin - SetGap := Gap; - SetStart := Start; - SetSkip := true; - EventDecode.SetEvent; + VideoSkiptime:=Gap; + NegativeSkipTime:=Start+Gap; + if Start+Gap > 0 then + begin + VideoTime:=Start+Gap; + try + ac_seek(videodecoder, -1, Floor((Start+Gap)*1000)); + except
+ Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
+ acClose;
+ end; + end else + begin + try + ac_seek(videodecoder, 0, 0); + except
+ Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
+ acClose;
+ end; + VideoTime:=0; + end; end; -procedure acGetFrame(Time: Extended); +procedure acSkip(Gap: Single; Start: Single); begin - SetTime := Time; - EventDecode.SetEvent; + VideoSkiptime:=Gap; + NegativeSkipTime:=Start+Gap; + if Start+Gap > 0 then + begin + VideoTime:=0; + ac_seek(videodecoder, -1, Floor((Start+Gap)*1000)); + if (acSearch(Gap+Start)=0) then + begin + ac_seek(videodecoder, 0, 0);
+ VideoTime:=0;
+ acSearch(Gap+Start);
+ end; + end else + begin + ac_seek(videodecoder, 0, 0); + VideoTime:=0; + end; +end; + +function acSearch(Time: Extended): integer; +var + FrameFinished: Integer; + errnum: Integer; + FrameDataPtr: PByteArray; + myTime: Extended; + +begin + Result := 0; + if not VideoOpened then Exit; + if (NegativeSkipTime < 0)and(Time+NegativeSkipTime>=0) then + NegativeSkipTime:=0; + + myTime:=Time+VideoSkipTime; + TimeDifference:=myTime-VideoTime; + + if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin + Exit;// we don't need a new frame now + end; + + pack := ac_read_package(inst); + FrameFinished:=0; + // read packets until we have a finished frame (or there are no more packets) + while ((VideoTime < Time-VideoTimeBase)) and (pack <> nil) do + begin + // if we got a packet from the video stream, then decode it + if (videodecoder^.stream_index = pack^.stream_index) then + begin + FrameFinished := ac_decode_package(pack, videodecoder); + VideoTime := videodecoder^.timecode; + ac_free_package(pack); + if ((VideoTime < Time-VideoTimeBase)) then + pack := ac_read_package(inst); + end else + begin + ac_free_package(pack); + pack := ac_read_package(inst); + end; + end; + if (pack<>nil) then + ac_free_package(pack); + + // if we did not get an new frame, there's nothing more to do + if Framefinished=0 then + begin + Exit; + end; + + errnum:=1; //TODO!! + if errnum >=0 then begin + FrameDataPtr:=Pointer(videodecoder^.buffer); + Result := 1; + glBindTexture(GL_TEXTURE_2D, VideoTex); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY, PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[0]); + + if Ini.Debug = 1 then + begin + //frame decode debug display + GoldenRec.Spawn(200,85,1,16,0,-1,ColoredStar,$ffff00,0); + end; + + end; end; -procedure TFrameThread.DoDecode; +procedure acGetFrame(Time: Extended); Const MAX = 3000; - FRAMEDROPCOUNT=3; var FrameFinished: Integer; @@ -400,8 +417,16 @@ var myTime: Extended; DropFrame: Boolean; droppedFrames: Integer; + I: Integer; + glError: glEnum; + glErrorStr: String; +const + FRAMEDROPCOUNT=3; begin + if not VideoOpened then Exit; + if VideoPaused then Exit; + mmfps := (Display.mFPS+mmfps)/2; if(Ini.PerformanceMode=1) then begin @@ -436,27 +461,38 @@ begin myTime:=Time+VideoSkipTime; TimeDifference:=myTime-VideoTime; + if Ini.Debug = 1 then + begin + timediff_str:= 't-diff: ' + FormatFloat('#0.00', TimeDifference); + mtime_str:= 'mytime: ' + FormatFloat('#0.00', myTime); + end; + DropFrame:=False; - if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then - Exit; + if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin + if Ini.Debug = 1 then + begin + // frame delay debug display + GoldenRec.Spawn(200,65,1,16,0,-1,ColoredStar,$00ff00,0); + end; + Exit;// we don't need a new frame now + end; + + if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then begin // skip frames + if Ini.Debug = 1 then + begin + //frame drop debug display + GoldenRec.Spawn(200,105,1,16,0,-1,ColoredStar,$ff0000,0); + end; - if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then - begin // skip frames DropFrame:=True; end; - if terminated then - Exit; - pack := ac_read_package(inst); FrameFinished:=0; // read packets until we have a finished frame (or there are no more packets) while (FrameFinished=0) and (pack <> nil) do begin - if terminated then - Exit; - // if we got a packet from the video stream, then decode it if (videodecoder^.stream_index = pack^.stream_index) then begin @@ -477,16 +513,11 @@ begin //acSearch(Time); for droppedFrames:=1 to FRAMEDROPCOUNT do begin - if terminated then - Exit; pack := ac_read_package(inst); FrameFinished:=0; // read packets until we have a finished frame (or there are no more packets) while (FrameFinished=0) and (pack <> nil) do begin - if terminated then - Exit; - // if we got a packet from the video stream, then decode it if (videodecoder^.stream_index = pack^.stream_index) then begin @@ -506,99 +537,105 @@ begin // if we did not get an new frame, there's nothing more to do if Framefinished=0 then begin - //acClose; +// GoldenRec.Spawn(220,15,1,16,0,-1,ColoredStar,$0000ff); + acClose; Exit; end; errnum:=1; //TODO!! if errnum >=0 then begin - FrameDataPtr := FrameData; - FrameDataPtr2:=Pointer(videodecoder^.buffer); - - if terminated then - Exit; + if(not pbo_supported) then + begin + FrameDataPtr:=Pointer(videodecoder^.buffer); - move(FrameDataPtr2[0], FrameDataPtr[0], numBytes*TexX*TexY); + glBindTexture(GL_TEXTURE_2D, VideoTex); - VideoTime := videodecoder^.timecode; + if(SkipLines>0)then + begin + for I := 0 to TexY - 1 do + begin + if(I mod (SkipLines+1) = 0) then + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (I div (SkipLines+1)), TexX, 1, + PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[I*numBytes*TexX]); + end; + end else + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY, + PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[0]); + end else + begin + glGetError(); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); - NewFrame := true; - end; -end; + glError := glGetError; + if glError <> GL_NO_ERROR then + begin + acClose;
+ Log.LogError('Error drawing Video "glBindBuffer"');
+ Exit;
+ end; -procedure TFrameThread.DoSkip; -var - SkipTime: Extended; + FrameDataPtr := glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); + glError := glGetError; + if glError <> GL_NO_ERROR then + begin + acClose;
+ Log.LogError('Error drawing Video pbo "glMapBuffer"');
+ Exit;
+ end; -begin - VideoSkiptime:=Gap; - NegativeSkipTime:=Start+Gap; - SkipTime := Start+Gap; -
- if SkipTime > 0 then - begin - VideoTime:=SkipTime; - try - ac_seek(videodecoder, -1, Floor((SkipTime)*1000)); - except
- Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
- end; - end else - begin - try - ac_seek(videodecoder, 0, 0); - except
- Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
- end; - VideoTime:=0; - end; -end; + FrameDataPtr2:=Pointer(videodecoder^.buffer); + move(FrameDataPtr2[0], FrameDataPtr[0], numBytes*TexX*TexY); -constructor TFrameThread.Create; -begin - inherited Create(true); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); + glError := glGetError; + if glError <> GL_NO_ERROR then + begin + acClose;
+ Log.LogError('Error drawing Video pbo "glUnmapBuffer"');
+ Exit;
+ end; - //Self.Priority := tpLower; - Self.FreeOnTerminate := false; + glBindTexture(GL_TEXTURE_2D, VideoTex); + glError := glGetError; + if glError <> GL_NO_ERROR then + begin + acClose;
+ Log.LogError('Error drawing Video pbo "glBindTexture"');
+ Exit;
+ end; - Time := 0; - iDecode := false; - iSkip := false; + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY, + PIXEL_FORMAT, GL_UNSIGNED_BYTE, nil); - Self.Resume; -end; + glError := glGetError; + if glError <> GL_NO_ERROR then + begin + acClose;
+ case glError of
+ GL_INVALID_ENUM: glErrorStr:='INVALID_ENUM';
+ GL_INVALID_VALUE: glErrorStr:='INVALID_VALUE';
+ GL_INVALID_OPERATION: glErrorStr:='INVALID_OPERATION';
+ GL_STACK_OVERFLOW: glErrorStr:='STACK_OVERFLOW';
+ GL_STACK_UNDERFLOW: glErrorStr:='STACK_UNDERFLOW';
+ GL_OUT_OF_MEMORY: glErrorStr:='OUT_OF_MEMORY';
+ else glErrorStr:='unknown error';
+ end;
+ Log.LogError('Error drawing Video pbo "glTexSubImage2D" ('+glErrorStr+')');
+ Exit;
+ end; + glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); + end; + VideoTime := videodecoder^.timecode; -procedure TFrameThread.Execute; -begin - while not terminated do - begin - if (EventDecode.WaitFor(100) = wrSignaled) then + if Ini.Debug = 1 then begin - try - if iSkip then - DoSkip; - - if iDecode then
- DoDecode();
- except
-
- end;
- end;
- if not terminated then
- Synchronize(Update);
- end;
-end; + //frame decode debug display + GoldenRec.Spawn(200,85,1,16,0,-1,ColoredStar,$ffff00,0); + end; -procedure TFrameThread.Update; -begin - Time := SetTime;
- iDecode := VideoOpened and not VideoPaused and not NewFrame; - iSkip := SetSkip; - SetSkip := false; - Gap := SetGap; - Start := SetStart;
- UploadNewFrame();
+ end; end; procedure ToggleAspectCorrection(); @@ -733,104 +770,6 @@ begin acDrawGLi(Screen, Window, 1, DoDraw);
end; -procedure UploadNewFrame; -var - FrameDataPtr: PByteArray; - FrameDataPtr2: PByteArray; - I: Integer; - glError: glEnum; - glErrorStr: String; - -begin - if VideoOpened and NewFrame then
- begin - if (not pbo_supported) then
- begin - FrameDataPtr:=FrameData; - - glBindTexture(GL_TEXTURE_2D, VideoTex); - - if(SkipLines>0)then - begin - for I := 0 to TexY - 1 do - begin - if(I mod (SkipLines+1) = 0) then - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (I div (SkipLines+1)), TexX, 1, - PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[I*numBytes*TexX]); - end; - end else - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY, - PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[0]); - end else - begin - glGetError(); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); - - glError := glGetError; - if glError <> GL_NO_ERROR then - begin - acClose;
- Log.LogError('Error drawing Video "glBindBuffer"');
- Exit;
- end; - - FrameDataPtr := glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); - glError := glGetError; - if glError <> GL_NO_ERROR then - begin - acClose;
- Log.LogError('Error drawing Video pbo "glMapBuffer"');
- Exit;
- end; - - FrameDataPtr2:=FrameData; - move(FrameDataPtr2[0], FrameDataPtr[0], numBytes*TexX*TexY); - - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); - glError := glGetError; - if glError <> GL_NO_ERROR then - begin - acClose;
- Log.LogError('Error drawing Video pbo "glUnmapBuffer"');
- Exit;
- end; - - glBindTexture(GL_TEXTURE_2D, VideoTex); - glError := glGetError; - if glError <> GL_NO_ERROR then - begin - acClose;
- Log.LogError('Error drawing Video pbo "glBindTexture"');
- Exit;
- end; - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY, - PIXEL_FORMAT, GL_UNSIGNED_BYTE, nil); - - glError := glGetError; - if glError <> GL_NO_ERROR then - begin - acClose;
- case glError of
- GL_INVALID_ENUM: glErrorStr:='INVALID_ENUM';
- GL_INVALID_VALUE: glErrorStr:='INVALID_VALUE';
- GL_INVALID_OPERATION: glErrorStr:='INVALID_OPERATION';
- GL_STACK_OVERFLOW: glErrorStr:='STACK_OVERFLOW';
- GL_STACK_UNDERFLOW: glErrorStr:='STACK_UNDERFLOW';
- GL_OUT_OF_MEMORY: glErrorStr:='OUT_OF_MEMORY';
- else glErrorStr:='unknown error';
- end;
- Log.LogError('Error drawing Video pbo "glTexSubImage2D" ('+glErrorStr+')');
- Exit;
- end; - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); - end;
- NewFrame := false;
- EventDecode.SetEvent;
- end;
-end; - procedure acDrawGLi(Screen: integer; Window: TRectCoords; Blend: real; DoDraw: boolean); var ScreenRect, TexRect: TRectCoords; diff --git a/Game/Code/Screens/UScreenSing.pas b/Game/Code/Screens/UScreenSing.pas index 402e24aa..2f8ee68f 100644 --- a/Game/Code/Screens/UScreenSing.pas +++ b/Game/Code/Screens/UScreenSing.pas @@ -1908,7 +1908,7 @@ begin if ShowFinish and AktSong.VideoLoaded then
begin
try
- acGetFrame(Czas.Teraz);
+ acGetFrame(Music.Position);
acDrawGL(ScreenAct, not WebCam); // this only draws
except
//If an Error occurs drawing: prevent Video from being Drawn again and Close Video
|