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