aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Game/Code/Classes/UIni.pas2
-rw-r--r--Game/Code/Classes/UVideo.pas503
-rw-r--r--Game/Code/Screens/UScreenSing.pas2
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