]> git.sesse.net Git - kdenlive/blob - src/kthumb.cpp
3e474a0c6b5cbbb82a1aeab9744903f02f0b4044
[kdenlive] / src / kthumb.cpp
1 /***************************************************************************
2                         krender.cpp  -  description
3                            -------------------
4   begin                : Fri Nov 22 2002
5   copyright            : (C) 2002 by Jason Wood
6   email                : jasonwood@blueyonder.co.uk
7   copyright            : (C) 2005 Lcio Fl�io Corr�  
8   email                : lucio.correa@gmail.com
9   copyright            : (C) Marco Gittler
10   email                : g.marco@freenet.de
11
12 ***************************************************************************/
13
14 /***************************************************************************
15  *                                                                         *
16  *   This program is free software; you can redistribute it and/or modify  *
17  *   it under the terms of the GNU General Public License as published by  *
18  *   the Free Software Foundation; either version 2 of the License, or     *
19  *   (at your option) any later version.                                   *
20  *                                                                         *
21  ***************************************************************************/
22
23 #include <qapplication.h>
24
25 #include <kio/netaccess.h>
26 #include <kdebug.h>
27 #include <klocale.h>
28 #include <kdenlivesettings.h>
29 #include <kfileitem.h>
30 #include <kmessagebox.h>
31
32 #include <mlt++/Mlt.h>
33
34 #include <qxml.h>
35 #include <qimage.h>
36 #include <qlabel.h>
37 #include <qthread.h>
38 #include <qapplication.h>
39
40
41
42 #include "renderer.h"
43 #include "kthumb.h"
44 #include "kdenlivesettings.h"
45
46 /*
47     void MyThread::init(KUrl url, QString target, double frame, double frameLength, int frequency, int channels, int arrayWidth)
48     {
49         stop_me = false;
50         m_isWorking = false;
51         f.setName(target);
52         m_url = url;
53         m_frame = frame;
54         m_frameLength = frameLength;
55         m_frequency = frequency;
56         m_channels = channels;
57         m_arrayWidth = arrayWidth;
58
59     }
60
61     bool MyThread::isWorking()
62     {
63         return m_isWorking;
64     }
65
66     void MyThread::run()
67     {
68                 if (!f.open( IO_WriteOnly )) {
69                         kdDebug()<<"++++++++  ERROR WRITING TO FILE: "<<f.name()<<endl;
70                         kdDebug()<<"++++++++  DISABLING AUDIO THUMBS"<<endl;
71                         KdenliveSettings::setAudiothumbnails(false);
72                         return;
73                 }
74                 m_isWorking = true;
75                 char *tmp = KRender::decodedString(m_url.path());
76                 Mlt::Producer m_producer(tmp);
77                 delete tmp;
78
79                 if (KdenliveSettings::normaliseaudiothumbs()) {
80                     Mlt::Filter m_convert("volume");
81                     m_convert.set("gain", "normalise");
82                     m_producer.attach(m_convert);
83                 }
84
85                 if (qApp->mainWidget()) 
86                     QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(-1, 10005));
87
88                 int last_val = 0;
89                 int val = 0;
90                 for (int z=(int) m_frame;z<(int) (m_frame+m_frameLength) && m_producer.is_valid();z++){
91                         if (stop_me) break;
92                         val=(int)((z-m_frame)/(m_frame+m_frameLength)*100.0);
93                         if (last_val!=val & val > 1){
94                                 QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(val, 10005));
95                                 last_val=val;
96                         }
97                                 m_producer.seek( z );
98                                 Mlt::Frame *mlt_frame = m_producer.get_frame();
99                                 if ( mlt_frame->is_valid() )
100                                 {
101                                         double m_framesPerSecond = mlt_producer_get_fps( m_producer.get_producer() ); //mlt_frame->get_double( "fps" );
102                                         int m_samples = mlt_sample_calculator( m_framesPerSecond, m_frequency, mlt_frame_get_position(mlt_frame->get_frame()) );
103                                         mlt_audio_format m_audioFormat = mlt_audio_pcm;
104                                 
105                                         int16_t* m_pcm = mlt_frame->get_audio(m_audioFormat, m_frequency, m_channels, m_samples ); 
106
107                                         for (int c=0;c< m_channels;c++){
108                                                 QByteArray m_array(m_arrayWidth);
109                                                 for (uint i = 0; i < m_array.size(); i++){
110                                                         m_array[i] =  QABS((*( m_pcm + c + i * m_samples / m_array.size() ))>>8);
111                                                 }
112                                                 f.writeBlock(m_array);
113                                         }
114                                 } else{
115                                         f.writeBlock(QByteArray(m_arrayWidth));
116                                 }
117                                 if (mlt_frame)
118                                         delete mlt_frame;
119                 }
120                 f.close();
121                 m_isWorking = false;
122                 if (stop_me) {
123                     f.remove();
124                     QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(-1, 10005));
125                 }
126                 else QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(0, 10005));
127     }
128
129
130 #define _S(a)           (a)>255 ? 255 : (a)<0 ? 0 : (a)
131 #define _R(y,u,v) (0x2568*(y)                          + 0x3343*(u)) /0x2000
132 #define _G(y,u,v) (0x2568*(y) - 0x0c92*(v) - 0x1a1e*(u)) /0x2000
133 #define _B(y,u,v) (0x2568*(y) + 0x40cf*(v))                                          /0x2000
134 */
135 KThumb::KThumb(KUrl url, int width, int height, QObject * parent, const char *name):QObject(parent), m_url(url), m_width(width), m_height(height)
136 {
137   kDebug()<<"+++++++++++  CREATING THMB PROD FOR: "<<url;
138   m_profile = Mlt::Profile((char*) KdenliveSettings::current_profile().data());
139 }
140
141 KThumb::~KThumb()
142 {
143     //if (thumbProducer.running ()) thumbProducer.exit();
144 }
145
146
147 //static
148 QPixmap KThumb::getImage(KUrl url, int width, int height)
149 {
150     if (url.isEmpty()) return QPixmap();
151     QPixmap pix(width, height);
152   kDebug()<<"+++++++++++  GET THMB IMG FOR: "<<url;
153     char *tmp = Render::decodedString(url.path());
154     Mlt::Profile prof((char*) KdenliveSettings::current_profile().data());
155     Mlt::Producer m_producer(prof, tmp);
156     delete tmp;
157
158     if (m_producer.is_blank()) {
159         pix.fill(Qt::black);
160         return pix;
161     }
162     Mlt::Frame * m_frame;
163     mlt_image_format format = mlt_image_rgb24a;
164     Mlt::Filter m_convert(prof, "avcolour_space");
165     m_convert.set("forced", mlt_image_rgb24a);
166     m_producer.attach(m_convert);
167     //m_producer.seek(frame);
168     m_frame = m_producer.get_frame();
169     if (m_frame && m_frame->is_valid()) {
170       uint8_t *thumb = m_frame->get_image(format, width, height);
171       QImage image(thumb, width, height, QImage::Format_ARGB32);
172       if (!image.isNull()) {
173         pix = pix.fromImage(image);
174       }
175       else pix.fill(Qt::black);
176     }
177     if (m_frame) delete m_frame;
178     return pix;
179 }
180
181 void KThumb::extractImage(int frame, int frame2)
182 {
183     if (m_url.isEmpty()) return;
184     QPixmap pix(m_width, m_height);
185     char *tmp = Render::decodedString(m_url.path());
186     Mlt::Producer m_producer(m_profile, tmp);
187     delete tmp;
188
189     if (m_producer.is_blank()) {
190         pix.fill(Qt::black);
191         emit thumbReady(frame, pix);
192         return;
193     }
194     Mlt::Frame * m_frame;
195     mlt_image_format format = mlt_image_rgb24a;
196     Mlt::Filter m_convert(m_profile, "avcolour_space");
197     m_convert.set("forced", mlt_image_rgb24a);
198     m_producer.attach(m_convert);
199     if (frame != -1) {
200       m_producer.seek(frame);
201       m_frame = m_producer.get_frame();
202       if (m_frame && m_frame->is_valid()) {
203         uint8_t *thumb = m_frame->get_image(format, m_width, m_height);
204         QImage image(thumb, m_width, m_height, QImage::Format_ARGB32);
205         if (!image.isNull()) {
206           pix = pix.fromImage(image);
207         }
208         else pix.fill(Qt::black);
209       }
210       if (m_frame) delete m_frame;
211       emit thumbReady(frame, pix);
212     }
213     if (frame2 == -1) return;
214     m_producer.seek(frame2);
215     m_frame = m_producer.get_frame();
216     if (m_frame && m_frame->is_valid()) {
217       uint8_t *thumb = m_frame->get_image(format, m_width, m_height);
218       QImage image(thumb, m_width, m_height, QImage::Format_ARGB32);
219       if (!image.isNull()) {
220         pix = pix.fromImage(image);
221       }
222       else pix.fill(Qt::black);
223     }
224     if (m_frame) delete m_frame;
225     emit thumbReady(frame2, pix);
226
227 }
228 /*
229 void KThumb::getImage(KUrl url, int frame, int width, int height)
230 {
231     if (url.isEmpty()) return;
232     QPixmap image(width, height);
233     char *tmp = KRender::decodedString(url.path());
234     Mlt::Producer m_producer(tmp);
235     delete tmp;
236     image.fill(Qt::black);
237
238     if (m_producer.is_blank()) {
239         emit thumbReady(frame, image);
240         return;
241     }
242     Mlt::Filter m_convert("avcolour_space");
243     m_convert.set("forced", mlt_image_rgb24a);
244     m_producer.attach(m_convert);
245     m_producer.seek(frame);
246     Mlt::Frame * m_frame = m_producer.get_frame();
247     mlt_image_format format = mlt_image_rgb24a;
248     width = width - 2;
249     height = height - 2;
250     if (m_frame && m_frame->is_valid()) {
251         uint8_t *thumb = m_frame->get_image(format, width, height);
252         QImage tmpimage(thumb, width, height, 32, NULL, 0, QImage::IgnoreEndian);
253         if (!tmpimage.isNull()) bitBlt(&image, 1, 1, &tmpimage, 0, 0, width + 2, height + 2);
254     }
255     if (m_frame) delete m_frame;
256     emit thumbReady(frame, image);
257 }
258
259 void KThumb::getThumbs(KUrl url, int startframe, int endframe, int width, int height)
260 {
261     if (url.isEmpty()) return;
262     QPixmap image(width, height);
263     char *tmp = KRender::decodedString(url.path());
264     Mlt::Producer m_producer(tmp);
265     delete tmp;
266     image.fill(Qt::black);
267
268     if (m_producer.is_blank()) {
269         emit thumbReady(startframe, image);
270         emit thumbReady(endframe, image);
271         return;
272     }
273     Mlt::Filter m_convert("avcolour_space");
274     m_convert.set("forced", mlt_image_rgb24a);
275     m_producer.attach(m_convert);
276     m_producer.seek(startframe);
277     Mlt::Frame * m_frame = m_producer.get_frame();
278     mlt_image_format format = mlt_image_rgb24a;
279     width = width - 2;
280     height = height - 2;
281
282     if (m_frame && m_frame->is_valid()) {
283         uint8_t *thumb = m_frame->get_image(format, width, height);
284         QImage tmpimage(thumb, width, height, 32, NULL, 0, QImage::IgnoreEndian);
285         if (!tmpimage.isNull()) bitBlt(&image, 1, 1, &tmpimage, 0, 0, width - 2, height - 2);
286     }
287     if (m_frame) delete m_frame;
288     emit thumbReady(startframe, image);
289
290     image.fill(Qt::black);
291     m_producer.seek(endframe);
292     m_frame = m_producer.get_frame();
293
294     if (m_frame && m_frame->is_valid()) {
295         uint8_t *thumb = m_frame->get_image(format, width, height);
296         QImage tmpimage(thumb, width, height, 32, NULL, 0, QImage::IgnoreEndian);
297         if (!tmpimage.isNull()) bitBlt(&image, 1, 1, &tmpimage, 0, 0, width - 2, height - 2);
298     }
299     if (m_frame) delete m_frame;
300     emit thumbReady(endframe, image);
301 }
302
303 void KThumb::stopAudioThumbs()
304 {
305         if (thumbProducer.running ()) thumbProducer.stop_me = true;
306 }
307
308
309 void KThumb::removeAudioThumb()
310 {
311         if (m_thumbFile.isEmpty()) return;
312         stopAudioThumbs();
313         QFile f(m_thumbFile);
314         f.remove();
315 }
316
317 void KThumb::getAudioThumbs(KUrl url, int channel, double frame, double frameLength, int arrayWidth){
318         if ((thumbProducer.running () && thumbProducer.isWorking()) || channel == 0) {
319             return;
320         }
321
322         QMap <int, QMap <int, QByteArray> > storeIn;
323        //FIXME: Hardcoded!!! 
324         int m_frequency = 48000;
325         int m_channels = channel;
326         if (m_url != url) {
327                 m_url = url;
328                 KMD5 context ((KFileItem(m_url,"text/plain", S_IFREG).timeString() + m_url.fileName()).ascii());
329                 m_thumbFile = KdenliveSettings::currenttmpfolder() + context.hexDigest().data() + ".thumb";
330         }
331         QFile f(m_thumbFile);
332         if (f.open( IO_ReadOnly )) {
333                 QByteArray channelarray = f.readAll();
334                 f.close();
335                 if (channelarray.size() != arrayWidth*(frame+frameLength)*m_channels) {
336                         kdDebug()<<"--- BROKEN THUMB FOR: "<<m_url.filename()<<" ---------------------- "<<endl;
337                         f.remove();
338                         return;
339                 }
340                 
341                 for (int z=(int) frame;z<(int) (frame+frameLength);z++) {
342                         for (int c=0;c< m_channels;c++){
343                                 QByteArray m_array(arrayWidth);
344                                 for (int i = 0; i < arrayWidth; i++)
345                                         m_array[i] = channelarray[z*arrayWidth*m_channels + c*arrayWidth + i];
346                                 storeIn[z][c] = m_array;
347                         }
348                 }
349                 emit audioThumbReady(storeIn);
350         }
351         else {
352                 if (thumbProducer.running()) return;
353                 thumbProducer.init(m_url, m_thumbFile, frame, frameLength, m_frequency, m_channels, arrayWidth);
354                 thumbProducer.start(QThread::LowestPriority );
355         }
356 }
357 */
358
359