1. Add IFDEFs for video recording
authorStepan777 <stepik-777@mail.ru>
Fri, 08 Jun 2012 02:52:35 +0400
changeset 7198 5debd5fe526e
parent 7196 4fba5519c37f
child 7231 f484455dd055
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)
QTfrontend/game.cpp
QTfrontend/net/recorder.cpp
hedgewars/ArgParsers.inc
hedgewars/avwrapper.c
hedgewars/hwengine.pas
hedgewars/options.inc
hedgewars/uCommandHandlers.pas
hedgewars/uConsts.pas
hedgewars/uStore.pas
hedgewars/uUtils.pas
hedgewars/uVariables.pas
hedgewars/uVideoRec.pas
hedgewars/uWorld.pas
--- 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;
 }
--- 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;
 }
--- 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;
--- 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);
 }
--- 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;
 
 ////////////////////////////////////////////////////////////////////////////////
--- 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}
--- 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);
--- 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';
--- 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
--- 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.
--- 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 = '';
 
--- 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);
--- 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);