Fix coverity issue
[platform/core/multimedia/libmm-fileinfo.git] / formats / ffmpeg / mm_file_format_ffmpeg.c
1 /*
2  * libmm-fileinfo
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Haejeong Kim <backto.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include <libavformat/avformat.h>
26 #include <libavcodec/avcodec.h>
27 #include <libavutil/imgutils.h>
28 #include <libswscale/swscale.h>
29 #include <mm_error.h>
30 #include <mm_types.h>
31 #include "mm_file_debug.h"
32 #include "mm_file_formats.h"
33 #include "mm_file_utils.h"
34 #include "mm_file_format_ffmpeg.h"
35
36 static int g_max_analyze_duration = 0;
37 static int g_probesize = 0;
38
39 #ifdef __MMFILE_TEST_MODE__
40 static void _dump_av_packet(AVPacket *pkt)
41 {
42         debug_msg(RELEASE, "--------- AV Packet -----------");
43         debug_msg(RELEASE, " pts: %lld", pkt->pts);
44         debug_msg(RELEASE, " dts: %lld", pkt->dts);
45         debug_msg(RELEASE, " data: %p", pkt->data);
46         debug_msg(RELEASE, " size: %d", pkt->size);
47         debug_msg(RELEASE, " stream_index: %d", pkt->stream_index);
48         debug_msg(RELEASE, " flags: 0x%08X, %s", pkt->flags, (pkt->flags & AV_PKT_FLAG_KEY) ? "Keyframe" : "_");
49         debug_msg(RELEASE, " duration: %lld", pkt->duration);
50         /*debug_msg(RELEASE, " destruct: %p", pkt->destruct);*/
51         /*debug_msg(RELEASE, " priv: %p", pkt->priv);*/
52         debug_msg(RELEASE, " pos: %lld", pkt->pos);
53         debug_msg(RELEASE, "-------------------------------");
54 }
55 #endif
56
57 static int      _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, AVFrame **pFrame, int cdis);
58
59 static int __convert_vidio_codec_type(int AVVideoCodecID)
60 {
61         switch (AVVideoCodecID) {
62         case AV_CODEC_ID_MPEG1VIDEO:
63                 return MM_VIDEO_CODEC_MPEG1;
64         case AV_CODEC_ID_MPEG2VIDEO:  /*/< preferred ID for MPEG-1/2 video decoding */
65         case AV_CODEC_ID_MPEG2TS:
66                 return MM_VIDEO_CODEC_MPEG2;
67         case AV_CODEC_ID_H261:
68                 return MM_VIDEO_CODEC_H261;
69         case AV_CODEC_ID_H263:
70                 return MM_VIDEO_CODEC_H263;
71         case AV_CODEC_ID_MPEG4:
72         case AV_CODEC_ID_MSMPEG4V1:
73         case AV_CODEC_ID_MSMPEG4V2:
74         case AV_CODEC_ID_MSMPEG4V3:
75                 return MM_VIDEO_CODEC_MPEG4;
76         case AV_CODEC_ID_WMV1:
77         case AV_CODEC_ID_WMV2:
78                 return MM_VIDEO_CODEC_WMV;
79         case AV_CODEC_ID_H263P:
80         case AV_CODEC_ID_H263I:
81                 return MM_VIDEO_CODEC_H263;
82         case AV_CODEC_ID_FLV1:
83                 return MM_VIDEO_CODEC_FLV;
84         case AV_CODEC_ID_H264:
85                 return MM_VIDEO_CODEC_H264;
86         case AV_CODEC_ID_INDEO2:
87         case AV_CODEC_ID_INDEO3:
88         case AV_CODEC_ID_INDEO4:
89         case AV_CODEC_ID_INDEO5:
90                 return MM_VIDEO_CODEC_INDEO;
91         case AV_CODEC_ID_THEORA:
92                 return MM_VIDEO_CODEC_THEORA;
93         case AV_CODEC_ID_CINEPAK:
94                 return MM_VIDEO_CODEC_CINEPAK;
95         case AV_CODEC_ID_VC1:
96                 return MM_VIDEO_CODEC_VC1;
97         case AV_CODEC_ID_WMV3:
98                 return MM_VIDEO_CODEC_WMV;
99         case AV_CODEC_ID_AVS:
100                 return MM_VIDEO_CODEC_AVS;
101         case AV_CODEC_ID_RL2:
102         case AV_CODEC_ID_RV10:  /* RealVideo 1 */
103         case AV_CODEC_ID_RV20:  /* RealVideo 2 */
104         case AV_CODEC_ID_RV30:  /* RealVideo 3 */
105         case AV_CODEC_ID_RV40:  /* RealVideo 4 */
106                 return MM_VIDEO_CODEC_REAL;
107         case AV_CODEC_ID_AV1:   /* AOMedia Video 1 */
108                 return MM_VIDEO_CODEC_AV1;
109         case AV_CODEC_ID_HEVC:
110                 return MM_VIDEO_CODEC_MPEG4;
111 #ifdef USE_CODEC_VPX
112         case AV_CODEC_ID_VP8:
113                 return MM_VIDEO_CODEC_VP8;
114         case AV_CODEC_ID_VP9:
115                 return MM_VIDEO_CODEC_VP9;
116 #endif
117         default:
118                 return MM_VIDEO_CODEC_NONE;
119         }
120 }
121
122 static int __convert_audio_codec_type(int AVAudioCodecID)
123 {
124         switch (AVAudioCodecID) {
125         case AV_CODEC_ID_AMR_NB:
126         case AV_CODEC_ID_AMR_WB:
127                 return MM_AUDIO_CODEC_AMR;
128         /* RealAudio codecs*/
129         case AV_CODEC_ID_RA_144:        /* RealAudio 1 */
130         case AV_CODEC_ID_RA_288:        /* RealAudio 2 */
131         case AV_CODEC_ID_COOK:          /* RealAudio 6 */
132                 return MM_AUDIO_CODEC_REAL;
133         case AV_CODEC_ID_MP2:
134                 return MM_AUDIO_CODEC_MP2;
135         case AV_CODEC_ID_MP3:
136         case AV_CODEC_ID_MP3ADU:
137         case AV_CODEC_ID_MP3ON4:
138                 return MM_AUDIO_CODEC_MP3;
139         case AV_CODEC_ID_AAC:
140                 return MM_AUDIO_CODEC_AAC;
141         case AV_CODEC_ID_AC3:
142                 return MM_AUDIO_CODEC_AC3;
143         case AV_CODEC_ID_VORBIS:
144                 return MM_AUDIO_CODEC_VORBIS;
145         case AV_CODEC_ID_WMAV1:
146         case AV_CODEC_ID_WMAV2:
147         case AV_CODEC_ID_WMAVOICE:
148         case AV_CODEC_ID_WMAPRO:
149         case AV_CODEC_ID_WMALOSSLESS:
150                 return MM_AUDIO_CODEC_WMA;
151         case AV_CODEC_ID_FLAC:
152                 return MM_AUDIO_CODEC_FLAC;
153         case AV_CODEC_ID_ALAC:
154                 return MM_AUDIO_CODEC_ALAC;
155         case AV_CODEC_ID_WAVPACK:
156                 return MM_AUDIO_CODEC_WAVE;
157         case AV_CODEC_ID_ATRAC3:
158         case AV_CODEC_ID_ATRAC3P:
159         case AV_CODEC_ID_EAC3:
160                 return MM_AUDIO_CODEC_AC3;
161         case AV_CODEC_ID_PCM_S8:
162         case AV_CODEC_ID_PCM_S16BE:
163         case AV_CODEC_ID_PCM_S24BE:
164         case AV_CODEC_ID_PCM_S32BE:
165                 return MM_AUDIO_CODEC_PCM;
166         default:
167                 return MM_AUDIO_CODEC_NONE;
168         }
169 }
170
171 /* plugin manadatory API */
172 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext);
173 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
174 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext);
175 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext);
176
177 static void __count_stream_num(AVFormatContext *pFormatCtx, MMFileFormatContext *formatContext)
178 {
179         unsigned int i = 0;
180
181         formatContext->videoTotalTrackNum = 0;
182         formatContext->audioTotalTrackNum = 0;
183
184         for (i = 0; i < pFormatCtx->nb_streams; i++) {
185                 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
186                         debug_msg(RELEASE, "FFMPEG video codec id: 0x%08X", pFormatCtx->streams[i]->codecpar->codec_id);
187
188                         AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
189                         if ((pkt.data != NULL) && (pkt.size > 0))
190                                 continue;
191
192                         /*eventhough codec_id is 0, avformat_find_stream_info() can find proper codec_id. */
193                         formatContext->videoTotalTrackNum += 1;
194                 }
195                 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
196                         debug_msg(RELEASE, "FFMPEG audio codec id: 0x%08X", pFormatCtx->streams[i]->codecpar->codec_id);
197                         formatContext->audioTotalTrackNum += 1;
198                 }
199         }
200 }
201
202 static bool __mmf_mem_open(MMFmemIOHandle **handle, const char *filename)
203 {
204         MMFmemIOHandle *memHandle = NULL;
205         char **splitedString = NULL;
206
207         filename += strlen(MMFILE_MEM_URI);
208         splitedString = g_strsplit(filename, ":", -1);
209
210         if (g_strv_length(splitedString) < 2) {
211                 debug_error(DEBUG, "invalid param");
212                 g_strfreev(splitedString);
213
214                 return false;
215         }
216
217         memHandle = g_new0(MMFmemIOHandle, 1);
218
219         /*memory allocation address changed. memHandle->ptr = (unsigned char*)atoi(splitedString[0]); */
220         memHandle->ptr = (unsigned char *)atoll(splitedString[0]);
221         memHandle->size = atoi(splitedString[1]);
222         memHandle->offset = 0;
223         memHandle->state = 0;
224
225         *handle = memHandle;
226
227         g_strfreev(splitedString);
228
229         return true;
230 }
231
232 static int __mmf_mem_read(void *opaque, uint8_t *buf, int size)
233 {
234         MMFmemIOHandle *memHandle = NULL;
235         const unsigned char *c = NULL;
236         int len = 0;
237
238         mm_file_retvm_if_fails(DEBUG, opaque, MMFILE_UTIL_FAIL);
239         mm_file_retvm_if_fails(DEBUG, buf, MMFILE_UTIL_FAIL);
240
241         memHandle = opaque;
242
243         mm_file_retvm_if_fails(DEBUG, memHandle->ptr, MMFILE_UTIL_FAIL);
244         mm_file_retvm_if_fails(DEBUG, memHandle->offset < memHandle->size, MMFILE_UTIL_FAIL);
245
246         c = memHandle->ptr + memHandle->offset;
247
248         if (memHandle->state != EOF) {
249                 len = size;
250                 if (len + memHandle->offset > memHandle->size)
251                         len = memHandle->size - memHandle->offset;
252         }
253
254         memcpy(buf, c, len);
255         memHandle->offset += len;
256
257         if (memHandle->offset == memHandle->size)
258                 memHandle->state = EOF;
259
260         return len;
261 }
262
263 static int64_t __mmf_mem_seek(void *opaque, int64_t pos, int whence)
264 {
265         MMFmemIOHandle *memHandle = NULL;
266         long long tmp_offset = 0;
267
268         mm_file_retvm_if_fails(DEBUG, opaque, MMFILE_UTIL_FAIL);
269
270         memHandle = opaque;
271
272         switch (whence) {
273         case SEEK_SET:
274                 tmp_offset = 0 + pos;
275                 break;
276         case SEEK_CUR:
277                 tmp_offset = memHandle->offset + pos;
278                 break;
279         case SEEK_END:
280                 tmp_offset = memHandle->size + pos;
281                 break;
282         case AVSEEK_SIZE:       /*FFMPEG specific*/
283                 return memHandle->size;
284         default:
285                 return MMFILE_UTIL_FAIL;
286         }
287
288         /*check validation*/
289         mm_file_retvm_if_fails(DEBUG, tmp_offset >= 0 && tmp_offset <= memHandle->size, MMFILE_UTIL_FAIL);
290
291         /*set */
292         memHandle->state = (tmp_offset >= memHandle->size) ? EOF : !EOF;
293         memHandle->offset = (unsigned int) tmp_offset;
294
295         return tmp_offset;
296 }
297
298
299 int mmfile_format_open_ffmpg(MMFileFormatContext *formatContext)
300 {
301         AVFormatContext     *pFormatCtx = NULL;
302         AVInputFormat       *grab_iformat = NULL;
303         char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0, };
304         AVIOContext          *pIOCtx = NULL;
305         MMFmemIOHandle *handle = NULL;
306         uint8_t *avio_ctx_buffer = NULL;
307
308         formatContext->ReadStream   = mmfile_format_read_stream_ffmpg;
309         formatContext->ReadFrame    = mmfile_format_read_frame_ffmpg;
310         formatContext->ReadTag      = mmfile_format_read_tag_ffmpg;
311         formatContext->Close        = mmfile_format_close_ffmpg;
312
313         debug_msg(RELEASE, "ffmpeg version: %d", avformat_version());
314         /**
315          * FFMPEG DEBUG LEVEL
316          *  AV_LOG_QUIET -1
317          *  AV_LOG_FATAL 0
318          *  AV_LOG_ERROR 0
319          *  AV_LOG_WARNING 1
320          *  AV_LOG_INFO 1
321          *  AV_LOG_VERBOSE 1
322          *  AV_LOG_DEBUG 2
323          */
324 #ifdef __MMFILE_TEST_MODE__
325         av_log_set_level(AV_LOG_TRACE);
326 #else
327         av_log_set_level(AV_LOG_QUIET);
328 #endif
329
330         if (formatContext->filesrc->type  == MM_FILE_SRC_TYPE_MEMORY) {
331                 if (mmfile_util_get_ffmpeg_format(formatContext->filesrc->memory.format, ffmpegFormatName) != MMFILE_UTIL_SUCCESS) {
332                         debug_error(DEBUG, "error: mmfile_util_get_ffmpeg_format");
333                         return MMFILE_FORMAT_FAIL;
334                 }
335
336                 grab_iformat = av_find_input_format(ffmpegFormatName);
337                 mm_file_retvm_if_fails(DEBUG, grab_iformat, MMFILE_UTIL_FAIL);
338
339                 avio_ctx_buffer = av_malloc(MMFILE_AVIO_BUFFER_LEN);
340                 mm_file_retvm_if_fails(DEBUG, avio_ctx_buffer, MMFILE_UTIL_FAIL);
341
342                 if (!__mmf_mem_open(&handle, formatContext->uriFileName)) {
343                         debug_error(DEBUG, "failed to _mmf_mem_open.");
344                         goto exception;
345                 }
346
347                 pIOCtx = avio_alloc_context(avio_ctx_buffer, MMFILE_AVIO_BUFFER_LEN, 0, handle, __mmf_mem_read, NULL, __mmf_mem_seek);
348                 if (!pIOCtx) {
349                         debug_error(DEBUG, "error: cannot alloc io context");
350                         goto exception;
351                 }
352
353                 pFormatCtx = avformat_alloc_context();
354                 if (!pFormatCtx) {
355                         debug_error(DEBUG, "failed to avformat_alloc_context");
356                         goto exception;
357                 }
358
359                 pFormatCtx->pb = pIOCtx;
360
361                 if (avformat_open_input(&pFormatCtx, "", grab_iformat, NULL) < 0) {
362                         debug_error(DEBUG, "error: cannot open %s", formatContext->uriFileName);
363                         goto exception;
364                 }
365
366                 formatContext->privateFormatData = pFormatCtx;
367         }
368
369         if (formatContext->filesrc->type  == MM_FILE_SRC_TYPE_FILE) {
370                 if (avformat_open_input(&pFormatCtx, formatContext->filesrc->file.path, NULL, NULL) < 0) {
371                         debug_error(DEBUG, "error: cannot open %s", formatContext->filesrc->file.path);
372                         goto exception;
373                 }
374
375                 formatContext->privateFormatData = pFormatCtx;
376         }
377
378         if (!pFormatCtx) {
379                 debug_warning(DEBUG, "failed to find av stream. maybe corrupted data.");
380                 goto exception;
381         }
382
383         debug_msg(RELEASE, "number of stream: %d", pFormatCtx->nb_streams);
384
385         __count_stream_num(pFormatCtx, formatContext);
386
387         debug_msg(RELEASE, "format: %s (%s)", pFormatCtx->iformat->name, pFormatCtx->iformat->long_name);
388 #ifdef __MMFILE_TEST_MODE__
389         av_dump_format(pFormatCtx, 0, formatContext->filesrc->file.path, 0);
390 #endif
391
392         return MMFILE_FORMAT_SUCCESS;
393
394 exception: /* fail to get content information */
395         if (formatContext->filesrc->type  == MM_FILE_SRC_TYPE_MEMORY) {
396                 if (avio_ctx_buffer)
397                         av_free(avio_ctx_buffer);
398
399                 mmfile_free(handle);
400
401                 if (pIOCtx)
402                         av_free(pIOCtx);
403                 if (pFormatCtx)
404                         avformat_close_input(&pFormatCtx);
405         } else {
406                 mmfile_format_close_ffmpg(formatContext);
407         }
408
409         formatContext->privateFormatData = NULL;
410
411         return MMFILE_FORMAT_FAIL;
412 }
413
414 static int __get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
415 {
416         double fps, round;
417
418         debug_msg(RELEASE, "frame count: %d, dur: %d, num: %d, den: %d", frame_cnt, duration, r_frame_rate.num, r_frame_rate.den);
419
420         if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
421                 return 0;
422
423         round = (is_roundup != 0 ? 0.50f : 0.00f);
424
425         fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
426
427         return (int)fps;
428 }
429
430 static bool __check_uhqa(int sample_rate, enum AVSampleFormat sample_fmt_info)
431 {
432         debug_error(RELEASE, "[sample rate %d, sample format %d]", sample_rate, sample_fmt_info);
433
434         if (sample_rate >= 44100 && sample_fmt_info >= AV_SAMPLE_FMT_S32) {
435                 debug_msg(RELEASE, "UHQA CONTENT");
436                 return true;
437         }
438
439         return false;
440 }
441
442 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext)
443 {
444         AVFormatContext *pFormatCtx = NULL;
445         AVCodecParameters *pAudioCodecCtx = NULL;
446         AVCodecParameters *pVideoCodecCtx = NULL;
447         MMFileFormatStream *videoStream = NULL;
448         MMFileFormatStream *audioStream = NULL;
449         unsigned int i = 0;
450
451         mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
452         mm_file_retvm_if_fails(DEBUG, formatContext->privateFormatData, MMFILE_FORMAT_FAIL);
453
454         pFormatCtx = formatContext->privateFormatData;
455         pFormatCtx->start_time = -1;
456
457         /**
458          * If you could not find codec parameters for stream info,
459          * consider increasing the value for the 'analyzeduration' and 'probesize' options.
460          */
461         /**
462          *@important if data is corrupted, occur segment fault by av_find_stream_info().
463          *                      - fixed 2009-06-25.
464          */
465         /**
466          * fixed 2021-11-09
467          * if the content is 8k, the mem-usage in avformat_find_stream_info() is too large, 300MB or more.
468          * so we adjust 'probesize' to reduce memory usage in avformat_find_stream_info().
469          * Please refer to below for detail.
470          * https://ffmpeg.org/ffmpeg-formats.html#Format-Options
471          */
472         if (g_max_analyze_duration == 0)
473                 g_max_analyze_duration = mmfile_get_int_from_ini(MMFILE_INI_MAXANLDURATION, MMFILE_DEFAULT_MAXANLDURATION);
474         if (g_probesize == 0)
475                 g_probesize = mmfile_get_int_from_ini(MMFILE_INI_PROBESIZE, MMFILE_DEFAULT_PROBESIZE);
476
477         if (formatContext->formatType == MM_FILE_FORMAT_M2TS)
478                 pFormatCtx->max_analyze_duration = g_max_analyze_duration;      // MPEGTS file timeout set
479         else
480                 pFormatCtx->probesize = g_probesize;    // the size of the data(packet) to probe stream information
481
482         debug_msg(RELEASE, "max_analyze_duration: %"PRId64", probesize: %"PRId64"", pFormatCtx->max_analyze_duration, pFormatCtx->probesize);
483
484         if (formatContext->cdis != 1) {
485                 if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
486                         debug_warning(DEBUG, "failed to find stream info");
487                         goto exception;
488                 }
489         }
490
491         debug_msg(RELEASE, "FFMPEG: dur %"PRId64", start %"PRId64"", pFormatCtx->duration, pFormatCtx->start_time);
492
493         /**
494          *@note asf has long duration bug. and Some content's start time is wrong(negative number).
495          * Generally, mpegts has wrong start time(positive large value). So skip start time for mpegts format.
496          */
497         if (pFormatCtx->start_time < 0 || formatContext->formatType == MM_FILE_FORMAT_M2TS) {
498                 debug_warning(DEBUG, "Wrong Start time = %"PRId64"", pFormatCtx->start_time);
499                 formatContext->duration = (long long)(pFormatCtx->duration) * 1000 / AV_TIME_BASE;
500         } else {
501                 formatContext->duration = (long long)(pFormatCtx->duration + pFormatCtx->start_time) * 1000 / AV_TIME_BASE;
502         }
503
504         formatContext->videoStreamId = -1;
505         formatContext->audioStreamId = -1;
506         formatContext->nbStreams = 0;
507         formatContext->videoTotalTrackNum = 0;
508         formatContext->audioTotalTrackNum = 0;
509
510         for (i = 0; i < pFormatCtx->nb_streams; i++) {
511                 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && formatContext->videoStreamId == -1) {
512                         videoStream = g_new0(MMFileFormatStream, 1);
513
514                         videoStream->streamType = MMFILE_VIDEO_STREAM;
515                         formatContext->streams[MMFILE_VIDEO_STREAM] = videoStream;
516                         formatContext->nbStreams += 1;
517                         formatContext->videoStreamId = i;
518                         formatContext->videoTotalTrackNum += 1;
519
520                         pVideoCodecCtx = pFormatCtx->streams[i]->codecpar;
521                         if (pVideoCodecCtx) {
522                                 videoStream->codecId            = __convert_vidio_codec_type(pVideoCodecCtx->codec_id);
523                                 if (videoStream->codecId == MM_VIDEO_CODEC_NONE) {
524                                         debug_error(RELEASE, "Proper codec is not found in [%d] stream", i);
525                                         formatContext->videoStreamId = -1;
526                                         mmfile_free(videoStream);
527                                         formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
528                                         videoStream = NULL;
529                                         continue;
530                                 }
531
532                                 /**
533                                  * Get FPS
534                                  * 1. try to get average fps of video stream.
535                                  * 2. if (1) failed, try to get fps of media container.
536                                  */
537                                 videoStream->framePerSec        = __get_video_fps(pFormatCtx->streams[i]->nb_frames,
538                                                                                         pFormatCtx->streams[i]->duration,
539                                                                                         pFormatCtx->streams[i]->time_base,
540                                                                                         1);
541
542                                 if (videoStream->framePerSec == 0) {
543                                         if ((int)av_q2d(pFormatCtx->streams[i]->avg_frame_rate) != 0)
544                                                 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->avg_frame_rate);
545                                         else
546                                                 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->r_frame_rate);
547                                 }
548
549                                 videoStream->width                      = pVideoCodecCtx->width;
550                                 videoStream->height                     = pVideoCodecCtx->height;
551                                 videoStream->bitRate            = pVideoCodecCtx->bit_rate;
552                         }
553                 } else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && formatContext->audioStreamId == -1) {
554                         audioStream = g_new0(MMFileFormatStream, 1);
555
556                         audioStream->streamType = MMFILE_AUDIO_STREAM;
557                         formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
558                         formatContext->nbStreams += 1;
559                         formatContext->audioStreamId = i;
560                         formatContext->audioTotalTrackNum += 1;
561
562                         pAudioCodecCtx = pFormatCtx->streams[i]->codecpar;
563                         if (pAudioCodecCtx) {
564                                 audioStream->codecId            = __convert_audio_codec_type(pAudioCodecCtx->codec_id);
565                                 audioStream->bitRate            = pAudioCodecCtx->bit_rate;
566                                 audioStream->nbChannel          = pAudioCodecCtx->channels;
567                                 audioStream->samplePerSec       = pAudioCodecCtx->sample_rate;
568                                 audioStream->bitPerSample       = pAudioCodecCtx->bits_per_coded_sample;
569                                 audioStream->is_uhqa = __check_uhqa(audioStream->samplePerSec, pFormatCtx->streams[i]->codecpar->format);
570                         }
571                 }
572         }
573
574         if (formatContext->nbStreams == 0) {
575                 debug_error(DEBUG, "error: there is no audio and video track");
576                 goto exception;
577         }
578
579 #ifdef __MMFILE_TEST_MODE__
580         mmfile_format_print_contents(formatContext);
581 #endif
582
583         return MMFILE_FORMAT_SUCCESS;
584
585 exception:
586         mmfile_free(videoStream);
587         mmfile_free(audioStream);
588
589         formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
590         formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
591
592         if (pFormatCtx) {
593                 avformat_close_input(&pFormatCtx);
594                 formatContext->privateFormatData = NULL;
595         }
596
597         formatContext->audioTotalTrackNum = 0;
598         formatContext->videoTotalTrackNum = 0;
599         formatContext->nbStreams = 0;
600
601         return MMFILE_FORMAT_FAIL;
602 }
603
604 #define DATA_LENGTH 4
605
606 static void __fill_picture_in_context(char *value, MMFileFormatContext *formatContext)
607 {
608         gsize len = 0;
609         guchar *meta_data = NULL;
610         int current_pos = DATA_LENGTH;
611         unsigned char current_data[DATA_LENGTH] = {0, };
612
613         meta_data = g_base64_decode(value, &len);
614         if (!meta_data) {
615                 debug_log(RELEASE, "no picture");
616                 return;
617         }
618
619         /* get mime_type */
620         memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
621         len = MMFILE_CONVERT_INT(current_data);
622
623         current_pos += DATA_LENGTH;
624         mmfile_free(formatContext->artworkMime);
625         formatContext->artworkMime = g_strndup((const char *)meta_data + current_pos, len);
626
627         /* get description */
628         current_pos += len;
629         memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
630         len = MMFILE_CONVERT_INT(current_data);
631
632         /* get picture data */
633         current_pos += len + (DATA_LENGTH * 5);
634         memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
635         len = MMFILE_CONVERT_INT(current_data);
636
637         formatContext->artworkSize = len;
638
639         current_pos += DATA_LENGTH;
640         mmfile_free(formatContext->artwork);
641         formatContext->artwork = g_memdup2(meta_data + current_pos, formatContext->artworkSize);
642         g_free(meta_data);
643 }
644
645 static void __fill_artwork_in_context(AVStream *st, MMFileFormatContext *formatContext)
646 {
647         AVPacket pkt = st->attached_pic;
648         int codec_id = st->codecpar->codec_id;
649
650         if (!pkt.data || pkt.size <= 0)
651                 return;
652
653         /*Set mime type*/
654         mmfile_free(formatContext->artworkMime);
655
656         if (codec_id == AV_CODEC_ID_MJPEG)
657                 formatContext->artworkMime = g_strdup("image/jpeg");
658         else if (codec_id == AV_CODEC_ID_PNG)
659                 formatContext->artworkMime = g_strdup("image/png");
660         else if (codec_id == AV_CODEC_ID_BMP)
661                 formatContext->artworkMime = g_strdup("image/bmp");
662         else
663                 debug_error(DEBUG, "Unknown cover type: 0x%x", codec_id);
664
665         /*Copy artwork*/
666         mmfile_free(formatContext->artwork);
667
668         formatContext->artworkSize = pkt.size;
669         formatContext->artwork = g_memdup2(pkt.data, pkt.size);
670 }
671
672 static void __fill_metainfo_in_context(AVDictionary *metainfo, MMFileFormatContext *formatContext)
673 {
674         AVDictionaryEntry *tag = NULL;
675
676         while ((tag = av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) {
677                 if (!tag->key)
678                         continue;
679
680                 if (!g_ascii_strcasecmp(tag->key, "title")) {
681                         mmfile_free(formatContext->title);
682                         formatContext->title = g_strdup(tag->value);
683                 } else if (!g_ascii_strcasecmp(tag->key, "artist")) {
684                         mmfile_free(formatContext->artist);
685                         formatContext->artist = g_strdup(tag->value);
686                 } else if (!g_ascii_strcasecmp(tag->key, "composer")) {
687                         mmfile_free(formatContext->composer);
688                         formatContext->composer = g_strdup(tag->value);
689                 } else if (!g_ascii_strcasecmp(tag->key, "album")) {
690                         mmfile_free(formatContext->album);
691                         formatContext->album = g_strdup(tag->value);
692                 } else if (!g_ascii_strcasecmp(tag->key, "album_artist")) {
693                         mmfile_free(formatContext->album_artist);
694                         formatContext->album_artist = g_strdup(tag->value);
695                 } else if (!g_ascii_strcasecmp(tag->key, "copyright")) {
696                         mmfile_free(formatContext->copyright);
697                         formatContext->copyright = g_strdup(tag->value);
698                 } else if (!g_ascii_strcasecmp(tag->key, "comment")) {
699                         mmfile_free(formatContext->comment);
700                         formatContext->comment = g_strdup(tag->value);
701                 } else if (!g_ascii_strcasecmp(tag->key, "description")) {
702                         mmfile_free(formatContext->description);
703                         formatContext->description = g_strdup(tag->value);
704                 } else if (!g_ascii_strcasecmp(tag->key, "genre")) {
705                         mmfile_free(formatContext->genre);
706                         formatContext->genre = g_strdup(tag->value);
707                 } else if (!g_ascii_strcasecmp(tag->key, "date")) {
708                         mmfile_free(formatContext->year);
709                         formatContext->year = g_strdup(tag->value);
710                 } else if (!g_ascii_strcasecmp(tag->key, "creation_time")) {
711                         mmfile_free(formatContext->recDate);
712                         formatContext->recDate = g_strdup(tag->value);
713                 } else if ((!g_ascii_strcasecmp(tag->key, "track")) || (!g_ascii_strcasecmp(tag->key, "tracknumber"))) {
714                         mmfile_free(formatContext->tagTrackNum);
715                         formatContext->tagTrackNum = g_strdup(tag->value);
716                 } else if (!g_ascii_strcasecmp(tag->key, "lyrics")) {
717                         mmfile_free(formatContext->unsyncLyrics);
718                         formatContext->unsyncLyrics = g_strdup(tag->value);
719                 } else if (!g_ascii_strcasecmp(tag->key, "rotate")) {   /*can be "90", "180", "270" */
720                         mmfile_free(formatContext->rotate);
721                         formatContext->rotate = g_strdup(tag->value);
722                 } else if (!g_ascii_strcasecmp(tag->key, "spherical-video")) {
723                         ParseSpatialVideoMetadataFromXMLString(tag->value, formatContext);
724                 } else if (!g_ascii_strcasecmp(tag->key, "metadata_block_picture")) {
725                         __fill_picture_in_context(tag->value, formatContext);
726                 } else {
727                         debug_log(RELEASE, "Not support metadata. [%s:%s]", tag->key, tag->value);
728                 }
729         }
730 }
731
732
733 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext)
734 {
735         AVFormatContext *pFormatCtx = NULL;
736         unsigned int idx = 0;
737
738         mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
739         mm_file_retvm_if_fails(DEBUG, formatContext->privateFormatData, MMFILE_FORMAT_FAIL);
740
741         if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4)
742                 MMFileUtilGetMetaDataFromMP4(formatContext);
743
744         if (formatContext->formatType == MM_FILE_FORMAT_MATROSKA)
745                 MMFileUtilGetMetaDataFromMKV(formatContext);
746
747         pFormatCtx = formatContext->privateFormatData;
748
749         /*metadata extracted by ffmpeg*/
750         for (idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) {
751                 AVDictionary *metainfo = NULL;
752                 AVStream *st = NULL;
753
754                 /* Check metadata of normal stream like audio, video, video cover art
755                  * (cover art saved in new stream). refer to mov_read_covr() in ffmpeg.
756                  */
757                 if (idx < pFormatCtx->nb_streams) {
758                         st = pFormatCtx->streams[idx];
759                         if (st != NULL)
760                                 metainfo = st->metadata;
761                 } else {        /*Check metadata of Content */
762                         if (pFormatCtx->metadata != NULL) {
763                                 metainfo = pFormatCtx->metadata;
764                         } else {
765                                 continue;
766                         }
767                 }
768
769                 /*refer to mov_read_covr() in ffmpeg.*/
770                 if (st)
771                         __fill_artwork_in_context(st, formatContext);
772
773                 if (metainfo)
774                         __fill_metainfo_in_context(metainfo, formatContext);
775
776 #ifdef __MMFILE_TEST_MODE__
777                 mmfile_format_print_tags(formatContext);
778 #endif
779         }
780
781         return MMFILE_FORMAT_SUCCESS;
782 }
783
784 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
785 {
786         AVFormatContext *pFormatCtx = NULL;
787         AVCodecContext *pVideoCodecCtx = NULL;
788         AVCodec *pVideoCodec = NULL;
789         AVCodecParameters *pVideoCodecPar = NULL;
790         AVFrame *pFrame = NULL;
791         struct SwsContext *img_convert_ctx = NULL;
792
793         int width = 0;
794         int height = 0;
795         int numBytes = 0;
796         int ret = 0;
797
798         mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
799         mm_file_retvm_if_fails(DEBUG, formatContext->privateFormatData, MMFILE_FORMAT_FAIL);
800         mm_file_retvm_if_fails(DEBUG, formatContext->videoTotalTrackNum > 0, MMFILE_FORMAT_FAIL);
801         mm_file_retvm_if_fails(DEBUG, frame, MMFILE_FORMAT_FAIL);
802
803         pFormatCtx = formatContext->privateFormatData;
804
805         mm_file_retvm_if_fails(DEBUG, formatContext->videoStreamId != -1, MMFILE_FORMAT_FAIL);
806
807         pVideoCodecPar = pFormatCtx->streams[formatContext->videoStreamId]->codecpar;
808         mm_file_retvm_if_fails(DEBUG, pVideoCodecPar, MMFILE_FORMAT_FAIL);
809
810         pVideoCodec = avcodec_find_decoder(pVideoCodecPar->codec_id);
811         mm_file_retvm_if_fails(DEBUG, pVideoCodec, MMFILE_FORMAT_FAIL);
812
813         pVideoCodecCtx = avcodec_alloc_context3(pVideoCodec);
814         mm_file_retvm_if_fails(DEBUG, pVideoCodecCtx, MMFILE_FORMAT_FAIL);
815
816         if (avcodec_parameters_to_context(pVideoCodecCtx, pVideoCodecPar) < 0) {
817                 debug_error(DEBUG, "error: avcodec_parameters_to_context");
818                 avcodec_free_context(&pVideoCodecCtx);
819                 return MMFILE_FORMAT_FAIL;
820         }
821
822         debug_msg(RELEASE, "flag: 0x%08X", pVideoCodec->capabilities);
823         /* debug_msg(RELEASE, "  DRAW_HORIZ_BAND : %d", pVideoCodec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND ? 1 : 0); */
824         /* debug_msg(RELEASE, "  DR1             : %d", pVideoCodec->capabilities & CODEC_CAP_DR1 ? 1 : 0); */
825         /* debug_msg(RELEASE, "  PARSE_ONLY      : %d", pVideoCodec->capabilities & CODEC_CAP_PARSE_ONLY ? 1 : 0); */
826         /* debug_msg(RELEASE, "  TRUNCATED       : %d", pVideoCodec->capabilities & CODEC_CAP_TRUNCATED ? 1 : 0); */
827         /* debug_msg(RELEASE, "  HWACCEL         : %d", pVideoCodec->capabilities & CODEC_CAP_HWACCEL ? 1 : 0); */
828         /* debug_msg(RELEASE, "  DELAY           : %d", pVideoCodec->capabilities & CODEC_CAP_DELAY ? 1 : 0); */
829         /* debug_msg(RELEASE, "  SMALL_LAST_FRAME: %d", pVideoCodec->capabilities & CODEC_CAP_SMALL_LAST_FRAME ? 1 : 0); */
830         /* debug_msg(RELEASE, "  HWACCEL_VDPAU   : %d", pVideoCodec->capabilities & CODEC_CAP_HWACCEL_VDPAU ? 1 : 0); */
831
832         if (pVideoCodec->capabilities & AV_CODEC_CAP_TRUNCATED)
833                 pVideoCodecCtx->flags |= AV_CODEC_FLAG_TRUNCATED;
834
835         /*set workaround bug flag*/
836         pVideoCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
837
838         /* this is solution for PLM issue P13091703323 */
839         /* If using thread when decoding frame, the result of decoding is not always same.
840             Thumbnail of video content is different with original file when copying file. */
841         pVideoCodecCtx->thread_type = 0;
842         pVideoCodecCtx->thread_count = 0;
843         if (avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL) < 0) {
844                 debug_error(DEBUG, "error: avcodec_open fail.");
845                 return MMFILE_FORMAT_FAIL;
846         }
847
848         /* search & decode */
849         ret = _get_first_good_video_frame(pFormatCtx, pVideoCodecCtx, &pFrame, formatContext->cdis);
850         if (ret != MMFILE_FORMAT_SUCCESS) {
851                 debug_error(DEBUG, "error: get key frame");
852                 goto EXCEPTION;
853         }
854
855         debug_msg(RELEASE, "Video default resolution = [%dx%d]", pVideoCodecCtx->coded_width, pVideoCodecCtx->coded_height);
856         debug_msg(RELEASE, "Video coded resolution = [%dx%d]", pVideoCodecCtx->width, pVideoCodecCtx->height);
857
858         if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
859                 width = pVideoCodecCtx->coded_width;
860                 height = pVideoCodecCtx->coded_height;
861         } else {
862                 width = pVideoCodecCtx->width;
863                 height = pVideoCodecCtx->height;
864         }
865
866         numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, width, height, 1);
867         if (numBytes <= 0) {
868                 debug_error(DEBUG, "error: av_image_get_buffer_size. [%d x %d]", width, height);
869                 goto EXCEPTION;
870         }
871
872         frame->frameData = av_malloc(numBytes);
873         if (!frame->frameData) {
874                 debug_error(DEBUG, "error: av_malloc.");
875                 goto EXCEPTION;
876         }
877
878         uint8_t *dst_data[4];
879         int dst_linesize[4];
880
881         ret = av_image_fill_arrays(dst_data, dst_linesize, frame->frameData, AV_PIX_FMT_RGB24, width, height, 1);
882         if (ret < 0) {
883                 debug_error(DEBUG, "error: av_image_fill_arrays fail. errcode = 0x%08X", ret);
884                 goto EXCEPTION;
885         }
886
887         img_convert_ctx = sws_getContext(width, height, pVideoCodecCtx->pix_fmt, width, height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
888
889         if (NULL == img_convert_ctx) {
890                 debug_error(DEBUG, "failed to get img convert ctx");
891                 goto EXCEPTION;
892         }
893
894         ret = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize, 0, height, dst_data, dst_linesize);
895         if (ret < 0) {
896                 debug_error(DEBUG, "failed to convert image");
897                 sws_freeContext(img_convert_ctx);
898                 img_convert_ctx = NULL;
899                 goto EXCEPTION;
900         }
901
902         sws_freeContext(img_convert_ctx);
903         img_convert_ctx = NULL;
904
905         frame->frameSize = numBytes;
906         frame->frameWidth = width;
907         frame->frameHeight = height;
908         frame->configLenth = 0;
909         frame->frameDataFree = av_free;
910
911         if (pFrame)
912                 av_frame_free(&pFrame);
913
914         avcodec_free_context(&pVideoCodecCtx);
915
916         return MMFILE_FORMAT_SUCCESS;
917
918 EXCEPTION:
919         avcodec_free_context(&pVideoCodecCtx);
920         av_freep(&frame->frameData);
921         av_frame_free(&pFrame);
922
923         return MMFILE_FORMAT_FAIL;
924 }
925
926
927
928 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext)
929 {
930         if (formatContext) {
931                 AVFormatContext *pFormatCtx = formatContext->privateFormatData;
932
933                 if (pFormatCtx) {
934                         avformat_close_input(&pFormatCtx);
935                         formatContext->privateFormatData = NULL;
936                 }
937         }
938
939         return MMFILE_FORMAT_SUCCESS;
940 }
941
942 /**
943  * return average of difference
944  */
945 static unsigned int _diff_memory(const void *s1, const void *s2, unsigned int n)
946 {
947         char *s = (char *)s1;
948         char *d = (char *)s2;
949         unsigned int i = 0;
950         unsigned int ret = 0;
951         int tmp = 0;
952
953         for (i = 0, ret = 0; i < n; i++) {
954                 if (*s++ != *d++) {
955                         tmp = (*s - *d);
956                         ret += (tmp < 0 ? -tmp : tmp);
957                 }
958         }
959
960         if (n != 0)
961                 ret /= n;
962
963         return ret;
964 }
965
966 /**
967  * compare with center line.
968  */
969 static bool __is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize)
970 {
971 #define _MM_CHUNK_NUM                   8                                               /*FIXME*/
972 #define _MM_CHUNK_LIMIT                 (_MM_CHUNK_NUM / 2)
973 #define _MM_CHUNK_DIFF_LIMIT    (_MM_CHUNK_LIMIT * 2 + 1)       /*FIXME*/
974
975         int i;
976         int step;
977         int point;
978         unsigned char *cnt;             /*center line of image*/
979         int is_different;
980         unsigned int sum_diff;
981         int cnt_offset;
982
983         /*set center line*/
984         step = ysize / _MM_CHUNK_NUM;
985         cnt_offset = (ysize / 2);
986         cnt = buf + cnt_offset * wrap;
987
988         debug_msg(RELEASE, "checking frame. %p, %d, %d, %d", buf, wrap, xsize, ysize);
989
990         /*if too small, always ok return.*/
991         if (ysize < _MM_CHUNK_NUM)
992                 return true;
993
994         for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
995                 if (i == cnt_offset)
996                         continue;
997
998                 /*binary compare*/
999                 is_different = _diff_memory(cnt, buf + i * wrap, xsize);
1000                 point += (is_different == 0 ? 0 : 1);
1001                 sum_diff += is_different;
1002
1003                 debug_msg(RELEASE, "check %04d line. %s [%d]", i, (is_different == 0 ? "same" : "different"), is_different);
1004
1005                 if (point < _MM_CHUNK_LIMIT)
1006                         continue;
1007
1008                 if (sum_diff <= _MM_CHUNK_DIFF_LIMIT) {
1009                         debug_msg(RELEASE, "Bad :-(");
1010                         return false;
1011                 }
1012
1013                 debug_msg(RELEASE, "Good :-)");
1014                 return true;
1015         }
1016
1017         return false;
1018 }
1019
1020 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1021 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
1022 {
1023         FILE *f;
1024         int i;
1025
1026         f = fopen(filename, "w");
1027         if (f) {
1028                 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
1029                 for (i = 0; i < ysize; i++)
1030                         fwrite(buf + i * wrap, 1, xsize, f);
1031                 fclose(f);
1032         }
1033 }
1034 #endif
1035
1036 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, AVFrame **pFrame, int cdis)
1037 {
1038 #define _RETRY_SEARCH_LIMIT             250
1039 #define _KEY_SEARCH_LIMIT               (_RETRY_SEARCH_LIMIT*2)         /*2 = 1 read. some frame need to read one more*/
1040 #define _FRAME_SEARCH_LIMIT             500
1041
1042 #define _RETRY_SEARCH_LIMIT_CDIS                10
1043 #define _KEY_SEARCH_LIMIT_CDIS          (_RETRY_SEARCH_LIMIT*2)         /*2 = 1 read. some frame need to read one more*/
1044 #define _FRAME_SEARCH_LIMIT_CDIS                10
1045
1046         AVPacket *pkt = NULL;
1047
1048         AVFrame *frame = NULL;
1049         AVFrame *tmp_frame = NULL;
1050         AVFrame *first_frame = NULL;
1051
1052         int found = 0;
1053         int i = 0;
1054         int v = 0;
1055         int ret;
1056         int retry = 0;
1057         bool key_detected = false;
1058 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1059         char pgm_name[256] = {0, };
1060 #endif
1061         int key_search_limit = (cdis == 1) ? _KEY_SEARCH_LIMIT_CDIS : _KEY_SEARCH_LIMIT;
1062         int frame_search_limit = (cdis == 1) ? _FRAME_SEARCH_LIMIT_CDIS : _FRAME_SEARCH_LIMIT;
1063
1064         first_frame = av_frame_alloc();
1065         tmp_frame = av_frame_alloc();
1066
1067         if (!first_frame || !tmp_frame) {
1068                 debug_error(DEBUG, "failed to alloc frame.");
1069                 av_frame_free(&first_frame);
1070                 av_frame_free(&tmp_frame);
1071
1072                 return MMFILE_FORMAT_FAIL;
1073         }
1074
1075         debug_msg(RELEASE, "frame: 1. %p, 2. %p", first_frame, tmp_frame);
1076
1077         pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1078         frame = first_frame;
1079
1080         while (i < key_search_limit && v < frame_search_limit) {
1081                 pkt = av_packet_alloc();
1082                 if (!pkt) {
1083                         debug_error(DEBUG, "packet allocation failed.");
1084                         break;
1085                 }
1086
1087                 if (av_read_frame(pFormatCtx, pkt) < 0) {
1088                         debug_error(DEBUG, "read failed. (maybe EOF or broken)");
1089                         break;
1090                 }
1091
1092                 if (avcodec_get_type(pFormatCtx->streams[pkt->stream_index]->codecpar->codec_id) != AVMEDIA_TYPE_VIDEO)
1093                         goto NEXT;
1094
1095                 v++;
1096                 if (!(pkt->flags & AV_PKT_FLAG_KEY) && !key_detected)
1097                         goto NEXT;
1098
1099 #ifdef __MMFILE_TEST_MODE__
1100                 _dump_av_packet(pkt);
1101 #endif
1102                 i++;
1103                 key_detected = false;
1104                 debug_msg(RELEASE, "video frame: %d, %d, %d", retry, i, v);
1105
1106                 ret = avcodec_send_packet(pCodecCtx, pkt);
1107                 if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
1108                         debug_error(RELEASE, "Error while avcodec_send_packet[%2d]", ret);
1109                         break;
1110                 }
1111
1112                 ret = avcodec_receive_frame(pCodecCtx, frame);
1113                 if (ret < 0) {
1114                         if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1115                                 debug_msg(RELEASE, "decode not completed.");
1116                                 key_detected = true;
1117                                 goto NEXT;
1118                         }
1119                         debug_warning(DEBUG, "Error while decoding frame %dth", i);
1120                         goto NEXT;
1121                 }
1122
1123                 if (!frame->key_frame) {
1124                         debug_msg(RELEASE, "skip (not key frame).");
1125 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1126                         memset(pgm_name, 0x00, sizeof(pgm_name));
1127                         snprintf(pgm_name, sizeof(pgm_name), "./not_key_%d_%d_%d.pgm", retry, i, v);
1128                         _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1129 #endif
1130                         goto NEXT;
1131                 }
1132
1133                 debug_msg(RELEASE, "key frame!");
1134 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1135                 memset(pgm_name, 0x00, sizeof(pgm_name));
1136                 snprintf(pgm_name, sizeof(pgm_name), "./key_%d_%d_%d.pgm", retry, i, v);
1137                 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1138 #endif
1139                 found++;
1140
1141                 if (__is_good_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height)) {
1142                         debug_msg(RELEASE, "is good frame.");
1143                         break;
1144                 }
1145
1146                 debug_warning(RELEASE, "not good fame. retry scanning.");
1147                 i = 0;
1148                 v = 0;
1149                 retry++;
1150
1151                 /*set buffer frame*/
1152                 frame = tmp_frame;
1153
1154                 if (retry > _RETRY_SEARCH_LIMIT)
1155                         break;
1156 NEXT:
1157                 av_packet_free(&pkt);
1158         }
1159
1160         /*free pkt after loop breaking*/
1161         av_packet_free(&pkt);
1162
1163         debug_msg(RELEASE, "found: %d, retry: %d", found, retry);
1164
1165         /*set decode frame to output*/
1166         if (found > 0) {
1167                 if (retry == 0 || found == retry) {
1168                         *pFrame = first_frame;
1169                         av_frame_free(&tmp_frame);
1170                 } else {
1171                         *pFrame = tmp_frame;
1172                         av_frame_free(&first_frame);
1173                 }
1174         } else {
1175                 av_frame_free(&first_frame);
1176                 av_frame_free(&tmp_frame);
1177         }
1178
1179         debug_msg(RELEASE, "out frame: %p", *pFrame);
1180
1181         pCodecCtx->skip_frame = AVDISCARD_NONE;
1182
1183         return (found > 0) ? MMFILE_FORMAT_SUCCESS : MMFILE_FORMAT_FAIL;
1184 }