7#include "MovieCapture.h"
8#include "MarbleDebug.h"
11#include <QElapsedTimer>
20class MovieCapturePrivate
23 explicit MovieCapturePrivate(MarbleWidget *widget)
24 : marbleWidget(widget)
25 , method(MovieCapture::TimeDriven)
32 void missingToolsWarning()
36 QObject::tr(
"Marble requires additional software in order to "
37 "create movies. Please get %1 ")
38 .arg(QStringLiteral(
"<a href=\"https://libav.org/"
39 "download.html\">avconv</a>")),
44 MarbleWidget *marbleWidget;
48 MovieCapture::SnapshotMethod method;
52MovieCapture::MovieCapture(MarbleWidget *widget,
QObject *parent)
54 , d_ptr(new MovieCapturePrivate(widget))
57 if (d->method == MovieCapture::TimeDriven) {
58 d->frameTimer.setInterval(1000 / 30);
62 MovieFormat avi(QStringLiteral(
"avi"), tr(
"AVI (mpeg4)"), QStringLiteral(
"avi"));
63 MovieFormat flv(QStringLiteral(
"flv"), tr(
"FLV"), QStringLiteral(
"flv"));
64 MovieFormat mkv(QStringLiteral(
"matroska"), tr(
"Matroska (h264)"), QStringLiteral(
"mkv"));
65 MovieFormat mp4(QStringLiteral(
"mp4"), tr(
"MPEG-4"), QStringLiteral(
"mp4"));
66 MovieFormat vob(QStringLiteral(
"vob"), tr(
"MPEG-2 PS (VOB)"), QStringLiteral(
"vob"));
67 MovieFormat ogg(QStringLiteral(
"ogg"), tr(
"OGG"), QStringLiteral(
"ogg"));
68 MovieFormat swf(QStringLiteral(
"swf"), tr(
"SWF"), QStringLiteral(
"swf"));
69 m_supportedFormats << avi << flv << mkv << mp4 << vob << ogg << swf;
72MovieCapture::~MovieCapture()
77void MovieCapture::setFps(
int fps)
80 if (d->method == MovieCapture::TimeDriven) {
81 d->frameTimer.setInterval(1000 / fps);
86void MovieCapture::setFilename(
const QString &path)
89 d->destinationFile =
path;
92void MovieCapture::setSnapshotMethod(MovieCapture::SnapshotMethod method)
98int MovieCapture::fps()
const
100 Q_D(
const MovieCapture);
104QString MovieCapture::destination()
const
106 Q_D(
const MovieCapture);
107 return d->destinationFile;
114 if (availableFormats.
isEmpty() && checkToolsAvailability()) {
116 for (
const MovieFormat &format : std::as_const(m_supportedFormats)) {
120 encoder.start(d->encoderExec, args);
121 encoder.waitForFinished();
124 if (isFormatAvailable) {
125 availableFormats << format;
129 return availableFormats;
132MovieCapture::SnapshotMethod MovieCapture::snapshotMethod()
const
134 Q_D(
const MovieCapture);
138bool MovieCapture::checkToolsAvailability()
141 static bool toolsAvailable =
false;
142 if (toolsAvailable ==
false) {
144 encoder.start(QStringLiteral(
"avconv"),
QStringList() << QStringLiteral(
"-version"));
145 encoder.waitForFinished();
146 if (!encoder.readAll().isEmpty()) {
147 d->encoderExec = QStringLiteral(
"avconv");
148 toolsAvailable =
true;
150 encoder.start(QStringLiteral(
"ffmpeg"),
QStringList() << QStringLiteral(
"-version"));
151 encoder.waitForFinished();
152 if (!encoder.readAll().isEmpty()) {
153 d->encoderExec = QStringLiteral(
"ffmpeg");
154 toolsAvailable =
true;
158 return toolsAvailable;
161void MovieCapture::recordFrame()
167 << QStringLiteral(
"rawvideo") << QStringLiteral(
"-pix_fmt") << QStringLiteral(
"rgb24")
168 << QStringLiteral(
"-s") << QStringLiteral(
"%1x%2").
arg(screenshot.
width()).
arg(screenshot.
height())
169 << QStringLiteral(
"-i") << QStringLiteral(
"pipe:") << QStringLiteral(
"-b") << QStringLiteral(
"2000k")
170 << d->destinationFile;
171 d->process.start(d->encoderExec, arguments);
172 connect(&d->process, SIGNAL(finished(
int)),
this, SLOT(processWrittenMovie(
int)));
175 for (
int i = 0; i < 30 && d->process.bytesToWrite() > 0; ++i) {
177 int then = d->process.bytesToWrite();
179 d->process.waitForBytesWritten(100);
181 int now = d->process.bytesToWrite();
182 int bytesWritten = then - now;
183 double rate = (bytesWritten * 1000.0) / (qMax(1, span) * 1024);
184 Q_EMIT rateCalculated(rate);
188bool MovieCapture::startRecording()
192 if (!checkToolsAvailability()) {
193 d->missingToolsWarning();
197 if (d->method == MovieCapture::TimeDriven) {
198 d->frameTimer.start();
204void MovieCapture::stopRecording()
208 d->frameTimer.stop();
209 d->process.closeWriteChannel();
212void MovieCapture::cancelRecording()
216 d->frameTimer.stop();
221void MovieCapture::processWrittenMovie(
int exitCode)
224 mDebug() <<
"[*] avconv finished with" << exitCode;
225 Q_EMIT errorOccured();
231#include "moc_MovieCapture.cpp"
Type type(const QSqlDatabase &db)
QString path(const QString &relativePath)
Binds a QML item to a specific geodetic location in screen coordinates.
qint64 elapsed() const const
qsizetype sizeInBytes() const const
bool isEmpty() const const
StandardButton warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromLatin1(QByteArrayView str)
QString number(double n, char format, int precision)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)