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