7#include "MovieCapture.h"
9#include "MarbleDebug.h"
14#include <QElapsedTimer>
20class MovieCapturePrivate
23 explicit MovieCapturePrivate(MarbleWidget *widget) :
24 marbleWidget(widget), method(MovieCapture::TimeDriven)
30 void missingToolsWarning() {
33 QObject::tr(
"Marble requires additional software in order to "
34 "create movies. Please get %1 "
35 ).arg(
"<a href=\"https://libav.org/"
36 "download.html\">avconv</a>"),
41 MarbleWidget *marbleWidget;
45 MovieCapture::SnapshotMethod method;
49MovieCapture::MovieCapture(MarbleWidget *widget,
QObject *parent) :
51 d_ptr(new MovieCapturePrivate(widget))
54 if( d->method == MovieCapture::TimeDriven ){
55 d->frameTimer.setInterval(1000/30);
56 connect(&d->frameTimer, SIGNAL(timeout()),
this, SLOT(recordFrame()));
59 MovieFormat avi(
"avi", tr(
"AVI (mpeg4)" ),
"avi" );
60 MovieFormat flv(
"flv", tr(
"FLV" ),
"flv" );
61 MovieFormat mkv(
"matroska", tr(
"Matroska (h264)" ),
"mkv" );
62 MovieFormat mp4(
"mp4", tr(
"MPEG-4" ),
"mp4" );
63 MovieFormat vob(
"vob", tr(
"MPEG-2 PS (VOB)" ),
"vob" );
64 MovieFormat ogg(
"ogg", tr(
"OGG" ),
"ogg" );
65 MovieFormat swf(
"swf", tr(
"SWF" ),
"swf" );
66 m_supportedFormats << avi << flv << mkv << mp4 << vob << ogg << swf;
69MovieCapture::~MovieCapture()
74void MovieCapture::setFps(
int fps)
77 if( d->method == MovieCapture::TimeDriven ){
78 d->frameTimer.setInterval(1000/fps);
83void MovieCapture::setFilename(
const QString &path)
86 d->destinationFile =
path;
89void MovieCapture::setSnapshotMethod(MovieCapture::SnapshotMethod method)
95int MovieCapture::fps()
const
97 Q_D(
const MovieCapture);
101QString MovieCapture::destination()
const
103 Q_D(
const MovieCapture);
104 return d->destinationFile;
111 if ( availableFormats.
isEmpty() && checkToolsAvailability() ) {
113 for (
const MovieFormat &format: m_supportedFormats ) {
117 encoder.start( d->encoderExec, args );
118 encoder.waitForFinished();
119 QString output = encoder.readAll();
121 if( isFormatAvailable ) {
122 availableFormats << format;
126 return availableFormats;
129MovieCapture::SnapshotMethod MovieCapture::snapshotMethod()
const
131 Q_D(
const MovieCapture);
135bool MovieCapture::checkToolsAvailability()
138 static bool toolsAvailable =
false;
139 if (toolsAvailable ==
false) {
141 encoder.start(
"avconv",
QStringList() <<
"-version");
142 encoder.waitForFinished();
143 if ( !encoder.readAll().isEmpty() ) {
144 d->encoderExec =
"avconv";
145 toolsAvailable =
true;
147 encoder.start(
"ffmpeg",
QStringList() <<
"-version");
148 encoder.waitForFinished();
149 if ( !encoder.readAll().isEmpty() ) {
150 d->encoderExec =
"ffmpeg";
151 toolsAvailable =
true;
155 return toolsAvailable;
158void MovieCapture::recordFrame()
166 <<
"-f" <<
"rawvideo"
167 <<
"-pix_fmt" <<
"rgb24"
171 << d->destinationFile;
172 d->process.start( d->encoderExec, arguments );
173 connect(&d->process, SIGNAL(finished(
int)),
this, SLOT(processWrittenMovie(
int)));
175 d->process.write( (
char*) screenshot.
bits(), screenshot.
sizeInBytes() );
176 for (
int i=0; i<30 && d->process.bytesToWrite()>0; ++i) {
178 int then = d->process.bytesToWrite();
180 d->process.waitForBytesWritten( 100 );
182 int now = d->process.bytesToWrite();
183 int bytesWritten = then - now;
184 double rate = ( bytesWritten * 1000.0 ) / ( qMax(1, span) * 1024 );
185 emit rateCalculated( rate );
189bool MovieCapture::startRecording()
193 if( !checkToolsAvailability() ) {
194 d->missingToolsWarning();
198 if( d->method == MovieCapture::TimeDriven ){
199 d->frameTimer.start();
205void MovieCapture::stopRecording()
209 d->frameTimer.stop();
210 d->process.closeWriteChannel();
213void MovieCapture::cancelRecording()
217 d->frameTimer.stop();
222void MovieCapture::processWrittenMovie(
int exitCode)
225 mDebug() <<
"[*] avconv finished with" << exitCode;
232#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 number(double n, char format, int precision)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)