74479c98e3788c3e2730f5b68c49c4ccea43a900
[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 #include <sys/time.h>
36
37 #define _SHORT_MEDIA_LIMIT              2000    /* under X seconds duration*/
38
39 /* internal functions */
40 static int _is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize);
41 #ifdef MMFILE_FORMAT_DEBUG_DUMP
42 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename);
43 #endif
44 #ifdef __MMFILE_TEST_MODE__
45 static void _dump_av_packet(AVPacket *pkt);
46 #endif
47
48 static int      _get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup);
49 static int      _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis);
50
51 static int      ConvertVideoCodecEnum(int AVVideoCodecID);
52 static int      ConvertAudioCodecEnum(int AVAudioCodecID);
53
54 /* plugin manadatory API */
55 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext);
56 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
57 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext);
58 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext);
59
60 static int _mmf_mem_read(void *opaque, uint8_t *buf, int size);
61 static int64_t _mmf_mem_seek(void *opaque, int64_t pos, int whence);
62
63 typedef struct {
64         unsigned char *ptr;
65         long long size;
66         long long offset;
67         int     state;
68 } MMFmemIOHandle;
69
70 static void __count_stream_num(AVFormatContext *pFormatCtx, MMFileFormatContext *formatContext)
71 {
72         unsigned int i = 0;
73
74         formatContext->videoTotalTrackNum = 0;
75         formatContext->audioTotalTrackNum = 0;
76
77         for (i = 0; i < pFormatCtx->nb_streams; i++) {
78                 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
79                         debug_msg(RELEASE, "FFMPEG video codec id: 0x%08X\n", pFormatCtx->streams[i]->codecpar->codec_id);
80
81                         AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
82                         if ((pkt.data != NULL) && (pkt.size > 0))
83                                 continue;
84
85                         /*eventhough codec_id is 0, avformat_find_stream_info() can find proper codec_id. */
86                         formatContext->videoTotalTrackNum += 1;
87                 }
88                 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
89                         debug_msg(RELEASE, "FFMPEG audio codec id: 0x%08X\n", pFormatCtx->streams[i]->codecpar->codec_id);
90                         formatContext->audioTotalTrackNum += 1;
91                 }
92         }
93 }
94
95 static int _mmf_mem_open(MMFmemIOHandle **handle, const char *filename)
96 {
97         MMFmemIOHandle *memHandle = NULL;
98         char **splitedString = NULL;
99
100         filename += strlen(MMFILE_MEM_URI);
101
102         splitedString = mmfile_strsplit(filename, ":");
103         if (splitedString == NULL) {
104                 debug_error(DEBUG, "invalid param\n");
105                 return MMFILE_IO_FAILED;
106         }
107
108         if (!splitedString[0] || !splitedString[1]) {
109                 debug_error(DEBUG, "invalid param\n");
110                 goto exception;
111         }
112
113         memHandle = mmfile_malloc(sizeof(MMFmemIOHandle));
114         if (!memHandle) {
115                 debug_error(DEBUG, "error: mmfile_malloc memHandle\n");
116                 goto exception;
117         }
118
119         memHandle->ptr = (unsigned char *)atoll(splitedString[0]);      /*memory allocation address changed. memHandle->ptr = (unsigned char*)atoi(splitedString[0]); */
120         memHandle->size = atoi(splitedString[1]);
121         memHandle->offset = 0;
122         memHandle->state = 0;
123
124         *handle = memHandle;
125
126         if (splitedString) {
127                 mmfile_strfreev(splitedString);
128         }
129
130         return MMFILE_IO_SUCCESS;
131
132 exception:
133
134         if (splitedString) {
135                 mmfile_strfreev(splitedString);
136         }
137
138         return MMFILE_IO_FAILED;
139 }
140
141 static int _mmf_mem_read(void *opaque, uint8_t *buf, int size)
142 {
143         MMFmemIOHandle *memHandle = NULL;
144         const unsigned char *c = NULL;
145         int len = 0;
146
147         if (!opaque || !buf) {
148                 debug_error(DEBUG, "invalid para\n");
149                 return MMFILE_UTIL_FAIL;
150         }
151
152         memHandle = opaque;
153
154         if (!memHandle->ptr) {
155                 debug_error(DEBUG, "invalid para\n");
156                 return MMFILE_UTIL_FAIL;
157         }
158
159         if (memHandle->offset >= memHandle->size) {
160                 /* for some file formats last file read */
161                 debug_error(DEBUG, "File Read is beyond the file Size\n");
162                 return MMFILE_UTIL_FAIL;
163
164         }
165
166         c = memHandle->ptr + memHandle->offset;
167
168         if (memHandle->state != EOF) {
169                 len = size;
170                 if (len + memHandle->offset > memHandle->size) {
171                         len = memHandle->size - memHandle->offset;
172                 }
173         }
174
175         memcpy(buf, c, len);
176
177         memHandle->offset += len;
178
179         if (memHandle->offset == memHandle->size) {
180                 memHandle->state = EOF;
181         }
182
183         return len;
184 }
185
186 static int64_t _mmf_mem_seek(void *opaque, int64_t pos, int whence)
187 {
188         MMFmemIOHandle *memHandle = NULL;
189         long long tmp_offset = 0;
190
191         if (!opaque) {
192                 debug_error(DEBUG, "invalid para\n");
193                 return MMFILE_UTIL_FAIL;
194         }
195
196         memHandle = opaque;
197
198         switch (whence) {
199         case SEEK_SET:
200                 tmp_offset = 0 + pos;
201                 break;
202         case SEEK_CUR:
203                 tmp_offset = memHandle->offset + pos;
204                 break;
205         case SEEK_END:
206                 tmp_offset = memHandle->size + pos;
207                 break;
208         case AVSEEK_SIZE:       /*FFMPEG specific*/
209                 return memHandle->size;
210         default:
211                 return MMFILE_UTIL_FAIL;
212         }
213
214         /*check validation*/
215         if (tmp_offset < 0 && tmp_offset > memHandle->size) {
216                 debug_error(DEBUG, "invalid file offset\n");
217                 return MMFILE_UTIL_FAIL;
218         }
219
220         /*set */
221         memHandle->state = (tmp_offset >= memHandle->size) ? EOF : !EOF;
222         memHandle->offset = (unsigned int) tmp_offset;
223
224         return tmp_offset;
225 }
226
227 EXPORT_API
228 int mmfile_format_open_ffmpg(MMFileFormatContext *formatContext)
229 {
230         AVFormatContext     *pFormatCtx = NULL;
231         AVInputFormat       *grab_iformat = NULL;
232         int ret = 0;
233         char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0, };
234         char mimeType[MMFILE_MIMETYPE_MAX_LEN] = {0, };
235         AVIOContext          *pIOCtx = NULL;
236         MMFmemIOHandle *handle = NULL;
237         uint8_t *avio_ctx_buffer = NULL;
238
239         formatContext->ReadStream   = mmfile_format_read_stream_ffmpg;
240         formatContext->ReadFrame    = mmfile_format_read_frame_ffmpg;
241         formatContext->ReadTag      = mmfile_format_read_tag_ffmpg;
242         formatContext->Close        = mmfile_format_close_ffmpg;
243
244         debug_msg(RELEASE, "ffmpeg version: %d\n", avformat_version());
245         /**
246          * FFMPEG DEBUG LEVEL
247          *  AV_LOG_QUIET -1
248          *  AV_LOG_FATAL 0
249          *  AV_LOG_ERROR 0
250          *  AV_LOG_WARNING 1
251          *  AV_LOG_INFO 1
252          *  AV_LOG_VERBOSE 1
253          *  AV_LOG_DEBUG 2
254          */
255 #ifdef __MMFILE_TEST_MODE__
256         av_log_set_level(AV_LOG_DEBUG);
257 #else
258         av_log_set_level(AV_LOG_QUIET);
259 #endif
260
261         av_register_all();
262
263         if (formatContext->filesrc->type  == MM_FILE_SRC_TYPE_MEMORY) {
264                 if (mmfile_util_get_mimetype(formatContext->filesrc->memory.format, mimeType, MMFILE_MIMETYPE_MAX_LEN) < 0) {
265                         debug_error(DEBUG, "error: Error in MIME Type finding\n");
266                         return MMFILE_FORMAT_FAIL;
267                 }
268
269                 memset(ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
270
271                 ret = mmfile_util_get_ffmpeg_format(mimeType, ffmpegFormatName);
272                 if (MMFILE_UTIL_SUCCESS != ret) {
273                         debug_error(DEBUG, "error: mmfile_util_get_ffmpeg_format\n");
274                         return MMFILE_FORMAT_FAIL;
275                 }
276
277                 grab_iformat = av_find_input_format(ffmpegFormatName);
278
279                 if (NULL == grab_iformat) {
280                         debug_error(DEBUG, "error: cannot find format\n");
281                         goto exception;
282                 }
283
284                 avio_ctx_buffer = av_malloc(MMFILE_AVIO_BUFFER_LEN);
285                 if (avio_ctx_buffer == NULL) {
286                         debug_error(DEBUG, "error: cannot alloc avio_ctx_buffert\n");
287                         goto exception;
288                 }
289
290                 ret = _mmf_mem_open(&handle, formatContext->uriFileName);
291                 if (ret != MMFILE_IO_SUCCESS) {
292                         debug_warning(DEBUG, "failed to _mmf_mem_open.\n");
293                         goto exception;
294                 }
295
296                 pIOCtx = avio_alloc_context(avio_ctx_buffer, MMFILE_AVIO_BUFFER_LEN, 0, handle, _mmf_mem_read, NULL, _mmf_mem_seek);
297                 if (pIOCtx == NULL) {
298                         debug_error(DEBUG, "error: cannot alloc io context\n");
299                         goto exception;
300                 }
301
302                 pFormatCtx = avformat_alloc_context();
303                 if (pFormatCtx == NULL) {
304                         debug_warning(DEBUG, "failed to avformat_alloc_context\n");
305                         goto exception;
306                 }
307
308                 pFormatCtx->pb = pIOCtx;
309
310                 ret = avformat_open_input(&pFormatCtx, "", grab_iformat, NULL);
311                 if (ret < 0) {
312                         debug_error(DEBUG, "error: cannot open %s %d\n", formatContext->uriFileName, ret);
313                         goto exception;
314                 }
315
316                 formatContext->privateFormatData = pFormatCtx;
317         }
318
319         if (formatContext->filesrc->type  == MM_FILE_SRC_TYPE_FILE) {
320
321                 ret = avformat_open_input(&pFormatCtx, formatContext->filesrc->file.path, NULL, NULL);
322                 if (ret < 0) {
323                         debug_error(DEBUG, "error: cannot open %s %d\n", formatContext->filesrc->file.path, ret);
324                         goto exception;
325                 }
326
327                 formatContext->privateFormatData = pFormatCtx;
328         }
329
330         if (!pFormatCtx/* || !(pFormatCtx->nb_streams > 0)*/) {
331                 debug_warning(DEBUG, "failed to find av stream. maybe corrupted data.\n");
332                 goto exception;
333         }
334
335         debug_msg(RELEASE, "number of stream: %d\n", pFormatCtx->nb_streams);
336
337         __count_stream_num(pFormatCtx, formatContext);
338
339         debug_msg(RELEASE, "format: %s (%s)\n", pFormatCtx->iformat->name, pFormatCtx->iformat->long_name);
340 #ifdef __MMFILE_TEST_MODE__
341         av_dump_format(pFormatCtx, 0, formatContext->filesrc->file.path, 0);
342 #endif
343
344         return MMFILE_FORMAT_SUCCESS;
345
346 exception: /* fail to get content information */
347         if (formatContext->filesrc->type  == MM_FILE_SRC_TYPE_MEMORY) {
348                 if (avio_ctx_buffer)
349                         av_free(avio_ctx_buffer);
350
351                 mmfile_free(handle);
352
353                 if (pIOCtx)
354                         av_free(pIOCtx);
355                 if (pFormatCtx)
356                         avformat_close_input(&pFormatCtx);
357         } else {
358                 mmfile_format_close_ffmpg(formatContext);
359         }
360
361         formatContext->privateFormatData = NULL;
362
363         return MMFILE_FORMAT_FAIL;
364 }
365
366 static bool __check_uhqa(int sample_rate,  enum AVSampleFormat sample_fmt_info)
367 {
368         bool ret = FALSE;
369
370         debug_error(RELEASE, "[sample rate %d, sample format %d]", sample_rate, sample_fmt_info);
371
372         if ((sample_rate >= 44100) && (sample_fmt_info >= AV_SAMPLE_FMT_S32)) {
373                 debug_msg(RELEASE, "UHQA CONTENT");
374                 ret = TRUE;
375         } else {
376                 ret = FALSE;
377         }
378
379         return ret;
380 }
381
382 EXPORT_API
383 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext)
384 {
385         AVFormatContext     *pFormatCtx = NULL;
386         AVCodecParameters      *pAudioCodecCtx = NULL;
387         AVCodecParameters      *pVideoCodecCtx = NULL;
388
389         MMFileFormatStream  *videoStream = NULL;
390         MMFileFormatStream  *audioStream = NULL;
391         unsigned int i = 0;
392         int ret = 0;
393
394         if (NULL == formatContext || NULL == formatContext->privateFormatData) {
395                 debug_error(DEBUG, "invalid param\n");
396                 return MMFILE_FORMAT_FAIL;
397         }
398
399         pFormatCtx = formatContext->privateFormatData;
400         pFormatCtx->start_time = -1;
401
402         /**
403          *@important if data is corrupted, occur segment fault by av_find_stream_info().
404          *                      - fixed 2009-06-25.
405          */
406         if (formatContext->formatType == MM_FILE_FORMAT_M2TS)
407                 pFormatCtx->max_analyze_duration = 100000;      // MPEGTS file timeout set
408
409         if (formatContext->cdis != 1)
410                 ret = avformat_find_stream_info(pFormatCtx, NULL);
411         else
412                 ret = 0;
413
414         if (ret < 0) {
415                 debug_warning(DEBUG, "failed to find stream info. errcode = %d\n", ret);
416                 goto exception;
417         }
418
419         debug_msg(RELEASE, "FFMPEG: dur %"PRId64", start %"PRId64"\n", pFormatCtx->duration, pFormatCtx->start_time);
420
421         /**
422          *@note asf has long duration bug. and Some content's start time is wrong(negative number).
423          * Generally, mpegts has wrong start time(positive large value). So skip start time for mpegts format.
424          */
425         if (pFormatCtx->start_time < 0 || formatContext->formatType == MM_FILE_FORMAT_M2TS) {
426                 debug_warning(DEBUG, "Wrong Start time = %"PRId64"\n", pFormatCtx->start_time);
427                 formatContext->duration = (long long)(pFormatCtx->duration) * 1000 / AV_TIME_BASE;
428         } else {
429                 formatContext->duration = (long long)(pFormatCtx->duration + pFormatCtx->start_time) * 1000 / AV_TIME_BASE;
430         }
431
432         formatContext->videoStreamId = -1;
433         formatContext->audioStreamId = -1;
434         formatContext->nbStreams = 0;
435         formatContext->videoTotalTrackNum = 0;
436         formatContext->audioTotalTrackNum = 0;
437
438         for (i = 0; i < pFormatCtx->nb_streams; i++) {
439                 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
440                         if (formatContext->videoStreamId == -1) {
441                                 videoStream = mmfile_malloc(sizeof(MMFileFormatStream));
442                                 if (NULL == videoStream) {
443                                         debug_error(DEBUG, "mmfile_malloc error\n");
444                                         goto exception;
445                                 }
446
447                                 videoStream->streamType = MMFILE_VIDEO_STREAM;
448                                 formatContext->streams[MMFILE_VIDEO_STREAM] = videoStream;
449                                 formatContext->nbStreams += 1;
450                                 formatContext->videoStreamId = i;
451                                 formatContext->videoTotalTrackNum += 1;
452
453                                 pVideoCodecCtx = pFormatCtx->streams[i]->codecpar;
454                                 if (pVideoCodecCtx) {
455                                         videoStream->codecId            = ConvertVideoCodecEnum(pVideoCodecCtx->codec_id);
456                                         if (videoStream->codecId == MM_VIDEO_CODEC_NONE) {
457                                                 debug_error(RELEASE, "Proper codec is not found in [%d] stream", i);
458                                                 formatContext->videoStreamId = -1;
459                                                 mmfile_free(videoStream);
460                                                 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
461                                                 videoStream = NULL;
462                                                 continue;
463                                         }
464
465                                         /**
466                                          * Get FPS
467                                          * 1. try to get average fps of video stream.
468                                          * 2. if (1) failed, try to get fps of media container.
469                                          */
470                                         videoStream->framePerSec        = _get_video_fps(pFormatCtx->streams[i]->nb_frames,
471                                                                                                 pFormatCtx->streams[i]->duration,
472                                                                                                 pFormatCtx->streams[i]->time_base,
473                                                                                                 1);
474
475                                         if (videoStream->framePerSec == 0) {
476 #ifndef __MMFILE_LIBAV_VERSION__
477                                                 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->r_frame_rate);
478 #else
479                                                 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->avg_frame_rate);
480 #endif
481                                         }
482
483                                         videoStream->width                      = pVideoCodecCtx->width;
484                                         videoStream->height                     = pVideoCodecCtx->height;
485                                         videoStream->bitRate            = pVideoCodecCtx->bit_rate;
486                                 }
487                         }
488                 }               else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
489                         if (formatContext->audioStreamId == -1) {
490                                 audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
491                                 if (NULL == audioStream) {
492                                         debug_error(DEBUG, "mmfile_malloc error\n");
493                                         goto exception;
494                                 }
495
496                                 audioStream->streamType = MMFILE_AUDIO_STREAM;
497                                 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
498                                 formatContext->nbStreams += 1;
499                                 formatContext->audioStreamId = i;
500                                 formatContext->audioTotalTrackNum += 1;
501
502                                 pAudioCodecCtx = pFormatCtx->streams[i]->codecpar;
503                                 if (pAudioCodecCtx) {
504                                         audioStream->codecId            = ConvertAudioCodecEnum(pAudioCodecCtx->codec_id);
505                                         audioStream->bitRate            = pAudioCodecCtx->bit_rate;
506                                         audioStream->nbChannel          = pAudioCodecCtx->channels;
507                                         audioStream->samplePerSec       = pAudioCodecCtx->sample_rate;
508 #if 0
509                                         if (audioStream->codecId == MM_AUDIO_CODEC_FLAC)
510                                                 audioStream->bitPerSample = pAudioCodecCtx->bits_per_raw_sample;
511                                         else
512 #endif
513                                                 audioStream->bitPerSample = pAudioCodecCtx->bits_per_coded_sample;
514                                         audioStream->is_uhqa = __check_uhqa(audioStream->samplePerSec, pFormatCtx->streams[i]->codecpar->format);
515                                 }
516                         }
517                 }
518         }
519
520         if (formatContext->nbStreams == 0) {
521                 debug_error(DEBUG, "error: there is no audio and video track\n");
522                 goto exception;
523         }
524
525 #ifdef __MMFILE_TEST_MODE__
526         mmfile_format_print_contents(formatContext);
527 #endif
528
529         return MMFILE_FORMAT_SUCCESS;
530
531 exception:
532         mmfile_free(videoStream);
533         mmfile_free(audioStream);
534
535         formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
536         formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
537
538         if (pFormatCtx) {
539                 avformat_close_input(&pFormatCtx);
540                 formatContext->privateFormatData = NULL;
541         }
542
543         formatContext->audioTotalTrackNum = 0;
544         formatContext->videoTotalTrackNum = 0;
545         formatContext->nbStreams = 0;
546
547         return MMFILE_FORMAT_FAIL;
548 }
549
550 #define DATA_LENGTH 4
551 #define POS_OF_MIME_LEN DATA_LENGTH
552 #define CONVERT_TO_INT(dest, src) {dest = 0; dest |= (0 | src[0] << 24) | (0 | src[1] << 16) | (0 | src[2] << 8) | (0 | src[3]); }
553
554 static void __fill_picture_in_context(char *value, MMFileFormatContext *formatContext)
555 {
556         gsize len = 0;
557         guchar *meta_data = NULL;
558
559         meta_data = g_base64_decode(value, &len);
560         if (!meta_data) {
561                 debug_log(RELEASE, "no picture");
562                 return;
563         }
564
565         /* in METADATA_BLOCK_PICTURE,
566         the length of mime type and  the length of description are flexible,
567         so, we have to get the length of their for getting correct postion of picture data. */
568         int mime_len = 0;
569         int description_len = 0;
570         int data_len = 0;
571         int current_pos = 0;
572         unsigned char current_data[DATA_LENGTH] = {0};
573
574         /* get length of mime_type */
575         memcpy(current_data, meta_data + POS_OF_MIME_LEN, DATA_LENGTH);
576         CONVERT_TO_INT(mime_len, current_data);
577
578         /* get length of description */
579         current_pos =  mime_len + (DATA_LENGTH * 2); /*current position is length of description */
580         memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
581         CONVERT_TO_INT(description_len, current_data);
582
583         /* get length of picture data */
584         current_pos = mime_len  + description_len + (DATA_LENGTH * 7); /*current position is length of picture data */
585         memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
586         CONVERT_TO_INT(data_len, current_data);
587
588         /* set the size of art work */
589         formatContext->artworkSize = data_len;
590
591         /* set mime type */
592         current_pos = POS_OF_MIME_LEN + DATA_LENGTH; /*current position is mime type */
593         mmfile_free(formatContext->artworkMime);
594         formatContext->artworkMime = strndup((const char *)meta_data + current_pos, mime_len);
595
596         /* set art work data */
597         current_pos = mime_len  + description_len + (DATA_LENGTH * 8); /*current position is picture data */
598         mmfile_free(formatContext->artwork);
599
600         formatContext->artwork = mmfile_malloc(data_len);
601         if (formatContext->artwork)
602                 memcpy(formatContext->artwork, meta_data + current_pos, data_len);
603
604         g_free(meta_data);
605 }
606
607 static void __fill_artwork_in_context(AVStream *st, MMFileFormatContext *formatContext)
608 {
609         AVPacket pkt = st->attached_pic;
610         int codec_id = st->codecpar->codec_id;
611
612         if (!pkt.data || pkt.size <= 0) {
613                 return;
614         }
615
616         /*Set mime type*/
617         mmfile_free(formatContext->artworkMime);
618
619         if (codec_id == AV_CODEC_ID_MJPEG)
620                 formatContext->artworkMime = mmfile_strdup("image/jpeg");
621         else if (codec_id == AV_CODEC_ID_PNG)
622                 formatContext->artworkMime = mmfile_strdup("image/png");
623         else if (codec_id == AV_CODEC_ID_BMP)
624                 formatContext->artworkMime = mmfile_strdup("image/bmp");
625         else
626                 debug_error(DEBUG, "Unknown cover type: 0x%x\n", codec_id);
627
628         /*Copy artwork*/
629         mmfile_free(formatContext->artwork);
630
631         formatContext->artworkSize = pkt.size;
632         formatContext->artwork = mmfile_malloc(pkt.size);
633         if (formatContext->artwork)
634                 memcpy(formatContext->artwork, pkt.data, pkt.size);
635 }
636
637 static void __fill_metainfo_in_context(AVDictionary *metainfo, MMFileFormatContext *formatContext)
638 {
639         AVDictionaryEntry *tag = NULL;
640
641         while ((tag = av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) {
642                 if (!tag->key) {
643                         continue;
644                 }
645
646                 if (!g_ascii_strcasecmp(tag->key, "title")) {
647                         MMFILE_SAFE_FREE(formatContext->title);
648                         formatContext->title = mmfile_strdup(tag->value);
649                 } else if (!g_ascii_strcasecmp(tag->key, "artist")) {
650                         MMFILE_SAFE_FREE(formatContext->artist);
651                         formatContext->artist = mmfile_strdup(tag->value);
652                 } else if (!g_ascii_strcasecmp(tag->key, "composer")) {
653                         MMFILE_SAFE_FREE(formatContext->composer);
654                         formatContext->composer = mmfile_strdup(tag->value);
655                 } else if (!g_ascii_strcasecmp(tag->key, "album")) {
656                         MMFILE_SAFE_FREE(formatContext->album);
657                         formatContext->album = mmfile_strdup(tag->value);
658                 } else if (!g_ascii_strcasecmp(tag->key, "album_artist")) {
659                         MMFILE_SAFE_FREE(formatContext->album_artist);
660                         formatContext->album_artist = mmfile_strdup(tag->value);
661                 } else if (!g_ascii_strcasecmp(tag->key, "copyright")) {
662                         MMFILE_SAFE_FREE(formatContext->copyright);
663                         formatContext->copyright = mmfile_strdup(tag->value);
664                 } else if (!g_ascii_strcasecmp(tag->key, "comment")) {
665                         MMFILE_SAFE_FREE(formatContext->comment);
666                         formatContext->comment = mmfile_strdup(tag->value);
667                 } else if (!g_ascii_strcasecmp(tag->key, "description")) {
668                         MMFILE_SAFE_FREE(formatContext->description);
669                         formatContext->description = mmfile_strdup(tag->value);
670                 } else if (!g_ascii_strcasecmp(tag->key, "genre")) {
671                         MMFILE_SAFE_FREE(formatContext->genre);
672                         formatContext->genre = mmfile_strdup(tag->value);
673                 } else if (!g_ascii_strcasecmp(tag->key, "date")) {
674                         MMFILE_SAFE_FREE(formatContext->year);
675                         formatContext->year = mmfile_strdup(tag->value);
676                 } else if (!g_ascii_strcasecmp(tag->key, "creation_time")) {
677                         MMFILE_SAFE_FREE(formatContext->recDate);
678                         formatContext->recDate = mmfile_strdup(tag->value);
679                 } else if ((!g_ascii_strcasecmp(tag->key, "track")) || (!g_ascii_strcasecmp(tag->key, "tracknumber"))) {
680                         MMFILE_SAFE_FREE(formatContext->tagTrackNum);
681                         formatContext->tagTrackNum = mmfile_strdup(tag->value);
682                 } else if (!g_ascii_strcasecmp(tag->key, "lyrics")) {
683                         MMFILE_SAFE_FREE(formatContext->unsyncLyrics);
684                         formatContext->unsyncLyrics = mmfile_strdup(tag->value);
685                 } else if (!g_ascii_strcasecmp(tag->key, "rotate")) {   /*can be "90", "180", "270" */
686                         MMFILE_SAFE_FREE(formatContext->rotate);
687                         formatContext->rotate = mmfile_strdup(tag->value);
688                 } else if (!g_ascii_strcasecmp(tag->key, "spherical-video")) {
689                         ParseSpatialVideoMetadataFromXMLString(tag->value, formatContext);
690                 } else if (!g_ascii_strcasecmp(tag->key, "metadata_block_picture")) {
691                         __fill_picture_in_context(tag->value, formatContext);
692                 } else {
693                         debug_log(RELEASE, "Not support metadata. [%s:%s]", tag->key, tag->value);
694                 }
695         }
696 }
697
698 EXPORT_API
699 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext)
700 {
701         AVFormatContext     *pFormatCtx = NULL;
702
703         if (NULL == formatContext || NULL == formatContext->privateFormatData) {
704                 debug_error(DEBUG, "invalid param\n");
705                 return MMFILE_FORMAT_FAIL;
706         }
707
708         pFormatCtx = formatContext->privateFormatData;
709         if (!pFormatCtx) {
710                 debug_warning(DEBUG, "No format information");
711                 return MMFILE_FORMAT_SUCCESS;
712         }
713
714         if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4) {
715                 MMFileUtilGetMetaDataFromMP4(formatContext);
716         }
717
718         if (formatContext->formatType == MM_FILE_FORMAT_MATROSKA) {
719                 MMFileUtilGetMetaDataFromMKV(formatContext);
720         }
721
722         /*metadata extracted by ffmpeg*/
723         unsigned int idx = 0;
724
725         for (idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) {
726                 AVDictionary *metainfo = NULL;
727                 AVStream *st = NULL;
728
729                 /* Check metadata of normal stream like audio, video, video cover art
730                  * (cover art saved in new stream). refer to mov_read_covr() in ffmpeg.
731                  */
732                 if (idx < pFormatCtx->nb_streams) {
733                         st = pFormatCtx->streams[idx];
734                         if (st != NULL)
735                                 metainfo = st->metadata;
736                 } else {        /*Check metadata of Content */
737                         if (pFormatCtx->metadata != NULL) {
738                                 metainfo = pFormatCtx->metadata;
739                         } else {
740                                 continue;
741                         }
742                 }
743
744                 /*refer to mov_read_covr() in ffmpeg.*/
745                 if (st)
746                         __fill_artwork_in_context(st, formatContext);
747
748                 if (metainfo)
749                         __fill_metainfo_in_context(metainfo, formatContext);
750
751 #ifdef __MMFILE_TEST_MODE__
752                 mmfile_format_print_tags(formatContext);
753 #endif
754         }
755
756         return MMFILE_FORMAT_SUCCESS;
757 }
758
759
760 EXPORT_API
761 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
762 {
763         AVFormatContext *pFormatCtx = NULL;
764         AVCodecContext  *pVideoCodecCtx = NULL;
765         AVCodec                 *pVideoCodec = NULL;
766         AVCodecParameters *pVideoCodecPar = NULL;
767         AVFrame                 *pFrame = NULL;
768
769         int width = 0;
770         int height = 0;
771         int numBytes = 0;
772         int ret = 0;
773
774         if (NULL == formatContext ||
775             NULL == frame ||
776             NULL == formatContext->privateFormatData ||
777             formatContext->videoTotalTrackNum <= 0) {
778
779                 debug_error(DEBUG, "invalid param\n");
780                 return MMFILE_FORMAT_FAIL;
781         }
782
783         pFormatCtx = formatContext->privateFormatData;
784
785         if (formatContext->videoStreamId != -1) {
786                 pVideoCodecPar = pFormatCtx->streams[formatContext->videoStreamId]->codecpar;
787                 if (NULL == pVideoCodecPar) {
788                         debug_error(DEBUG, "invalid param\n");
789                         return MMFILE_FORMAT_FAIL;
790                 }
791
792                 pVideoCodec = avcodec_find_decoder(pVideoCodecPar->codec_id);
793                 if (NULL == pVideoCodec) {
794                         debug_error(DEBUG, "error: avcodec_find_decoder failed\n");
795                         return MMFILE_FORMAT_FAIL;
796                 }
797
798                 pVideoCodecCtx = avcodec_alloc_context3(pVideoCodec);
799                 if (NULL == pVideoCodecCtx) {
800                         debug_error(DEBUG, "error: avcodec_alloc_context3 failed\n");
801                         return MMFILE_FORMAT_FAIL;
802                 }
803
804                 ret = avcodec_parameters_to_context(pVideoCodecCtx, pVideoCodecPar);
805                 if (ret < 0) {
806                         debug_error(DEBUG, "error: avcodec_parameters_to_context\n");
807                         avcodec_free_context(&pVideoCodecCtx);
808                         return MMFILE_FORMAT_FAIL;
809                 }
810
811                 debug_msg(RELEASE, "flag: 0x%08X\n", pVideoCodec->capabilities);
812                 /* debug_msg(RELEASE, "  DRAW_HORIZ_BAND : %d\n", pVideoCodec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND ? 1 : 0); */
813                 /* debug_msg(RELEASE, "  DR1             : %d\n", pVideoCodec->capabilities & CODEC_CAP_DR1 ? 1 : 0); */
814                 /* debug_msg(RELEASE, "  PARSE_ONLY      : %d\n", pVideoCodec->capabilities & CODEC_CAP_PARSE_ONLY ? 1 : 0); */
815                 /* debug_msg(RELEASE, "  TRUNCATED       : %d\n", pVideoCodec->capabilities & CODEC_CAP_TRUNCATED ? 1 : 0); */
816                 /* debug_msg(RELEASE, "  HWACCEL         : %d\n", pVideoCodec->capabilities & CODEC_CAP_HWACCEL ? 1 : 0); */
817                 /* debug_msg(RELEASE, "  DELAY           : %d\n", pVideoCodec->capabilities & CODEC_CAP_DELAY ? 1 : 0); */
818                 /* debug_msg(RELEASE, "  SMALL_LAST_FRAME: %d\n", pVideoCodec->capabilities & CODEC_CAP_SMALL_LAST_FRAME ? 1 : 0); */
819                 /* debug_msg(RELEASE, "  HWACCEL_VDPAU   : %d\n", pVideoCodec->capabilities & CODEC_CAP_HWACCEL_VDPAU ? 1 : 0); */
820
821                 if (pVideoCodec->capabilities & CODEC_CAP_TRUNCATED) {
822                         pVideoCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
823                 }
824
825                 /*set workaround bug flag*/
826                 pVideoCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
827
828                 /* this is solution for PLM issue P13091703323 */
829                 /* If using thread when decoding frame, the result of decoding is not always same.
830                     Thumbnail of video content is different with original file when copying file. */
831                 pVideoCodecCtx->thread_type = 0;
832                 pVideoCodecCtx->thread_count = 0;
833                 ret = avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL);
834                 if (ret < 0) {
835                         debug_error(DEBUG, "error: avcodec_open fail.\n");
836                         return MMFILE_FORMAT_FAIL;
837                 }
838
839                 /* search & decode */
840                 /* seek_ts = formatContext->duration > _SHORT_MEDIA_LIMIT ? seek_ts : 0; */     /*if short media, seek first key frame*/
841                 ret = _get_first_good_video_frame(pFormatCtx, pVideoCodecCtx, formatContext->videoStreamId, &pFrame, formatContext->cdis);
842                 if (ret != MMFILE_FORMAT_SUCCESS) {
843                         debug_error(DEBUG, "error: get key frame\n");
844                         ret = MMFILE_FORMAT_FAIL;
845                         goto exception;
846                 }
847
848                 debug_msg(RELEASE, "Video default resolution = [%dx%d]\n", pVideoCodecCtx->coded_width, pVideoCodecCtx->coded_height);
849                 debug_msg(RELEASE, "Video coded resolution = [%dx%d]\n", pVideoCodecCtx->width, pVideoCodecCtx->height);
850
851                 /*sometimes, ffmpeg's width/height is wrong*/
852 #if 0   /*coded_width/height sometimes wrong. so use width/height*/
853                 width = pVideoCodecCtx->coded_width == 0 ? pVideoCodecCtx->width : pVideoCodecCtx->coded_width;
854                 height = pVideoCodecCtx->coded_height == 0 ? pVideoCodecCtx->height : pVideoCodecCtx->coded_height;
855 #endif
856                 if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
857                         width = pVideoCodecCtx->coded_width;
858                         height = pVideoCodecCtx->coded_height;
859                 } else {
860                         width = pVideoCodecCtx->width;
861                         height = pVideoCodecCtx->height;
862                 }
863
864                 numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, width, height, 1);
865                 if (numBytes < 0) {
866                         debug_error(DEBUG, "error: av_image_get_buffer_size. [%d x %d]\n", width, height);
867                         ret = MMFILE_FORMAT_FAIL;
868                         goto exception;
869                 }
870
871                 frame->frameData = mmfile_malloc(numBytes);
872                 if (NULL == frame->frameData) {
873                         debug_error(DEBUG, "error: mmfile_malloc. [%d]\n", numBytes);
874                         ret = MMFILE_FORMAT_FAIL;
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: avpicture_fill fail. errcode = 0x%08X\n", ret);
884                         ret = MMFILE_FORMAT_FAIL;
885                         goto exception;
886                 }
887
888                 struct SwsContext *img_convert_ctx = NULL;
889
890                 img_convert_ctx = sws_getContext(width, height, pVideoCodecCtx->pix_fmt, width, height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
891
892                 if (NULL == img_convert_ctx) {
893                         debug_error(DEBUG, "failed to get img convet ctx\n");
894                         ret = MMFILE_FORMAT_FAIL;
895                         goto exception;
896                 }
897
898                 ret = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize, 0, height, dst_data, dst_linesize);
899                 if (ret < 0) {
900                         debug_error(DEBUG, "failed to convet image\n");
901                         ret = MMFILE_FORMAT_FAIL;
902                         sws_freeContext(img_convert_ctx);
903                         img_convert_ctx = NULL;
904                         goto exception;
905                 }
906
907                 sws_freeContext(img_convert_ctx);
908                 img_convert_ctx = NULL;
909
910                 frame->frameSize = numBytes;
911                 frame->frameWidth = width;
912                 frame->frameHeight = height;
913                 frame->configLenth = 0;
914                 frame->bCompressed = 0; /* false */
915
916                 if (pFrame)                     av_frame_free(&pFrame);
917
918                 avcodec_free_context(&pVideoCodecCtx);
919
920                 return MMFILE_FORMAT_SUCCESS;
921         }
922
923
924 exception:
925         if (pVideoCodecCtx)     avcodec_free_context(&pVideoCodecCtx);
926
927         mmfile_free(frame->frameData);
928
929         if (pFrame)             av_frame_free(&pFrame);
930
931         return ret;
932 }
933
934
935 EXPORT_API
936 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext)
937 {
938         if (formatContext) {
939                 AVFormatContext *pFormatCtx = formatContext->privateFormatData;
940
941                 if (pFormatCtx) {
942                         avformat_close_input(&pFormatCtx);
943                         formatContext->privateFormatData = NULL;
944                 }
945         }
946
947         return MMFILE_FORMAT_SUCCESS;
948 }
949
950 /**
951  * return average of difference
952  */
953 static unsigned int _diff_memory(const void *s1, const void *s2, unsigned int n)
954 {
955         char *s = (char *)s1;
956         char *d = (char *)s2;
957         unsigned int i = 0;
958         unsigned int ret = 0;
959         int tmp = 0;
960
961         for (i = 0, ret = 0; i < n; i++) {
962                 if (*s++ != *d++) {
963                         tmp = (*s - *d);
964                         ret += (tmp < 0 ? -tmp : tmp);
965                 }
966         }
967
968         if (n != 0)
969                 ret /= n;
970
971         return ret;
972 }
973
974 int64_t gettime(void)
975 {
976         struct timeval tv;
977         gettimeofday(&tv, NULL);
978         return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
979 }
980
981
982 #define IS_GOOD_OLD_METHOD
983 #ifdef IS_GOOD_OLD_METHOD
984 /**
985  * compare with center line.
986  */
987 static int _is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize)
988 {
989 #define _MM_CHUNK_NUM                   8                                               /*FIXME*/
990 #define _MM_CHUNK_LIMIT                 (_MM_CHUNK_NUM / 2)
991 #define _MM_CHUNK_DIFF_LIMIT    (_MM_CHUNK_LIMIT * 2 + 1)       /*FIXME*/
992
993         int i;
994         int step;
995         int point;
996         unsigned char *cnt;             /*center line of image*/
997         int is_different;
998         unsigned int sum_diff;
999         int cnt_offset;
1000
1001         /*set center line*/
1002         step = ysize / _MM_CHUNK_NUM;
1003         cnt_offset = (ysize / 2);
1004         cnt = buf + cnt_offset * wrap;
1005
1006         debug_msg(RELEASE, "checking frame. %p, %d, %d, %d\n", buf, wrap, xsize, ysize);
1007
1008         /*if too small, always ok return.*/
1009         if (ysize < _MM_CHUNK_NUM)
1010                 return 1;
1011
1012         for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
1013                 if (i != cnt_offset) {
1014
1015                         /*binary compare*/
1016                         is_different = _diff_memory(cnt, buf + i * wrap, xsize);
1017                         point += (is_different == 0 ? 0 : 1);
1018                         sum_diff += is_different;
1019
1020                         debug_msg(RELEASE, "check %04d line. %s [%d]\n", i, (is_different == 0 ? "same" : "different"), is_different);
1021
1022                         if (point >= _MM_CHUNK_LIMIT) {
1023                                 if (sum_diff > _MM_CHUNK_DIFF_LIMIT) {
1024                                         debug_msg(RELEASE, "Good :-)\n");
1025                                         return 1;
1026                                 } else {
1027                                         debug_msg(RELEASE, "Bad :-(\n");
1028                                         return 0;
1029                                 }
1030                         }
1031                 }
1032
1033         }
1034         return 0;
1035 }
1036 #else /* IS_GOOD_OLD_METHOD  */
1037 /* ToDo : for enhancement */
1038 #endif /* IS_GOOD_OLD_METHOD */
1039
1040
1041
1042 static int
1043 _get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
1044 {
1045         double fps, round;
1046
1047         debug_msg(RELEASE, "frame count: %d, dur: %d, num: %d, den: %d\n", frame_cnt, duration, r_frame_rate.num, r_frame_rate.den);
1048
1049         if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
1050                 return 0;
1051
1052         round = (is_roundup != 0 ? 0.50f : 0.00f);
1053
1054         fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
1055
1056         return (int)fps;
1057 }
1058
1059 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1060 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
1061 {
1062         FILE *f;
1063         int i;
1064
1065         f = fopen(filename, "w");
1066         if (f) {
1067                 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
1068                 for (i = 0; i < ysize; i++)
1069                         fwrite(buf + i * wrap, 1, xsize, f);
1070                 fclose(f);
1071         }
1072 }
1073 #endif
1074
1075 #ifdef __MMFILE_TEST_MODE__
1076 static void _dump_av_packet(AVPacket *pkt)
1077 {
1078         debug_msg(RELEASE, "--------- AV Packet -----------\n");
1079         debug_msg(RELEASE, " pts: %lld\n", pkt->pts);
1080         debug_msg(RELEASE, " dts: %lld\n", pkt->dts);
1081         debug_msg(RELEASE, " data: %p\n", pkt->data);
1082         debug_msg(RELEASE, " size: %d\n", pkt->size);
1083         debug_msg(RELEASE, " stream_index: %d\n", pkt->stream_index);
1084         debug_msg(RELEASE, " flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & AV_PKT_FLAG_KEY) ? "Keyframe" : "_");
1085         debug_msg(RELEASE, " duration: %lld\n", pkt->duration);
1086         /*debug_msg(RELEASE, " destruct: %p\n", pkt->destruct);*/
1087         /*debug_msg(RELEASE, " priv: %p\n", pkt->priv);*/
1088         debug_msg(RELEASE, " pos: %lld\n", pkt->pos);
1089         debug_msg(RELEASE, "-------------------------------\n");
1090 }
1091 #endif
1092
1093 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis)
1094 {
1095         /* AVStream *st = NULL; */
1096         AVPacket pkt;
1097
1098         AVFrame *frame = NULL;
1099         AVFrame *tmp_frame = NULL;
1100         AVFrame *first_frame = NULL;
1101
1102         /* long long timestamp; */
1103         /*int stream_id = videoStream;*/
1104         int ret;
1105         int found = 0;
1106         int i, v, len;
1107         int retry = 0;
1108         int key_detected;
1109 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1110         char pgm_name[256] = {0, };
1111 #endif
1112         int key_search_limit = 0;
1113         int frame_search_limit = 0;
1114
1115 #define _RETRY_SEARCH_LIMIT             250
1116 #define _KEY_SEARCH_LIMIT               (_RETRY_SEARCH_LIMIT*2)         /*2 = 1 read. some frame need to read one more*/
1117 #define _FRAME_SEARCH_LIMIT             500
1118
1119 #define _RETRY_SEARCH_LIMIT_CDIS                10
1120 #define _KEY_SEARCH_LIMIT_CDIS          (_RETRY_SEARCH_LIMIT*2)         /*2 = 1 read. some frame need to read one more*/
1121 #define _FRAME_SEARCH_LIMIT_CDIS                10
1122
1123         first_frame = av_frame_alloc();
1124         tmp_frame = av_frame_alloc();
1125
1126         if (!first_frame || !tmp_frame) {
1127                 debug_error(DEBUG, "failed to alloc frame.\n");
1128                 if (first_frame) av_frame_free(&first_frame);
1129                 if (tmp_frame) av_frame_free(&tmp_frame);
1130                 return MMFILE_FORMAT_FAIL;
1131         }
1132
1133         debug_msg(RELEASE, "frame: 1. %p, 2. %p\n", first_frame, tmp_frame);
1134
1135         pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1136
1137         if (cdis == 1) {
1138                 key_search_limit = _KEY_SEARCH_LIMIT_CDIS;
1139                 frame_search_limit = _FRAME_SEARCH_LIMIT_CDIS;
1140         } else {
1141                 key_search_limit = _KEY_SEARCH_LIMIT;
1142                 frame_search_limit = _FRAME_SEARCH_LIMIT;
1143         }
1144
1145         for (i = 0, v = 0, key_detected = 0, frame = first_frame; i < key_search_limit && v < frame_search_limit;) {
1146                 av_init_packet(&pkt);
1147
1148                 ret = av_read_frame(pFormatCtx, &pkt);
1149                 if (ret < 0) {
1150                         debug_error(DEBUG, "read failed. (maybe EOF or broken)\n");
1151                         break;
1152                 }
1153
1154                 if (avcodec_get_type(pFormatCtx->streams[pkt.stream_index]->codecpar->codec_id) == AVMEDIA_TYPE_VIDEO) {
1155                         v++;
1156                         if ((pkt.flags & AV_PKT_FLAG_KEY) || (key_detected == 1)) {
1157                                 debug_msg(RELEASE, "video frame: %d, %d, %d\n", retry, i, v);
1158 #ifdef __MMFILE_TEST_MODE__
1159                                 _dump_av_packet(&pkt);
1160 #endif
1161
1162                                 i++;
1163                                 key_detected = 0;
1164
1165                                 len = avcodec_send_packet(pCodecCtx, &pkt);
1166                                 if (len < 0 && len != AVERROR(EAGAIN) && len != AVERROR_EOF) {
1167                                         debug_error(RELEASE, "Error while avcodec_send_packet[%2d]", len);
1168                                         break;
1169                                 }
1170
1171                                 len = avcodec_receive_frame(pCodecCtx, frame);
1172                                 if (len < 0 && len != AVERROR(EAGAIN) && len != AVERROR_EOF) {
1173                                         debug_warning(DEBUG, "Error while decoding frame %dth\n", i);
1174                                 } else if (len >= 0) {
1175                                         if (frame->key_frame) {
1176                                                 debug_msg(RELEASE, "key frame!\n");
1177 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1178                                                 memset(pgm_name, 0x00, sizeof(pgm_name));
1179                                                 snprintf(pgm_name, sizeof(pgm_name), "./key_%d_%d_%d.pgm", retry, i, v);
1180                                                 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1181 #endif
1182
1183                                                 found++;
1184
1185 #ifdef __MMFILE_TEST_MODE__
1186                                                 int64_t ti;
1187                                                 ti = gettime();
1188 #endif
1189                                                 ret = _is_good_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height);
1190 #ifdef __MMFILE_TEST_MODE__
1191                                                 ti = gettime() - ti;
1192                                                 debug_msg(RELEASE, "Elapsed time = %lld\n", ti);
1193 #endif
1194                                                 if (ret != 0) {
1195                                                         debug_msg(RELEASE, "is good frame.\n");
1196                                                         break;
1197                                                 }
1198
1199                                                 /*reset video frame count & retry searching*/
1200                                                 debug_warning(RELEASE, "not good fame. retry scanning.\n");
1201                                                 i = 0;
1202                                                 v = 0;
1203                                                 retry++;
1204
1205                                                 /*set buffer frame*/
1206                                                 frame = tmp_frame;
1207
1208                                                 /*limit of retry.*/
1209                                                 if (retry > _RETRY_SEARCH_LIMIT)        break;
1210
1211                                         } else {
1212                                                 debug_msg(RELEASE, "skip (not key frame).\n");
1213 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1214                                                 memset(pgm_name, 0x00, sizeof(pgm_name));
1215                                                 snprintf(pgm_name, sizeof(pgm_name), "./not_key_%d_%d_%d.pgm", retry, i, v);
1216                                                 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1217 #endif
1218                                         }
1219                                 } else {
1220                                         debug_msg(RELEASE, "decode not completed.\n");
1221                                         key_detected = 1;
1222                                 }
1223                         }
1224                 }
1225
1226                 av_packet_unref(&pkt);
1227         }
1228
1229         /*free pkt after loop breaking*/
1230         av_packet_unref(&pkt);
1231
1232         debug_msg(RELEASE, "found: %d, retry: %d\n", found, retry);
1233
1234         /*set decode frame to output*/
1235         if (found > 0) {
1236                 ret = MMFILE_FORMAT_SUCCESS;
1237                 if (retry == 0 || found == retry) {
1238                         *pFrame = first_frame;
1239                         if (tmp_frame) av_frame_free(&tmp_frame);
1240                 } else {
1241                         *pFrame = tmp_frame;
1242                         if (first_frame) av_frame_free(&first_frame);
1243                 }
1244         } else {
1245                 ret = MMFILE_FORMAT_FAIL;
1246                 if (first_frame) av_frame_free(&first_frame);
1247                 if (tmp_frame) av_frame_free(&tmp_frame);
1248         }
1249
1250         debug_msg(RELEASE, "out frame: %p\n", *pFrame);
1251
1252         pCodecCtx->skip_frame = AVDISCARD_NONE;
1253
1254         return ret;
1255 }
1256
1257 static int ConvertVideoCodecEnum(int AVVideoCodecID)
1258 {
1259         int ret_codecid = 0;
1260
1261         switch (AVVideoCodecID) {
1262         case AV_CODEC_ID_NONE:
1263                 ret_codecid = MM_VIDEO_CODEC_NONE;
1264                 break;
1265         case AV_CODEC_ID_MPEG1VIDEO:
1266                 ret_codecid = MM_VIDEO_CODEC_MPEG1;
1267                 break;
1268         case AV_CODEC_ID_MPEG2VIDEO:  /*/< preferred ID for MPEG-1/2 video decoding */
1269         case AV_CODEC_ID_MPEG2VIDEO_XVMC:
1270         case AV_CODEC_ID_MPEG2TS:
1271                 ret_codecid = MM_VIDEO_CODEC_MPEG2;
1272                 break;
1273         case AV_CODEC_ID_H261:
1274                 ret_codecid = MM_VIDEO_CODEC_H261;
1275                 break;
1276         case AV_CODEC_ID_H263:
1277                 ret_codecid = MM_VIDEO_CODEC_H263;
1278                 break;
1279         case AV_CODEC_ID_MPEG4:
1280                 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1281                 break;
1282         case AV_CODEC_ID_MSMPEG4V1:
1283                 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1284                 break;
1285         case AV_CODEC_ID_MSMPEG4V2:
1286                 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1287                 break;
1288         case AV_CODEC_ID_MSMPEG4V3:
1289                 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1290                 break;
1291         case AV_CODEC_ID_WMV1:
1292                 ret_codecid = MM_VIDEO_CODEC_WMV;
1293                 break;
1294         case AV_CODEC_ID_WMV2:
1295                 ret_codecid = MM_VIDEO_CODEC_WMV;
1296                 break;
1297         case AV_CODEC_ID_H263P:
1298                 ret_codecid = MM_VIDEO_CODEC_H263;
1299                 break;
1300         case AV_CODEC_ID_H263I:
1301                 ret_codecid = MM_VIDEO_CODEC_H263;
1302                 break;
1303         case AV_CODEC_ID_FLV1:
1304                 ret_codecid = MM_VIDEO_CODEC_FLV;
1305                 break;
1306         case AV_CODEC_ID_H264:
1307                 ret_codecid = MM_VIDEO_CODEC_H264;
1308                 break;
1309         case AV_CODEC_ID_INDEO2:
1310         case AV_CODEC_ID_INDEO3:
1311         case AV_CODEC_ID_INDEO4:
1312         case AV_CODEC_ID_INDEO5:
1313                 ret_codecid = MM_VIDEO_CODEC_INDEO;
1314                 break;
1315         case AV_CODEC_ID_THEORA:
1316                 ret_codecid = MM_VIDEO_CODEC_THEORA;
1317                 break;
1318         case AV_CODEC_ID_CINEPAK:
1319                 ret_codecid = MM_VIDEO_CODEC_CINEPAK;
1320                 break;
1321         case AV_CODEC_ID_VC1:
1322                 ret_codecid = MM_VIDEO_CODEC_VC1;
1323                 break;
1324         case AV_CODEC_ID_WMV3:
1325                 ret_codecid = MM_VIDEO_CODEC_WMV;
1326                 break;
1327         case AV_CODEC_ID_AVS:
1328                 ret_codecid = MM_VIDEO_CODEC_AVS;
1329                 break;
1330         case AV_CODEC_ID_RL2:
1331         case AV_CODEC_ID_RV10:  /* RealVideo 1 */
1332         case AV_CODEC_ID_RV20:  /* RealVideo 2 */
1333         case AV_CODEC_ID_RV30:  /* RealVideo 3 */
1334         case AV_CODEC_ID_RV40:  /* RealVideo 4 */
1335                 ret_codecid = MM_VIDEO_CODEC_REAL;
1336                 break;
1337 #ifdef __MMFILE_LIBAV_VERSION__
1338         case AV_CODEC_ID_HEVC:
1339                 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1340                 break;
1341 #endif
1342 #ifdef USE_PRODUCT_FEATURE
1343         case AV_CODEC_ID_VP8:
1344                 ret_codecid = MM_VIDEO_CODEC_VP8;
1345                 break;
1346         case AV_CODEC_ID_VP9:
1347                 ret_codecid = MM_VIDEO_CODEC_VP9;
1348                 break;
1349 #endif
1350         default:
1351                 ret_codecid = MM_VIDEO_CODEC_NONE;
1352                 break;
1353         }
1354
1355         return ret_codecid;
1356 }
1357
1358
1359 static int ConvertAudioCodecEnum(int AVAudioCodecID)
1360 {
1361         int ret_codecid = 0;
1362
1363         switch (AVAudioCodecID) {
1364         case AV_CODEC_ID_AMR_NB:
1365         case AV_CODEC_ID_AMR_WB:
1366                 ret_codecid = MM_AUDIO_CODEC_AMR;
1367                 break;
1368         /* RealAudio codecs*/
1369         case AV_CODEC_ID_RA_144:        /* RealAudio 1 */
1370         case AV_CODEC_ID_RA_288:        /* RealAudio 2 */
1371         case AV_CODEC_ID_COOK:          /* RealAudio 6 */
1372                 ret_codecid = MM_AUDIO_CODEC_REAL;
1373                 break;
1374         case AV_CODEC_ID_MP2:
1375                 ret_codecid = MM_AUDIO_CODEC_MP2;
1376                 break;
1377         case AV_CODEC_ID_MP3:
1378         case AV_CODEC_ID_MP3ADU:
1379         case AV_CODEC_ID_MP3ON4:
1380                 ret_codecid = MM_AUDIO_CODEC_MP3;
1381                 break;
1382         case AV_CODEC_ID_AAC:
1383                 ret_codecid = MM_AUDIO_CODEC_AAC;
1384                 break;
1385         case AV_CODEC_ID_AC3:
1386                 ret_codecid = MM_AUDIO_CODEC_AC3;
1387                 break;
1388         case AV_CODEC_ID_VORBIS:
1389                 ret_codecid = MM_AUDIO_CODEC_VORBIS;
1390                 break;
1391         case AV_CODEC_ID_WMAV1:
1392         case AV_CODEC_ID_WMAV2:
1393         case AV_CODEC_ID_WMAVOICE:
1394         case AV_CODEC_ID_WMAPRO:
1395         case AV_CODEC_ID_WMALOSSLESS:
1396                 ret_codecid = MM_AUDIO_CODEC_WMA;
1397                 break;
1398         case AV_CODEC_ID_FLAC:
1399                 ret_codecid = MM_AUDIO_CODEC_FLAC;
1400                 break;
1401         case AV_CODEC_ID_ALAC:
1402                 ret_codecid = MM_AUDIO_CODEC_ALAC;
1403                 break;
1404         case AV_CODEC_ID_WAVPACK:
1405                 ret_codecid = MM_AUDIO_CODEC_WAVE;
1406                 break;
1407         case AV_CODEC_ID_ATRAC3:
1408         case AV_CODEC_ID_ATRAC3P:
1409         case AV_CODEC_ID_EAC3:
1410                 ret_codecid = MM_AUDIO_CODEC_AC3;
1411                 break;
1412         case AV_CODEC_ID_PCM_S8:
1413         case AV_CODEC_ID_PCM_S16BE:
1414         case AV_CODEC_ID_PCM_S24BE:
1415         case AV_CODEC_ID_PCM_S32BE:
1416                 ret_codecid = MM_AUDIO_CODEC_PCM;
1417                 break;
1418         default:
1419                 ret_codecid = MM_AUDIO_CODEC_NONE;
1420                 break;
1421         }
1422
1423         return ret_codecid;
1424 }