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