hedgewars/uVideoRec.pas
changeset 7280 fd707afbc3a2
parent 7235 baa69bd025d9
child 7286 068adc6948e3
--- a/hedgewars/uVideoRec.pas	Sun Jun 24 20:31:26 2012 +0400
+++ b/hedgewars/uVideoRec.pas	Sun Jun 24 20:57:02 2012 +0400
@@ -44,7 +44,7 @@
 
 implementation
 
-uses uVariables, uUtils, GLunit, SDLh, SysUtils;
+uses uVariables, uUtils, GLunit, SDLh, SysUtils, uIO;
 
 {$IFDEF WIN32}
 const AVWrapperLibName = 'libavwrapper.dll';
@@ -55,35 +55,35 @@
 {$IFDEF WIN32}
 procedure AVWrapper_Init(
               AddLog: TAddFileLogRaw;
-              filename, finalFilename, soundFile, format, vcodec, acodec, preset: PChar;
-              width, height, framerateNum, framerateDen, frequency, channels, vquality, aquality: LongInt); cdecl; external AVWrapperLibName;
+              filename, desc, soundFile, format, vcodec, acodec, preset: PChar;
+              width, height, framerateNum, framerateDen, vquality, aquality: LongInt); cdecl; external AVWrapperLibName;
 procedure AVWrapper_Close; cdecl; external AVWrapperLibName;
 procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external AVWrapperLibName;
 {$ELSE}
 procedure AVWrapper_Init(
               AddLog: TAddFileLogRaw;
-              filename, finalFilename, soundFile, format, vcodec, acodec, preset: PChar;
-              width, height, framerateNum, framerateDen, frequency, channels, vquality, aquality: LongInt); cdecl; external;
+              filename, desc, soundFile, format, vcodec, acodec, preset: PChar;
+              width, height, framerateNum, framerateDen, vquality, aquality: LongInt); cdecl; external;
 procedure AVWrapper_Close; cdecl; external;
 procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external;
 {$ENDIF}
 
+type TFrame = record
+                  ticks: LongWord;
+                  CamX, CamY: LongInt;
+                  zoom: single;
+              end;
+
 var YCbCr_Planes: array[0..2] of PByte;
     RGB_Buffer: PByte;
-
-    frequency, channels: LongInt;
-
-    cameraFile: TextFile;
+    cameraFile: File of TFrame;
     audioFile: File;
-
-    numPixels: LongInt;
-
-    firstTick, nframes: Int64;
-
+    numPixels: LongWord;
+    startTime, numFrames: LongWord;
     cameraFilePath, soundFilePath: shortstring;
 
 function BeginVideoRecording: Boolean;
-var filename, finalFilename: shortstring;
+var filename, desc: shortstring;
 begin
     AddFileLog('BeginVideoRecording');
 
@@ -99,19 +99,27 @@
         AddFileLog('Error: Could not read from ' + cameraFilePath);
         exit(false);
     end;
-
-    ReadLn(cameraFile, frequency, channels);
 {$IOCHECKS ON}
 
+    desc:= '';
+    if UserNick <> '' then
+        desc+= 'Player: ' + UserNick + #10;
+    if recordFileName <> '' then
+        desc+= 'Record: ' + recordFileName + #10;
+    if cMapName <> '' then
+        desc+= 'Map: ' + cMapName + #10;
+    if Theme <> '' then
+        desc+= 'Theme: ' + Theme + #10;
+    desc+= #0;
+
     filename:= UserPathPrefix + '/VideoTemp/' + cRecPrefix + #0;
-    finalFilename:= UserPathPrefix + '/Videos/' + cRecPrefix + #0;
     soundFilePath:= UserPathPrefix + '/VideoTemp/' + cRecPrefix + '.sw' + #0;
     cAVFormat+= #0;
     cAudioCodec+= #0;
     cVideoCodec+= #0;
     cVideoPreset+= #0;
-    AVWrapper_Init(@AddFileLogRaw, @filename[1], @finalFilename[1], @soundFilePath[1], @cAVFormat[1], @cVideoCodec[1], @cAudioCodec[1], @cVideoPreset[1],
-                   cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, frequency, channels, cAudioQuality, cVideoQuality);
+    AVWrapper_Init(@AddFileLogRaw, @filename[1], @desc[1], @soundFilePath[1], @cAVFormat[1], @cVideoCodec[1], @cAudioCodec[1], @cVideoPreset[1],
+                   cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, cAudioQuality, cVideoQuality);
 
     YCbCr_Planes[0]:= GetMem(numPixels);
     YCbCr_Planes[1]:= GetMem(numPixels div 4);
