OSDN Git Service

[COMMON][Qt] Fix BYTEORDER of PIXEL@RGB888.Updated SOVERSION.
[csp-qt/common_source_project-fm7.git] / source / src / qt / avio / movie_loader.cpp
1 /*
2  * Common Source Code Project for Qt : movie loader
3  * (C) 2016 K.Ohta <whatisthis.sowhat _at_ gmail.com>
4  *  License: GPLv2
5  *  History: June 30, 2016 : Initial. This refer from sample of ffmpeg .
6  */
7
8 #include "../osd.h"
9 #include "movie_loader.h"
10 #include "csp_logger.h"
11
12 #include <QMutex>
13 #include <QMutexLocker>
14
15 MOVIE_LOADER::MOVIE_LOADER(OSD *osd, config_t *cfg) : QObject(NULL)
16 {
17         p_osd = osd;
18         p_cfg = cfg;
19         p_logger = osd->get_logger();
20         
21         video_mutex = new QMutex(QMutex::Recursive);
22         snd_write_lock = new QMutex(QMutex::Recursive);
23         
24         frame_rate = 29.97;
25         video_frame_count = 0;
26         duration_us = 0;
27         audio_total_samples = 0;
28         
29         now_opening = false;
30         use_hwaccel = false;
31         
32         _filename.clear();
33
34         video_format.clear();
35         video_codec.clear();
36         audio_codec.clear();
37         hwaccel_method.clear();
38
39         now_pausing = false;
40         now_playing = false;
41         
42         src_width = 640;
43         src_height = 200;
44         dst_width = 640;
45         dst_height = 200;
46         old_dst_width = dst_width;
47         old_dst_height = dst_height;
48         mod_frames = 0.0;
49         sound_rate = 44100;
50         req_transfer = true;
51
52 #if defined(USE_LIBAV)
53         fmt_ctx = NULL;
54         video_dec_ctx = NULL;
55         audio_dec_ctx = NULL;
56         sws_context = NULL;
57         swr_context = NULL;
58         video_stream = NULL;
59         audio_stream = NULL;
60         for(int i = 0; i < 4; i++) video_dst_data[i] = NULL;
61         for(int i = 0; i < 4; i++) video_dst_linesize[i] = 0;
62         video_dst_bufsize = 0;
63         video_stream_idx = -1;
64         audio_stream_idx = -1;
65         frame = NULL;
66         refcount = 0;
67 #endif
68
69 }
70
71 MOVIE_LOADER::~MOVIE_LOADER()
72 {
73         delete video_mutex;
74 }
75
76
77 #if defined(USE_LIBAV)
78 int MOVIE_LOADER::decode_packet(int *got_frame, int cached)
79 {
80         int ret = 0;
81         int decoded = pkt.size;
82         
83         *got_frame = 0;
84         
85         if (pkt.stream_index == video_stream_idx) {
86                 /* decode video frame */
87                 ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt);
88                 if (ret < 0) {
89                         char str_buf[AV_ERROR_MAX_STRING_SIZE] = {0};
90                         av_make_error_string(str_buf, AV_ERROR_MAX_STRING_SIZE, ret);
91                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Error decoding video frame (%s)\n", str_buf);
92                         return ret;
93                 }
94                 if (*got_frame) {
95             if (frame->width != src_width || frame->height != src_height ||
96                 frame->format != pix_fmt) {
97                 /* To handle this change, one could call av_image_alloc again and
98                  * decode the following frames into another rawvideo file. */
99                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Error: Width, height and pixel format have to be "
100                                                           "constant in a rawvideo file, but the width, height or "
101                                                           "pixel format of the input video changed:\n"
102                                                           "old: width = %d, height = %d, format = %s\n"
103                                                           "new: width = %d, height = %d, format = %s\n",
104                                                           src_width, src_height, av_get_pix_fmt_name(pix_fmt),
105                                                           frame->width, frame->height,
106                                                                           av_get_pix_fmt_name((enum AVPixelFormat)frame->format));
107                 return -1;
108             }
109                         if((old_dst_width != dst_width) || (old_dst_height != dst_height)) { // You sould allocate on opening.
110                                 QMutexLocker Locker_V(video_mutex);
111                                 //video_mutex->lock();
112                                 for(int i = 0; i < 4; i++) av_free(video_dst_data[i]);
113                                 ret = av_image_alloc(video_dst_data, video_dst_linesize,
114                                                                          dst_width, dst_height, AV_PIX_FMT_RGBA, 1);
115                                 
116                                 if(ret < 0) {
117                                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "MOVIE_LOADER: Could not re-allocate output buffer\n");
118                                         old_dst_width = dst_width;
119                                         old_dst_height = dst_height;
120                                         //video_mutex->unlock();
121                                         return -1;
122                                 }
123                                 old_dst_width = dst_width;
124                                 old_dst_height = dst_height;
125                                 //video_mutex->unlock();
126                         }
127                         
128                         char str_buf2[AV_TS_MAX_STRING_SIZE] = {0};
129
130
131                         video_frame_count++;
132                         //av_ts_make_time_string(str_buf2, frame->pts, &video_dec_ctx->time_base);
133                         //p_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_MOVIE_LOADER, "video_frame%s n:%d coded_n:%d pts:%s\n",
134                         //                        cached ? "(cached)" : "",
135                         //                        video_frame_count++, frame->coded_picture_number,
136                         //                        str_buf2);
137                         
138             /* copy decoded frame to destination buffer:
139              * this is required since rawvideo expects non aligned data */
140                         if(sws_context == NULL) {
141                                 sws_context = sws_getContext(frame->width, frame->height,
142                                                                                          (enum AVPixelFormat) frame->format,
143                                                                                          dst_width, dst_height,
144                                                                                          AV_PIX_FMT_RGBA,
145                                                                                          SCALE_FLAGS, NULL, NULL, NULL);
146                                 //p_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_MOVIE_LOADER, "Src frame=%dx%d Allocate frame: %dx%d", frame->width, frame->height, dst_width, dst_height);
147
148                                 if (sws_context == NULL) {
149                                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER,
150                                                                   "MOVIE_LOADER: Could not initialize the conversion context\n");
151                                         return -1;
152                                 }
153                                 
154                         }
155                         video_mutex->lock();
156                         sws_scale(sws_context,
157                                           frame->data, frame->linesize,
158                                           0, frame->height, video_dst_data, video_dst_linesize);
159                         req_transfer = true;
160                         video_mutex->unlock();
161                 }
162         } else if (pkt.stream_index == audio_stream_idx) {
163                 /* decode audio frame */
164                 ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt);
165                 if (ret < 0) {
166                         char str_buf[AV_ERROR_MAX_STRING_SIZE] = {0};
167                         av_make_error_string(str_buf, AV_ERROR_MAX_STRING_SIZE, ret);
168                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Error decoding audio frame (%s)\n", str_buf);
169                         return ret;
170                 }
171                 /* Some audio decoders decode only part of the packet, and have to be
172                  * called again with the remainder of the packet data.
173                  * Sample: fate-suite/lossless-audio/luckynight-partial.shn
174                  * Also, some decoders might over-read the packet. */
175                 decoded = FFMIN(ret, pkt.size);
176                         
177                 if (*got_frame) {
178                         //size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample((enum AVSampleFormat)frame->format);
179                         char str_buf[AV_TS_MAX_STRING_SIZE] = {0};
180                         AVCodecContext *c = audio_stream->codec;
181                         int dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_context, c->sample_rate) + frame->nb_samples,
182                                                                                                 c->sample_rate, c->sample_rate,  AV_ROUND_UP);
183                         //av_ts_make_time_string(str_buf, frame->pts, &audio_dec_ctx->time_base);
184                         //p_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_MOVIE_LOADER,"audio_frame%s n:%d nb_samples:%d pts:%s\n",
185                         //                        cached ? "(cached)" : "",
186                         //                        audio_frame_count++, frame->nb_samples,
187                         //                        str_buf);
188                         audio_total_samples += (int64_t)dst_nb_samples;
189                         /* Write the raw audio data samples of the first plane. This works
190                          * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However,
191                          * most audio decoders output planar audio, which uses a separate
192                          * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P).
193                          * In other words, this code will write only the first audio channel
194                          * in these cases.
195                          * You should use libswresample or libavfilter to convert the frame
196                          * to packed data. */
197                         sound_data_queue_t *px = (sound_data_queue_t *)malloc(sizeof(sound_data_queue_t));
198                         if(px != NULL) {
199                                 px->data[0] = (uint8_t *)malloc((long)dst_nb_samples * 2 * sizeof(int16_t));
200                                 px->data[1] = px->data[2] = px->data[3] = NULL;
201                                 if(px->data[0] == NULL) {
202                                         free(px);
203                                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Error while converting\n");
204                                         return -1;
205                                 }
206                                 ret = swr_convert(swr_context,
207                                                                   px->data, dst_nb_samples,
208                                                                   (const uint8_t **)frame->data, frame->nb_samples);
209                                 if (ret < 0) {
210                                         free(px->data[0]);
211                                         free(px);
212                                         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Error while converting\n");
213                                         return -1;
214                                 }
215                                 px->unpadded_linesize = (long)dst_nb_samples * 2 * sizeof(int16_t);
216                                 snd_write_lock->lock();
217                                 sound_data_queue.enqueue(px);
218                                 snd_write_lock->unlock();
219                         } else {
220                                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Error while converting\n");
221                                 return -1;
222                         }
223                 }
224         }
225
226
227     /* If we use frame reference counting, we own the data and need
228      * to de-reference it when we don't use it anymore */
229     if (*got_frame && refcount)
230         av_frame_unref(frame);
231
232     return decoded;
233 }
234
235 int MOVIE_LOADER::open_codec_context(int *stream_idx,
236                                                                          AVFormatContext *fmt_ctx, enum AVMediaType type)
237 {
238     int ret, stream_index;
239     AVStream *st;
240     AVCodecContext *dec_ctx = NULL;
241     AVCodec *dec = NULL;
242     AVDictionary *opts = NULL;
243
244     ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
245     if (ret < 0) {
246         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Could not find %s stream in input file '%s'\n",
247                 av_get_media_type_string(type), _filename.toLocal8Bit().constData());
248         return ret;
249     } else {
250         stream_index = ret;
251         st = fmt_ctx->streams[stream_index];
252
253         /* find decoder for the stream */
254         dec_ctx = st->codec;
255         dec = avcodec_find_decoder(dec_ctx->codec_id);
256         if (!dec) {
257             p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Failed to find %s codec\n",
258                     av_get_media_type_string(type));
259             return AVERROR(EINVAL);
260         }
261
262         /* Init the decoders, with or without reference counting */
263         av_dict_set(&opts, "refcounted_frames", refcount ? "1" : "0", 0);
264         if ((ret = avcodec_open2(dec_ctx, dec, &opts)) < 0) {
265             p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Failed to open %s codec\n",
266                     av_get_media_type_string(type));
267             return ret;
268         }
269         *stream_idx = stream_index;
270     }
271
272     return 0;
273 }
274
275 int MOVIE_LOADER::get_format_from_sample_fmt(const char **fmt,
276                                                                                          enum AVSampleFormat sample_fmt)
277 {
278     int i;
279     struct sample_fmt_entry {
280         enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le;
281     } sample_fmt_entries[] = {
282         { AV_SAMPLE_FMT_U8,  "u8",    "u8"    },
283         { AV_SAMPLE_FMT_S16, "s16be", "s16le" },
284         { AV_SAMPLE_FMT_S32, "s32be", "s32le" },
285         { AV_SAMPLE_FMT_FLT, "f32be", "f32le" },
286         { AV_SAMPLE_FMT_DBL, "f64be", "f64le" },
287     };
288     *fmt = NULL;
289
290     for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) {
291         struct sample_fmt_entry *entry = &sample_fmt_entries[i];
292         if (sample_fmt == entry->sample_fmt) {
293             *fmt = AV_NE(entry->fmt_be, entry->fmt_le);
294             return 0;
295         }
296     }
297
298     p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER,
299             "sample format %s is not supported as output format\n",
300             av_get_sample_fmt_name(sample_fmt));
301     return -1;
302 }
303
304 #endif // USE_LIBAV
305
306 bool MOVIE_LOADER::open(QString filename)
307 {
308     int ret = 0, got_frame;
309         _filename = filename;
310         if(_filename.isEmpty()) return false;
311         
312         mod_frames = 0.0;
313         req_transfer = true;
314         
315         duration_us = 0;
316         video_frame_count = 0;
317         audio_total_samples = 0;
318         
319     /* register all formats and codecs */
320     av_register_all();
321
322     /* open input file, and allocate format context */
323     if (avformat_open_input(&fmt_ctx, _filename.toLocal8Bit().constData(), NULL, NULL) < 0) {
324         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Could not open source file %s\n", _filename.toLocal8Bit().constData());
325         return -1;
326     }
327
328     /* retrieve stream information */
329     if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
330         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Could not find stream information\n");
331         return -1;;
332     }
333
334     if (open_codec_context(&video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) {
335         video_stream = fmt_ctx->streams[video_stream_idx];
336         video_dec_ctx = video_stream->codec;
337
338         /* allocate image where the decoded image will be put */
339         src_width = video_dec_ctx->width;
340         src_height = video_dec_ctx->height;
341         pix_fmt = video_dec_ctx->pix_fmt;
342                 AVRational rate;
343                 rate = av_stream_get_r_frame_rate(video_stream);
344                 frame_rate = av_q2d(rate);
345         if (ret < 0) {
346             p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Could not allocate raw video buffer\n");
347             goto _end;
348         }
349         video_dst_bufsize = ret;
350     }
351
352     if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) {
353         audio_stream = fmt_ctx->streams[audio_stream_idx];
354         audio_dec_ctx = audio_stream->codec;
355                 sound_rate = audio_stream->codec->sample_rate;
356     }
357         swr_context = swr_alloc();
358         if(swr_context == NULL) {
359                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Could not allocate resampler context\n");
360                 goto _end;
361         }
362         av_opt_set_int     (swr_context, "in_channel_count",   audio_stream->codec->channels,      0);
363         av_opt_set_int     (swr_context, "in_sample_rate",         audio_stream->codec->sample_rate,    0);
364         av_opt_set_sample_fmt(swr_context, "in_sample_fmt",        audio_stream->codec->sample_fmt, 0);
365         av_opt_set_int     (swr_context, "out_channel_count",  2,          0);
366         av_opt_set_int     (swr_context, "out_sample_rate",        sound_rate,  0);
367         av_opt_set_sample_fmt(swr_context, "out_sample_fmt",   AV_SAMPLE_FMT_S16,        0);
368         
369         /* initialize the resampling context */
370         if ((ret = swr_init(swr_context)) < 0) {
371                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Failed to initialize the resampling context\n");
372                 goto _end;
373         }
374
375     /* dump input information to stderr */
376     av_dump_format(fmt_ctx, 0, _filename.toLocal8Bit().constData(), 0);
377         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Video is %f fps", frame_rate);
378         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Audio is %d Hz ", sound_rate);
379     if (!audio_stream && !video_stream) {
380         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Could not find audio or video stream in the input, aborting\n");
381         ret = 1;
382         goto _end;
383     }
384
385     frame = av_frame_alloc();
386     if (!frame) {
387         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "Could not allocate frame\n");
388         ret = AVERROR(ENOMEM);
389         goto _end;
390     }
391
392     /* initialize packet, set data to NULL, let the demuxer fill it */
393     av_init_packet(&pkt);
394     pkt.data = NULL;
395     pkt.size = 0;
396
397         // Re-allocate buffer;
398         video_mutex->lock();
399         ret = av_image_alloc(video_dst_data, video_dst_linesize,
400                              dst_width, dst_height, AV_PIX_FMT_RGBA, 1);
401         old_dst_width = dst_width;
402         old_dst_height = dst_height;
403         video_mutex->unlock();
404         if(ret < 0) {
405                 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "MOVIE_LOADER: Could not re-allocate output buffer\n");
406                 //video_mutex->unlock();
407                 goto _end;
408         }
409
410         // ToDo : Initialize SWScaler and SWresampler.
411         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "MOVIE_LOADER: Loading movie completed.\n");
412         return true;
413 _end:
414         this->close();
415         return false;
416 }
417
418 void MOVIE_LOADER::close(void)
419 {
420     if(video_dec_ctx != NULL) avcodec_close(video_dec_ctx);
421     if(audio_dec_ctx != NULL) avcodec_close(audio_dec_ctx);
422     avformat_close_input(&fmt_ctx);
423         if(sws_context != NULL) {
424                 sws_freeContext(sws_context);
425         }
426         swr_free(&swr_context);
427         
428         video_mutex->lock();
429         req_transfer = true;
430         if(frame != NULL) av_frame_free(&frame);
431         for(int i = 0; i < 4; i++) {
432                 if(video_dst_data[i] != NULL) av_free(video_dst_data[i]);
433                 video_dst_data[i] = NULL;
434                 video_dst_linesize[i] = 0;
435         }
436         video_mutex->unlock();
437         
438         video_dec_ctx = NULL;
439         audio_dec_ctx = NULL;
440         sws_context = NULL;
441         swr_context = NULL;
442         video_frame_count = 0;
443         duration_us = 0;
444         
445         now_playing = false;
446         now_pausing = false;
447         p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_MOVIE_LOADER, "MOVIE_LOADER: Close movie.");
448 }
449
450 double MOVIE_LOADER::get_movie_frame_rate(void)
451 {
452         return frame_rate;
453 }
454
455 int MOVIE_LOADER::get_movie_sound_rate(void)
456 {
457         return sound_rate;
458 }
459
460 uint64_t MOVIE_LOADER::get_current_frame(void)
461 {
462         return video_frame_count;
463 }
464
465 bool MOVIE_LOADER::is_playing(void)
466 {
467         return now_playing;
468 }
469
470
471 bool MOVIE_LOADER::is_pausing(void)
472 {
473         return now_pausing;
474 }
475
476
477 void MOVIE_LOADER::do_play()
478 {
479         now_playing = true;
480         now_pausing = false;
481 }
482
483 void MOVIE_LOADER::do_stop()
484 {
485         now_playing = false;
486         now_pausing = false;
487         duration_us = 0;
488         // Still not closing.
489 }
490
491 void MOVIE_LOADER::do_pause(bool flag)
492 {
493         if(now_playing) {
494                 // Pause button
495                 now_pausing = flag;
496         }
497 }
498
499 void MOVIE_LOADER::do_mute(bool left, bool right)
500 {
501         // Real Mute
502 }
503
504 void MOVIE_LOADER::do_decode_frames(int frames, int width, int height)
505 {
506         int got_frame;
507         bool end_of_frame = false;
508         int real_frames = 0;
509         double d_frames = (double)frames * (frame_rate / p_osd->vm_frame_rate());
510         if(now_pausing) return;
511         if(now_playing) duration_us = duration_us + (int64_t)((1.0e6 * (double)frames) / p_osd->vm_frame_rate());
512
513         mod_frames = mod_frames + d_frames;
514         real_frames = (int)mod_frames;
515         mod_frames = mod_frames - (double)real_frames;
516
517         if(width > 0) dst_width = width;
518         if(height > 0) dst_height = height;
519         
520         if(real_frames <= 0) {
521                 do_dequeue_audio();
522                 ///if(frames < 0) emit sig_decoding_error(MOVIE_LOADER_ILL_FRAME_NUMBER);
523                 return;
524         }
525
526         if(!now_playing || now_pausing) {
527                 uint8_t *null_sound;
528                 double t;
529                 uint32_t l;
530             t = (double)(p_cfg->sound_frequency) / frame_rate;
531                 l = 2 * sizeof(int16_t) * (int)(t + 0.5);
532                 null_sound = (uint8_t *)malloc(l);
533                 if(null_sound != NULL) {
534                         memset(null_sound, 0x00, sizeof(null_sound));
535                         emit sig_send_audio_frame(null_sound, l);
536                 }
537                 if(!now_pausing) {
538                         if(video_dst_data[0] != NULL) {
539                                 uint32_t *q;
540                                 video_mutex->lock();
541                                 for(int yy = 0; yy < dst_height; yy++) { 
542                                         q = (uint32_t *)(&(video_dst_data[0][yy * video_dst_linesize[0]]));
543                                         if((q != NULL) && (dst_width != 0)) {
544                                                 memset(q, 0x00, dst_width * sizeof(uint32_t));
545                                         }
546                                 }
547                                 video_mutex->unlock();
548                         }
549                 }
550                 return;
551         }
552         bool a_f = true;
553         bool v_f = true;
554         while(v_f || a_f) {
555                 v_f = (av_rescale_rnd(video_frame_count, 1000000000, (int64_t)(frame_rate * 1000.0), AV_ROUND_UP) < duration_us);
556                 a_f = (av_rescale_rnd(audio_total_samples, 1000000, audio_stream->codec->sample_rate, AV_ROUND_UP) < duration_us);
557                 //p_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_MOVIE_LOADER, "%lld usec. V=%lld A=%lld, %d - %d\n", duration_us, video_frame_count, audio_total_samples, v_f, a_f);
558                 if(!a_f && !v_f) break; 
559                 if(av_read_frame(fmt_ctx, &pkt) < 0) {
560                         this->close();
561                         return;
562                 }
563                 decode_packet(&got_frame, 0);
564                 if(got_frame == 0) {
565                         end_of_frame = true;
566                         break;
567                 }
568         }
569         if(end_of_frame) {
570                 // if real_frames > 1 then clear screen ?
571                 do_dequeue_audio();
572                 emit sig_movie_end(true);
573                 return;
574         }
575         do_dequeue_audio();
576         return;
577 }
578
579 void MOVIE_LOADER::get_video_frame()
580 {
581         uint32_t cacheline[8];
582         uint32_t *p;
583         uint32_t *q;
584         int xx;
585
586         QMutexLocker Locker_S(p_osd->screen_mutex);
587         QMutexLocker Locker_V(video_mutex);
588
589         if(req_transfer) {
590                 //p_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_MOVIE_LOADER, "Transfer frame: %dx%d", dst_width, dst_height);
591                 req_transfer = false;
592                 for(int yy = 0; yy < dst_height; yy++) {
593                         q = (uint32_t *)(p_osd->get_vm_screen_buffer(yy));
594 #if 1
595                         p = (uint32_t *)(&(video_dst_data[0][yy * video_dst_linesize[0]]));
596                         if((p == NULL) || (q == NULL)) break;
597                         for(xx = dst_width; xx > 7;) {
598 __DECL_VECTORIZED_LOOP
599                                 for(int i = 0; i < 8; i++) {
600                                         cacheline[i] = p[i];
601                                         q[i] = cacheline[i];
602                                 }
603                                 p += 8;
604                                 q += 8;
605                                 xx -= 8;
606                                 if(xx < 8) break;
607                         }
608                         for(; xx > 0; xx--) {
609                                 *q++ = *p++;
610                         }
611 #else
612                         //uint32_t col = 0xff000000 | (yy & 1) ? 0x00000000 : 0x00ff0000 | (yy & 2) ? 0x00000000 : 0x0000ff00 | (yy & 4) ? 0x00000000 : 0x000000ff;
613                         uint32_t col = 0xffffffff;
614                         if(q == NULL) break;
615                         for(xx = dst_width; xx > 7;) {
616 __DECL_VECTORIZED_LOOP
617                                 for(int i = 0; i < 8; i++) {
618                                         q[i] = col;
619                                 }
620                                 p += 8;
621                                 q += 8;
622                                 xx -= 8;
623                                 if(xx < 8) break;
624                         }
625                         for(; xx > 0; xx--) {
626                                 *q++ = col;
627                         }
628 #endif             
629                 }
630         }
631 }
632
633 void MOVIE_LOADER::do_seek_frame(bool relative, int frames)
634 {
635         // TODO.
636 }
637
638 void MOVIE_LOADER::do_dequeue_audio()
639 {
640         long audio_data_size = 0;
641         sound_data_queue_t *tmpq = NULL;
642         
643         snd_write_lock->lock();
644         int il = sound_data_queue.count();
645         while(il > 0) {
646                 tmpq = sound_data_queue.at(il - 1);
647                 if(tmpq != NULL) {
648                         audio_data_size += tmpq->unpadded_linesize;
649                 }
650                 il = il - 1;
651         }
652         tmpq = NULL;
653         uint8_t *tmpdata = NULL;
654         long dptr = 0;
655         if(audio_data_size > 0) {
656                 tmpdata = (uint8_t *)malloc(audio_data_size);
657                 int ii;
658                 il = sound_data_queue.count();
659                 for(ii = 0; ii < il; ii++) {
660                         tmpq = sound_data_queue.dequeue();
661                         if(tmpq != NULL) {
662                                 if(tmpq->data[0] != NULL) {
663                                         if((tmpq->unpadded_linesize != 0) && (dptr < audio_data_size)) {
664                                                 if(tmpdata != NULL) {
665                                                         my_memcpy(&tmpdata[dptr], tmpq->data[0], tmpq->unpadded_linesize);
666                                                 }
667                                                 dptr += tmpq->unpadded_linesize;
668                                         }
669                                         free(tmpq->data[0]);
670                                 }
671                                 free(tmpq);
672                         }
673                 }
674         }
675         snd_write_lock->unlock();
676         if((tmpdata != NULL) && (dptr != 0)) {
677                 //emit sig_send_audio_frame(tmpdata,dptr); // Please free arg1 after calling sound_callback of vm.
678                 //if(p_osd != NULL) p_osd->do_run_movie_audio_callback(tmpdata, dptr / (sizeof(int16_t) * 2));
679                 if(p_osd != NULL) p_osd->do_run_movie_audio_callback(tmpdata, dptr);
680         }
681 }       
682
683 void MOVIE_LOADER::do_set_enable_hwaccel_decoding(bool enable)
684 {
685         // ToDo.
686 }
687
688 void MOVIE_LOADER::do_set_enable_hwaccel_scaling(bool enable)
689 {
690         // ToDo.
691 }
692
693 void MOVIE_LOADER::do_set_dst_geometry(int width, int height)
694 {
695         if(width > 0) dst_width = width;
696         if(height > 0) dst_height = height;
697 }
698
699 void MOVIE_LOADER::do_set_dst_pixfmt(int type)
700 {
701         // ToDo.
702 }