1. Implement new page in frontend with options for video recording.
2. Store temoprary files in different directory
--- 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