@@ -144,6 +152,7 @@
     AVWrapper_Close();
     DeleteFile(cameraFilePath);
     DeleteFile(soundFilePath);
+    SendIPC(_S'v');
 end;
 
 function pixel(x, y, color: LongInt): LongInt;
@@ -175,24 +184,25 @@
         end;
 
     AVWrapper_WriteFrame(YCbCr_Planes[0], YCbCr_Planes[1], YCbCr_Planes[2]);
+
+    // inform frontend that we have encoded new frame (p for progress)
+    SendIPC(_S'p');
 end;
 
 // returns new game ticks
 function LoadNextCameraPosition: LongInt;
-var NextTime: LongInt;
-    NextZoom: LongInt;
-    NextWorldDx, NextWorldDy: LongInt;
+var frame: TFrame;
 begin
 {$IOCHECKS OFF}
     if eof(cameraFile) then
         exit(-1);
-    ReadLn(cameraFile, NextTime, NextWorldDx, NextWorldDy, NextZoom);
+    BlockRead(cameraFile, frame, 1);
 {$IOCHECKS ON}
-    WorldDx:= NextWorldDx;
-    WorldDy:= NextWorldDy + cScreenHeight div 2;
-    zoom:= NextZoom/10000*cScreenWidth;
+    WorldDx:= frame.CamX;
+    WorldDy:= frame.CamY + cScreenHeight div 2;
+    zoom:= frame.zoom*cScreenWidth;
     ZoomValue:= zoom;
-    LoadNextCameraPosition:= NextTime;
+    LoadNextCameraPosition:= frame.ticks;
 end;
 
 // Callback which records sound.
@@ -208,15 +218,17 @@
 procedure BeginPreRecording;
 var format: word;
     filePrefix, filename: shortstring;
+    frequency, channels: LongInt;
 begin
     AddFileLog('BeginPreRecording');
 
-    nframes:= 0;
-    firstTick:= SDL_GetTicks();
+    numFrames:= 0;
+    startTime:= SDL_GetTicks();
 
     filePrefix:= FormatDateTime('YYYY-MM-DD_HH-mm-ss', Now());
 
     Mix_QuerySpec(@frequency, @format, @channels);
+    AddFileLog('sound: frequency = ' + IntToStr(frequency) + ', format = ' + IntToStr(format) + ', channels = ' + IntToStr(channels));
     if format <> $8010 then
     begin
         // TODO: support any audio format
@@ -244,8 +256,10 @@
         AddFileLog('Error: Could not write to ' + filename);
         exit;
     end;
+
+    BlockWrite(audioFile, frequency, 4);
+    BlockWrite(audioFile, channels, 4);
 {$IOCHECKS ON}
-    WriteLn(cameraFile, inttostr(frequency) + ' ' + inttostr(channels));
 
     // register callback for actual audio recording
     Mix_SetPostMix(@RecordPostMix, nil);
@@ -267,13 +281,18 @@
 end;
 
 procedure SaveCameraPosition;
-var Ticks: LongInt;
+var curTime: LongInt;
+    frame: TFrame;
 begin
-    Ticks:= SDL_GetTicks();
-    while (Ticks - firstTick)*cVideoFramerateNum > nframes*cVideoFramerateDen*1000 do
+    curTime:= SDL_GetTicks();
+    while Int64(curTime - startTime)*cVideoFramerateNum > Int64(numFrames)*cVideoFramerateDen*1000 do
     begin
-        WriteLn(cameraFile, inttostr(GameTicks) + ' ' + inttostr(WorldDx) + ' ' + inttostr(WorldDy - cScreenHeight div 2) + ' ' + inttostr(Round(zoom*10000/cScreenWidth)));
-        inc(nframes);
+        frame.ticks:= GameTicks;
+        frame.CamX:= WorldDx;
+        frame.CamY:= WorldDy - cScreenHeight div 2;
+        frame.zoom:= zoom/cScreenWidth;
+        BlockWrite(cameraFile, frame, 1);
+        inc(numFrames);
     end;
 end;