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