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