# HG changeset patch # User Stepan777 # Date 1339109555 -14400 # Node ID 5debd5fe526ed7b1e494add3f0db3b4652fc6929 # Parent 4fba5519c37fd10e72f985742b068e761bd428cd 1. Add IFDEFs for video recording 2. Options for video recording were hardcoded in engine, now they are hardcoded in frontend and passed to engine thru command line (later it will be possible to change them in frontend) diff -r 4fba5519c37f -r 5debd5fe526e QTfrontend/game.cpp --- a/QTfrontend/game.cpp Fri Jun 08 02:41:14 2012 +0400 +++ b/QTfrontend/game.cpp Fri Jun 08 02:52:35 2012 +0400 @@ -333,6 +333,8 @@ arguments << QString::number(config->translateQuality()); arguments << QString::number(config->stereoMode()); arguments << tr("en.txt"); + arguments << "30"; // framerate num + arguments << "1"; // framerate den return arguments; } diff -r 4fba5519c37f -r 5debd5fe526e QTfrontend/net/recorder.cpp --- a/QTfrontend/net/recorder.cpp Fri Jun 08 02:41:14 2012 +0400 +++ b/QTfrontend/net/recorder.cpp Fri Jun 08 02:52:35 2012 +0400 @@ -87,7 +87,15 @@ arguments << QString::number(config->translateQuality()); arguments << QString::number(config->stereoMode()); arguments << HWGame::tr("en.txt"); + arguments << "30"; // framerate num + arguments << "1"; // framerate den arguments << prefix; + arguments << "mp4"; + arguments << "mpeg4"; // arguments << "libx264"; + arguments << "5"; // video quality + arguments << "medium"; + arguments << "libmp3lame"; + arguments << "5"; // audio quality return arguments; } diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/ArgParsers.inc --- a/hedgewars/ArgParsers.inc Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/ArgParsers.inc Fri Jun 08 02:52:35 2012 +0400 @@ -61,13 +61,28 @@ else cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp-6))); cLocaleFName:= ParamStr(17); - if ParamCount > 17 then - begin - cRecPrefix:= ParamStr(18); - GameType:= gmtRecord; - end; +{$IFDEF USE_VIDEO_RECORDING} + cVideoFramerateNum:= StrToInt(ParamStr(18)); + cVideoFramerateDen:= StrToInt(ParamStr(19)); +{$ENDIF} end; +{$IFDEF USE_VIDEO_RECORDING} +procedure internalStartVideoRecordingWithParameters(); +begin + internalStartGameWithParameters(); + GameType:= gmtRecord; + cRecPrefix:= ParamStr(20); + cAVFormat:= ParamStr(21); + cVideoCodec:= ParamStr(22); + cVideoQuality:= StrToInt(ParamStr(23)); + cVideoPreset:= ParamStr(24); + cAudioCodec:= ParamStr(25); + // cRecordAudio:= cAudioCodec <> 'no'; + cAudioQuality:= StrToInt(ParamStr(26)); +end; +{$ENDIF} + procedure setVideo(screenWidth: LongInt; screenHeight: LongInt; bitsStr: LongInt); begin cScreenWidth:= screenWidth; diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/avwrapper.c --- a/hedgewars/avwrapper.c Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/avwrapper.c Fri Jun 08 02:52:35 2012 +0400 @@ -16,8 +16,11 @@ static AVCodecContext* g_pAudio; static AVCodecContext* g_pVideo; -static int g_Width, g_Height, g_Framerate; +static int g_Width, g_Height; static int g_Frequency, g_Channels; +static int g_VQuality, g_AQuality; +static AVRational g_Framerate; +static const char* g_pPreset; static FILE* g_pSoundFile; static int16_t* g_pSamples; @@ -77,7 +80,7 @@ AddFileLogRaw(Buffer); } -static void AddAudioStream(enum CodecID codec_id) +static void AddAudioStream() { #if LIBAVCODEC_VERSION_MAJOR >= 54 g_pAStream = avformat_new_stream(g_pContainer, g_pACodec); @@ -89,15 +92,24 @@ g_pAStream->id = 1; g_pAudio = g_pAStream->codec; + avcodec_get_context_defaults3(g_pAudio, g_pACodec); - g_pAudio->codec_id = codec_id; + g_pAudio->codec_id = g_pACodec->id; // put parameters g_pAudio->sample_fmt = AV_SAMPLE_FMT_S16; - // pContext->bit_rate = 128000; g_pAudio->sample_rate = g_Frequency; g_pAudio->channels = g_Channels; + // set quality + if (g_AQuality > 100) + g_pAudio->bit_rate = g_AQuality; + else + { + g_pAudio->flags |= CODEC_FLAG_QSCALE; + g_pAudio->global_quality = g_AQuality*FF_QP2LAMBDA; + } + // some formats want stream headers to be separate if (g_pFormat->flags & AVFMT_GLOBALHEADER) g_pAudio->flags |= CODEC_FLAG_GLOBAL_HEADER; @@ -123,6 +135,9 @@ // returns non-zero if there is more sound static int WriteAudioFrame() { + if (!g_pAStream) + return 0; + AVPacket Packet = { 0 }; av_init_packet(&Packet); @@ -166,7 +181,7 @@ } // add a video output stream -static void AddVideoStream(enum CodecID codec_id) +static void AddVideoStream() { #if LIBAVCODEC_VERSION_MAJOR >= 54 g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec); @@ -177,8 +192,9 @@ FatalError("Could not allocate video stream"); g_pVideo = g_pVStream->codec; - avcodec_get_context_defaults3( g_pVideo, g_pVCodec ); - g_pVideo->codec_id = codec_id; + + avcodec_get_context_defaults3(g_pVideo, g_pVCodec); + g_pVideo->codec_id = g_pVCodec->id; // put parameters // resolution must be a multiple of two @@ -188,29 +204,28 @@ of which frame timestamps are represented. for fixed-fps content, timebase should be 1/framerate and timestamp increments should be identically 1. */ - g_pVideo->time_base.den = g_Framerate; - g_pVideo->time_base.num = 1; + g_pVideo->time_base.den = g_Framerate.num; + g_pVideo->time_base.num = g_Framerate.den; //g_pVideo->gop_size = 12; /* emit one intra frame every twelve frames at most */ g_pVideo->pix_fmt = PIX_FMT_YUV420P; + // set quality + if (g_VQuality > 100) + g_pVideo->bit_rate = g_VQuality; + else + { + g_pVideo->flags |= CODEC_FLAG_QSCALE; + g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA; + } + + AVDictionary* pDict = NULL; + if (strcmp(g_pVCodec->name, "libx264") == 0) + av_dict_set(&pDict, "preset", g_pPreset, 0); + // some formats want stream headers to be separate if (g_pFormat->flags & AVFMT_GLOBALHEADER) g_pVideo->flags |= CODEC_FLAG_GLOBAL_HEADER; - AVDictionary* pDict = NULL; - if (codec_id == CODEC_ID_H264) - { - // av_dict_set(&pDict, "tune", "animation", 0); - // av_dict_set(&pDict, "preset", "veryslow", 0); - av_dict_set(&pDict, "crf", "20", 0); - } - else - { - g_pVideo->flags |= CODEC_FLAG_QSCALE; - // g_pVideo->bit_rate = g_Width*g_Height*g_Framerate/4; - g_pVideo->global_quality = 15*FF_QP2LAMBDA; - } - // open the codec if (avcodec_open2(g_pVideo, g_pVCodec, &pDict) < 0) FatalError("Could not open video codec %s", g_pVCodec->long_name); @@ -237,6 +252,9 @@ AudioTime = (double)g_pAStream->pts.val*g_pAStream->time_base.num/g_pAStream->time_base.den; while (AudioTime < VideoTime && WriteAudioFrame()); } + + if (!g_pVStream) + return 0; AVPacket Packet; av_init_packet(&Packet); @@ -300,111 +318,73 @@ WriteFrame(g_pVFrame); } -void AVWrapper_GetList() -{ - // initialize libav and register all codecs and formats - av_register_all(); - -#if 0 - AVOutputFormat* pFormat = NULL; - while (pFormat = av_oformat_next(pFormat)) - { - Log("%s; %s; %s;\n", pFormat->name, pFormat->long_name, pFormat->mime_type); - - AVCodec* pCodec = NULL; - while (pCodec = av_codec_next(pCodec)) - { - if (!av_codec_is_encoder(pCodec)) - continue; - if (avformat_query_codec(pFormat, pCodec->id, FF_COMPLIANCE_NORMAL) != 1) - continue; - if (pCodec->type = AVMEDIA_TYPE_VIDEO) - { - if (pCodec->supported_framerate != NULL) - continue; - Log(" Video: %s; %s;\n", pCodec->name, pCodec->long_name); - } - if (pCodec->type = AVMEDIA_TYPE_AUDIO) - { - /* if (pCodec->supported_samplerates == NULL) - continue; - int i; - for(i = 0; i <) - supported_samplerates*/ - Log(" Audio: %s; %s;\n", pCodec->name, pCodec->long_name); - } - } - /* struct AVCodecTag** pTags = pCur->codec_tag; - int i; - for (i = 0; ; i++) - { - enum CodecID id = av_codec_get_id(pTags, i); - if (id == CODEC_ID_NONE) - break; - AVCodec* pCodec = avcodec_find_encoder(id); - Log(" %i: %s; %s;\n", id, pCodec->name, pCodec->long_name); - }*/ - } -#endif -} - -void AVWrapper_Init(void (*pAddFileLogRaw)(const char*), const char* pFilename, const char* pSoundFile, int Width, int Height, int Framerate, int Frequency, int Channels) +void AVWrapper_Init( + void (*pAddFileLogRaw)(const char*), + const char* pFilename, + const char* pSoundFile, + const char* pFormatName, + const char* pVCodecName, + const char* pACodecName, + const char* pVPreset, + int Width, int Height, + int FramerateNum, int FramerateDen, + int Frequency, int Channels, + int VQuality, int AQuality) { AddFileLogRaw = pAddFileLogRaw; av_log_set_callback( &LogCallback ); g_Width = Width; g_Height = Height; - g_Framerate = Framerate; + g_Framerate.num = FramerateNum; + g_Framerate.den = FramerateDen; g_Frequency = Frequency; g_Channels = Channels; + g_VQuality = VQuality; + g_AQuality = AQuality; + g_pPreset = pVPreset; // initialize libav and register all codecs and formats av_register_all(); - - AVWrapper_GetList(); - // allocate the output media context -#if LIBAVCODEC_VERSION_MAJOR >= 54 - avformat_alloc_output_context2(&g_pContainer, NULL, "mp4", pFilename); -#else - g_pFormat = av_guess_format(NULL, pFilename, NULL); + // find format + g_pFormat = av_guess_format(pFormatName, NULL, NULL); if (!g_pFormat) - FatalError("guess_format"); + FatalError("Format \"%s\" was not found", pFormatName); // allocate the output media context g_pContainer = avformat_alloc_context(); - if (g_pContainer) - { - g_pContainer->oformat = g_pFormat; - snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s", pFilename); - } -#endif if (!g_pContainer) FatalError("Could not allocate output context"); - g_pFormat = g_pContainer->oformat; + g_pContainer->oformat = g_pFormat; - enum CodecID VideoCodecID = g_pFormat->video_codec;//CODEC_ID_H264; - enum CodecID AudioCodecID = g_pFormat->audio_codec; + // append extesnion to filename + snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), + "%s.%*s", + pFilename, + strcspn(g_pFormat->extensions, ","), g_pFormat->extensions); + // find codecs + g_pVCodec = avcodec_find_encoder_by_name(pVCodecName); + g_pACodec = avcodec_find_encoder_by_name(pACodecName); + + // add audio and video stream to container g_pVStream = NULL; g_pAStream = NULL; - if (VideoCodecID != CODEC_ID_NONE) - { - g_pVCodec = avcodec_find_encoder(VideoCodecID); - if (!g_pVCodec) - FatalError("Video codec not found"); - AddVideoStream(VideoCodecID); - } + + if (g_pVCodec) + AddVideoStream(); + else + Log("Video codec \"%s\" was not found; video will be ignored.\n", pVCodecName); - if (AudioCodecID != CODEC_ID_NONE) - { - g_pACodec = avcodec_find_encoder(AudioCodecID); - if (!g_pACodec) - FatalError("Audio codec not found"); - AddAudioStream(AudioCodecID); - } + if (g_pACodec) + AddAudioStream(); + else + Log("Audio codec \"%s\" was not found; audio will be ignored.\n", pACodecName); + + if (!g_pAStream && !g_pVStream) + FatalError("No video, no audio, aborting..."); if (g_pAStream) { @@ -414,17 +394,18 @@ } // write format info to log - av_dump_format(g_pContainer, 0, pFilename, 1); + av_dump_format(g_pContainer, 0, g_pContainer->filename, 1); // open the output file, if needed if (!(g_pFormat->flags & AVFMT_NOFILE)) { - if (avio_open(&g_pContainer->pb, pFilename, AVIO_FLAG_WRITE) < 0) + if (avio_open(&g_pContainer->pb, g_pContainer->filename, AVIO_FLAG_WRITE) < 0) FatalError("Could not open output file (%s)", pFilename); } // write the stream header, if any avformat_write_header(g_pContainer, NULL); + g_pVFrame->pts = -1; } @@ -439,32 +420,27 @@ // write the trailer, if any. av_write_trailer(g_pContainer); - // close each codec - if( g_pVStream ) + // close the output file + if (!(g_pFormat->flags & AVFMT_NOFILE)) + avio_close(g_pContainer->pb); + + // free everything + if (g_pVStream) { - avcodec_close(g_pVStream->codec); + avcodec_close(g_pVideo); + av_free(g_pVideo); + av_free(g_pVStream); av_free(g_pVFrame); } - if( g_pAStream ) + if (g_pAStream) { - avcodec_close(g_pAStream->codec); + avcodec_close(g_pAudio); + av_free(g_pAudio); + av_free(g_pAStream); av_free(g_pAFrame); av_free(g_pSamples); fclose(g_pSoundFile); } - // free the streams - int i; - for (i = 0; i < g_pContainer->nb_streams; i++) - { - av_freep(&g_pContainer->streams[i]->codec); - av_freep(&g_pContainer->streams[i]); - } - - // close the output file - if (!(g_pFormat->flags & AVFMT_NOFILE)) - avio_close(g_pContainer->pb); - - // free the stream av_free(g_pContainer); } diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/hwengine.pas Fri Jun 08 02:52:35 2012 +0400 @@ -31,7 +31,8 @@ uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler, uSound, uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uRandom, uLandTexture, uCollisions, - SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted, uVideoRec + SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted + {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF} {$IFDEF SDL13}, uTouch{$ENDIF}{$IFDEF ANDROID}, GLUnit{$ENDIF}; {$IFDEF HWLIBRARY} @@ -101,8 +102,10 @@ SwapBuffers; +{$IFDEF USE_VIDEO_RECORDING} if flagPrerecording then SaveCameraPosition; +{$ENDIF} if flagMakeCapture then begin @@ -264,7 +267,7 @@ end; end; -//////////////// +{$IFDEF USE_VIDEO_RECORDING} procedure RecorderMainLoop; var CurrTime, PrevTime: LongInt; begin @@ -289,6 +292,7 @@ end; StopVideoRecording(); end; +{$ENDIF} /////////////// procedure Game{$IFDEF HWLIBRARY}(gameArgs: PPChar); cdecl; export{$ENDIF}; @@ -572,11 +576,14 @@ else if (ParamCount = 3) and ((ParamStr(3) = '--stats-only') or (ParamStr(3) = 'landpreview')) then internalSetGameTypeLandPreviewFromParameters() + else if ParamCount = cDefaultParamNum then + internalStartGameWithParameters() +{$IFDEF USE_VIDEO_RECORDING} + else if ParamCount = cVideorecParamNum then + internalStartVideoRecordingWithParameters() +{$ENDIF} else - if (ParamCount = cDefaultParamNum) or (ParamCount = cDefaultParamNum+1) then - internalStartGameWithParameters() - else - playReplayFileWithParameters(); + playReplayFileWithParameters(); end; //////////////////////////////////////////////////////////////////////////////// diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/options.inc --- a/hedgewars/options.inc Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/options.inc Fri Jun 08 02:52:35 2012 +0400 @@ -67,6 +67,7 @@ {$IFNDEF MOBILE} {$DEFINE USE_AM_NUMCOLUMN} + {$DEFINE USE_VIDEO_RECORDING} {$ENDIF} {$DEFINE USE_LUA_SCRIPT} diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/uCommandHandlers.pas Fri Jun 08 02:52:35 2012 +0400 @@ -26,7 +26,8 @@ procedure freeModule; implementation -uses SysUtils, uCommands, uTypes, uVariables, uIO, uDebug, uConsts, uScript, uUtils, SDLh, uRandom, uCaptions, uVideoRec; +uses uCommands, uTypes, uVariables, uIO, uDebug, uConsts, uScript, uUtils, SDLh, uRandom, uCaptions + {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF}; var prevGState: TGameState = gsConfirm; @@ -532,10 +533,12 @@ procedure chRecord(var s: shortstring); begin s:= s; // avoid compiler hint +{$IFDEF USE_VIDEO_RECORDING} if flagPrerecording then - StopPreRecording + StopPreRecording() else - BeginPreRecording(FormatDateTime('YYYY-MM-DD_HH-mm-ss', Now())); + BeginPreRecording(); +{$ENDIF} end; procedure chSetMap(var s: shortstring); diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/uConsts.pas Fri Jun 08 02:52:35 2012 +0400 @@ -27,7 +27,12 @@ const sfMax = 1000; +{$IFNDEF USE_VIDEO_RECORDING} cDefaultParamNum = 17; +{$ELSE} + cDefaultParamNum = 19; + cVideorecParamNum = cDefaultParamNum + 7; +{$ENDIF} // message constants errmsgCreateSurface = 'Error creating SDL surface'; diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/uStore.pas --- a/hedgewars/uStore.pas Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/uStore.pas Fri Jun 08 02:52:35 2012 +0400 @@ -47,7 +47,7 @@ implementation uses uMisc, uConsole, uMobile, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands, - uDebug{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF}, glut; + uDebug{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF} {$IFDEF USE_VIDEO_RECORDING}, glut {$ENDIF}; //type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple); @@ -439,6 +439,7 @@ IMG_Quit(); end; +{$IF NOT DEFINED(S3D_DISABLED) OR DEFINED(USE_VIDEO_RECORDING)} procedure CreateFramebuffer(var frame, depth, tex: GLuint); begin glGenFramebuffersEXT(1, @frame); @@ -461,6 +462,7 @@ glDeleteRenderbuffersEXT(1, @depth); glDeleteFramebuffersEXT(1, @frame); end; +{$ENDIF} procedure StoreRelease(reload: boolean); var ii: TSprite; @@ -535,8 +537,10 @@ end; end; end; +{$IFDEF USE_VIDEO_RECORDING} if defaultFrame <> 0 then DeleteFramebuffer(defaultFrame, depthv, texv); +{$ENDIF} {$IFNDEF S3D_DISABLED} if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then begin @@ -707,9 +711,10 @@ AddFileLog(' \----- Extensions: '); AddFileLogRaw(glGetString(GL_EXTENSIONS)); AddFileLog(''); - //TODO: don't have the Extensions line trimmed but slipt it into multiple lines + //TODO: slipt Extensions line into multiple lines defaultFrame:= 0; +{$IFDEF USE_VIDEO_RECORDING} if GameType = gmtRecord then begin if AuxBufNum > 0 then @@ -731,6 +736,7 @@ AddFileLog('Warning: off-screen rendering is not supported; using back buffer but it may not work.'); end; end; +{$ENDIF} {$IFNDEF S3D_DISABLED} if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/uUtils.pas --- a/hedgewars/uUtils.pas Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/uUtils.pas Fri Jun 08 02:52:35 2012 +0400 @@ -82,8 +82,10 @@ {$IFDEF DEBUGFILE} var f: textfile; +{$IFDEF USE_VIDEO_RECORDING} logMutex: TRTLCriticalSection; // mutex for debug file {$ENDIF} +{$ENDIF} var CharArray: array[byte] of Char; procedure SplitBySpace(var a,b: shortstring); @@ -305,22 +307,30 @@ begin s:= s; {$IFDEF DEBUGFILE} +{$IFDEF USE_VIDEO_RECORDING} EnterCriticalSection(logMutex); +{$ENDIF} writeln(f, inttostr(GameTicks) + ': ' + s); flush(f); +{$IFDEF USE_VIDEO_RECORDING} LeaveCriticalSection(logMutex); {$ENDIF} +{$ENDIF} end; procedure AddFileLogRaw(s: pchar); cdecl; begin s:= s; {$IFDEF DEBUGFILE} +{$IFDEF USE_VIDEO_RECORDING} EnterCriticalSection(logMutex); +{$ENDIF} write(f, s); flush(f); +{$IFDEF USE_VIDEO_RECORDING} LeaveCriticalSection(logMutex); {$ENDIF} +{$ENDIF} end; function CheckCJKFont(s: ansistring; font: THWFont): THWFont; @@ -414,7 +424,9 @@ logfileBase:= 'game' else logfileBase:= 'preview'; +{$IFDEF USE_VIDEO_RECORDING} InitCriticalSection(logMutex); +{$ENDIF} {$I-} {$IFDEF MOBILE} {$IFDEF IPHONEOS} Assign(f,'../Documents/hw-' + logfileBase + '.log'); {$ENDIF} @@ -451,8 +463,10 @@ writeln(f, 'halt at ' + inttostr(GameTicks) + ' ticks. TurnTimeLeft = ' + inttostr(TurnTimeLeft)); flush(f); close(f); +{$IFDEF USE_VIDEO_RECORDING} DoneCriticalSection(logMutex); {$ENDIF} +{$ENDIF} end; end. diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/uVariables.pas Fri Jun 08 02:52:35 2012 +0400 @@ -52,7 +52,17 @@ cReadyDelay : Longword = 5000; cStereoMode : TStereoMode = smNone; cOnlyStats : boolean = False; - cRecPrefix : shortstring = ''; +{$IFDEF USE_VIDEO_RECORDING} + cRecPrefix : shortstring; + cAVFormat : shortstring; + cVideoCodec : shortstring; + cVideoFramerateNum : Int64; + cVideoFramerateDen : Int64; + cVideoQuality : LongInt; + cVideoPreset : shortstring; + cAudioCodec : shortstring; + cAudioQuality : LongInt; +{$ENDIF} ////////////////////////// cMapName : shortstring = ''; diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/uVideoRec.pas --- a/hedgewars/uVideoRec.pas Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/uVideoRec.pas Fri Jun 08 02:52:35 2012 +0400 @@ -36,7 +36,7 @@ procedure EncodeFrame; procedure StopVideoRecording; -function BeginPreRecording(filePrefix: shortstring): Boolean; +procedure BeginPreRecording; procedure StopPreRecording; procedure SaveCameraPosition; @@ -53,11 +53,17 @@ type TAddFileLogRaw = procedure (s: pchar); cdecl; {$IFDEF WIN32} -procedure AVWrapper_Init(AddLog: TAddFileLogRaw; filename, soundFile: PChar; width, height, framerate, frequency, channels: LongInt); cdecl; external AVWrapperLibName; +procedure AVWrapper_Init( + AddLog: TAddFileLogRaw; + filename, soundFile, format, vcodec, acodec, preset: PChar; + width, height, framerateNum, framerateDen, frequency, channels, 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, soundFile: PChar; width, height, framerate, frequency, channels: LongInt); cdecl; external; +procedure AVWrapper_Init( + AddLog: TAddFileLogRaw; + filename, soundFile, format, vcodec, acodec, preset: PChar; + width, height, framerateNum, framerateDen, frequency, channels, vquality, aquality: LongInt); cdecl; external; procedure AVWrapper_Close; cdecl; external; procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external; {$ENDIF} @@ -72,7 +78,6 @@ numPixels: LongInt; - framerate: Int64 = 30; firstTick, nframes: Int64; cameraFilePath, soundFilePath: shortstring; @@ -98,9 +103,14 @@ ReadLn(cameraFile, frequency, channels); {$IOCHECKS ON} - filename:= UserPathPrefix + '/Videos/' + cRecPrefix + '.mp4' + #0; + filename:= UserPathPrefix + '/Videos/' + cRecPrefix + #0; soundFilePath:= UserPathPrefix + '/Videos/' + cRecPrefix + '.hwsound' + #0; - AVWrapper_Init(@AddFileLogRaw, @filename[1], @soundFilePath[1], cScreenWidth, cScreenHeight, framerate, frequency, channels); + cAVFormat+= #0; + cAudioCodec+= #0; + cVideoCodec+= #0; + cVideoPreset+= #0; + AVWrapper_Init(@AddFileLogRaw, @filename[1], @soundFilePath[1], @cAVFormat[1], @cVideoCodec[1], @cAudioCodec[1], @cVideoPreset[1], + cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, frequency, channels, cAudioQuality, cVideoQuality); YCbCr_Planes[0]:= GetMem(numPixels); YCbCr_Planes[1]:= GetMem(numPixels div 4); @@ -194,21 +204,23 @@ {$IOCHECKS ON} end; -function BeginPreRecording(filePrefix: shortstring): Boolean; +procedure BeginPreRecording; var format: word; - filename: shortstring; + filePrefix, filename: shortstring; begin AddFileLog('BeginPreRecording'); - + nframes:= 0; firstTick:= SDL_GetTicks(); + filePrefix:= FormatDateTime('YYYY-MM-DD_HH-mm-ss', Now()); + Mix_QuerySpec(@frequency, @format, @channels); if format <> $8010 then begin // TODO: support any audio format AddFileLog('Error: Unexpected audio format ' + IntToStr(format)); - exit(false); + exit; end; {$IOCHECKS OFF} @@ -218,7 +230,7 @@ if IOResult <> 0 then begin AddFileLog('Error: Could not write to ' + filename); - exit(false); + exit; end; filename:= UserPathPrefix + '/Videos/' + filePrefix + '.txtout'; @@ -227,7 +239,7 @@ if IOResult <> 0 then begin AddFileLog('Error: Could not write to ' + filename); - exit(false); + exit; end; {$IOCHECKS ON} WriteLn(cameraFile, inttostr(frequency) + ' ' + inttostr(channels)); @@ -236,7 +248,6 @@ Mix_SetPostMix(@RecordPostMix, nil); flagPrerecording:= true; - BeginPreRecording:= true; end; procedure StopPreRecording; @@ -256,7 +267,7 @@ var Ticks: LongInt; begin Ticks:= SDL_GetTicks(); - while (Ticks - firstTick)*framerate > nframes*1000 do + while (Ticks - firstTick)*cVideoFramerateNum > nframes*cVideoFramerateDen*1000 do begin WriteLn(cameraFile, inttostr(GameTicks) + ' ' + inttostr(WorldDx) + ' ' + inttostr(WorldDy) + ' ' + inttostr(Round(zoom*10000))); inc(nframes); diff -r 4fba5519c37f -r 5debd5fe526e hedgewars/uWorld.pas --- a/hedgewars/uWorld.pas Fri Jun 08 02:41:14 2012 +0400 +++ b/hedgewars/uWorld.pas Fri Jun 08 02:52:35 2012 +0400 @@ -1574,7 +1574,8 @@ end end; -// rec +{$IFDEF USE_VIDEO_RECORDING} +// during video prerecording draw red blinking circle and text 'rec' if flagPrerecording then begin if recTexture = nil then @@ -1598,6 +1599,7 @@ Tint($FF, $FF, $FF, $FF); glEnable(GL_TEXTURE_2D); end; +{$ENDIF} SetScale(zoom);