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