1. Implement new page in frontend with options for video recording.
authorStepan777 <stepik-777@mail.ru>
Mon, 11 Jun 2012 18:15:30 +0400
changeset 7235 baa69bd025d9
parent 7231 f484455dd055
child 7238 313b2ecc4441
1. Implement new page in frontend with options for video recording. 2. Store temoprary files in different directory
QTfrontend/CMakeLists.txt
QTfrontend/game.cpp
QTfrontend/gameuiconfig.cpp
QTfrontend/gameuiconfig.h
QTfrontend/hwform.cpp
QTfrontend/hwform.h
QTfrontend/main.cpp
QTfrontend/net/recorder.cpp
QTfrontend/ui/page/pagemain.cpp
QTfrontend/ui/page/pagemain.h
QTfrontend/ui/page/pagevideos.cpp
QTfrontend/ui/page/pagevideos.h
QTfrontend/ui_hwform.cpp
QTfrontend/ui_hwform.h
QTfrontend/util/libav_iteraction.cpp
QTfrontend/util/libav_iteraction.h
hedgewars/ArgParsers.inc
hedgewars/avwrapper.c
hedgewars/hwengine.pas
hedgewars/options.inc
hedgewars/uStore.pas
hedgewars/uVideoRec.pas
project_files/hedgewars.pro
--- a/QTfrontend/CMakeLists.txt	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/CMakeLists.txt	Mon Jun 11 18:15:30 2012 +0400
@@ -154,6 +154,9 @@
     endif()
 endif()
 
+IF (WIN32)
+    link_directories(${CMAKE_SOURCE_DIR}/misc/winutils/lib)
+ENDIF()
 
 add_executable(hedgewars WIN32
     ${hwfr_src}
@@ -165,6 +168,9 @@
 
 set(HW_LINK_LIBS
     quazip
+    avformat
+    avcodec
+    avutil
     ${QT_LIBRARIES}
     ${SDL_LIBRARY}
     ${SDLMIXER_LIBRARY}
--- a/QTfrontend/game.cpp	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/game.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -333,7 +333,7 @@
     arguments << QString::number(config->translateQuality());
     arguments << QString::number(config->stereoMode());
     arguments << tr("en.txt");
-    arguments << "30"; // framerate num
+    arguments << QString::number(config->rec_Framerate()); // framerate num
     arguments << "1";  // framerate den
 
     return arguments;
--- a/QTfrontend/gameuiconfig.cpp	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/gameuiconfig.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -26,6 +26,7 @@
 #include "gameuiconfig.h"
 #include "hwform.h"
 #include "pageoptions.h"
+#include "pagevideos.h"
 #include "pagenetserver.h"
 #include "hwconsts.h"
 #include "fpsedit.h"
@@ -42,6 +43,7 @@
     resizeToConfigValues();
 
     reloadValues();
+    reloadVideosValues();
 }
 
 void GameUIConfig::reloadValues(void)
@@ -110,6 +112,29 @@
     else if (depth > 16) depth = 32;
 }
 
+void GameUIConfig::reloadVideosValues(void)
+{
+    Form->ui.pageVideos->framerateBox->setValue(value("videorec/fps",25).toUInt());
+    bool useGameRes = value("videorec/usegameres",true).toBool();
+    if (useGameRes)
+    {
+        QRect res = vid_Resolution();
+        Form->ui.pageVideos->widthEdit->setText(QString::number(res.width()));
+        Form->ui.pageVideos->heightEdit->setText(QString::number(res.height()));
+    }
+    else
+    {
+        Form->ui.pageVideos->widthEdit->setText(value("videorec/width","800").toString());
+        Form->ui.pageVideos->heightEdit->setText(value("videorec/height","600").toString());
+    }
+    Form->ui.pageVideos->CBUseGameRes->setChecked(useGameRes);
+    Form->ui.pageVideos->CBRecordAudio->setChecked(value("videorec/audio",true).toBool());
+    if (!Form->ui.pageVideos->tryCodecs(value("videorec/format","no").toString(),
+                                        value("videorec/videocodec","no").toString(),
+                                        value("videorec/audiocodec","no").toString()))
+        Form->ui.pageVideos->setDefaultCodecs();
+}
+
 QStringList GameUIConfig::GetTeamsList()
 {
     QDir teamdir;
@@ -182,6 +207,22 @@
 #ifdef SPARKLE_ENABLED
     setValue("misc/autoUpdate", isAutoUpdateEnabled());
 #endif
+
+    Form->gameSettings->sync();
+}
+
+void GameUIConfig::SaveVideosOptions()
+{
+    QRect res = rec_Resolution();
+    setValue("videorec/format", AVFormat());
+    setValue("videorec/videocodec", videoCodec());
+    setValue("videorec/audiocodec", audioCodec());
+    setValue("videorec/fps", rec_Framerate());
+    setValue("videorec/width", res.width());
+    setValue("videorec/height", res.height());
+    setValue("videorec/usegameres", Form->ui.pageVideos->CBUseGameRes->isChecked());
+    setValue("videorec/audio", recordAudio());
+
     Form->gameSettings->sync();
 }
 
@@ -380,3 +421,37 @@
 {
     return Form->ui.pageOptions->volumeBox->value() * 128 / 100;
 }
+
+QString GameUIConfig::AVFormat()
+{
+    return Form->ui.pageVideos->getFormat();
+}
+
+QString GameUIConfig::videoCodec()
+{
+    return Form->ui.pageVideos->getVideoCodec();
+}
+
+QString GameUIConfig::audioCodec()
+{
+    return Form->ui.pageVideos->getAudioCodec();
+}
+
+QRect GameUIConfig::rec_Resolution()
+{
+    if (Form->ui.pageVideos->CBUseGameRes->isChecked())
+        return vid_Resolution();
+    QRect res(0,0,0,0);
+    res.setWidth(Form->ui.pageVideos->widthEdit->text().toUInt());
+    res.setHeight(Form->ui.pageVideos->heightEdit->text().toUInt());
+}
+
+int GameUIConfig::rec_Framerate()
+{
+    return Form->ui.pageVideos->framerateBox->value();
+}
+
+bool GameUIConfig::recordAudio()
+{
+    return Form->ui.pageVideos->CBRecordAudio->isChecked();
+}
--- a/QTfrontend/gameuiconfig.h	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/gameuiconfig.h	Mon Jun 11 18:15:30 2012 +0400
@@ -59,18 +59,27 @@
         void resizeToConfigValues();
         quint32 stereoMode() const;
 
