hedgewars/uVideoRec.pas
changeset 7198 5debd5fe526e
parent 7180 53ffc8853008
child 7235 baa69bd025d9
equal deleted inserted replaced
7196:4fba5519c37f 7198:5debd5fe526e
    34 function BeginVideoRecording: Boolean;
    34 function BeginVideoRecording: Boolean;
    35 function LoadNextCameraPosition: LongInt;
    35 function LoadNextCameraPosition: LongInt;
    36 procedure EncodeFrame;
    36 procedure EncodeFrame;
    37 procedure StopVideoRecording;
    37 procedure StopVideoRecording;
    38 
    38 
    39 function BeginPreRecording(filePrefix: shortstring): Boolean;
    39 procedure BeginPreRecording;
    40 procedure StopPreRecording;
    40 procedure StopPreRecording;
    41 procedure SaveCameraPosition;
    41 procedure SaveCameraPosition;
    42 
    42 
    43 procedure freeModule;
    43 procedure freeModule;
    44 
    44 
    51 {$ENDIF}
    51 {$ENDIF}
    52 
    52 
    53 type TAddFileLogRaw = procedure (s: pchar); cdecl;
    53 type TAddFileLogRaw = procedure (s: pchar); cdecl;
    54 
    54 
    55 {$IFDEF WIN32}
    55 {$IFDEF WIN32}
    56 procedure AVWrapper_Init(AddLog: TAddFileLogRaw; filename, soundFile: PChar; width, height, framerate, frequency, channels: LongInt); cdecl; external AVWrapperLibName;
    56 procedure AVWrapper_Init(
       
    57               AddLog: TAddFileLogRaw;
       
    58               filename, soundFile, format, vcodec, acodec, preset: PChar;
       
    59               width, height, framerateNum, framerateDen, frequency, channels, vquality, aquality: LongInt); cdecl; external AVWrapperLibName;
    57 procedure AVWrapper_Close; cdecl; external AVWrapperLibName;
    60 procedure AVWrapper_Close; cdecl; external AVWrapperLibName;
    58 procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external AVWrapperLibName;
    61 procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external AVWrapperLibName;
    59 {$ELSE}
    62 {$ELSE}
    60 procedure AVWrapper_Init(AddLog: TAddFileLogRaw; filename, soundFile: PChar; width, height, framerate, frequency, channels: LongInt); cdecl; external;
    63 procedure AVWrapper_Init(
       
    64               AddLog: TAddFileLogRaw;
       
    65               filename, soundFile, format, vcodec, acodec, preset: PChar;
       
    66               width, height, framerateNum, framerateDen, frequency, channels, vquality, aquality: LongInt); cdecl; external;
    61 procedure AVWrapper_Close; cdecl; external;
    67 procedure AVWrapper_Close; cdecl; external;
    62 procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external;
    68 procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external;
    63 {$ENDIF}
    69 {$ENDIF}
    64 
    70 
    65 var YCbCr_Planes: array[0..2] of PByte;
    71 var YCbCr_Planes: array[0..2] of PByte;
    70     cameraFile: TextFile;
    76     cameraFile: TextFile;
    71     audioFile: File;
    77     audioFile: File;
    72     
    78     
    73     numPixels: LongInt;
    79     numPixels: LongInt;
    74 
    80 
    75     framerate: Int64 = 30;
       
    76     firstTick, nframes: Int64;
    81     firstTick, nframes: Int64;
    77     
    82     
    78     cameraFilePath, soundFilePath: shortstring;
    83     cameraFilePath, soundFilePath: shortstring;
    79 
    84 
    80 function BeginVideoRecording: Boolean;
    85 function BeginVideoRecording: Boolean;
    96     end;
   101     end;
    97 
   102 
    98     ReadLn(cameraFile, frequency, channels);
   103     ReadLn(cameraFile, frequency, channels);
    99 {$IOCHECKS ON}
   104 {$IOCHECKS ON}
   100 
   105 
   101     filename:= UserPathPrefix + '/Videos/' + cRecPrefix + '.mp4' + #0;
   106     filename:= UserPathPrefix + '/Videos/' + cRecPrefix + #0;
   102     soundFilePath:= UserPathPrefix + '/Videos/' + cRecPrefix + '.hwsound' + #0;
   107     soundFilePath:= UserPathPrefix + '/Videos/' + cRecPrefix + '.hwsound' + #0;
   103     AVWrapper_Init(@AddFileLogRaw, @filename[1], @soundFilePath[1], cScreenWidth, cScreenHeight, framerate, frequency, channels);
   108     cAVFormat+= #0;
       
   109     cAudioCodec+= #0;
       
   110     cVideoCodec+= #0;
       
   111     cVideoPreset+= #0;
       
   112     AVWrapper_Init(@AddFileLogRaw, @filename[1], @soundFilePath[1], @cAVFormat[1], @cVideoCodec[1], @cAudioCodec[1], @cVideoPreset[1],
       
   113                    cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, frequency, channels, cAudioQuality, cVideoQuality);
   104 
   114 
   105     YCbCr_Planes[0]:= GetMem(numPixels);
   115     YCbCr_Planes[0]:= GetMem(numPixels);
   106     YCbCr_Planes[1]:= GetMem(numPixels div 4);
   116     YCbCr_Planes[1]:= GetMem(numPixels div 4);
   107     YCbCr_Planes[2]:= GetMem(numPixels div 4);
   117     YCbCr_Planes[2]:= GetMem(numPixels div 4);
   108 
   118 
   192 {$IOCHECKS OFF}
   202 {$IOCHECKS OFF}
   193     BlockWrite(audioFile, stream^, len);
   203     BlockWrite(audioFile, stream^, len);
   194 {$IOCHECKS ON}
   204 {$IOCHECKS ON}
   195 end;
   205 end;
   196 
   206 
   197 function BeginPreRecording(filePrefix: shortstring): Boolean;
   207 procedure BeginPreRecording;
   198 var format: word;
   208 var format: word;
   199     filename: shortstring;
   209     filePrefix, filename: shortstring;
   200 begin
   210 begin
   201     AddFileLog('BeginPreRecording');
   211     AddFileLog('BeginPreRecording');
   202 
   212     
   203     nframes:= 0;
   213     nframes:= 0;
   204     firstTick:= SDL_GetTicks();
   214     firstTick:= SDL_GetTicks();
   205 
   215 
       
   216     filePrefix:= FormatDateTime('YYYY-MM-DD_HH-mm-ss', Now());
       
   217 
   206     Mix_QuerySpec(@frequency, @format, @channels);
   218     Mix_QuerySpec(@frequency, @format, @channels);
   207     if format <> $8010 then
   219     if format <> $8010 then
   208     begin
   220     begin
   209         // TODO: support any audio format
   221         // TODO: support any audio format
   210         AddFileLog('Error: Unexpected audio format ' + IntToStr(format));
   222         AddFileLog('Error: Unexpected audio format ' + IntToStr(format));
   211         exit(false);
   223         exit;
   212     end;
   224     end;
   213 
   225 
   214 {$IOCHECKS OFF}
   226 {$IOCHECKS OFF}
   215     filename:= UserPathPrefix + '/Videos/' + filePrefix + '.hwsound';
   227     filename:= UserPathPrefix + '/Videos/' + filePrefix + '.hwsound';
   216     Assign(audioFile, filename);
   228     Assign(audioFile, filename);
   217     Rewrite(audioFile, 1);
   229     Rewrite(audioFile, 1);
   218     if IOResult <> 0 then
   230     if IOResult <> 0 then
   219     begin
   231     begin
   220         AddFileLog('Error: Could not write to ' + filename);
   232         AddFileLog('Error: Could not write to ' + filename);
   221         exit(false);
   233         exit;
   222     end;
   234     end;
   223 
   235 
   224     filename:= UserPathPrefix + '/Videos/' + filePrefix + '.txtout';
   236     filename:= UserPathPrefix + '/Videos/' + filePrefix + '.txtout';
   225     Assign(cameraFile, filename);
   237     Assign(cameraFile, filename);
   226     Rewrite(cameraFile);
   238     Rewrite(cameraFile);
   227     if IOResult <> 0 then
   239     if IOResult <> 0 then
   228     begin
   240     begin
   229         AddFileLog('Error: Could not write to ' + filename);
   241         AddFileLog('Error: Could not write to ' + filename);
   230         exit(false);
   242         exit;
   231     end;
   243     end;
   232 {$IOCHECKS ON}
   244 {$IOCHECKS ON}
   233     WriteLn(cameraFile, inttostr(frequency) + ' ' + inttostr(channels));
   245     WriteLn(cameraFile, inttostr(frequency) + ' ' + inttostr(channels));
   234 
   246 
   235     // register callback for actual audio recording
   247     // register callback for actual audio recording
   236     Mix_SetPostMix(@RecordPostMix, nil);
   248     Mix_SetPostMix(@RecordPostMix, nil);
   237 
   249 
   238     flagPrerecording:= true;
   250     flagPrerecording:= true;
   239     BeginPreRecording:= true;
       
   240 end;
   251 end;
   241 
   252 
   242 procedure StopPreRecording;
   253 procedure StopPreRecording;
   243 begin
   254 begin
   244     AddFileLog('StopPreRecording');
   255     AddFileLog('StopPreRecording');
   254 
   265 
   255 procedure SaveCameraPosition;
   266 procedure SaveCameraPosition;
   256 var Ticks: LongInt;
   267 var Ticks: LongInt;
   257 begin
   268 begin
   258     Ticks:= SDL_GetTicks();
   269     Ticks:= SDL_GetTicks();
   259     while (Ticks - firstTick)*framerate > nframes*1000 do
   270     while (Ticks - firstTick)*cVideoFramerateNum > nframes*cVideoFramerateDen*1000 do
   260     begin
   271     begin
   261         WriteLn(cameraFile, inttostr(GameTicks) + ' ' + inttostr(WorldDx) + ' ' + inttostr(WorldDy) + ' ' + inttostr(Round(zoom*10000)));
   272         WriteLn(cameraFile, inttostr(GameTicks) + ' ' + inttostr(WorldDx) + ' ' + inttostr(WorldDy) + ' ' + inttostr(Round(zoom*10000)));
   262         inc(nframes);
   273         inc(nframes);
   263     end;
   274     end;
   264 end;
   275 end;