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