+        QString AVFormat();
+        QString videoCodec();
+        QString audioCodec();
+        QRect rec_Resolution();
+        int rec_Framerate();
+        bool recordAudio();
+
 #ifdef __APPLE__
 #ifdef SPARKLE_ENABLED
         bool isAutoUpdateEnabled();
 #endif
 #endif
-        void reloadValues(void);
+        void reloadValues();
+        void reloadVideosValues();
 
     signals:
         void frontendFullscreen(bool value);
 
     public slots:
         void SaveOptions();
+        void SaveVideosOptions();
         void updNetNick();
     private:
         bool netPasswordIsValid();
--- a/QTfrontend/hwform.cpp	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/hwform.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -76,6 +76,7 @@
 #include "pagegamestats.h"
 #include "pageplayrecord.h"
 #include "pagedata.h"
+#include "pagevideos.h"
 #include "hwconsts.h"
 #include "newnetclient.h"
 #include "gamecfgwidget.h"
@@ -141,6 +142,8 @@
 
     config = new GameUIConfig(this, cfgdir->absolutePath() + "/hedgewars.ini");
 
+    ui.pageVideos->config = config;
+
 #ifdef __APPLE__
     panel = new M3Panel;
 
@@ -199,6 +202,9 @@
     connect(ui.pageNetGame, SIGNAL(DLCClicked()), pageSwitchMapper, SLOT(map()));
     pageSwitchMapper->setMapping(ui.pageNetGame, ID_PAGE_DATADOWNLOAD);
 
+    connect(ui.pageMain->BtnVideos, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
+    pageSwitchMapper->setMapping(ui.pageMain->BtnVideos, ID_PAGE_VIDEOS);
+
     //connect(ui.pageMain->BtnExit, SIGNAL(pressed()), this, SLOT(btnExitPressed()));
     //connect(ui.pageMain->BtnExit, SIGNAL(clicked()), this, SLOT(btnExitClicked()));
 
@@ -289,6 +295,7 @@
 
     connect(ui.pageConnecting, SIGNAL(cancelConnection()), this, SLOT(GoBack()));
 
+    connect(ui.pageVideos, SIGNAL(goBack()), config, SLOT(SaveVideosOptions()));
 
     ammoSchemeModel = new AmmoSchemeModel(this, cfgdir->absolutePath() + "/schemes.ini");
     ui.pageScheme->setModel(ammoSchemeModel);
@@ -604,6 +611,11 @@
         config->reloadValues();
     }
 
+    if (id == ID_PAGE_VIDEOS )
+    {
+        config->reloadVideosValues();
+    }
+
     // load and save ignore/friends lists
     if (lastid == ID_PAGE_NETGAME) // leaving a room
         ui.pageNetGame->pChatWidget->saveLists(ui.pageOptions->editNetNick->text());
@@ -1409,15 +1421,16 @@
         }
     }
 
-    QDir videosDir(cfgdir->absolutePath() + "/Videos/");
+    // encode videos
+    QDir videosDir(cfgdir->absolutePath() + "/VideoTemp/");
     QStringList files = videosDir.entryList(QStringList("*.txtout"), QDir::Files);
-    for (QStringList::iterator str = files.begin(); str != files.end(); str++)
+    foreach (const QString & str, files)
     {
-        str->chop(7); // remove ".txtout"
-        // need to rename this file to not open it twice
-        videosDir.rename(*str + ".txtout", *str + ".txtin");
+        QString prefix = str;
+        prefix.chop(7); // remove ".txtout"
+        videosDir.rename(prefix + ".txtout", prefix + ".txtin"); // rename this file to not open it twice
         HWRecorder* pRecorder = new HWRecorder(config);
-        pRecorder->EncodeVideo(record, *str);
+        pRecorder->EncodeVideo(record, prefix);
     }
 }
 
@@ -1459,6 +1472,7 @@
     xfire_free();
 #endif
     config->SaveOptions();
+    config->SaveVideosOptions();
     event->accept();
 }
 
--- a/QTfrontend/hwform.h	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/hwform.h	Mon Jun 11 18:15:30 2012 +0400
@@ -175,6 +175,7 @@
             ID_PAGE_DRAWMAP        ,
             ID_PAGE_DATADOWNLOAD   ,
             ID_PAGE_FEEDBACK	   ,
+            ID_PAGE_VIDEOS,
 	    MAX_PAGE
         };
         QPointer<HWGame> game;
--- a/QTfrontend/main.cpp	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/main.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -200,6 +200,7 @@
         checkForDir(cfgdir->absolutePath() + "/Teams");
         checkForDir(cfgdir->absolutePath() + "/Logs");
         checkForDir(cfgdir->absolutePath() + "/Videos");
+        checkForDir(cfgdir->absolutePath() + "/VideoTemp");
     }
 
     datadir->cd(bindir->absolutePath());
--- a/QTfrontend/net/recorder.cpp	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/net/recorder.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -37,7 +37,7 @@
 void HWRecorder::onClientDisconnect()
 {
 }
