diff options
author | brunzelchen <brunzelchen@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2011-02-07 23:05:43 +0000 |
---|---|---|
committer | brunzelchen <brunzelchen@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2011-02-07 23:05:43 +0000 |
commit | d5cf0ceae7fbbdb0ed21685e05c18541fb71675b (patch) | |
tree | 259d73f4418819a79901992eb9684c6134e147f0 /Game/Code | |
parent | 61be36a5af28943f27bd4a42f52fa4ca879adaa5 (diff) | |
download | usdx-d5cf0ceae7fbbdb0ed21685e05c18541fb71675b.tar.gz usdx-d5cf0ceae7fbbdb0ed21685e05c18541fb71675b.tar.xz usdx-d5cf0ceae7fbbdb0ed21685e05c18541fb71675b.zip |
- added "ac_drop_decode_video_package" - method to acinerella: decoding of a frame without scaling
- added threaded video decoding
- added video frame buffer (50 frames)
git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/1.0.1 Challenge MOD@2803 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to 'Game/Code')
-rw-r--r-- | Game/Code/Classes/UVideo.pas | 698 | ||||
-rw-r--r-- | Game/Code/UltraStar.bdsproj | 4 | ||||
-rw-r--r-- | Game/Code/UltraStar.dpr | 2 | ||||
-rw-r--r-- | Game/Code/lib/acinerella/acinerella.c | 44 | ||||
-rw-r--r-- | Game/Code/lib/acinerella/acinerella.h | 1 | ||||
-rw-r--r-- | Game/Code/lib/acinerella/acinerella.pas | 1 |
6 files changed, 516 insertions, 234 deletions
diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas index b89f5cc0..a93ee778 100644 --- a/Game/Code/Classes/UVideo.pas +++ b/Game/Code/Classes/UVideo.pas @@ -9,7 +9,6 @@ //{$define Info} - unit UVideo; interface @@ -29,13 +28,15 @@ uses SDL, glu, glext, SysUtils, + SyncObjs, {$ifdef DebugDisplay} {$ifdef win32} dialogs, {$endif} {$ENDIF} UIni, - UTime; + UTime, + windows; type TAspectCorrection = (acoStretch, acoCrop, acoLetterBox); //from 1.1 @@ -50,20 +51,43 @@ type ZoomFaktor: real;
end; + TFrameBuffer = record + frame: Pointer; + time: Extended; + displayed: Boolean; + end; + + TFrameThread = class(TThread) + private
+ Time: Extended;
+ Gap: Single;
+ Start: Single;
+ + iSkip: Boolean;
+ waiting: Boolean;
+
+ procedure DoDecode;
+ procedure DoSkip;
+ procedure Copy;
+ procedure Update();
+ protected
+ constructor Create;
+ procedure Execute; override;
+ 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; @@ -118,6 +142,19 @@ var EnableVideoDraw: boolean; + FrameData: Pointer; + NewFrame: boolean; + SetTime: Extended; + SetGap: Single; + SetStart: Single; + SetSkip: boolean; + + FrameThread: TFrameThread; + + EventDecode: TEvent; + FrameBuffer: array [0..49] of TFrameBuffer; + MutexFramebuffer: PSDL_Mutex; + MutexSyncSignals: PSDL_Mutex; implementation @@ -133,10 +170,13 @@ 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; +var + i: integer; + begin inst := nil; videodecoder := nil; @@ -161,6 +201,32 @@ begin PIXEL_FORMAT := GL_RGBA;
EnableVideoDraw := true;
+
+ SetTime := 0;
+ if(FrameData<>nil) then
+ FreeMem(FrameData);
+ FrameData := nil;
+
+ for i := 0 to High(FrameBuffer) do
+ begin
+ if(FrameBuffer[i].frame <> nil) then
+ FreeMem(FrameBuffer[i].frame);
+ FrameBuffer[i].frame := nil;
+
+ FrameBuffer[i].time := -1;
+ FrameBuffer[i].displayed := true;
+ end;
+
+ if (FrameThread<>nil) then
+ begin
+ FrameThread.Terminate;
+ FrameThread.WaitFor;
+ FrameThread.Free;
+ FrameThread := nil;
+ end;
+
+ MutexFramebuffer := SDL_CreateMutex;
+ MutexSyncSignals := SDL_CreateMutex;
end; procedure acOpenFile(FileName: pAnsiChar); @@ -168,6 +234,7 @@ var I: integer; begin + acClose; VideoPaused := False;
VideoTimeBase := 0;
@@ -175,7 +242,6 @@ begin LastFrameTime := 0;
TimeDifference := 0; Counter := 0; - acClose; if not FileExists(FileName) then Exit; //TODO: error.log
@@ -234,6 +300,12 @@ begin dataX := Round(Power(2, Ceil(Log2(TexX))));
dataY := Round(Power(2, Ceil(Log2(TexY))));
+ GetMem(FrameData, numBytes*TexX*TexY);
+ for I := 0 to high(FrameBuffer) do
+ begin
+ GetMem(FrameBuffer[I].frame, numBytes*TexX*TexY);
+ end;
+
// calculate some information for video display
VideoAspect:=videodecoder^.stream_info.additional_info.video_info.pixel_aspect;
if (VideoAspect = 0) then
@@ -268,11 +340,39 @@ 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; +var + I: Integer; + begin - if VideoOpened then begin + if VideoOpened then + begin + if (FrameThread<>nil) then + begin
+ FrameThread.Terminate;
+ FrameThread.WaitFor;
+ FrameThread.Free;
+ FrameThread := nil;
+ end; + + FreeAndNil(EventDecode); + + NewFrame := false; + SetSkip := false; if videodecoder <> nil then ac_free_decoder(videodecoder);
@@ -286,6 +386,20 @@ begin VideoOpened:=False; fName := ''; + + if(FrameData<>nil) then + FreeMem(FrameData);
+ FrameData := nil; + + for I := 0 to High(FrameBuffer) do + begin
+ if(FrameBuffer[i].frame <> nil) then
+ FreeMem(FrameBuffer[i].frame);
+ FrameBuffer[i].frame := nil;
+
+ FrameBuffer[i].time := -1;
+ FrameBuffer[i].displayed := false;
+ end; end; end; @@ -297,137 +411,46 @@ end; procedure acSkip2(Gap: Single; Start: Single); begin - 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 acSkip(Gap: Single; Start: Single); -begin - 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; + SDL_LockMutex(MutexSyncSignals); + try + SetGap := Gap;
+ SetStart := Start; + SetSkip := true;
+ finally
+ SDL_UnlockMutex(MutexSyncSignals);
end; + EventDecode.SetEvent; end; -function acSearch(Time: Extended): integer; -var - FrameFinished: Integer; - errnum: Integer; - FrameDataPtr: PByteArray; - myTime: Extended; - +procedure acGetFrame(Time: 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 + if (Time-SetTime>=0) or (SetTime>Time) then 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); + SDL_LockMutex(MutexSyncSignals); + try + SetTime := Time;
+ finally
+ SDL_UnlockMutex(MutexSyncSignals);
end; - + UploadNewFrame(); + EventDecode.SetEvent; end; end; -procedure acGetFrame(Time: Extended); +procedure TFrameThread.DoDecode; Const MAX = 3000; + FRAMEDROPCOUNT=4; var FrameFinished: Integer; - errnum: Integer; - FrameDataPtr: PByteArray; - FrameDataPtr2: PByteArray; 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; + {mmfps := (Display.mFPS+mmfps)/2; if(Ini.PerformanceMode=1) then begin if (mmfps<MIN_FPS) then @@ -454,45 +477,31 @@ begin end; if (Counter>MAX) then - Counter := MAX; + Counter := MAX;} if (NegativeSkipTime < 0)and(Time+NegativeSkipTime>=0) then NegativeSkipTime:=0; 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 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 + while (FrameFinished=0) and (pack <> nil) and not DropFrame 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 @@ -510,15 +519,51 @@ begin if DropFrame then begin - //acSearch(Time); - for droppedFrames:=1 to FRAMEDROPCOUNT do + for droppedFrames:=1 to FRAMEDROPCOUNT-1 do begin - pack := ac_read_package(inst); + if terminated then + Exit; + + if (droppedFrames>1) then + 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 we got a packet from the video stream, then decode it + if terminated then + Exit; + + // if we got a packet from the video stream, then decode it (without scaling) + if (videodecoder^.stream_index = pack^.stream_index) then + begin + FrameFinished := ac_drop_decode_package(pack, videodecoder); + ac_free_package(pack); + if (FrameFinished=0) then + pack := ac_read_package(inst); + end else + begin + ac_free_package(pack); + pack := ac_read_package(inst); + end; + end; + end; + + for I:=droppedFrames to FRAMEDROPCOUNT do + begin + if terminated then + Exit; + + if (droppedFrames>1) then + 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 (with scaling) if (videodecoder^.stream_index = pack^.stream_index) then begin FrameFinished := ac_decode_package(pack, videodecoder); @@ -536,108 +581,160 @@ begin // 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); - acClose; Exit; - end; - errnum:=1; //TODO!! - if errnum >=0 then - begin - if(not pbo_supported) then - begin - FrameDataPtr:=Pointer(videodecoder^.buffer); + //cope the decoded frame into buffer + Copy; +end; - glBindTexture(GL_TEXTURE_2D, VideoTex); +procedure TFrameThread.Copy(); +var + num: Integer; + FrameDataPtr: PByteArray; + FrameDataPtr2: PByteArray; + I: Integer; - 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]); +begin + num := -1;
+ SDL_LockMutex(MutexFramebuffer); + try + for I := 0 to high(FrameBuffer) do
+ begin + if FrameBuffer[I].displayed then
+ begin
+ num := I;
+ break;
+ end;
+ end; + + if (num = -1) then + begin +
waiting := true; end else begin - glGetError(); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); + FrameDataPtr := FrameBuffer[num].frame; + FrameBuffer[num].time := VideoTime; + FrameBuffer[num].displayed := false; - glError := glGetError; - if glError <> GL_NO_ERROR then - begin - acClose;
- Log.LogError('Error drawing Video "glBindBuffer"');
- Exit;
- end; + FrameDataPtr2:=Pointer(videodecoder^.buffer); - 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; + if terminated then + Exit; - FrameDataPtr2:=Pointer(videodecoder^.buffer); 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; + VideoTime := videodecoder^.timecode;
+
+ waiting := false;
+ end;
+ finally
+ SDL_UnLockMutex(MutexFramebuffer);
+ end;
+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; +procedure TFrameThread.DoSkip; +var + SkipTime: Extended; + I: Integer; - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY, - PIXEL_FORMAT, GL_UNSIGNED_BYTE, nil); +begin + SDL_LockMutex(MutexSyncSignals); + try + VideoSkiptime:=Gap;
+ NegativeSkipTime:=Start+Gap; + SkipTime := Start+Gap;
+ finally
+ SDL_UnlockMutex(MutexSyncSignals);
+ 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); + 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; - VideoTime := videodecoder^.timecode; - - if Ini.Debug = 1 then - begin - //frame decode debug display - GoldenRec.Spawn(200,85,1,16,0,-1,ColoredStar,$ffff00,0); + end else + begin + try + ac_seek(videodecoder, 0, 0); + except
+ Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
end; + VideoTime:=0; + end; + + waiting := false; + SDL_LockMutex(MutexFramebuffer); + try + for I := 0 to High(FrameBuffer) do
+ begin
+ FrameBuffer[i].time := -1;
+ FrameBuffer[i].displayed := true;
+ end;
+ finally
+ SDL_UnLockMutex(MutexFramebuffer);
end; end; +constructor TFrameThread.Create; +begin + inherited Create(true); + Self.Priority := tpNormal; + Self.FreeOnTerminate := false; + + Time := 0; + iSkip := false; + waiting := false; + + Self.Resume; +end; + +procedure TFrameThread.Execute; +begin + while not terminated do + begin + if (EventDecode.WaitFor(1) = wrSignaled) or not waiting then + begin + try + if iSkip then + begin + DoSkip; + iSkip := false; + end; + + if not waiting then
+ DoDecode();
+
+ if waiting then
+ Copy();
+ except
+
+ end;
+ end;
+ if not terminated then
+ Update;
+ end;
+end; + +procedure TFrameThread.Update; +begin + SDL_LockMutex(MutexSyncSignals); + try + Time := SetTime;
+ if (SetSkip) then
+ iSkip := true; + + SetSkip := false; + Gap := SetGap; + Start := SetStart;
+ finally
+ SDL_UnlockMutex(MutexSyncSignals);
+ end; +
end; + procedure ToggleAspectCorrection(); begin case fAspectCorrection of @@ -770,6 +867,149 @@ begin acDrawGLi(Screen, Window, 1, DoDraw);
end; +procedure UploadNewFrame; +var + FrameDataPtr: PByteArray; + FrameDataPtr2: PByteArray; + I: Integer; + glError: glEnum; + glErrorStr: String; + num: Integer; + + function FindFrame(): Integer; + var + I: Integer; + diff, td: Extended; + begin + Result := -1; + diff := 10000000; + + for I := 0 to high(FrameBuffer) do + begin + td := SetTime + VideoSkipTime - FrameBuffer[I].time; + if not FrameBuffer[I].displayed and (td < diff) and + (td > VideoTimeBase) then + begin + diff := Abs(FrameBuffer[I].time - SetTime - VideoSkipTime); + Result := I; + end; + + if (td > VideoTimeBase*2) then + FrameBuffer[I].displayed := true; + end; + + if (Result<>-1) then + FrameBuffer[Result].displayed := true + end; + +begin + if VideoOpened then
+ begin + if (not pbo_supported) then
+ begin + SDL_LockMutex(MutexFramebuffer); + try + num := FindFrame(); + + if (num>=0) then + begin + FrameDataPtr:=FrameBuffer[num].frame;
+ + 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;
+ finally
+ SDL_UnLockMutex(MutexFramebuffer);
+ end; + 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; + + SDL_LockMutex(MutexFramebuffer); + try + num := FindFrame(); + if (num>=0) then + begin + FrameDataPtr2:=FrameBuffer[num].frame;
+ move(FrameDataPtr2[0], FrameDataPtr[0], numBytes*TexX*TexY);
+ end;
+ finally
+ SDL_UnLockMutex(MutexFramebuffer);
+ end; + + 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;
+ EventDecode.SetEvent;
+ end;
+end; + procedure acDrawGLi(Screen: integer; Window: TRectCoords; Blend: real; DoDraw: boolean); var ScreenRect, TexRect: TRectCoords; @@ -947,7 +1187,7 @@ begin SetFontItalic(False); SetFontSize(7); SetFontPos (5, 50); - glPrint(PChar('vtime: ' + FormatFloat('#0.00', VideoTime))); + glPrint(PChar('tdiff: ' + FormatFloat('#0.00', TimeDifference))); SetFontPos (5, 65); glPrint(PChar(timediff_str)); diff --git a/Game/Code/UltraStar.bdsproj b/Game/Code/UltraStar.bdsproj index 2f94b78a..36df4a05 100644 --- a/Game/Code/UltraStar.bdsproj +++ b/Game/Code/UltraStar.bdsproj @@ -170,9 +170,7 @@ <VersionInfoKeys Name="ProductName"></VersionInfoKeys>
<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
<VersionInfoKeys Name="Comments"></VersionInfoKeys>
- </VersionInfoKeys>
-
- <Excluded_Packages>
+ </VersionInfoKeys> <Excluded_Packages>
<Excluded_Packages Name="c:\program files\borland\bds\4.0\Bin\dclib100.bpl">Borland InterBase Express Components</Excluded_Packages>
<Excluded_Packages Name="c:\program files\borland\bds\4.0\Bin\dclIntraweb_80_100.bpl">Intraweb 8.0 Design Package for Borland Development Studio 2006</Excluded_Packages>
<Excluded_Packages Name="c:\program files\borland\bds\4.0\Bin\dclIndyCore100.bpl">Indy 10 Core Design Time</Excluded_Packages>
diff --git a/Game/Code/UltraStar.dpr b/Game/Code/UltraStar.dpr index ba63c085..efdb9017 100644 --- a/Game/Code/UltraStar.dpr +++ b/Game/Code/UltraStar.dpr @@ -123,7 +123,7 @@ uses const
VersionName = 'UltraStar Deluxe Challenge, Medley & Duet Edition';
- VersionNumber = 'r9.7';
+ VersionNumber = 'r9.9';
var
WndTitle: string;
diff --git a/Game/Code/lib/acinerella/acinerella.c b/Game/Code/lib/acinerella/acinerella.c index 5b0178e4..d807ec4f 100644 --- a/Game/Code/lib/acinerella/acinerella.c +++ b/Game/Code/lib/acinerella/acinerella.c @@ -680,7 +680,7 @@ int ac_decode_video_package(lp_ac_package pPackage, lp_ac_video_decoder pDecoder pDecoder->pSwsCtx = sws_getCachedContext(pDecoder->pSwsCtx,
pDecoder->pCodecCtx->width, pDecoder->pCodecCtx->height, pDecoder->pCodecCtx->pix_fmt,
pDecoder->pCodecCtx->width, pDecoder->pCodecCtx->height, convert_pix_format(pDecoder->decoder.pacInstance->output_format),
- SWS_BICUBIC, NULL, NULL, NULL);
+ SWS_FAST_BILINEAR, NULL, NULL, NULL);
sws_scale(
pDecoder->pSwsCtx,
@@ -780,6 +780,48 @@ int CALL_CONVT ac_decode_package(lp_ac_package pPackage, lp_ac_decoder pDecoder) return 0;
}
+int CALL_CONVT ac_drop_decode_package(lp_ac_package pPackage, lp_ac_decoder pDecoder) {
+ if (pDecoder->type == AC_DECODER_TYPE_VIDEO) {
+ return ac_drop_decode_video_package(pPackage, (lp_ac_video_decoder)pDecoder, pDecoder);
+ }
+ return 0;
+}
+
+int ac_drop_decode_video_package(lp_ac_package pPackage, lp_ac_video_decoder pDecoder, lp_ac_decoder pDec) {
+ int finished;
+ double pts;
+
+ avcodec_decode_video2(
+ pDecoder->pCodecCtx, pDecoder->pFrame, &finished,
+ &(((lp_ac_package_data)pPackage)->ffpackage));
+
+ if (finished) {
+ pts=0;
+ global_video_pkt_pts = ((lp_ac_package_data)pPackage)->ffpackage.pts;
+
+ if(((lp_ac_package_data)pPackage)->ffpackage.dts == AV_NOPTS_VALUE &&
+ *(uint64_t*)pDecoder->pFrame->opaque != AV_NOPTS_VALUE ){
+ pts = *(uint64_t*)pDecoder->pFrame->opaque;
+ } else if(((lp_ac_package_data)pPackage)->ffpackage.dts != AV_NOPTS_VALUE){
+ pts = ((lp_ac_package_data)pPackage)->ffpackage.dts;
+ } else {
+ pts = 0;
+ }
+
+ if(((lp_ac_data)pDec->pacInstance)->pFormatCtx->streams[pPackage->stream_index]->start_time != AV_NOPTS_VALUE){
+ pts -= ((lp_ac_data)pDec->pacInstance)->pFormatCtx->streams[pPackage->stream_index]->start_time;
+ }
+
+ pts *= av_q2d(((lp_ac_data)pDec->pacInstance)->pFormatCtx->streams[pPackage->stream_index]->time_base);
+
+ pts = ac_sync_video(pPackage, pDec, pDecoder->pFrame, pts);
+ pDec->timecode = pts;
+
+ return 1;
+ }
+ return 0;
+}
+
//Seek function
int CALL_CONVT ac_seek(lp_ac_decoder pDecoder, int dir, int64_t target_pos) {
AVRational timebase =
diff --git a/Game/Code/lib/acinerella/acinerella.h b/Game/Code/lib/acinerella/acinerella.h index 9eded573..a568b84c 100644 --- a/Game/Code/lib/acinerella/acinerella.h +++ b/Game/Code/lib/acinerella/acinerella.h @@ -241,6 +241,7 @@ extern void CALL_CONVT ac_free_decoder(lp_ac_decoder pDecoder); /*Decodes a package using the specified decoder. The decodec data is stored in the
"buffer" property of the decoder.*/
extern int CALL_CONVT ac_decode_package(lp_ac_package pPackage, lp_ac_decoder pDecoder);
+extern int CALL_CONVT ac_drop_decode_package(lp_ac_package pPackage, lp_ac_decoder pDecoder);
/*Seeks to the given target position in the file. The seek funtion is not able to seek a single audio/video stream
but seeks the whole file forward. The stream number paremter (nb) is only used for the timecode reference.
diff --git a/Game/Code/lib/acinerella/acinerella.pas b/Game/Code/lib/acinerella/acinerella.pas index 2d267027..316204c2 100644 --- a/Game/Code/lib/acinerella/acinerella.pas +++ b/Game/Code/lib/acinerella/acinerella.pas @@ -237,6 +237,7 @@ procedure ac_free_decoder(pDecoder: PAc_decoder); cdecl; external ac_dll; {Decodes a package using the specified decoder. The decodec data is stored in the
"buffer" property of the decoder.}
function ac_decode_package(pPackage: PAc_package; pDecoder: PAc_decoder): integer; cdecl; external ac_dll;
+function ac_drop_decode_package(pPackage: PAc_package; pDecoder: PAc_decoder): integer; cdecl; external ac_dll;
{Seeks to the given target position in the file. The seek funtion is not able to seek a single audio/video stream
but seeks the whole file forward. The deocder parameter is only used as an timecode reference.
|