2.4 sync
[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         return MMFILE_FORMAT_SUCCESS;
935 }
936
937 /**
938  * return average of difference
939  */
940 static unsigned int _diff_memory(const void *s1, const void *s2, unsigned int n)
941 {
942         char *s = (char *)s1;
943         char *d = (char *)s2;
944         unsigned int i;
945         unsigned int ret;
946         int tmp;
947
948         for (i = 0, ret = 0; i < n; i++) {
949                 if (*s++ != *d++) {
950                         tmp = (*s - *d);
951                         ret += (tmp < 0 ? -tmp : tmp);
952                 }
953         }
954         ret /= n;
955         return ret;
956 }
957
958 int64_t gettime(void)
959 {
960         struct timeval tv;
961         gettimeofday(&tv, NULL);
962         return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
963 }
964
965
966 #define IS_GOOD_OLD_METHOD
967 #ifdef IS_GOOD_OLD_METHOD
968 /**
969  * compare with center line.
970  */
971 static int _is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize)
972 {
973 #define _MM_CHUNK_NUM                   8                                               /*FIXME*/
974 #define _MM_CHUNK_LIMIT                 (_MM_CHUNK_NUM / 2)
975 #define _MM_CHUNK_DIFF_LIMIT    (_MM_CHUNK_LIMIT * 2 + 1)       /*FIXME*/
976
977         int i;
978         int step;
979         int point;
980         unsigned char *cnt;             /*center line of image*/
981         int is_different;
982         unsigned int sum_diff;
983         int cnt_offset;
984
985         /*set center line*/
986         step = ysize / _MM_CHUNK_NUM;
987         cnt_offset = (ysize / 2);
988         cnt = buf + cnt_offset * wrap;
989
990 #ifdef __MMFILE_TEST_MODE__
991         debug_msg("checking frame. %p, %d, %d, %d\n", buf, wrap, xsize, ysize);
992 #endif
993
994         /*if too small, always ok return.*/
995         if (ysize < _MM_CHUNK_NUM)
996                 return 1;
997
998         for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
999                 if (i != cnt_offset) {
1000
1001                         /*binary compare*/
1002                         is_different = _diff_memory(cnt, buf + i * wrap, xsize);
1003                         point += (is_different == 0 ? 0 : 1);
1004                         sum_diff += is_different;
1005
1006 #ifdef __MMFILE_TEST_MODE__
1007                         debug_msg("check %04d line. %s [%d]\n", i, (is_different == 0 ? "same" : "different"), is_different);
1008 #endif
1009
1010                         if (point >= _MM_CHUNK_LIMIT) {
1011                                 if (sum_diff > _MM_CHUNK_DIFF_LIMIT) {
1012 #ifdef __MMFILE_TEST_MODE__
1013                                         debug_msg("Good :-)\n");
1014 #endif
1015                                         return 1;
1016                                 } else {
1017 #ifdef __MMFILE_TEST_MODE__
1018                                         debug_msg("Bad :-(\n");
1019 #endif
1020                                         return 0;
1021                                 }
1022                         }
1023                 }
1024
1025         }
1026         return 0;
1027 }
1028 #else /* IS_GOOD_OLD_METHOD  */
1029 /* ToDo : for enhancement */
1030 #endif /* IS_GOOD_OLD_METHOD */
1031
1032
1033
1034 static int
1035 _get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
1036 {
1037         double fps, round;
1038
1039 #ifdef __MMFILE_TEST_MODE__
1040         debug_msg("frame count: %d, dur: %d, num: %d, den: %d\n", frame_cnt, duration, r_frame_rate.num, r_frame_rate.den);
1041 #endif
1042
1043         if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
1044                 return 0;
1045
1046         round = (is_roundup != 0 ? 0.50f : 0.00f);
1047
1048         fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
1049
1050         return (int)fps;
1051 }
1052
1053 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1054 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
1055 {
1056         FILE *f;
1057         int i;
1058
1059         f = fopen(filename, "w");
1060         if (f) {
1061                 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
1062                 for (i = 0; i < ysize; i++)
1063                         fwrite(buf + i * wrap, 1, xsize, f);
1064                 fclose(f);
1065         }
1066 }
1067 #endif
1068
1069 #ifdef __MMFILE_TEST_MODE__
1070 static void _dump_av_packet(AVPacket *pkt)
1071 {
1072         debug_msg("--------- AV Packet -----------\n");
1073         debug_msg(" pts: %lld\n", pkt->pts);
1074         debug_msg(" dts: %lld\n", pkt->dts);
1075         debug_msg(" data: %p\n", pkt->data);
1076         debug_msg(" size: %d\n", pkt->size);
1077         debug_msg(" stream_index: %d\n", pkt->stream_index);
1078 #ifdef __MMFILE_FFMPEG_V085__
1079         debug_msg(" flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & AV_PKT_FLAG_KEY) ? "Keyframe" : "_");
1080 #else
1081         debug_msg(" flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & PKT_FLAG_KEY) ? "Keyframe" : "_");
1082 #endif
1083         debug_msg(" duration: %d\n", pkt->duration);
1084         /*debug_msg(" destruct: %p\n", pkt->destruct);*/
1085         /*debug_msg(" priv: %p\n", pkt->priv);*/
1086         debug_msg(" pos: %lld\n", pkt->pos);
1087         debug_msg(" convergence_duration: %lld\n", pkt->convergence_duration);
1088         debug_msg("-------------------------------\n");
1089 }
1090 #endif
1091
1092 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis)
1093 {
1094         /* AVStream *st = NULL; */
1095         AVPacket pkt;
1096
1097         AVFrame *frame = NULL;
1098         AVFrame *tmp_frame = NULL;
1099         AVFrame *first_frame = NULL;
1100
1101         /* long long timestamp; */
1102         int stream_id = videoStream;
1103         int ret;
1104         int found = 0;
1105         int i, v, len, got_picture;
1106         int retry = 0;
1107         int key_detected;
1108 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1109         char pgm_name[256] = {0, };
1110 #endif
1111         int key_search_limit = 0;
1112         int frame_search_limit = 0;
1113
1114 #define _RETRY_SEARCH_LIMIT             75
1115 #define _KEY_SEARCH_LIMIT               (_RETRY_SEARCH_LIMIT*2)         /*2 = 1 read. some frame need to read one more*/
1116 #define _FRAME_SEARCH_LIMIT             500
1117
1118 #define _RETRY_SEARCH_LIMIT_CDIS                10
1119 #define _KEY_SEARCH_LIMIT_CDIS          (_RETRY_SEARCH_LIMIT*2)         /*2 = 1 read. some frame need to read one more*/
1120 #define _FRAME_SEARCH_LIMIT_CDIS                10
1121
1122         first_frame = av_frame_alloc();
1123         tmp_frame = av_frame_alloc();
1124
1125         if (!first_frame || !tmp_frame) {
1126                 debug_error("failed to alloc frame.\n");
1127                 if (first_frame) av_free(first_frame);
1128                 if (tmp_frame) av_free(tmp_frame);
1129                 return MMFILE_FORMAT_FAIL;
1130         }
1131
1132 #ifdef __MMFILE_TEST_MODE__
1133         debug_msg("frame: 1. %p, 2. %p\n", first_frame, tmp_frame);
1134 #endif
1135
1136 #ifdef __MMFILE_FFMPEG_V085__
1137         pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1138 #else
1139         pCodecCtx->hurry_up = 1;
1140 #endif
1141
1142         if (cdis == 1) {
1143                 key_search_limit = _KEY_SEARCH_LIMIT_CDIS;
1144                 frame_search_limit = _FRAME_SEARCH_LIMIT_CDIS;
1145         } else {
1146                 key_search_limit = _KEY_SEARCH_LIMIT;
1147                 frame_search_limit = _FRAME_SEARCH_LIMIT;
1148         }
1149
1150         for (i = 0, v = 0, key_detected = 0, frame = first_frame; i < key_search_limit && v < frame_search_limit;) {
1151                 av_init_packet(&pkt);
1152                 got_picture = 0;
1153
1154                 ret = av_read_frame(pFormatCtx, &pkt);
1155                 if (ret < 0) {
1156                         debug_error("read failed. (maybe EOF or broken)\n");
1157                         break;
1158                 } else {
1159                         if (pkt.stream_index == stream_id) {
1160                                 v++;
1161 #ifdef __MMFILE_FFMPEG_V085__
1162                                 if ((pkt.flags & AV_PKT_FLAG_KEY) || (key_detected == 1))
1163 #else
1164                                 if ((pkt.flags & PKT_FLAG_KEY) || (key_detected == 1))
1165 #endif
1166                                 {
1167 #ifdef __MMFILE_TEST_MODE__
1168                                         debug_msg("video frame: %d, %d, %d\n", retry, i, v);
1169                                         _dump_av_packet(&pkt);
1170 #endif
1171
1172                                         i++;
1173                                         key_detected = 0;
1174 #ifdef __MMFILE_FFMPEG_V085__
1175                                         len = avcodec_decode_video2(pCodecCtx, frame, &got_picture, &pkt);
1176 #else
1177                                         len = avcodec_decode_video(pCodecCtx, frame, &got_picture, pkt.data, pkt.size);
1178 #endif
1179                                         if (len < 0) {
1180                                                 debug_warning("Error while decoding frame %dth\n", i);
1181                                         } else if (got_picture) {
1182                                                 if (frame->key_frame) {
1183 #ifdef __MMFILE_TEST_MODE__
1184                                                         debug_msg("key frame!\n");
1185 #endif
1186 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1187                                                         sprintf(pgm_name, "./key_%d_%d_%d.pgm", retry, i, v);
1188                                                         _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1189 #endif
1190
1191                                                         found++;
1192
1193 #ifdef __MMFILE_TEST_MODE__
1194                                                         int64_t ti;
1195                                                         ti = gettime();
1196 #endif
1197                                                         ret = _is_good_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height);
1198 #ifdef __MMFILE_TEST_MODE__
1199                                                         ti = gettime() - ti;
1200                                                         debug_msg("Elapsed time = %lld\n", ti);
1201 #endif
1202                                                         if (ret != 0) {
1203 #ifdef __MMFILE_TEST_MODE__
1204                                                                 debug_msg("is good frame.\n");
1205 #endif
1206                                                                 break;
1207                                                         } else {
1208                                                                 /*reset video frame count & retry searching*/
1209 #ifdef __MMFILE_TEST_MODE__
1210                                                                 debug_warning("not good fame. retry scanning.\n");
1211 #endif
1212                                                                 i = 0;
1213                                                                 v = 0;
1214                                                                 retry++;
1215                                                         }
1216
1217                                                         /*set buffer frame*/
1218                                                         frame = tmp_frame;
1219
1220                                                         /*limit of retry.*/
1221                                                         if (retry > _RETRY_SEARCH_LIMIT)        break;
1222
1223                                                 } else {
1224 #ifdef __MMFILE_TEST_MODE__
1225                                                         debug_msg("skip (not key frame).\n");
1226 #endif
1227 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1228                                                         sprintf(pgm_name, "./not_key_%d_%d_%d.pgm", retry, i, v);
1229                                                         _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1230 #endif
1231                                                 }
1232                                         } else {
1233 #ifdef __MMFILE_TEST_MODE__
1234                                                 debug_msg("decode not completed.\n");
1235 #endif
1236                                                 key_detected = 1;
1237                                         }
1238                                 }
1239                         }
1240                 }
1241                 av_free_packet(&pkt);
1242         }
1243
1244         /*free pkt after loop breaking*/
1245         if (pkt.data) av_free_packet(&pkt);
1246
1247 #ifdef __MMFILE_TEST_MODE__
1248         debug_msg("found: %d, retry: %d\n", found, retry);
1249 #endif
1250
1251         /*set decode frame to output*/
1252         if (found > 0) {
1253                 ret = MMFILE_FORMAT_SUCCESS;
1254                 if (retry == 0 || found == retry) {
1255                         *pFrame = first_frame;
1256                         if (tmp_frame) av_free(tmp_frame);
1257                 } else {
1258                         *pFrame = tmp_frame;
1259                         if (first_frame) av_free(first_frame);
1260                 }
1261         } else {
1262                 ret = MMFILE_FORMAT_FAIL;
1263                 if (first_frame) av_free(first_frame);
1264                 if (tmp_frame) av_free(tmp_frame);
1265         }
1266
1267 #ifdef __MMFILE_TEST_MODE__
1268         debug_msg("out frame: %p\n", *pFrame);
1269 #endif
1270
1271 #ifdef __MMFILE_FFMPEG_V085__
1272         pCodecCtx->skip_frame = AVDISCARD_NONE;
1273 #else
1274         pCodecCtx->hurry_up = 0;
1275 #endif
1276
1277         return ret;
1278 }
1279
1280 static int ConvertVideoCodecEnum(int AVVideoCodecID)
1281 {
1282         int ret_codecid = 0;
1283
1284         switch (AVVideoCodecID) {
1285                 case AV_CODEC_ID_NONE:
1286                         ret_codecid = MM_VIDEO_CODEC_NONE;
1287                         break;
1288                 case AV_CODEC_ID_MPEG1VIDEO:
1289                         ret_codecid = MM_VIDEO_CODEC_MPEG1;
1290                         break;
1291                 case AV_CODEC_ID_MPEG2VIDEO:  /*/< preferred ID for MPEG-1/2 video decoding */
1292                 case AV_CODEC_ID_MPEG2VIDEO_XVMC:
1293                 case AV_CODEC_ID_MPEG2TS:
1294                         ret_codecid = MM_VIDEO_CODEC_MPEG2;
1295                         break;
1296                 case AV_CODEC_ID_H261:
1297                         ret_codecid = MM_VIDEO_CODEC_H261;
1298                         break;
1299                 case AV_CODEC_ID_H263:
1300                         ret_codecid = MM_VIDEO_CODEC_H263;
1301                         break;
1302                 case AV_CODEC_ID_MPEG4:
1303                         ret_codecid = MM_VIDEO_CODEC_MPEG4;
1304                         break;
1305                 case AV_CODEC_ID_MSMPEG4V1:
1306                         ret_codecid = MM_VIDEO_CODEC_MPEG4;
1307                         break;
1308                 case AV_CODEC_ID_MSMPEG4V2:
1309                         ret_codecid = MM_VIDEO_CODEC_MPEG4;
1310                         break;
1311                 case AV_CODEC_ID_MSMPEG4V3:
1312                         ret_codecid = MM_VIDEO_CODEC_MPEG4;
1313                         break;
1314                 case AV_CODEC_ID_WMV1:
1315                         ret_codecid = MM_VIDEO_CODEC_WMV;
1316                         break;
1317                 case AV_CODEC_ID_WMV2:
1318                         ret_codecid = MM_VIDEO_CODEC_WMV;
1319                         break;
1320                 case AV_CODEC_ID_H263P:
1321                         ret_codecid = MM_VIDEO_CODEC_H263;
1322                         break;
1323                 case AV_CODEC_ID_H263I:
1324                         ret_codecid = MM_VIDEO_CODEC_H263;
1325                         break;
1326                 case AV_CODEC_ID_FLV1:
1327                         ret_codecid = MM_VIDEO_CODEC_FLV;
1328                         break;
1329                 case AV_CODEC_ID_H264:
1330                         ret_codecid = MM_VIDEO_CODEC_H264;
1331                         break;
1332                 case AV_CODEC_ID_INDEO2:
1333                 case AV_CODEC_ID_INDEO3:
1334                 case AV_CODEC_ID_INDEO4:
1335                 case AV_CODEC_ID_INDEO5:
1336                         ret_codecid = MM_VIDEO_CODEC_INDEO;
1337                         break;
1338                 case AV_CODEC_ID_THEORA:
1339                         ret_codecid = MM_VIDEO_CODEC_THEORA;
1340                         break;
1341                 case AV_CODEC_ID_CINEPAK:
1342                         ret_codecid = MM_VIDEO_CODEC_CINEPAK;
1343                         break;
1344 #if (!defined __MMFILE_FFMPEG_V085__ && !defined __MMFILE_LIBAV_VERSION__)
1345                 case AV_CODEC_ID_XVID:
1346                         ret_codecid = MM_VIDEO_CODEC_XVID;
1347                         break;
1348 #endif
1349                 case AV_CODEC_ID_VC1:
1350                         ret_codecid = MM_VIDEO_CODEC_VC1;
1351                         break;
1352                 case AV_CODEC_ID_WMV3:
1353                         ret_codecid = MM_VIDEO_CODEC_WMV;
1354                         break;
1355                 case AV_CODEC_ID_AVS:
1356                         ret_codecid = MM_VIDEO_CODEC_AVS;
1357                         break;
1358                 case AV_CODEC_ID_RL2:
1359                 case AV_CODEC_ID_RV10:  /* RealVideo 1 */
1360                 case AV_CODEC_ID_RV20:  /* RealVideo 2 */
1361                 case AV_CODEC_ID_RV30:  /* RealVideo 3 */
1362                 case AV_CODEC_ID_RV40:  /* RealVideo 4 */
1363                         ret_codecid = MM_VIDEO_CODEC_REAL;
1364                         break;
1365 #ifdef __MMFILE_LIBAV_VERSION__
1366                 case AV_CODEC_ID_HEVC:
1367                         ret_codecid = MM_VIDEO_CODEC_MPEG4;
1368                         break;
1369 #endif
1370                 default:
1371                         ret_codecid = MM_VIDEO_CODEC_NONE;
1372                         break;
1373         }
1374
1375         return ret_codecid;
1376 }
1377
1378
1379 static int ConvertAudioCodecEnum(int AVAudioCodecID)
1380 {
1381         int ret_codecid = 0;
1382
1383         switch (AVAudioCodecID) {
1384                 case AV_CODEC_ID_AMR_NB:
1385                 case AV_CODEC_ID_AMR_WB:
1386                         ret_codecid = MM_AUDIO_CODEC_AMR;
1387                         break;
1388                 /* RealAudio codecs*/
1389                 case AV_CODEC_ID_RA_144:        /* RealAudio 1 */
1390                 case AV_CODEC_ID_RA_288:        /* RealAudio 2 */
1391                 case AV_CODEC_ID_COOK:          /* RealAudio 6 */
1392                         ret_codecid = MM_AUDIO_CODEC_REAL;
1393                         break;
1394                 case AV_CODEC_ID_MP2:
1395                         ret_codecid = MM_AUDIO_CODEC_MP2;
1396                         break;
1397                 case AV_CODEC_ID_MP3:
1398                 case AV_CODEC_ID_MP3ADU:
1399                 case AV_CODEC_ID_MP3ON4:
1400                         ret_codecid = MM_AUDIO_CODEC_MP3;
1401                         break;
1402                 case AV_CODEC_ID_AAC:
1403                         ret_codecid = MM_AUDIO_CODEC_AAC;
1404                         break;
1405                 case AV_CODEC_ID_AC3:
1406                         ret_codecid = MM_AUDIO_CODEC_AC3;
1407                         break;
1408                 case AV_CODEC_ID_VORBIS:
1409                         ret_codecid = MM_AUDIO_CODEC_VORBIS;
1410                         break;
1411                 case AV_CODEC_ID_WMAV1:
1412                 case AV_CODEC_ID_WMAV2:
1413                 case AV_CODEC_ID_WMAVOICE:
1414                 case AV_CODEC_ID_WMAPRO:
1415                 case AV_CODEC_ID_WMALOSSLESS:
1416                         ret_codecid = MM_AUDIO_CODEC_WMA;
1417                         break;
1418                 case AV_CODEC_ID_FLAC:
1419                         ret_codecid = MM_AUDIO_CODEC_FLAC;
1420                         break;
1421                 case AV_CODEC_ID_ALAC:
1422                         ret_codecid = MM_AUDIO_CODEC_ALAC;
1423                         break;
1424                 case AV_CODEC_ID_WAVPACK:
1425                         ret_codecid = MM_AUDIO_CODEC_WAVE;
1426                         break;
1427                 case AV_CODEC_ID_ATRAC3:
1428                 case AV_CODEC_ID_ATRAC3P:
1429                 case AV_CODEC_ID_EAC3:
1430                         ret_codecid = MM_AUDIO_CODEC_AC3;
1431                         break;
1432                 case AV_CODEC_ID_PCM_S8:
1433                 case AV_CODEC_ID_PCM_S16BE:
1434                 case AV_CODEC_ID_PCM_S24BE:
1435                 case AV_CODEC_ID_PCM_S32BE:
1436                         ret_codecid = MM_AUDIO_CODEC_PCM;
1437                         break;
1438                 default:
1439                         ret_codecid = MM_AUDIO_CODEC_NONE;
1440                         break;
1441         }
1442
1443         return ret_codecid;
1444 }
1445
1446
1447
1448 static int getMimeType(int formatId, char *mimeType, int buf_size)
1449 {
1450         int ret = 0;    /*default: success*/
1451
1452         switch (formatId) {
1453                 case MM_FILE_FORMAT_3GP:
1454                 case MM_FILE_FORMAT_MP4:
1455                         snprintf(mimeType, buf_size, "video/3gpp");
1456                         break;
1457                 case MM_FILE_FORMAT_ASF:
1458                 case MM_FILE_FORMAT_WMA:
1459                 case MM_FILE_FORMAT_WMV:
1460                         snprintf(mimeType, buf_size, "video/x-ms-asf");
1461                         break;
1462                 case  MM_FILE_FORMAT_AVI:
1463                         snprintf(mimeType, buf_size, "video/avi");
1464                         break;
1465                 case MM_FILE_FORMAT_OGG:
1466                         snprintf(mimeType, buf_size, "video/ogg");
1467                         break;
1468                 case MM_FILE_FORMAT_REAL:
1469                         snprintf(mimeType, buf_size, "video/vnd.rn-realmedia");
1470                         break;
1471                 case MM_FILE_FORMAT_AMR:
1472                         snprintf(mimeType, buf_size, "audio/AMR");
1473                         break;
1474                 case MM_FILE_FORMAT_AAC:
1475                         snprintf(mimeType, buf_size, "audio/aac");
1476                         break;
1477                 case MM_FILE_FORMAT_MP3:
1478                         snprintf(mimeType, buf_size, "audio/mp3");
1479                         break;
1480                 case MM_FILE_FORMAT_AIFF:
1481                 case MM_FILE_FORMAT_WAV:
1482                         snprintf(mimeType, buf_size, "audio/wave");
1483                         break;
1484                 case MM_FILE_FORMAT_MID:
1485                         snprintf(mimeType, buf_size, "audio/midi");
1486                         break;
1487                 case MM_FILE_FORMAT_MMF:
1488                         snprintf(mimeType, buf_size, "audio/mmf");
1489                         break;
1490                 case MM_FILE_FORMAT_DIVX:
1491                         snprintf(mimeType, buf_size, "video/divx");
1492                         break;
1493                 case MM_FILE_FORMAT_IMELODY:
1494                         snprintf(mimeType, buf_size, "audio/iMelody");
1495                         break;
1496                 case MM_FILE_FORMAT_JPG:
1497                         snprintf(mimeType, buf_size, "image/jpeg");
1498                         break;
1499                 case MM_FILE_FORMAT_AU:
1500                         snprintf(mimeType, buf_size, "audio/basic");
1501                         break;
1502                 case MM_FILE_FORMAT_VOB:
1503                         snprintf(mimeType, buf_size, "video/dvd");
1504                         break;
1505                 case MM_FILE_FORMAT_FLV:
1506                         snprintf(mimeType, buf_size, "video/x-flv");
1507                         break;
1508                 case MM_FILE_FORMAT_QT:
1509                         snprintf(mimeType, buf_size, "video/quicktime");
1510                         break;
1511                 case MM_FILE_FORMAT_MATROSKA:
1512                         snprintf(mimeType, buf_size, "video/x-matroska");
1513                         break;
1514                 case MM_FILE_FORMAT_FLAC:
1515                         snprintf(mimeType, buf_size, "audio/x-flac");
1516                         break;
1517                 case MM_FILE_FORMAT_M2TS:
1518                         snprintf(mimeType, buf_size, "video/MP2T");
1519                         break;
1520                 case MM_FILE_FORMAT_M2PS:
1521                         snprintf(mimeType, buf_size, "video/MP2P");
1522                         break;
1523                 case MM_FILE_FORMAT_M1AUDIO:
1524                         snprintf(mimeType, buf_size, "audio/x-mpegaudio");
1525                         break;
1526                 case MM_FILE_FORMAT_M1VIDEO:
1527                         snprintf(mimeType, buf_size, "video/mpeg");
1528                         break;
1529                 default:
1530                         ret = -1;
1531         }
1532
1533 #ifdef __MMFILE_TEST_MODE__
1534         debug_msg("id: %d, mimetype: %s\n", formatId, mimeType);
1535 #endif
1536
1537         return ret;
1538 }
1539
1540