-     
+
 void HWRecorder::onClientRead()
 {
     quint8 msglen;
@@ -69,7 +69,7 @@
 QStringList HWRecorder::getArguments()
 {
     QStringList arguments;
-    QRect resolution = config->vid_Resolution();
+    QRect resolution = config->rec_Resolution();
     arguments << cfgdir->absolutePath();
     arguments << QString::number(resolution.width());
     arguments << QString::number(resolution.height());
@@ -87,14 +87,17 @@
     arguments << QString::number(config->translateQuality());
     arguments << QString::number(config->stereoMode());
     arguments << HWGame::tr("en.txt");
-    arguments << "30"; // framerate num
+    arguments << QString::number(config->rec_Framerate()); // framerate num
     arguments << "1";  // framerate den
     arguments << prefix;
-    arguments << "mp4";
-    arguments << "mpeg4"; // arguments << "libx264";
+    arguments << config->AVFormat();
+    arguments << config->videoCodec();
     arguments << "5"; // video quality
     arguments << "medium";
-    arguments << "libmp3lame";
+    if (config->recordAudio())
+        arguments << config->audioCodec();
+    else
+        arguments << "no";
     arguments << "5"; // audio quality
 
     return arguments;
--- a/QTfrontend/ui/page/pagemain.cpp	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/ui/page/pagemain.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -85,9 +85,13 @@
     bottomLayout->setStretch(0,1);
 
     btnBack->setWhatsThis(tr("Exit game"));
-    
-    BtnSetup = addButton(":/res/Settings.png", bottomLayout, 1, true);
+
+    BtnVideos = addButton(":/res/Record.png", bottomLayout, 1, true);
+    BtnVideos->setWhatsThis(tr("Manage videos recorded from game"));
+
+    BtnSetup = addButton(":/res/Settings.png", bottomLayout, 2, true);
     BtnSetup->setWhatsThis(tr("Edit game preferences"));
+
     return bottomLayout;
 }
 
--- a/QTfrontend/ui/page/pagemain.h	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/ui/page/pagemain.h	Mon Jun 11 18:15:30 2012 +0400
@@ -34,6 +34,7 @@
         QPushButton * BtnFeedback;
         QPushButton * BtnInfo;
         QPushButton * BtnDataDownload;
+        QPushButton * BtnVideos;
         QLabel * mainNote;
 
     private:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/page/pagevideos.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -0,0 +1,262 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <QGridLayout>
+#include <QPushButton>
+#include <QGroupBox>
+#include <QComboBox>
+#include <QCheckBox>
+#include <QLabel>
+#include <QLineEdit>
+#include <QSpinBox>
+#include <QTableWidget>
+
+#include "pagevideos.h"
+#include "igbox.h"
+#include "libav_iteraction.h"
+#include "gameuiconfig.h"
+
+QLayout * PageVideos::bodyLayoutDefinition()
+{
+    QGridLayout * pageLayout = new QGridLayout();
+    pageLayout->setColumnStretch(0, 1);
+    pageLayout->setColumnStretch(1, 1);
+
+    {
+        IconedGroupBox* groupRec = new IconedGroupBox(this);
+        groupRec->setIcon(QIcon(":/res/graphicsicon.png"));
+        groupRec->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+        groupRec->setTitle(QGroupBox::tr("Video recording options"));
+        QGridLayout * RecLayout = new QGridLayout(groupRec);
+
+        // Label for format
+        QLabel *labelFormat = new QLabel(groupRec);
+        labelFormat->setText(QLabel::tr("Format"));
+        RecLayout->addWidget(labelFormat, 0, 0);
+
+        // List of supported formats
+        CBAVFormats = new QComboBox(groupRec);
+        RecLayout->addWidget(CBAVFormats, 0, 1, 1, 4);
+        LibavIteraction::instance().FillFormats(CBAVFormats);
+
+        QFrame * hr = new QFrame(groupRec);
+        hr->setFrameStyle(QFrame::HLine);
+        hr->setLineWidth(3);
+        hr->setFixedHeight(10);
+        RecLayout->addWidget(hr, 1, 0, 1, 5);
+
+        // Label for audio codec
+        QLabel *labelACodec = new QLabel(groupRec);
+        labelACodec->setText(QLabel::tr("Audio codec"));
+        RecLayout->addWidget(labelACodec, 2, 0);
+
+        // List of supported audio codecs
+        CBAudioCodecs = new QComboBox(groupRec);
+        RecLayout->addWidget(CBAudioCodecs, 2, 1, 1, 3);
+
+        // record audio
+        CBRecordAudio = new QCheckBox(groupRec);
+        CBRecordAudio->setText(QCheckBox::tr("Record audio"));
+        RecLayout->addWidget(CBRecordAudio, 2, 4);
+
+        hr = new QFrame(groupRec);
+        hr->setFrameStyle(QFrame::HLine);
+        hr->setLineWidth(3);
+        hr->setFixedHeight(10);
+        RecLayout->addWidget(hr, 3, 0, 1, 5);
+
+        // Label for video codec
+        QLabel *labelVCodec = new QLabel(groupRec);
+        labelVCodec->setText(QLabel::tr("Video codec"));
+        RecLayout->addWidget(labelVCodec, 4, 0);
+
+        // List of supported video codecs
+        CBVideoCodecs = new QComboBox(groupRec);
+        RecLayout->addWidget(CBVideoCodecs, 4, 1, 1, 4);
+
+        // Label for resolution
+        QLabel *labelRes = new QLabel(groupRec);
+        labelRes->setText(QLabel::tr("Resolution"));
+        RecLayout->addWidget(labelRes, 5, 0);
+
+        // width
+        widthEdit = new QLineEdit(groupRec);
+        widthEdit->setValidator(new QIntValidator(this));
+        RecLayout->addWidget(widthEdit, 5, 1);
+
+        // x
+        QLabel *labelX = new QLabel(groupRec);
+        labelX->setText("X");
+        RecLayout->addWidget(labelX, 5, 2);
+
+        // height
+        heightEdit = new QLineEdit(groupRec);
+        heightEdit->setValidator(new QIntValidator(groupRec));
+        RecLayout->addWidget(heightEdit, 5, 3);
+
+        // use game res
+        CBUseGameRes = new QCheckBox(groupRec);
+        CBUseGameRes->setText(QCheckBox::tr("Use game resolution"));
+        RecLayout->addWidget(CBUseGameRes, 5, 4);
+
+        // Label for framerate
+        QLabel *labelFramerate = new QLabel(groupRec);
+        labelFramerate->setText(QLabel::tr("Framerate"));
+        RecLayout->addWidget(labelFramerate, 6, 0);
+
+        // framerate
+        framerateBox = new QSpinBox(groupRec);
+        framerateBox->setRange(1, 200);
+        framerateBox->setSingleStep(1);
+        RecLayout->addWidget(framerateBox, 6, 1);
+
+        BtnDefaults = new QPushButton(groupRec);
+        BtnDefaults->setText(QPushButton::tr("Set default options"));
+        RecLayout->addWidget(BtnDefaults, 7, 0, 1, 5);
+
+        pageLayout->addWidget(groupRec, 0, 0);
+    }
+
+    {
+        IconedGroupBox* groupTable = new IconedGroupBox(this);
+        //groupRec->setContentTopPadding(0);
+        groupTable->setIcon(QIcon(":/res/graphicsicon.png"));
+        groupTable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+        groupTable->setTitle(QGroupBox::tr("Videos"));
+
+        QStringList columns;
+        columns << tr("Name") << tr("Lenght") << tr("...");
+
+        filesTable = new QTableWidget(groupTable);
+        filesTable->setColumnCount(3);
+        filesTable->setHorizontalHeaderLabels(columns);
+        QVBoxLayout *box = new QVBoxLayout(groupTable);
+        box->addWidget(filesTable);
+
+        pageLayout->addWidget(groupTable, 0, 1, 2, 1);
+    }
+
+    return pageLayout;
+}
+
+QLayout * PageVideos::footerLayoutDefinition()
+{
+    return NULL;
+}
+
+void PageVideos::connectSignals()
+{
+    connect(CBUseGameRes, SIGNAL(stateChanged(int)), this, SLOT(changeUseGameRes(int)));
+    connect(CBRecordAudio, SIGNAL(stateChanged(int)), this, SLOT(changeRecordAudio(int)));
+    connect(CBAVFormats, SIGNAL(currentIndexChanged(int)), this, SLOT(changeAVFormat(int)));
+    connect(BtnDefaults, SIGNAL(clicked()), this, SLOT(setDefaultOptions()));
+}
+
+PageVideos::PageVideos(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+}
+
+void PageVideos::changeAVFormat(int index)
+{
+    QString prevVCodec = getVideoCodec();
+    QString prevACodec = getAudioCodec();
+    CBVideoCodecs->clear();
+    CBAudioCodecs->clear();
+    LibavIteraction::instance().FillCodecs(CBAVFormats->itemData(index), CBVideoCodecs, CBAudioCodecs);
+    if (CBAudioCodecs->count() == 0)
+    {
+        CBRecordAudio->setChecked(false);
+        CBRecordAudio->setEnabled(false);
+    }
+    else
+        CBRecordAudio->setEnabled(true);
+    int iVCodec = CBVideoCodecs->findData(prevVCodec);
+    if (iVCodec != -1)
+        CBVideoCodecs->setCurrentIndex(iVCodec);
+    int iACodec = CBAudioCodecs->findData(prevACodec);
+    if (iACodec != -1)
+        CBAudioCodecs->setCurrentIndex(iACodec);
+}
+
+void PageVideos::changeUseGameRes(int state)
+{
+    if (state && config)
+    {
+        QRect resolution = config->vid_Resolution();
+        widthEdit->setText(QString::number(resolution.width()));
+        heightEdit->setText(QString::number(resolution.height()));
+    }
+    widthEdit->setEnabled(!state);
+    heightEdit->setEnabled(!state);
+}
+
+void PageVideos::changeRecordAudio(int state)
+{
+    CBAudioCodecs->setEnabled(!!state);
+}
+
+void PageVideos::setDefaultCodecs()
+{
+    if (tryCodecs("mp4", "libx264", "libmp3lame"))
+        return;
+    if (tryCodecs("mp4", "libx264", "ac3_fixed"))
+        return;
+    if (tryCodecs("avi", "libxvid", "libmp3lame"))
+        return;
+    if (tryCodecs("avi", "libxvid", "ac3_fixed"))
+        return;
+    if (tryCodecs("avi", "mpeg4", "libmp3lame"))
+        return;
+    if (tryCodecs("avi", "mpeg4", "ac3_fixed"))
+        return;
+
+    // this shouldn't happen, just in case
+    if (tryCodecs("ogg", "libtheora", "libvorbis"))
+        return;
+    tryCodecs("ogg", "libtheora", "flac");
+}
+
+void PageVideos::setDefaultOptions()
+{
+    framerateBox->setValue(25);
+    CBRecordAudio->setChecked(true);
+    CBUseGameRes->setChecked(true);
+    setDefaultCodecs();
+}
+
+bool PageVideos::tryCodecs(const QString & format, const QString & vcodec, const QString & acodec)
+{
+    int iFormat = CBAVFormats->findData(format);
+    if (iFormat == -1)
+        return false;
+    CBAVFormats->setCurrentIndex(iFormat);
+
+    int iVCodec = CBVideoCodecs->findData(vcodec);
+    if (iVCodec == -1)
+        return false;
+    CBVideoCodecs->setCurrentIndex(iVCodec);
+
+    int iACodec = CBAudioCodecs->findData(acodec);
+    if (iACodec == -1 && CBRecordAudio->isChecked())
+        return false;
+    if (iACodec != -1)
+        CBAudioCodecs->setCurrentIndex(iACodec);
+
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/page/pagevideos.h	Mon Jun 11 18:15:30 2012 +0400
@@ -0,0 +1,76 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef PAGE_VIDEOS_H
+#define PAGE_VIDEOS_H
+
+#include <QPushButton>
+#include <QTableWidget>
+#include "AbstractPage.h"
+
+class GameUIConfig;
+
+class PageVideos : public AbstractPage
+{
+        Q_OBJECT
+
+    public:
+        PageVideos(QWidget* parent = 0);
+
+        QComboBox *CBAVFormats;
+        QComboBox *CBVideoCodecs;
+        QComboBox *CBAudioCodecs;
+        QSpinBox  *framerateBox;
+        QLineEdit *widthEdit;
+        QLineEdit *heightEdit;
+        QCheckBox *CBUseGameRes;
+        QCheckBox *CBRecordAudio;
+
+        QString getFormat()
+        { return CBAVFormats->itemData(CBAVFormats->currentIndex()).toString(); }
+
+        QString getVideoCodec()
+        { return CBVideoCodecs->itemData(CBVideoCodecs->currentIndex()).toString(); }
+
+        QString getAudioCodec()
+        { return CBAudioCodecs->itemData(CBAudioCodecs->currentIndex()).toString(); }
+
+        void setDefaultCodecs();
+        bool tryCodecs(const QString & format, const QString & vcodec, const QString & acodec);
+
+        GameUIConfig * config;
+
+    signals:
+
+    private:
+        QLayout * bodyLayoutDefinition();
+        QLayout * footerLayoutDefinition();
+        void connectSignals();
+
+        QPushButton *BtnDefaults;
+        QTableWidget *filesTable;
+
+    private slots:
+        void changeAVFormat(int index);
+        void changeUseGameRes(int state);
+        void changeRecordAudio(int state);
+        void setDefaultOptions();
+};
+
+#endif // PAGE_VIDEOS_H
--- a/QTfrontend/ui_hwform.cpp	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/ui_hwform.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -46,6 +46,7 @@
 #include "pagegamestats.h"
 #include "pageplayrecord.h"
 #include "pagedata.h"
+#include "pagevideos.h"
 #include "hwconsts.h"
 
 void Ui_HWForm::setupUi(HWForm *HWForm)
@@ -145,4 +146,7 @@
 
     pageFeedback = new PageFeedback();
     Pages->addWidget(pageFeedback);
+
+    pageVideos = new PageVideos();
+    Pages->addWidget(pageVideos);
 }
--- a/QTfrontend/ui_hwform.h	Mon Jun 11 17:56:10 2012 +0400
+++ b/QTfrontend/ui_hwform.h	Mon Jun 11 18:15:30 2012 +0400
@@ -43,6 +43,7 @@
 class PageAdmin;
 class PageNetType;
 class PageDrawMap;
+class PageVideos;
 class QStackedLayout;
 class QFont;
 class QWidget;
@@ -78,6 +79,7 @@
         PageNetType *pageNetType;
         PageCampaign *pageCampaign;
         PageDrawMap *pageDrawMap;
+        PageVideos *pageVideos;
 
         QStackedLayout *Pages;
         QFont *font14;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/util/libav_iteraction.cpp	Mon Jun 11 18:15:30 2012 +0400
@@ -0,0 +1,269 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#define __STDC_CONSTANT_MACROS
+extern "C"
+{
+#include "libavformat/avformat.h"
+}
+#include <QVector>
+#include <QList>
+#include <QMessageBox>
+
+#include "libav_iteraction.h"
+#include "HWApplication.h"
+
+struct Codec
+{
+    CodecID id;
+    bool isAudio;
+    QString shortName; // used for identification
+    QString longName; // used for displaying to user
+    bool isRecomended;
+};
+
+struct Format
+{
+    QString shortName;
+    QString longName;
+    bool isRecomended;
+  //  QString extension;
+    QVector<Codec*> codecs;
+};
+
+QList<Codec> codecs;
+QMap<QString,Format> formats;
+
+LibavIteraction & LibavIteraction::instance()
+{
+    static LibavIteraction instance;
+    return instance;
+}
+
+bool FormatQueryCodec(AVOutputFormat *ofmt, enum CodecID codec_id)
+{  
+#if LIBAVFORMAT_VERSION_MAJOR >= 54
+    return avformat_query_codec(ofmt, codec_id, FF_COMPLIANCE_NORMAL) == 1;
+#else
+    if (ofmt->codec_tag)
+        return !!av_codec_get_tag(ofmt->codec_tag, codec_id);
+    return codec_id == ofmt->video_codec || codec_id == ofmt->audio_codec;
+#endif
+}
+
+LibavIteraction::LibavIteraction()
+{
+    // initialize libav and register all codecs and formats
+    av_register_all();
+
+    // get list of all codecs
+    AVCodec* pCodec = NULL;
+    while (pCodec = av_codec_next(pCodec))
+    {
+#if LIBAVCODEC_VERSION_MAJOR >= 54
+        if (!av_codec_is_encoder(pCodec))
+#else
+        if (!pCodec->encode)
+#endif
+            continue;
+
+        if (pCodec->capabilities & CODEC_CAP_EXPERIMENTAL)
+            continue;
+
+        if (pCodec->type != AVMEDIA_TYPE_VIDEO && pCodec->type != AVMEDIA_TYPE_AUDIO)
+            continue;
+
+        // this encoders seems to be buggy
+        if (strcmp(pCodec->name, "rv10") == 0 ||
+            strcmp(pCodec->name, "rv20") == 0)
+            continue;
+
+        // doesn't support stereo sound
+        if (strcmp(pCodec->name, "real_144") == 0)
+            continue;
+#if LIBAVCODEC_VERSION_MAJOR < 54
+        // FIXME: theese doesn't work for some reason
+        if (strcmp(pCodec->name, "libx264") == 0)
+            continue;
+        if (strcmp(pCodec->name, "libxvid") == 0)
+            continue;
+#endif
+
+        if (pCodec->type == AVMEDIA_TYPE_VIDEO)
+        {
+            if (pCodec->supported_framerates != NULL)
+                continue;
+
+            // check if codec supports yuv 4:2:0 format
+            if (!pCodec->pix_fmts)
+                continue;
+            bool yuv420Supported = false;
+            for (const PixelFormat* pfmt = pCodec->pix_fmts; *pfmt != -1; pfmt++)
+                if (*pfmt == PIX_FMT_YUV420P)
+                {
+                    yuv420Supported = true;
+                    break;
+                }
+            if (!yuv420Supported)
+                continue;
+        }
+        if (pCodec->type == AVMEDIA_TYPE_AUDIO)
+        {
+            // check if codec supports signed 16-bit format
+            if (!pCodec->sample_fmts)
+                continue;
+            bool s16Supported = false;
+            for (const AVSampleFormat* pfmt = pCodec->sample_fmts; *pfmt != -1; pfmt++)
+                if (*pfmt == AV_SAMPLE_FMT_S16/* || *pfmt == AV_SAMPLE_FMT_FLT*/)
+                {
+                    s16Supported = true;
+                    break;
+                }
+            if (!s16Supported)
+                continue;
+        }
+        // add codec to list of codecs
+        codecs.push_back(Codec());
+        Codec & codec = codecs.back();
+        codec.id = pCodec->id;
+        codec.isAudio = pCodec->type == AVMEDIA_TYPE_AUDIO;
+        codec.shortName = pCodec->name;
+        codec.longName = pCodec->long_name;
+
+        codec.isRecomended = false;
+        if (strcmp(pCodec->name, "libx264") == 0)
+        {
+            codec.longName = "H.264/MPEG-4 Part 10 AVC (x264)";
+            codec.isRecomended = true;
+        }
+        else if (strcmp(pCodec->name, "libxvid") == 0)
+        {
+            codec.longName = "MPEG-4 Part 2 (Xvid)";
+            codec.isRecomended = true;
+        }
+        else if (strcmp(pCodec->name, "libmp3lame") == 0)
+        {
+            codec.longName = "MP3 (MPEG audio layer 3) (LAME)";
+            codec.isRecomended = true;
+        }
+        else
+            codec.longName = pCodec->long_name;
+
+        if (strcmp(pCodec->name, "mpeg4") == 0 || strcmp(pCodec->name, "ac3_fixed") == 0)
+            codec.isRecomended = true;
+
+        // FIXME: remove next line
+        codec.longName += QString(" (%1)").arg(codec.shortName);
+    }
+
+    // get list of all formats
+    AVOutputFormat* pFormat = NULL;
+    while (pFormat = av_oformat_next(pFormat))
+    {
+        if (!pFormat->extensions)
+            continue;
+
+        // skip some strange formats to not confuse users
+        if (strstr(pFormat->long_name, "raw"))
+            continue;
+
+        Format format;
+        bool hasVideoCodec = false;
+        for (QList<Codec>::iterator codec = codecs.begin(); codec != codecs.end(); ++codec)
+        {
+            if (!FormatQueryCodec(pFormat, codec->id))
+                continue;
+            format.codecs.push_back(&*codec);
+            if (!codec->isAudio)
+                hasVideoCodec = true;
+        }
+        if (!hasVideoCodec)
+            continue;
+        format.shortName = pFormat->name;
+
+        QString ext(pFormat->extensions);
+        ext.truncate(strcspn(pFormat->extensions, ","));
+        format.longName = QString("%1 (*.%2)").arg(pFormat->long_name).arg(ext);
+
+        // FIXME: remove next line
+        format.longName += QString(" (%1)").arg(format.shortName);
+
+        format.isRecomended = strcmp(pFormat->name, "mp4") == 0 || strcmp(pFormat->name, "avi") == 0;
+
+        formats[pFormat->name] = format;
+    }
+}
+
+void LibavIteraction::FillFormats(QComboBox * pFormats)
+{
+    // first insert recomended formats
+    foreach(const Format & format, formats)
+        if (format.isRecomended)
+            pFormats->addItem(format.longName, format.shortName);
+
+    // remember where to place separator between recomended and other formats
+    int sep = pFormats->count();
+
+    // insert remaining formats
+    foreach(const Format & format, formats)
+        if (!format.isRecomended)
+            pFormats->addItem(format.longName, format.shortName);
+
+    // insert separator if necessary
+    if (sep != 0 && sep != pFormats->count())
+        pFormats->insertSeparator(sep);
+}
+
+void LibavIteraction::FillCodecs(const QVariant & fmt, QComboBox * pVCodecs, QComboBox * pACodecs)
+{
+    Format & format = formats[fmt.toString()];
+
+    // first insert recomended codecs
+    foreach(Codec * codec, format.codecs)
+    {
+        if (codec->isRecomended)
+        {
+            if (codec->isAudio)
+                pACodecs->addItem(codec->longName, codec->shortName);
+            else
+                pVCodecs->addItem(codec->longName, codec->shortName);
+        }
+    }
+
+    // remember where to place separators between recomended and other codecs
+    int vsep = pVCodecs->count();
+    int asep = pACodecs->count();
+
+    // insert remaining codecs
+    foreach(Codec * codec, format.codecs)
+    {
+        if (!codec->isRecomended)
+        {
+            if (codec->isAudio)
+                pACodecs->addItem(codec->longName, codec->shortName);
+            else
+                pVCodecs->addItem(codec->longName, codec->shortName);
+        }
+    }
+
+    // insert separators if necessary
+    if (vsep != 0 && vsep != pVCodecs->count())
+        pVCodecs->insertSeparator(vsep);
+    if (asep != 0 && asep != pACodecs->count())
+        pACodecs->insertSeparator(asep);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/util/libav_iteraction.h	Mon Jun 11 18:15:30 2012 +0400
@@ -0,0 +1,41 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef LIBAV_ITERACTION
+#define LIBAV_ITERACTION
+
+#include <QComboBox>
+
+/**
+ * @brief Class for interacting with ffmpeg/libav libraries
+ *
+ * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
+ */
+class LibavIteraction
+{
+    LibavIteraction();
+
+public:
+
+    static LibavIteraction & instance();
+
+    void FillFormats(QComboBox * pFormats);
+    void FillCodecs(const QVariant & format, QComboBox * pVCodecs, QComboBox * pACodecs);
+};
+
+#endif // LIBAV_ITERACTION
--- a/hedgewars/ArgParsers.inc	Mon Jun 11 17:56:10 2012 +0400
+++ b/hedgewars/ArgParsers.inc	Mon Jun 11 18:15:30 2012 +0400
@@ -78,7 +78,6 @@
     cVideoQuality:= StrToInt(ParamStr(23));
     cVideoPreset:= ParamStr(24);
     cAudioCodec:= ParamStr(25);
-  // cRecordAudio:= cAudioCodec <> 'no';
     cAudioQuality:= StrToInt(ParamStr(26));
 end;
 {$ENDIF}
--- a/hedgewars/avwrapper.c	Mon Jun 11 17:56:10 2012 +0400
+++ b/hedgewars/avwrapper.c	Mon Jun 11 18:15:30 2012 +0400
@@ -26,6 +26,8 @@
 static int16_t* g_pSamples;
 static int g_NumSamples;
 
+static char g_Filename[1024];
+
 /*
 Initially I wrote code for latest ffmpeg, but on Linux (Ubuntu)
 only older version is available from repository. That's why you see here
@@ -82,7 +84,7 @@
 
 static void AddAudioStream()
 {
-#if LIBAVCODEC_VERSION_MAJOR >= 54
+#if LIBAVFORMAT_VERSION_MAJOR >= 54
     g_pAStream = avformat_new_stream(g_pContainer, g_pACodec);
 #else
     g_pAStream = av_new_stream(g_pContainer, 1);
@@ -183,7 +185,7 @@
 // add a video output stream
 static void AddVideoStream()
 {
-#if LIBAVCODEC_VERSION_MAJOR >= 54
+#if LIBAVFORMAT_VERSION_MAJOR >= 54
     g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec);
 #else
     g_pVStream = av_new_stream(g_pContainer, 0);
@@ -192,7 +194,7 @@
         FatalError("Could not allocate video stream");
 
     g_pVideo = g_pVStream->codec;
-    
+
     avcodec_get_context_defaults3(g_pVideo, g_pVCodec);
     g_pVideo->codec_id = g_pVCodec->id;
 
@@ -321,6 +323,7 @@
 void AVWrapper_Init(
          void (*pAddFileLogRaw)(const char*),
          const char* pFilename,
+         const char* pFinalFilename,
          const char* pSoundFile,
          const char* pFormatName,
          const char* pVCodecName,
@@ -360,10 +363,12 @@
     g_pContainer->oformat = g_pFormat;
 
     // append extesnion to filename
-    snprintf(g_pContainer->filename, sizeof(g_pContainer->filename),
-             "%s.%*s",
-             pFilename,
-             strcspn(g_pFormat->extensions, ","), g_pFormat->extensions);
+    char ext[16];
+    strncpy(ext, g_pFormat->extensions, 16);
+    ext[15] = 0;
+    ext[strcspn(ext,",")] = 0;
+    snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s.%s", pFilename, ext);
+    snprintf(g_Filename, sizeof(g_Filename), "%s.%s", pFinalFilename, ext);
 
     // find codecs
     g_pVCodec = avcodec_find_encoder_by_name(pVCodecName);
@@ -423,6 +428,9 @@
     // close the output file
     if (!(g_pFormat->flags & AVFMT_NOFILE))
         avio_close(g_pContainer->pb);
+        
+    // move file to destination
+    rename(g_pContainer->filename, g_Filename);
 
     // free everything
     if (g_pVStream)
--- a/hedgewars/hwengine.pas	Mon Jun 11 17:56:10 2012 +0400
+++ b/hedgewars/hwengine.pas	Mon Jun 11 18:15:30 2012 +0400
@@ -415,10 +415,12 @@
     isDeveloperMode:= false;
     TryDo(InitStepsFlags = cifAllInited, 'Some parameters not set (flags = ' + inttostr(InitStepsFlags) + ')', true);
     ParseCommand('rotmask', true);
-
+    
+{$IFDEF USE_VIDEO_RECORDING}
     if GameType = gmtRecord then
         RecorderMainLoop()
     else
+{$ENDIF}
         MainLoop();
 
     // clean up all the memory allocated
--- a/hedgewars/options.inc	Mon Jun 11 17:56:10 2012 +0400
+++ b/hedgewars/options.inc	Mon Jun 11 18:15:30 2012 +0400
@@ -50,6 +50,7 @@
     {$DEFINE USE_TOUCH_INTERFACE}
 {$ELSE}
     {$DEFINE USE_AM_NUMCOLUMN}
+    {$DEFINE USE_VIDEO_RECORDING}
 {$ENDIF}
 
 
@@ -63,7 +64,6 @@
     {$ENDIF}
 {$ENDIF}
 
-    {$DEFINE USE_VIDEO_RECORDING}
 
 {$IFDEF PAS2C}
     {$DEFINE NOCONSOLE}
--- a/hedgewars/uStore.pas	Mon Jun 11 17:56:10 2012 +0400
+++ b/hedgewars/uStore.pas	Mon Jun 11 18:15:30 2012 +0400
@@ -40,7 +40,9 @@
 procedure ShowWeaponTooltip(x, y: LongInt);
 procedure FreeWeaponTooltip;
 procedure MakeCrossHairs;
+{$IFDEF USE_VIDEO_RECORDING}
 procedure InitOffscreenOpenGL;
+{$ENDIF}
 
 procedure WarpMouse(x, y: Word); inline;
 procedure SwapBuffers; inline;
@@ -1022,6 +1024,7 @@
 WeaponTooltipTex:= nil
 end;
 
+{$IFDEF USE_VIDEO_RECORDING}
 procedure InitOffscreenOpenGL;
 var ArgCount: LongInt;
     PrgName: pchar;
@@ -1034,6 +1037,7 @@
     glutHideWindow();
     SetupOpenGL();
 end;
+{$ENDIF}
 
 procedure chFullScr(var s: shortstring);
 var flags: Longword = 0;
--- a/hedgewars/uVideoRec.pas	Mon Jun 11 17:56:10 2012 +0400
+++ b/hedgewars/uVideoRec.pas	Mon Jun 11 18:15:30 2012 +0400
@@ -55,14 +55,14 @@
 {$IFDEF WIN32}
 procedure AVWrapper_Init(
               AddLog: TAddFileLogRaw;
-              filename, soundFile, format, vcodec, acodec, preset: PChar;
+              filename, finalFilename, 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, format, vcodec, acodec, preset: PChar;
+              filename, finalFilename, 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;
@@ -75,15 +75,15 @@
 
     cameraFile: TextFile;
     audioFile: File;
-    
+
     numPixels: LongInt;
 
     firstTick, nframes: Int64;
-    
+
     cameraFilePath, soundFilePath: shortstring;
 
 function BeginVideoRecording: Boolean;
-var filename: shortstring;
+var filename, finalFilename: shortstring;
 begin
     AddFileLog('BeginVideoRecording');
 
@@ -91,7 +91,7 @@
 
 {$IOCHECKS OFF}
     // open file with prerecorded camera positions
-    cameraFilePath:= UserPathPrefix + '/Videos/' + cRecPrefix + '.txtin';
+    cameraFilePath:= UserPathPrefix + '/VideoTemp/' + cRecPrefix + '.txtin';
     Assign(cameraFile, cameraFilePath);
     Reset(cameraFile);
     if IOResult <> 0 then
@@ -103,13 +103,14 @@
     ReadLn(cameraFile, frequency, channels);
 {$IOCHECKS ON}
 
-    filename:= UserPathPrefix + '/Videos/' + cRecPrefix + #0;
-    soundFilePath:= UserPathPrefix + '/Videos/' + cRecPrefix + '.hwsound' + #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], @soundFilePath[1], @cAVFormat[1], @cVideoCodec[1], @cAudioCodec[1], @cVideoPreset[1],
+    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);
 
     YCbCr_Planes[0]:= GetMem(numPixels);
@@ -176,6 +177,7 @@
     AVWrapper_WriteFrame(YCbCr_Planes[0], YCbCr_Planes[1], YCbCr_Planes[2]);
 end;
 
+// returns new game ticks
 function LoadNextCameraPosition: LongInt;
 var NextTime: LongInt;
     NextZoom: LongInt;
@@ -186,19 +188,18 @@
         exit(-1);
     ReadLn(cameraFile, NextTime, NextWorldDx, NextWorldDy, NextZoom);
 {$IOCHECKS ON}
-    if NextTime = 0 then
-        exit(-1);
     WorldDx:= NextWorldDx;
-    WorldDy:= NextWorldDy;
-    zoom:= NextZoom/10000;
-    ZoomValue:= NextZoom/10000;
+    WorldDy:= NextWorldDy + cScreenHeight div 2;
+    zoom:= NextZoom/10000*cScreenWidth;
+    ZoomValue:= zoom;
     LoadNextCameraPosition:= NextTime;
 end;
 
-// this procedure may be called from different thread
+// Callback which records sound.
+// This procedure may be called from different thread.
 procedure RecordPostMix(udata: pointer; stream: PByte; len: LongInt); cdecl;
 begin
-    udata:= udata;
+    udata:= udata; // avoid warning
 {$IOCHECKS OFF}
     BlockWrite(audioFile, stream^, len);
 {$IOCHECKS ON}
@@ -209,7 +210,7 @@
     filePrefix, filename: shortstring;
 begin
     AddFileLog('BeginPreRecording');
-    
+
     nframes:= 0;
     firstTick:= SDL_GetTicks();
 
@@ -224,7 +225,8 @@
     end;
 
 {$IOCHECKS OFF}
-    filename:= UserPathPrefix + '/Videos/' + filePrefix + '.hwsound';
+    // create sound file
+    filename:= UserPathPrefix + '/VideoTemp/' + filePrefix + '.sw';
     Assign(audioFile, filename);
     Rewrite(audioFile, 1);
     if IOResult <> 0 then
@@ -233,7 +235,8 @@
         exit;
     end;
 
-    filename:= UserPathPrefix + '/Videos/' + filePrefix + '.txtout';
+    // create file with camera positions
+    filename:= UserPathPrefix + '/VideoTemp/' + filePrefix + '.txtout';
     Assign(cameraFile, filename);
     Rewrite(cameraFile);
     if IOResult <> 0 then
@@ -269,7 +272,7 @@
     Ticks:= SDL_GetTicks();
     while (Ticks - firstTick)*cVideoFramerateNum > nframes*cVideoFramerateDen*1000 do
     begin
-        WriteLn(cameraFile, inttostr(GameTicks) + ' ' + inttostr(WorldDx) + ' ' + inttostr(WorldDy) + ' ' + inttostr(Round(zoom*10000)));
+        WriteLn(cameraFile, inttostr(GameTicks) + ' ' + inttostr(WorldDx) + ' ' + inttostr(WorldDy - cScreenHeight div 2) + ' ' + inttostr(Round(zoom*10000/cScreenWidth)));
         inc(nframes);
     end;
 end;
--- a/project_files/hedgewars.pro	Mon Jun 11 17:56:10 2012 +0400
+++ b/project_files/hedgewars.pro	Mon Jun 11 18:15:30 2012 +0400
@@ -105,7 +105,9 @@
     ../QTfrontend/ui/widget/colorwidget.h \
     ../QTfrontend/model/HatModel.h \
     ../QTfrontend/model/GameStyleModel.h \
-    ../QTfrontend/recorder.h
+    ../QTfrontend/util/libav_iteraction.h \
+    ../QTfrontend/ui/page/pagevideos.h \
+    ../QTfrontend/net/recorder.h
 
 SOURCES += ../QTfrontend/model/ammoSchemeModel.cpp \
     ../QTfrontend/model/MapModel.cpp \
@@ -188,7 +190,9 @@
     ../QTfrontend/ui/widget/colorwidget.cpp \
     ../QTfrontend/model/HatModel.cpp \
     ../QTfrontend/model/GameStyleModel.cpp \
-    ../QTfrontend/recorder.cpp
+    ../QTfrontend/util/libav_iteraction.cpp \
+    ../QTfrontend/ui/page/pagevideos.cpp \
+    ../QTfrontend/net/recorder.cpp
 
 win32 {
     SOURCES += ../QTfrontend/xfire.cpp