]> git.sesse.net Git - kdenlive/blob - src/kthumb.cpp
Start of image clips
[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
45 /*
46     void MyThread::init(KUrl url, QString target, double frame, double frameLength, int frequency, int channels, int arrayWidth)
47     {
48         stop_me = false;
49         m_isWorking = false;
50         f.setName(target);
51         m_url = url;
52         m_frame = frame;
53         m_frameLength = frameLength;
54         m_frequency = frequency;
55         m_channels = channels;
56         m_arrayWidth = arrayWidth;
57
58     }
59
60     bool MyThread::isWorking()
61     {
62         return m_isWorking;
63     }
64
65     void MyThread::run()
66     {
67                 if (!f.open( IO_WriteOnly )) {
68                         kdDebug()<<"++++++++  ERROR WRITING TO FILE: "<<f.name()<<endl;
69                         kdDebug()<<"++++++++  DISABLING AUDIO THUMBS"<<endl;
70                         KdenliveSettings::setAudiothumbnails(false);
71                         return;
72                 }
73                 m_isWorking = true;
74                 char *tmp = KRender::decodedString(m_url.path());
75                 Mlt::Producer m_producer(tmp);
76                 delete tmp;
77
78                 if (KdenliveSettings::normaliseaudiothumbs()) {
79                     Mlt::Filter m_convert("volume");
80                     m_convert.set("gain", "normalise");
81                     m_producer.attach(m_convert);
82                 }
83
84                 if (qApp->mainWidget()) 
85                     QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(-1, 10005));
86
87                 int last_val = 0;
88                 int val = 0;
89                 for (int z=(int) m_frame;z<(int) (m_frame+m_frameLength) && m_producer.is_valid();z++){
90                         if (stop_me) break;
91                         val=(int)((z-m_frame)/(m_frame+m_frameLength)*100.0);
92                         if (last_val!=val & val > 1){
93                                 QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(val, 10005));
94                                 last_val=val;
95                         }
96                                 m_producer.seek( z );
97                                 Mlt::Frame *mlt_frame = m_producer.get_frame();
98                                 if ( mlt_frame->is_valid() )
99                                 {
100                                         double m_framesPerSecond = mlt_producer_get_fps( m_producer.get_producer() ); //mlt_frame->get_double( "fps" );
101                                         int m_samples = mlt_sample_calculator( m_framesPerSecond, m_frequency, mlt_frame_get_position(mlt_frame->get_frame()) );
102                                         mlt_audio_format m_audioFormat = mlt_audio_pcm;
103                                 
104                                         int16_t* m_pcm = mlt_frame->get_audio(m_audioFormat, m_frequency, m_channels, m_samples ); 
105
106                                         for (int c=0;c< m_channels;c++){
107                                                 QByteArray m_array(m_arrayWidth);
108                                                 for (uint i = 0; i < m_array.size(); i++){
109                                                         m_array[i] =  QABS((*( m_pcm + c + i * m_samples / m_array.size() ))>>8);
110                                                 }
111                                                 f.writeBlock(m_array);
112                                         }
113                                 } else{
114                                         f.writeBlock(QByteArray(m_arrayWidth));
115                                 }
116                                 if (mlt_frame)
117                                         delete mlt_frame;
118                 }
119                 f.close();
120                 m_isWorking = false;
121                 if (stop_me) {
122                     f.remove();
123                     QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(-1, 10005));
124                 }
125                 else QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(0, 10005));
126     }
127
128
129 #define _S(a)           (a)>255 ? 255 : (a)<0 ? 0 : (a)
130 #define _R(y,u,v) (0x2568*(y)                          + 0x3343*(u)) /0x2000
131 #define _G(y,u,v) (0x2568*(y) - 0x0c92*(v) - 0x1a1e*(u)) /0x2000
132 #define _B(y,u,v) (0x2568*(y) + 0x40cf*(v))                                          /0x2000
133 */
134 KThumb::KThumb(KUrl url, QObject * parent, const char *name):QObject(parent), m_url(url)
135 {
136 }
137
138 KThumb::~KThumb()
139 {
140     //if (thumbProducer.running ()) thumbProducer.exit();
141 }
142
143
144 //static
145 QPixmap KThumb::getImage(KUrl url, int width, int height)
146 {
147     if (url.isEmpty()) return QPixmap();
148     QPixmap pix(width, height);
149     char *tmp = Render::decodedString(url.path());
150     Mlt::Producer m_producer(tmp);
151     delete tmp;
152
153     if (m_producer.is_blank()) {
154         pix.fill(Qt::black);
155         return pix;
156     }
157     Mlt::Frame * m_frame;
158     mlt_image_format format = mlt_image_rgb24a;
159     Mlt::Filter m_convert("avcolour_space");
160     m_convert.set("forced", mlt_image_rgb24a);
161     m_producer.attach(m_convert);
162     //m_producer.seek(frame);
163     m_frame = m_producer.get_frame();
164     if (m_frame && m_frame->is_valid()) {
165       uint8_t *thumb = m_frame->get_image(format, width, height);
166       QImage image(thumb, width, height, QImage::Format_ARGB32);
167       if (!image.isNull()) {
168         pix = pix.fromImage(image);
169       }
170       else pix.fill(Qt::black);
171     }
172     if (m_frame) delete m_frame;
173     return pix;
174 }
175
176 void KThumb::extractImage(int frame, int frame2, int width, int height)
177 {
178     if (m_url.isEmpty()) return;
179     QPixmap pix(width, height);
180     char *tmp = Render::decodedString(m_url.path());
181     Mlt::Producer m_producer(tmp);
182     delete tmp;
183
184     if (m_producer.is_blank()) {
185         pix.fill(Qt::black);
186         emit thumbReady(frame, pix);
187         return;
188     }
189     Mlt::Frame * m_frame;
190     mlt_image_format format = mlt_image_rgb24a;
191     Mlt::Filter m_convert("avcolour_space");
192     m_convert.set("forced", mlt_image_rgb24a);
193     m_producer.attach(m_convert);
194     if (frame != -1) {
195       m_producer.seek(frame);
196       m_frame = m_producer.get_frame();
197       if (m_frame && m_frame->is_valid()) {
198         uint8_t *thumb = m_frame->get_image(format, width, height);
199         QImage image(thumb, width, height, QImage::Format_ARGB32);
200         if (!image.isNull()) {
201           pix = pix.fromImage(image);
202         }
203         else pix.fill(Qt::black);
204       }
205       if (m_frame) delete m_frame;
206       emit thumbReady(frame, pix);
207     }
208     if (frame2 == -1) return;
209     m_producer.seek(frame2);
210     m_frame = m_producer.get_frame();
211     if (m_frame && m_frame->is_valid()) {
212       uint8_t *thumb = m_frame->get_image(format, width, height);
213       QImage image(thumb, width, height, QImage::Format_ARGB32);
214       if (!image.isNull()) {
215         pix = pix.fromImage(image);
216       }
217       else pix.fill(Qt::black);
218     }
219     if (m_frame) delete m_frame;
220     emit thumbReady(frame2, pix);
221
222 }
223 /*
224 void KThumb::getImage(KUrl url, int frame, int width, int height)
225 {
226     if (url.isEmpty()) return;
227     QPixmap image(width, height);
228     char *tmp = KRender::decodedString(url.path());
229     Mlt::Producer m_producer(tmp);
230     delete tmp;
231     image.fill(Qt::black);
232
233     if (m_producer.is_blank()) {
234         emit thumbReady(frame, image);
235         return;
236     }
237     Mlt::Filter m_convert("avcolour_space");
238     m_convert.set("forced", mlt_image_rgb24a);
239     m_producer.attach(m_convert);
240     m_producer.seek(frame);
241     Mlt::Frame * m_frame = m_producer.get_frame();
242     mlt_image_format format = mlt_image_rgb24a;
243     width = width - 2;
244     height = height - 2;
245     if (m_frame && m_frame->is_valid()) {
246         uint8_t *thumb = m_frame->get_image(format, width, height);
247         QImage tmpimage(thumb, width, height, 32, NULL, 0, QImage::IgnoreEndian);
248         if (!tmpimage.isNull()) bitBlt(&image, 1, 1, &tmpimage, 0, 0, width + 2, height + 2);
249     }
250     if (m_frame) delete m_frame;
251     emit thumbReady(frame, image);
252 }
253
254 void KThumb::getThumbs(KUrl url, int startframe, int endframe, int width, int height)
255 {
256     if (url.isEmpty()) return;
257     QPixmap image(width, height);
258     char *tmp = KRender::decodedString(url.path());
259     Mlt::Producer m_producer(tmp);
260     delete tmp;
261     image.fill(Qt::black);
262
263     if (m_producer.is_blank()) {
264         emit thumbReady(startframe, image);
265         emit thumbReady(endframe, image);
266         return;
267     }
268     Mlt::Filter m_convert("avcolour_space");
269     m_convert.set("forced", mlt_image_rgb24a);
270     m_producer.attach(m_convert);
271     m_producer.seek(startframe);
272     Mlt::Frame * m_frame = m_producer.get_frame();
273     mlt_image_format format = mlt_image_rgb24a;
274     width = width - 2;
275     height = height - 2;
276
277     if (m_frame && m_frame->is_valid()) {
278         uint8_t *thumb = m_frame->get_image(format, width, height);
279         QImage tmpimage(thumb, width, height, 32, NULL, 0, QImage::IgnoreEndian);
280         if (!tmpimage.isNull()) bitBlt(&image, 1, 1, &tmpimage, 0, 0, width - 2, height - 2);
281     }
282     if (m_frame) delete m_frame;
283     emit thumbReady(startframe, image);
284
285     image.fill(Qt::black);
286     m_producer.seek(endframe);
287     m_frame = m_producer.get_frame();
288
289     if (m_frame && m_frame->is_valid()) {
290         uint8_t *thumb = m_frame->get_image(format, width, height);
291         QImage tmpimage(thumb, width, height, 32, NULL, 0, QImage::IgnoreEndian);
292         if (!tmpimage.isNull()) bitBlt(&image, 1, 1, &tmpimage, 0, 0, width - 2, height - 2);
293     }
294     if (m_frame) delete m_frame;
295     emit thumbReady(endframe, image);
296 }
297
298 void KThumb::stopAudioThumbs()
299 {
300         if (thumbProducer.running ()) thumbProducer.stop_me = true;
301 }
302
303
304 void KThumb::removeAudioThumb()
305 {
306         if (m_thumbFile.isEmpty()) return;
307         stopAudioThumbs();
308         QFile f(m_thumbFile);
309         f.remove();
310 }
311
312 void KThumb::getAudioThumbs(KUrl url, int channel, double frame, double frameLength, int arrayWidth){
313         if ((thumbProducer.running () && thumbProducer.isWorking()) || channel == 0) {
314             return;
315         }
316
317         QMap <int, QMap <int, QByteArray> > storeIn;
318        //FIXME: Hardcoded!!! 
319         int m_frequency = 48000;
320         int m_channels = channel;
321         if (m_url != url) {
322                 m_url = url;
323                 KMD5 context ((KFileItem(m_url,"text/plain", S_IFREG).timeString() + m_url.fileName()).ascii());
324                 m_thumbFile = KdenliveSettings::currenttmpfolder() + context.hexDigest().data() + ".thumb";
325         }
326         QFile f(m_thumbFile);
327         if (f.open( IO_ReadOnly )) {
328                 QByteArray channelarray = f.readAll();
329                 f.close();
330                 if (channelarray.size() != arrayWidth*(frame+frameLength)*m_channels) {
331                         kdDebug()<<"--- BROKEN THUMB FOR: "<<m_url.filename()<<" ---------------------- "<<endl;
332                         f.remove();
333                         return;
334                 }
335                 
336                 for (int z=(int) frame;z<(int) (frame+frameLength);z++) {
337                         for (int c=0;c< m_channels;c++){
338                                 QByteArray m_array(arrayWidth);
339                                 for (int i = 0; i < arrayWidth; i++)
340                                         m_array[i] = channelarray[z*arrayWidth*m_channels + c*arrayWidth + i];
341                                 storeIn[z][c] = m_array;
342                         }
343                 }
344                 emit audioThumbReady(storeIn);
345         }
346         else {
347                 if (thumbProducer.running()) return;
348                 thumbProducer.init(m_url, m_thumbFile, frame, frameLength, m_frequency, m_channels, arrayWidth);
349                 thumbProducer.start(QThread::LowestPriority );
350         }
351 }
352 */
353
354