4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Haejeong Kim <backto.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
36 #include <drm_client.h>
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"
45 #include "mm_file_format_ffmpeg_drm.h"
48 #include "mm_file_format_ffmpeg_mem.h"
51 #define _SHORT_MEDIA_LIMIT 2000 /* under X seconds duration*/
53 extern int img_convert(AVPicture *dst, int dst_pix_fmt, const AVPicture *src, int src_pix_fmt, int src_width, int src_height);
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);
60 #ifdef __MMFILE_TEST_MODE__
61 static void _dump_av_packet(AVPacket *pkt);
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);
67 static int ConvertVideoCodecEnum(int AVVideoCodecID);
68 static int ConvertAudioCodecEnum(int AVAudioCodecID);
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);
80 int mmfile_format_open_ffmpg(MMFileFormatContext *formatContext)
82 AVFormatContext *pFormatCtx = NULL;
83 AVInputFormat *grab_iformat = NULL;
87 drm_content_info_s contentInfo = {0, };
89 char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0, };
90 char mimeType[MMFILE_MIMETYPE_MAX_LEN] = {0, };
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;
97 #ifdef __MMFILE_TEST_MODE__
98 debug_msg("ffmpeg version: %d\n", avformat_version());
109 av_log_set_level(AV_LOG_DEBUG);
111 av_log_set_level(AV_LOG_QUIET);
116 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
118 #if (defined __MMFILE_FFMPEG_V085__ && !defined __MMFILE_LIBAV_VERSION__)
119 ffurl_register_protocol(&MMFileMEMProtocol, sizeof(URLProtocol));
121 ffurl_register_protocol(&MMFileMEMProtocol);
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;
128 memset(ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
130 ret = mmfile_util_get_ffmpeg_format(mimeType, ffmpegFormatName);
132 if (MMFILE_UTIL_SUCCESS != ret) {
133 debug_error("error: mmfile_util_get_ffmpeg_format\n");
134 return MMFILE_FORMAT_FAIL;
137 grab_iformat = av_find_input_format(ffmpegFormatName);
139 if (NULL == grab_iformat) {
140 debug_error("error: cannot find format\n");
144 #ifdef __MMFILE_FFMPEG_V085__
145 ret = avformat_open_input(&pFormatCtx, formatContext->uriFileName, grab_iformat, NULL);
147 ret = av_open_input_file(&pFormatCtx, formatContext->uriFileName, grab_iformat, 0, NULL);
150 debug_error("error: cannot open %s %d\n", formatContext->uriFileName, ret);
153 formatContext->privateFormatData = pFormatCtx;
156 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_FILE) {
158 if (formatContext->isdrm == MM_FILE_DRM_OMA) {
160 if (formatContext->formatType == MM_FILE_FORMAT_DIVX || formatContext->formatType == MM_FILE_FORMAT_AVI) {
161 goto HANDLING_DRM_DIVX;
164 #ifdef __MMFILE_FFMPEG_V085__
165 ffurl_register_protocol(&MMFileDRMProtocol, sizeof(URLProtocol));
167 ffurl_register_protocol(&MMFileDRMProtocol);
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;
175 memset(ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
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;
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);
189 grab_iformat = av_find_input_format(ffmpegFormatName);
191 if (NULL == grab_iformat) {
192 debug_error("error: cannot find format\n");
196 #ifdef __MMFILE_FFMPEG_V085__
197 ret = avformat_open_input(&pFormatCtx, formatContext->uriFileName, grab_iformat, NULL);
199 ret = av_open_input_file(&pFormatCtx, formatContext->uriFileName, grab_iformat, 0, NULL);
202 debug_error("error: cannot open %s %d\n", formatContext->uriFileName, ret);
205 formatContext->privateFormatData = pFormatCtx;
212 #ifdef __MMFILE_FFMPEG_V085__
213 ret = avformat_open_input(&pFormatCtx, formatContext->filesrc->file.path, NULL, NULL);
215 ret = av_open_input_file(&pFormatCtx, formatContext->filesrc->file.path, NULL, 0, NULL);
218 debug_error("error: cannot open %s %d\n", formatContext->filesrc->file.path, ret);
222 formatContext->privateFormatData = pFormatCtx;
226 if (!pFormatCtx/* || !(pFormatCtx->nb_streams > 0)*/) {
227 debug_warning("failed to find av stream. maybe corrupted data.\n");
231 #ifdef __MMFILE_TEST_MODE__
232 debug_msg("number of stream: %d\n", pFormatCtx->nb_streams);
235 formatContext->videoTotalTrackNum = 0;
236 formatContext->audioTotalTrackNum = 0;
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);
245 AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
246 if ((pkt.data != NULL) && (pkt.size > 0))
249 /*eventhough codec_id is 0, avformat_find_stream_info() can find proper codec_id. */
250 formatContext->videoTotalTrackNum += 1;
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);
256 formatContext->audioTotalTrackNum += 1;
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);
263 formatContext->videoTotalTrackNum += 1;
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);
269 formatContext->audioTotalTrackNum += 1;
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);
279 dump_format(pFormatCtx, 0, formatContext->filesrc->file.path, 0);
283 return MMFILE_FORMAT_SUCCESS;
285 exception: /* fail to get content information */
287 mmfile_format_close_ffmpg(formatContext);
288 formatContext->privateFormatData = NULL;
290 return MMFILE_FORMAT_FAIL;
293 static bool __check_uhqa(int sample_rate, enum AVSampleFormat sample_fmt_info)
297 #ifdef __MMFILE_TEST_MODE__
298 debug_error("[sample rate %d, sample format %d]", sample_rate, sample_fmt_info);
301 if ((sample_rate >= 44100) && (sample_fmt_info >= AV_SAMPLE_FMT_S32)) {
302 #ifdef __MMFILE_TEST_MODE__
303 debug_msg("UHQA CONTENT");
314 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext)
316 AVFormatContext *pFormatCtx = NULL;
317 AVCodecContext *pAudioCodecCtx = NULL;
318 AVCodecContext *pVideoCodecCtx = NULL;
320 MMFileFormatStream *videoStream = NULL;
321 MMFileFormatStream *audioStream = NULL;
324 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
325 debug_error("invalid param\n");
326 return MMFILE_FORMAT_FAIL;
329 pFormatCtx = formatContext->privateFormatData;
330 pFormatCtx->start_time = -1;
333 *@important if data is corrupted, occur segment fault by av_find_stream_info().
334 * - fixed 2009-06-25.
336 #ifdef __MMFILE_FFMPEG_V100__
337 if (formatContext->cdis != 1)
338 ret = avformat_find_stream_info(pFormatCtx, NULL);
342 ret = av_find_stream_info(pFormatCtx);
345 debug_warning("failed to find stream info. errcode = %d\n", ret);
349 #ifdef __MMFILE_TEST_MODE__
350 debug_msg("FFMPEG: dur %lld, start %lld\n", pFormatCtx->duration, pFormatCtx->start_time);
354 *@note asf has long duration bug. and Some content's start time is wrong(negative number).
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;
360 formatContext->duration = (long long)(pFormatCtx->duration + pFormatCtx->start_time) * 1000 / AV_TIME_BASE;
363 formatContext->videoStreamId = -1;
364 formatContext->audioStreamId = -1;
365 formatContext->nbStreams = 0;
366 formatContext->videoTotalTrackNum = 0;
367 formatContext->audioTotalTrackNum = 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) {
374 if (pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_VIDEO) {
376 if (formatContext->videoStreamId == -1) {
377 videoStream = mmfile_malloc(sizeof(MMFileFormatStream));
378 if (NULL == videoStream) {
379 debug_error("mmfile_malloc error\n");
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;
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;
403 * 1. try to get average fps of video stream.
404 * 2. if (1) failed, try to get fps of media container.
406 videoStream->framePerSec = _get_video_fps(pFormatCtx->streams[i]->nb_frames,
407 pFormatCtx->streams[i]->duration,
408 pFormatCtx->streams[i]->time_base,
411 if (videoStream->framePerSec == 0) {
412 #ifndef __MMFILE_LIBAV_VERSION__
413 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->r_frame_rate);
415 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->avg_frame_rate);
419 videoStream->width = pVideoCodecCtx->width;
420 videoStream->height = pVideoCodecCtx->height;
421 videoStream->bitRate = pVideoCodecCtx->bit_rate;
425 #ifdef __MMFILE_FFMPEG_V085__
426 else if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
428 else if (pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_AUDIO) {
430 if (formatContext->audioStreamId == -1) {
431 audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
432 if (NULL == audioStream) {
433 debug_error("mmfile_malloc error\n");
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;
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;
452 audioStream->bitPerSample = pAudioCodecCtx->bits_per_coded_sample;
453 audioStream->is_uhqa = __check_uhqa(audioStream->samplePerSec, pFormatCtx->streams[i]->codec->sample_fmt);
459 if (formatContext->nbStreams == 0) {
460 debug_error("error: there is no audio and video track\n");
464 #ifdef __MMFILE_TEST_MODE__
465 mmfile_format_print_contents(formatContext);
468 return MMFILE_FORMAT_SUCCESS;
472 mmfile_free(videoStream);
473 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
477 mmfile_free(audioStream);
478 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
482 #ifdef __MMFILE_FFMPEG_V100__
483 avformat_close_input(&pFormatCtx);
485 av_close_input_file(pFormatCtx);
487 formatContext->privateFormatData = NULL;
490 formatContext->audioTotalTrackNum = 0;
491 formatContext->videoTotalTrackNum = 0;
492 formatContext->nbStreams = 0;
494 return MMFILE_FORMAT_FAIL;
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]);}
502 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext)
504 AVFormatContext *pFormatCtx = NULL;
506 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
507 debug_error("invalid param\n");
508 return MMFILE_FORMAT_FAIL;
511 pFormatCtx = formatContext->privateFormatData;
513 if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4) {
514 MMFileUtilGetMetaDataFromMP4(formatContext);
517 #ifdef __MMFILE_FFMPEG_V085__
518 /*metadata extracted by ffmpeg*/
519 unsigned int idx = 0;
521 if (pFormatCtx != NULL) {
522 for (idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) {
523 AVDictionary *metainfo = NULL;
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];
529 metainfo = st->metadata;
530 } else { /*Check metadata of Content */
531 if (pFormatCtx->metadata != NULL) {
532 metainfo = pFormatCtx->metadata;
538 /*refer to mov_read_covr() in ffmpeg.*/
540 AVPacket pkt = st->attached_pic;
541 int codec_id = st->codec->codec_id;
543 if ((pkt.data != NULL) && (pkt.size > 0)) {
545 if (formatContext->artworkMime) mmfile_free(formatContext->artworkMime);
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");
554 debug_error("Unknown cover type: 0x%x\n", codec_id);
557 if (formatContext->artwork) mmfile_free(formatContext->artwork);
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);
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")) {
614 guchar *meta_data = NULL;
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. */
622 int description_len = 0;
625 unsigned char current_data[DATA_LENGTH] = {0};
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);
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);
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);
641 /* set the size of art work */
642 formatContext->artworkSize = data_len;
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);
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);
653 formatContext->artwork = mmfile_malloc(data_len);
654 if (formatContext->artwork != NULL)
655 memcpy(formatContext->artwork, meta_data + current_pos, data_len);
660 #ifdef __MMFILE_TEST_MODE__
661 debug_log("Not support metadata. [%s:%s]", tag->key, tag->value);
667 #ifdef __MMFILE_TEST_MODE__
668 mmfile_format_print_tags(formatContext);
673 if (pFormatCtx->title[0]) {
674 if (formatContext->title)
675 free(formatContext->title);
676 formatContext->title = mmfile_strdup(pFormatCtx->title);
678 if (pFormatCtx->author[0]) {
679 if (formatContext->author)
680 free(formatContext->author);
681 formatContext->author = mmfile_strdup(pFormatCtx->author);
683 if (pFormatCtx->copyright[0]) {
684 if (formatContext->copyright)
685 free(formatContext->copyright);
686 formatContext->copyright = mmfile_strdup(pFormatCtx->copyright);
688 if (pFormatCtx->comment[0]) {
689 if (formatContext->comment)
690 free(formatContext->comment);
691 formatContext->comment = mmfile_strdup(pFormatCtx->comment);
693 if (pFormatCtx->album[0]) {
694 if (formatContext->album)
695 free(formatContext->album);
696 formatContext->album = mmfile_strdup(pFormatCtx->album);
698 if (pFormatCtx->genre[0]) {
699 if (formatContext->genre)
700 free(formatContext->genre);
701 formatContext->genre = mmfile_strdup(pFormatCtx->genre);
704 if (pFormatCtx->year) {
705 char year[10] = {0, };
706 snprintf(year, 10, "%d", pFormatCtx->year);
708 if (formatContext->year)
709 free(formatContext->year);
710 formatContext->year = mmfile_strdup(year);
713 if (pFormatCtx->track) {
714 char tracknum[10] = {0, };
715 snprintf(tracknum, 10, "%d", pFormatCtx->track);
717 if (formatContext->tagTrackNum)
718 free(formatContext->tagTrackNum);
719 formatContext->tagTrackNum = mmfile_strdup(tracknum);
723 return MMFILE_FORMAT_SUCCESS;
728 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
730 AVFormatContext *pFormatCtx = NULL;
731 AVCodecContext *pVideoCodecCtx = NULL;
732 AVCodec *pVideoCodec = NULL;
733 AVFrame *pFrame = NULL;
734 AVFrame *pFrameRGB = NULL;
741 if (NULL == formatContext ||
743 NULL == formatContext->privateFormatData ||
744 formatContext->videoTotalTrackNum <= 0) {
746 debug_error("invalid param\n");
747 return MMFILE_FORMAT_FAIL;
750 if (formatContext->isdrm == MM_FILE_DRM_PROTECTED) {
751 debug_error("This is protected drm file\n");
752 return MMFILE_FORMAT_FAIL;
755 pFormatCtx = formatContext->privateFormatData;
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;
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;
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); */
782 if (pVideoCodec->capabilities & CODEC_CAP_TRUNCATED) {
783 pVideoCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
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);
796 ret = avcodec_open(pVideoCodecCtx, pVideoCodec);
799 debug_error("error: avcodec_open fail.\n");
800 return MMFILE_FORMAT_FAIL;
803 pFrameRGB = av_frame_alloc();
806 debug_error("error: pFrame or pFrameRGB is NULL\n");
807 ret = MMFILE_FORMAT_FAIL;
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;
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);
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;
830 if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
831 width = pVideoCodecCtx->coded_width;
832 height = pVideoCodecCtx->coded_height;
834 width = pVideoCodecCtx->width;
835 height = pVideoCodecCtx->height;
838 numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
840 debug_error("error: avpicture_get_size. [%d x %d]\n", width, height);
841 ret = MMFILE_FORMAT_FAIL;
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;
852 ret = avpicture_fill((AVPicture *)pFrameRGB, frame->frameData, PIX_FMT_RGB24, width, height);
854 debug_error("error: avpicture_fill fail. errcode = 0x%08X\n", ret);
855 ret = MMFILE_FORMAT_FAIL;
859 #ifdef __MMFILE_FFMPEG_V085__
860 struct SwsContext *img_convert_ctx = NULL;
862 img_convert_ctx = sws_getContext(width, height, pVideoCodecCtx->pix_fmt,
863 width, height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
865 if (NULL == img_convert_ctx) {
866 debug_error("failed to get img convet ctx\n");
867 ret = MMFILE_FORMAT_FAIL;
871 ret = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize,
872 0, height, pFrameRGB->data, pFrameRGB->linesize);
874 debug_error("failed to convet image\n");
875 ret = MMFILE_FORMAT_FAIL;
876 sws_freeContext(img_convert_ctx);
877 img_convert_ctx = NULL;
881 sws_freeContext(img_convert_ctx);
882 img_convert_ctx = NULL;
884 ret = img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture *)pFrame, pVideoCodecCtx->pix_fmt, width, height);
886 debug_error("failed to convet image\n");
887 ret = MMFILE_FORMAT_FAIL;
891 frame->frameSize = numBytes;
892 frame->frameWidth = width;
893 frame->frameHeight = height;
894 frame->configLenth = 0;
895 frame->bCompressed = 0; /* false */
897 if (pFrame) av_free(pFrame);
898 if (pFrameRGB) av_free(pFrameRGB);
900 avcodec_close(pVideoCodecCtx);
902 return MMFILE_FORMAT_SUCCESS;
907 if (pVideoCodecCtx) avcodec_close(pVideoCodecCtx);
908 if (frame->frameData) {
909 mmfile_free(frame->frameData);
910 frame->frameData = NULL;
912 if (pFrame) av_free(pFrame);
913 if (pFrameRGB) av_free(pFrameRGB);
919 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext)
922 AVFormatContext *pFormatCtx = formatContext->privateFormatData;
925 #ifdef __MMFILE_FFMPEG_V100__
926 avformat_close_input(&pFormatCtx);
928 av_close_input_file(pFormatCtx);
930 formatContext->privateFormatData = NULL;
934 return MMFILE_FORMAT_SUCCESS;
938 * return average of difference
940 static unsigned int _diff_memory(const void *s1, const void *s2, unsigned int n)
942 char *s = (char *)s1;
943 char *d = (char *)s2;
948 for (i = 0, ret = 0; i < n; i++) {
951 ret += (tmp < 0 ? -tmp : tmp);
958 int64_t gettime(void)
961 gettimeofday(&tv, NULL);
962 return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
966 #define IS_GOOD_OLD_METHOD
967 #ifdef IS_GOOD_OLD_METHOD
969 * compare with center line.
971 static int _is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize)
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*/
980 unsigned char *cnt; /*center line of image*/
982 unsigned int sum_diff;
986 step = ysize / _MM_CHUNK_NUM;
987 cnt_offset = (ysize / 2);
988 cnt = buf + cnt_offset * wrap;
990 #ifdef __MMFILE_TEST_MODE__
991 debug_msg("checking frame. %p, %d, %d, %d\n", buf, wrap, xsize, ysize);
994 /*if too small, always ok return.*/
995 if (ysize < _MM_CHUNK_NUM)
998 for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
999 if (i != cnt_offset) {
1002 is_different = _diff_memory(cnt, buf + i * wrap, xsize);
1003 point += (is_different == 0 ? 0 : 1);
1004 sum_diff += is_different;
1006 #ifdef __MMFILE_TEST_MODE__
1007 debug_msg("check %04d line. %s [%d]\n", i, (is_different == 0 ? "same" : "different"), is_different);
1010 if (point >= _MM_CHUNK_LIMIT) {
1011 if (sum_diff > _MM_CHUNK_DIFF_LIMIT) {
1012 #ifdef __MMFILE_TEST_MODE__
1013 debug_msg("Good :-)\n");
1017 #ifdef __MMFILE_TEST_MODE__
1018 debug_msg("Bad :-(\n");
1028 #else /* IS_GOOD_OLD_METHOD */
1029 /* ToDo : for enhancement */
1030 #endif /* IS_GOOD_OLD_METHOD */
1035 _get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
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);
1043 if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
1046 round = (is_roundup != 0 ? 0.50f : 0.00f);
1048 fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
1053 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1054 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
1059 f = fopen(filename, "w");
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);
1069 #ifdef __MMFILE_TEST_MODE__
1070 static void _dump_av_packet(AVPacket *pkt)
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" : "_");
1081 debug_msg(" flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & PKT_FLAG_KEY) ? "Keyframe" : "_");
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");
1092 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis)
1094 /* AVStream *st = NULL; */
1097 AVFrame *frame = NULL;
1098 AVFrame *tmp_frame = NULL;
1099 AVFrame *first_frame = NULL;
1101 /* long long timestamp; */
1102 int stream_id = videoStream;
1105 int i, v, len, got_picture;
1108 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1109 char pgm_name[256] = {0, };
1111 int key_search_limit = 0;
1112 int frame_search_limit = 0;
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
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
1122 first_frame = av_frame_alloc();
1123 tmp_frame = av_frame_alloc();
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;
1132 #ifdef __MMFILE_TEST_MODE__
1133 debug_msg("frame: 1. %p, 2. %p\n", first_frame, tmp_frame);
1136 #ifdef __MMFILE_FFMPEG_V085__
1137 pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1139 pCodecCtx->hurry_up = 1;
1143 key_search_limit = _KEY_SEARCH_LIMIT_CDIS;
1144 frame_search_limit = _FRAME_SEARCH_LIMIT_CDIS;
1146 key_search_limit = _KEY_SEARCH_LIMIT;
1147 frame_search_limit = _FRAME_SEARCH_LIMIT;
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);
1154 ret = av_read_frame(pFormatCtx, &pkt);
1156 debug_error("read failed. (maybe EOF or broken)\n");
1159 if (pkt.stream_index == stream_id) {
1161 #ifdef __MMFILE_FFMPEG_V085__
1162 if ((pkt.flags & AV_PKT_FLAG_KEY) || (key_detected == 1))
1164 if ((pkt.flags & PKT_FLAG_KEY) || (key_detected == 1))
1167 #ifdef __MMFILE_TEST_MODE__
1168 debug_msg("video frame: %d, %d, %d\n", retry, i, v);
1169 _dump_av_packet(&pkt);
1174 #ifdef __MMFILE_FFMPEG_V085__
1175 len = avcodec_decode_video2(pCodecCtx, frame, &got_picture, &pkt);
1177 len = avcodec_decode_video(pCodecCtx, frame, &got_picture, pkt.data, pkt.size);
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");
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);
1193 #ifdef __MMFILE_TEST_MODE__
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);
1203 #ifdef __MMFILE_TEST_MODE__
1204 debug_msg("is good frame.\n");
1208 /*reset video frame count & retry searching*/
1209 #ifdef __MMFILE_TEST_MODE__
1210 debug_warning("not good fame. retry scanning.\n");
1217 /*set buffer frame*/
1221 if (retry > _RETRY_SEARCH_LIMIT) break;
1224 #ifdef __MMFILE_TEST_MODE__
1225 debug_msg("skip (not key frame).\n");
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);
1233 #ifdef __MMFILE_TEST_MODE__
1234 debug_msg("decode not completed.\n");
1241 av_free_packet(&pkt);
1244 /*free pkt after loop breaking*/
1245 if (pkt.data) av_free_packet(&pkt);
1247 #ifdef __MMFILE_TEST_MODE__
1248 debug_msg("found: %d, retry: %d\n", found, retry);
1251 /*set decode frame to output*/
1253 ret = MMFILE_FORMAT_SUCCESS;
1254 if (retry == 0 || found == retry) {
1255 *pFrame = first_frame;
1256 if (tmp_frame) av_free(tmp_frame);
1258 *pFrame = tmp_frame;
1259 if (first_frame) av_free(first_frame);
1262 ret = MMFILE_FORMAT_FAIL;
1263 if (first_frame) av_free(first_frame);
1264 if (tmp_frame) av_free(tmp_frame);
1267 #ifdef __MMFILE_TEST_MODE__
1268 debug_msg("out frame: %p\n", *pFrame);
1271 #ifdef __MMFILE_FFMPEG_V085__
1272 pCodecCtx->skip_frame = AVDISCARD_NONE;
1274 pCodecCtx->hurry_up = 0;
1280 static int ConvertVideoCodecEnum(int AVVideoCodecID)
1282 int ret_codecid = 0;
1284 switch (AVVideoCodecID) {
1285 case AV_CODEC_ID_NONE:
1286 ret_codecid = MM_VIDEO_CODEC_NONE;
1288 case AV_CODEC_ID_MPEG1VIDEO:
1289 ret_codecid = MM_VIDEO_CODEC_MPEG1;
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;
1296 case AV_CODEC_ID_H261:
1297 ret_codecid = MM_VIDEO_CODEC_H261;
1299 case AV_CODEC_ID_H263:
1300 ret_codecid = MM_VIDEO_CODEC_H263;
1302 case AV_CODEC_ID_MPEG4:
1303 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1305 case AV_CODEC_ID_MSMPEG4V1:
1306 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1308 case AV_CODEC_ID_MSMPEG4V2:
1309 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1311 case AV_CODEC_ID_MSMPEG4V3:
1312 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1314 case AV_CODEC_ID_WMV1:
1315 ret_codecid = MM_VIDEO_CODEC_WMV;
1317 case AV_CODEC_ID_WMV2:
1318 ret_codecid = MM_VIDEO_CODEC_WMV;
1320 case AV_CODEC_ID_H263P:
1321 ret_codecid = MM_VIDEO_CODEC_H263;
1323 case AV_CODEC_ID_H263I:
1324 ret_codecid = MM_VIDEO_CODEC_H263;
1326 case AV_CODEC_ID_FLV1:
1327 ret_codecid = MM_VIDEO_CODEC_FLV;
1329 case AV_CODEC_ID_H264:
1330 ret_codecid = MM_VIDEO_CODEC_H264;
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;
1338 case AV_CODEC_ID_THEORA:
1339 ret_codecid = MM_VIDEO_CODEC_THEORA;
1341 case AV_CODEC_ID_CINEPAK:
1342 ret_codecid = MM_VIDEO_CODEC_CINEPAK;
1344 #if (!defined __MMFILE_FFMPEG_V085__ && !defined __MMFILE_LIBAV_VERSION__)
1345 case AV_CODEC_ID_XVID:
1346 ret_codecid = MM_VIDEO_CODEC_XVID;
1349 case AV_CODEC_ID_VC1:
1350 ret_codecid = MM_VIDEO_CODEC_VC1;
1352 case AV_CODEC_ID_WMV3:
1353 ret_codecid = MM_VIDEO_CODEC_WMV;
1355 case AV_CODEC_ID_AVS:
1356 ret_codecid = MM_VIDEO_CODEC_AVS;
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;
1365 #ifdef __MMFILE_LIBAV_VERSION__
1366 case AV_CODEC_ID_HEVC:
1367 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1371 ret_codecid = MM_VIDEO_CODEC_NONE;
1379 static int ConvertAudioCodecEnum(int AVAudioCodecID)
1381 int ret_codecid = 0;
1383 switch (AVAudioCodecID) {
1384 case AV_CODEC_ID_AMR_NB:
1385 case AV_CODEC_ID_AMR_WB:
1386 ret_codecid = MM_AUDIO_CODEC_AMR;
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;
1394 case AV_CODEC_ID_MP2:
1395 ret_codecid = MM_AUDIO_CODEC_MP2;
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;
1402 case AV_CODEC_ID_AAC:
1403 ret_codecid = MM_AUDIO_CODEC_AAC;
1405 case AV_CODEC_ID_AC3:
1406 ret_codecid = MM_AUDIO_CODEC_AC3;
1408 case AV_CODEC_ID_VORBIS:
1409 ret_codecid = MM_AUDIO_CODEC_VORBIS;
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;
1418 case AV_CODEC_ID_FLAC:
1419 ret_codecid = MM_AUDIO_CODEC_FLAC;
1421 case AV_CODEC_ID_ALAC:
1422 ret_codecid = MM_AUDIO_CODEC_ALAC;
1424 case AV_CODEC_ID_WAVPACK:
1425 ret_codecid = MM_AUDIO_CODEC_WAVE;
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;
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;
1439 ret_codecid = MM_AUDIO_CODEC_NONE;
1448 static int getMimeType(int formatId, char *mimeType, int buf_size)
1450 int ret = 0; /*default: success*/
1453 case MM_FILE_FORMAT_3GP:
1454 case MM_FILE_FORMAT_MP4:
1455 snprintf(mimeType, buf_size, "video/3gpp");
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");
1462 case MM_FILE_FORMAT_AVI:
1463 snprintf(mimeType, buf_size, "video/avi");
1465 case MM_FILE_FORMAT_OGG:
1466 snprintf(mimeType, buf_size, "video/ogg");
1468 case MM_FILE_FORMAT_REAL:
1469 snprintf(mimeType, buf_size, "video/vnd.rn-realmedia");
1471 case MM_FILE_FORMAT_AMR:
1472 snprintf(mimeType, buf_size, "audio/AMR");
1474 case MM_FILE_FORMAT_AAC:
1475 snprintf(mimeType, buf_size, "audio/aac");
1477 case MM_FILE_FORMAT_MP3:
1478 snprintf(mimeType, buf_size, "audio/mp3");
1480 case MM_FILE_FORMAT_AIFF:
1481 case MM_FILE_FORMAT_WAV:
1482 snprintf(mimeType, buf_size, "audio/wave");
1484 case MM_FILE_FORMAT_MID:
1485 snprintf(mimeType, buf_size, "audio/midi");
1487 case MM_FILE_FORMAT_MMF:
1488 snprintf(mimeType, buf_size, "audio/mmf");
1490 case MM_FILE_FORMAT_DIVX:
1491 snprintf(mimeType, buf_size, "video/divx");
1493 case MM_FILE_FORMAT_IMELODY:
1494 snprintf(mimeType, buf_size, "audio/iMelody");
1496 case MM_FILE_FORMAT_JPG:
1497 snprintf(mimeType, buf_size, "image/jpeg");
1499 case MM_FILE_FORMAT_AU:
1500 snprintf(mimeType, buf_size, "audio/basic");
1502 case MM_FILE_FORMAT_VOB:
1503 snprintf(mimeType, buf_size, "video/dvd");
1505 case MM_FILE_FORMAT_FLV:
1506 snprintf(mimeType, buf_size, "video/x-flv");
1508 case MM_FILE_FORMAT_QT:
1509 snprintf(mimeType, buf_size, "video/quicktime");
1511 case MM_FILE_FORMAT_MATROSKA:
1512 snprintf(mimeType, buf_size, "video/x-matroska");
1514 case MM_FILE_FORMAT_FLAC:
1515 snprintf(mimeType, buf_size, "audio/x-flac");
1517 case MM_FILE_FORMAT_M2TS:
1518 snprintf(mimeType, buf_size, "video/MP2T");
1520 case MM_FILE_FORMAT_M2PS:
1521 snprintf(mimeType, buf_size, "video/MP2P");
1523 case MM_FILE_FORMAT_M1AUDIO:
1524 snprintf(mimeType, buf_size, "audio/x-mpegaudio");
1526 case MM_FILE_FORMAT_M1VIDEO:
1527 snprintf(mimeType, buf_size, "video/mpeg");
1533 #ifdef __MMFILE_TEST_MODE__
1534 debug_msg("id: %d, mimetype: %s\n", formatId, mimeType);