]> git.sesse.net Git - kdenlive/blob - src/projecttree/proxyclipjob.cpp
Start implementing a generic clip job framework that can be used
[kdenlive] / src / projecttree / proxyclipjob.cpp
1 /***************************************************************************
2  *                                                                         *
3  *   Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
19  ***************************************************************************/
20
21 #include "proxyclipjob.h"
22 #include "kdenlivesettings.h"
23 #include "kdenlivedoc.h"
24
25 #include <KDebug>
26 #include <KLocale>
27
28 ProxyJob::ProxyJob(JOBTYPE type, CLIPTYPE cType, const QString &id, QStringList parameters) : AbstractClipJob(type, cType, id, parameters)
29 {
30     description = i18n("proxy");
31     m_dest = parameters.at(0);
32     m_src = parameters.at(1);
33     m_exif = parameters.at(2).toInt();
34     m_proxyParams = parameters.at(3);
35     m_renderWidth = parameters.at(4).toInt();
36     m_renderHeight = parameters.at(5).toInt();
37 }
38
39 QProcess *ProxyJob::startJob(bool *ok)
40 {
41     // Special case: playlist clips (.mlt or .kdenlive project files)
42     if (clipType == PLAYLIST) {
43         // change FFmpeg params to MLT format
44         QStringList mltParameters;
45                 mltParameters << m_src;
46                 mltParameters << "-consumer" << "avformat:" + m_dest;
47                 QStringList params = m_proxyParams.split('-', QString::SkipEmptyParts);
48                 
49                 foreach(QString s, params) {
50                     s = s.simplified();
51                     if (s.count(' ') == 0) {
52                         s.append("=1");
53                     }
54                     else s.replace(' ', '=');
55                     mltParameters << s;
56                 }
57         
58             mltParameters.append(QString("real_time=-%1").arg(KdenliveSettings::mltthreads()));
59
60             //TODO: currently, when rendering an xml file through melt, the display ration is lost, so we enforce it manualy
61             double display_ratio = KdenliveDoc::getDisplayRatio(m_src);
62             mltParameters << "aspect=" + QString::number(display_ratio);
63
64             QProcess *myProcess = new QProcess;
65             myProcess->setProcessChannelMode(QProcess::MergedChannels);
66             myProcess->start(KdenliveSettings::rendererpath(), mltParameters);
67             myProcess->waitForStarted();
68             return myProcess;
69     }
70     else if (clipType == IMAGE) {
71         // Image proxy
72         QImage i(m_src);
73         if (i.isNull()) {
74             *ok = false;
75             return NULL;
76         }
77         
78         QImage proxy;
79         // Images are scaled to profile size. 
80         //TODO: Make it be configurable?
81         if (i.width() > i.height()) proxy = i.scaledToWidth(m_renderWidth);
82         else proxy = i.scaledToHeight(m_renderHeight);
83         if (m_exif > 1) {
84             // Rotate image according to exif data
85             QImage processed;
86             QMatrix matrix;
87
88             switch ( m_exif ) {
89                 case 2:
90                     matrix.scale( -1, 1 );
91                     break;
92                 case 3:
93                     matrix.rotate( 180 );
94                     break;
95                 case 4:
96                     matrix.scale( 1, -1 );
97                     break;
98                 case 5:
99                     matrix.rotate( 270 );
100                     matrix.scale( -1, 1 );
101                     break;
102                 case 6:
103                     matrix.rotate( 90 );
104                     break;
105                 case 7:
106                     matrix.rotate( 90 );
107                     matrix.scale( -1, 1 );
108                     break;
109                 case 8:
110                     matrix.rotate( 270 );
111                     break;
112             }
113             processed = proxy.transformed( matrix );
114             processed.save(m_dest);
115         }
116         else proxy.save(m_dest);
117         *ok = true;
118         return NULL;
119     }
120     else {
121         QStringList parameters;
122         parameters << "-i" << m_src;
123         QString params = m_proxyParams;
124         foreach(QString s, params.split(' '))
125         parameters << s;
126
127         // Make sure we don't block when proxy file already exists
128         parameters << "-y";
129         parameters << m_dest;
130         QProcess *myProcess = new QProcess;
131         myProcess->setProcessChannelMode(QProcess::MergedChannels);
132         myProcess->start("ffmpeg", parameters);
133         myProcess->waitForStarted();
134         return myProcess;
135     }
136 }
137
138 ProxyJob::~ProxyJob()
139 {
140 }
141
142 const QString ProxyJob::destination() const
143 {
144     return m_dest;
145 }
146
147 stringMap ProxyJob::cancelProperties()
148 {
149     QMap <QString, QString> props;
150     props.insert("proxy", "-");
151     return props;
152 }
153
154