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 <libavcodec/avcodec.h>
27 #include <libavutil/samplefmt.h>
28 #ifdef __MMFILE_FFMPEG_V085__
29 #include <libswscale/swscale.h>
35 #include <drm_client.h>
38 #include "mm_file_debug.h"
39 #include "mm_file_formats.h"
40 #include "mm_file_utils.h"
41 #include "mm_file_format_ffmpeg.h"
44 #include "mm_file_format_ffmpeg_drm.h"
47 #include "mm_file_format_ffmpeg_mem.h"
50 #define _SHORT_MEDIA_LIMIT 2000 /* under X seconds duration*/
52 extern int img_convert (AVPicture *dst, int dst_pix_fmt, const AVPicture *src, int src_pix_fmt,int src_width, int src_height);
54 /* internal functions */
55 static int _is_good_pgm (unsigned char *buf, int wrap, int xsize, int ysize);
56 #ifdef MMFILE_FORMAT_DEBUG_DUMP
57 static void _save_pgm (unsigned char *buf, int wrap, int xsize, int ysize, char *filename);
59 #ifdef __MMFILE_TEST_MODE__
60 static void _dump_av_packet (AVPacket *pkt);
63 static int _get_video_fps (int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup);
64 static int _get_first_good_video_frame (AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis);
66 static int ConvertVideoCodecEnum (int AVVideoCodecID);
67 static int ConvertAudioCodecEnum (int AVAudioCodecID);
69 /* plugin manadatory API */
70 int mmfile_format_read_stream_ffmpg (MMFileFormatContext * formatContext);
71 int mmfile_format_read_frame_ffmpg (MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
72 int mmfile_format_read_tag_ffmpg (MMFileFormatContext *formatContext);
73 int mmfile_format_close_ffmpg (MMFileFormatContext *formatContext);
74 static int getMimeType(int formatId, char *mimeType, int buf_size);
79 int mmfile_format_open_ffmpg (MMFileFormatContext *formatContext)
81 AVFormatContext *pFormatCtx = NULL;
82 AVInputFormat *grab_iformat = NULL;
86 drm_content_info_s contentInfo = {0,};
88 char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0,};
89 char mimeType[MMFILE_MIMETYPE_MAX_LEN] = {0,};
91 formatContext->ReadStream = mmfile_format_read_stream_ffmpg;
92 formatContext->ReadFrame = mmfile_format_read_frame_ffmpg;
93 formatContext->ReadTag = mmfile_format_read_tag_ffmpg;
94 formatContext->Close = mmfile_format_close_ffmpg;
96 #ifdef __MMFILE_TEST_MODE__
97 debug_msg ("ffmpeg version: %d\n", avformat_version ());
108 av_log_set_level (AV_LOG_DEBUG);
110 av_log_set_level (AV_LOG_QUIET);
115 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
117 #if (defined __MMFILE_FFMPEG_V085__ && ! defined __MMFILE_LIBAV_VERSION__)
118 ffurl_register_protocol(&MMFileMEMProtocol, sizeof (URLProtocol));
120 register_protocol (&MMFileMEMProtocol);
122 if(getMimeType(formatContext->filesrc->memory.format,mimeType, MMFILE_MIMETYPE_MAX_LEN)< 0) {
123 debug_error ("error: Error in MIME Type finding\n");
124 return MMFILE_FORMAT_FAIL;
127 memset (ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
129 ret = mmfile_util_get_ffmpeg_format (mimeType,ffmpegFormatName);
131 if (MMFILE_UTIL_SUCCESS != ret) {
132 debug_error ("error: mmfile_util_get_ffmpeg_format\n");
133 return MMFILE_FORMAT_FAIL;
136 grab_iformat = av_find_input_format (ffmpegFormatName);
138 if (NULL == grab_iformat) {
139 debug_error ("error: cannot find format\n");
143 #ifdef __MMFILE_FFMPEG_V085__
144 ret = avformat_open_input (&pFormatCtx, formatContext->uriFileName, grab_iformat, NULL);
146 ret = av_open_input_file (&pFormatCtx, formatContext->uriFileName, grab_iformat, 0, NULL);
149 debug_error("error: cannot open %s %d\n", formatContext->uriFileName, ret);
152 formatContext->privateFormatData = pFormatCtx;
155 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_FILE) {
157 if (formatContext->isdrm == MM_FILE_DRM_OMA) {
159 if (formatContext->formatType == MM_FILE_FORMAT_DIVX || formatContext->formatType == MM_FILE_FORMAT_AVI) {
160 goto HANDLING_DRM_DIVX;
163 #ifdef __MMFILE_FFMPEG_V085__
164 ffurl_register_protocol(&MMFileDRMProtocol, sizeof (URLProtocol));
166 register_protocol (&MMFileDRMProtocol);
168 memset(&contentInfo, 0x0, sizeof(drm_content_info_s));
169 if (DRM_RETURN_SUCCESS != drm_get_content_info (formatContext->filesrc->file.path, &contentInfo)) {
170 debug_error ("error: drm_get_content_info\n");
171 return MMFILE_FORMAT_FAIL;
174 memset (ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
176 ret = mmfile_util_get_ffmpeg_format (contentInfo.mime_type, ffmpegFormatName);
177 if (MMFILE_UTIL_SUCCESS != ret) {
178 debug_error ("error: mmfile_util_get_ffmpeg_format\n");
179 return MMFILE_FORMAT_FAIL;
182 #ifdef __MMFILE_TEST_MODE__
183 debug_warning ("FFMPEG: test........... : %s\n", ffmpegFormatName);
184 debug_warning ("FFMPEG: DRM URI = %s\n", formatContext->uriFileName);
185 debug_warning ("FFMPEG: ffmpeg name = %s\n", ffmpegFormatName);
188 grab_iformat = av_find_input_format (ffmpegFormatName);
190 if (NULL == grab_iformat) {
191 debug_error ("error: cannot find format\n");
195 #ifdef __MMFILE_FFMPEG_V085__
196 ret = avformat_open_input (&pFormatCtx, formatContext->uriFileName, grab_iformat, NULL);
198 ret = av_open_input_file (&pFormatCtx, formatContext->uriFileName, grab_iformat, 0, NULL);
201 debug_error("error: cannot open %s %d\n", formatContext->uriFileName, ret);
204 formatContext->privateFormatData = pFormatCtx;
208 #ifdef __MMFILE_FFMPEG_V085__
209 ret = avformat_open_input(&pFormatCtx, formatContext->filesrc->file.path, NULL, NULL);
211 ret = av_open_input_file(&pFormatCtx, formatContext->filesrc->file.path, NULL, 0, NULL);
214 debug_error("error: cannot open %s %d\n", formatContext->filesrc->file.path, ret);
218 formatContext->privateFormatData = pFormatCtx;
222 if (!pFormatCtx/* || !(pFormatCtx->nb_streams > 0)*/) {
223 debug_warning ("failed to find av stream. maybe corrupted data.\n");
227 #ifdef __MMFILE_TEST_MODE__
228 debug_msg ("number of stream: %d\n", pFormatCtx->nb_streams);
231 formatContext->videoTotalTrackNum = 0;
232 formatContext->audioTotalTrackNum = 0;
234 for(i = 0; i < pFormatCtx->nb_streams; i++) {
235 #ifdef __MMFILE_FFMPEG_V085__
236 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
237 #ifdef __MMFILE_TEST_MODE__
238 debug_msg ("FFMPEG video codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
241 AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
242 if((pkt.data != NULL) && (pkt.size > 0))
245 //eventhough codec_id is 0, avformat_find_stream_info() can find proper codec_id.
246 formatContext->videoTotalTrackNum += 1;
248 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
249 #ifdef __MMFILE_TEST_MODE__
250 debug_msg ("FFMPEG audio codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
252 formatContext->audioTotalTrackNum += 1;
255 if (pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_VIDEO) {
256 #ifdef __MMFILE_TEST_MODE__
257 debug_msg ("FFMPEG video codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
259 formatContext->videoTotalTrackNum += 1;
261 if (pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_AUDIO) {
262 #ifdef __MMFILE_TEST_MODE__
263 debug_msg ("FFMPEG audio codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
265 formatContext->audioTotalTrackNum += 1;
270 #ifdef __MMFILE_TEST_MODE__
271 debug_msg ("format: %s (%s)\n", pFormatCtx->iformat->name, pFormatCtx->iformat->long_name);
272 #ifdef __MMFILE_FFMPEG_V085__
273 av_dump_format (pFormatCtx, 0, formatContext->filesrc->file.path, 0);
275 dump_format (pFormatCtx, 0, formatContext->filesrc->file.path, 0);
279 return MMFILE_FORMAT_SUCCESS;
281 exception: /* fail to get content information */
283 mmfile_format_close_ffmpg (formatContext);
284 formatContext->privateFormatData = NULL;
286 return MMFILE_FORMAT_FAIL;
289 static bool __check_uhqa(int sample_rate, enum AVSampleFormat sample_fmt_info)
293 #ifdef __MMFILE_TEST_MODE__
294 debug_error("[sample rate %d, sample format %d]", sample_rate, sample_fmt_info);
297 if ((sample_rate >= 44100) && (sample_fmt_info >= AV_SAMPLE_FMT_S32)) {
298 #ifdef __MMFILE_TEST_MODE__
299 debug_msg("UHQA CONTENT");
310 int mmfile_format_read_stream_ffmpg (MMFileFormatContext * formatContext)
312 AVFormatContext *pFormatCtx = NULL;
313 AVCodecContext *pAudioCodecCtx = NULL;
314 AVCodecContext *pVideoCodecCtx = NULL;
316 MMFileFormatStream *videoStream = NULL;
317 MMFileFormatStream *audioStream = NULL;
320 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
321 debug_error ("invalid param\n");
322 return MMFILE_FORMAT_FAIL;
325 pFormatCtx = formatContext->privateFormatData;
326 pFormatCtx->start_time = -1;
329 *@important if data is corrupted, occur segment fault by av_find_stream_info().
330 * - fixed 2009-06-25.
332 #ifdef __MMFILE_FFMPEG_V100__
333 if (formatContext->cdis != 1)
334 ret = avformat_find_stream_info (pFormatCtx, NULL);
338 ret = av_find_stream_info (pFormatCtx);
341 debug_warning ("failed to find stream info. errcode = %d\n", ret);
345 #ifdef __MMFILE_TEST_MODE__
346 debug_msg ("FFMPEG: dur %lld, start %lld\n", pFormatCtx->duration, pFormatCtx->start_time);
350 *@note asf has long duration bug. and Some content's start time is wrong(negative number).
352 if(pFormatCtx->start_time < 0) {
353 debug_warning ("Wrong Start time = %lld\n", pFormatCtx->start_time);
354 formatContext->duration = (long long)(pFormatCtx->duration) * 1000 / AV_TIME_BASE;
357 formatContext->duration = (long long)(pFormatCtx->duration + pFormatCtx->start_time) * 1000 / AV_TIME_BASE;
360 formatContext->videoStreamId = -1;
361 formatContext->audioStreamId = -1;
362 formatContext->nbStreams = 0;
363 formatContext->videoTotalTrackNum = 0;
364 formatContext->audioTotalTrackNum = 0;
367 for ( i = 0; i < pFormatCtx->nb_streams; i++ ) {
368 #ifdef __MMFILE_FFMPEG_V085__
369 if ( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
371 if ( pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_VIDEO) {
373 if (formatContext->videoStreamId == -1) {
374 videoStream = mmfile_malloc (sizeof(MMFileFormatStream));
375 if (NULL == videoStream) {
376 debug_error ("mmfile_malloc error\n");
380 videoStream->streamType = MMFILE_VIDEO_STREAM;
381 formatContext->streams[MMFILE_VIDEO_STREAM] = videoStream;
382 formatContext->nbStreams += 1;
383 formatContext->videoStreamId = i;
384 formatContext->videoTotalTrackNum += 1;
386 pVideoCodecCtx = pFormatCtx->streams[i]->codec;
387 if (pVideoCodecCtx) {
388 videoStream->codecId = ConvertVideoCodecEnum (pVideoCodecCtx->codec_id);
389 if (videoStream->codecId == MM_VIDEO_CODEC_NONE) {
390 debug_error("Proper codec is not found in [%d] stream", i);
391 formatContext->videoStreamId = -1;
392 mmfile_free(videoStream);
393 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
400 * 1. try to get average fps of video stream.
401 * 2. if (1) failed, try to get fps of media container.
403 videoStream->framePerSec = _get_video_fps (pFormatCtx->streams[i]->nb_frames,
404 pFormatCtx->streams[i]->duration,
405 pFormatCtx->streams[i]->time_base,
408 if (videoStream->framePerSec == 0) {
409 #ifndef __MMFILE_LIBAV_VERSION__
410 videoStream->framePerSec = av_q2d (pFormatCtx->streams[i]->r_frame_rate);
412 videoStream->framePerSec = av_q2d (pFormatCtx->streams[i]->avg_frame_rate);
416 videoStream->width = pVideoCodecCtx->width;
417 videoStream->height = pVideoCodecCtx->height;
418 videoStream->bitRate = pVideoCodecCtx->bit_rate;
422 #ifdef __MMFILE_FFMPEG_V085__
423 else if ( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO ) {
425 else if ( pFormatCtx->streams[i]->codec->codec_type == AV_CODEC_TYPE_AUDIO ) {
427 if (formatContext->audioStreamId == -1) {
428 audioStream = mmfile_malloc (sizeof(MMFileFormatStream));
429 if (NULL == audioStream) {
430 debug_error ("mmfile_malloc error\n");
434 audioStream->streamType = MMFILE_AUDIO_STREAM;
435 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
436 formatContext->nbStreams += 1;
437 formatContext->audioStreamId = i;
438 formatContext->audioTotalTrackNum += 1;
440 pAudioCodecCtx = pFormatCtx->streams[i]->codec;
441 if (pAudioCodecCtx) {
442 audioStream->codecId = ConvertAudioCodecEnum (pAudioCodecCtx->codec_id);
443 audioStream->bitRate = pAudioCodecCtx->bit_rate;
444 audioStream->nbChannel = pAudioCodecCtx->channels;
445 audioStream->samplePerSec = pAudioCodecCtx->sample_rate;
446 if (audioStream->codecId == MM_AUDIO_CODEC_FLAC)
447 audioStream->bitPerSample = pAudioCodecCtx->bits_per_raw_sample;
449 audioStream->bitPerSample = pAudioCodecCtx->bits_per_coded_sample;
450 audioStream->is_uhqa = __check_uhqa(audioStream->samplePerSec, pFormatCtx->streams[i]->codec->sample_fmt);
456 if ( formatContext->nbStreams == 0 ) {
457 debug_error("error: there is no audio and video track\n");
461 #ifdef __MMFILE_TEST_MODE__
462 mmfile_format_print_contents (formatContext);
465 return MMFILE_FORMAT_SUCCESS;
469 mmfile_free (videoStream);
470 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
474 mmfile_free (audioStream);
475 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
479 #ifdef __MMFILE_FFMPEG_V100__
480 avformat_close_input (&pFormatCtx);
482 av_close_input_file (pFormatCtx);
484 formatContext->privateFormatData = NULL;
487 formatContext->audioTotalTrackNum = 0;
488 formatContext->videoTotalTrackNum = 0;
489 formatContext->nbStreams = 0;
491 return MMFILE_FORMAT_FAIL;
494 #define DATA_LENGTH 4
495 #define POS_OF_MIME_LEN DATA_LENGTH
496 #define CONVERT_TO_INT(dest, src) {dest = 0; dest |= (0 |src[0] << 24) | (0 | src[1] << 16) | (0 | src[2] << 8) | (0 | src[3]);}
499 int mmfile_format_read_tag_ffmpg (MMFileFormatContext *formatContext)
501 AVFormatContext *pFormatCtx = NULL;
503 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
504 debug_error ("invalid param\n");
505 return MMFILE_FORMAT_FAIL;
508 pFormatCtx = formatContext->privateFormatData;
510 if (formatContext->formatType == MM_FILE_FORMAT_3GP ||formatContext->formatType == MM_FILE_FORMAT_MP4) {
511 MMFileUtilGetMetaDataFromMP4 (formatContext);
514 #ifdef __MMFILE_FFMPEG_V085__
515 /*metadata extracted by ffmpeg*/
518 if(pFormatCtx != NULL) {
519 for(idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) {
520 AVDictionary *metainfo = NULL;
523 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.
524 st = pFormatCtx->streams[idx];
526 metainfo = st->metadata;
527 } else { //Check metadata of Content
528 if(pFormatCtx->metadata != NULL) {
529 metainfo = pFormatCtx->metadata;
535 /*refer to mov_read_covr() in ffmpeg.*/
537 AVPacket pkt = st->attached_pic;
538 int codec_id = st->codec->codec_id;
540 if((pkt.data != NULL) && (pkt.size > 0)) {
542 if (formatContext->artworkMime) mmfile_free (formatContext->artworkMime);
544 if(codec_id == AV_CODEC_ID_MJPEG)
545 formatContext->artworkMime = mmfile_strdup("image/jpeg");
546 else if(codec_id == AV_CODEC_ID_PNG)
547 formatContext->artworkMime = mmfile_strdup("image/png");
548 else if(codec_id == AV_CODEC_ID_BMP)
549 formatContext->artworkMime = mmfile_strdup("image/bmp");
551 debug_error ("Unknown cover type: 0x%x\n", codec_id);
554 if (formatContext->artwork) mmfile_free (formatContext->artwork);
556 formatContext->artworkSize = pkt.size;
557 formatContext->artwork = mmfile_malloc (pkt.size);
558 memcpy (formatContext->artwork, pkt.data, pkt.size);
562 if(metainfo != NULL) {
563 AVDictionaryEntry *tag = NULL;
564 while((tag=av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) {
565 if(tag->key != NULL) {
566 if(!strcasecmp(tag->key, "title")) {
567 if (formatContext->title) free (formatContext->title);
568 formatContext->title = mmfile_strdup (tag->value);
569 } else if(!strcasecmp(tag->key, "artist")) {
570 if (formatContext->artist) free (formatContext->artist);
571 formatContext->artist = mmfile_strdup (tag->value);
572 } else if(!strcasecmp(tag->key, "composer")) {
573 if (formatContext->composer) free (formatContext->composer);
574 formatContext->composer = mmfile_strdup (tag->value);
575 } else if(!strcasecmp(tag->key, "album")) {
576 if (formatContext->album) free (formatContext->album);
577 formatContext->album = mmfile_strdup (tag->value);
578 } else if(!strcasecmp(tag->key, "album_artist")) {
579 if (formatContext->album_artist) free (formatContext->album_artist);
580 formatContext->album_artist = mmfile_strdup (tag->value);
581 } else if(!strcasecmp(tag->key, "copyright")) {
582 if (formatContext->copyright) free (formatContext->copyright);
583 formatContext->copyright = mmfile_strdup (tag->value);
584 } else if(!strcasecmp(tag->key, "comment")) {
585 if (formatContext->comment) free (formatContext->comment);
586 formatContext->comment = mmfile_strdup (tag->value);
587 } else if(!strcasecmp(tag->key, "description")) {
588 if (formatContext->description) free (formatContext->description);
589 formatContext->description = mmfile_strdup (tag->value);
590 } else if(!strcasecmp(tag->key, "genre")) {
591 if (formatContext->genre) free (formatContext->genre);
592 formatContext->genre = mmfile_strdup (tag->value);
593 } else if(!strcasecmp(tag->key, "date")) {
594 if (formatContext->year) free (formatContext->year);
595 formatContext->year = mmfile_strdup (tag->value);
596 } else if(!strcasecmp(tag->key, "creation_time")) {
597 if (formatContext->recDate) free (formatContext->recDate);
598 formatContext->recDate = mmfile_strdup (tag->value);
599 } else if((!strcasecmp(tag->key, "track")) || (!strcasecmp(tag->key, "tracknumber"))) {
600 if (formatContext->tagTrackNum) free (formatContext->tagTrackNum);
601 formatContext->tagTrackNum = mmfile_strdup (tag->value);
602 } else if(!strcasecmp(tag->key, "lyrics")) {
603 if (formatContext->unsyncLyrics) free (formatContext->unsyncLyrics);
604 formatContext->unsyncLyrics= mmfile_strdup (tag->value);
605 } else if(!strcasecmp(tag->key, "rotate")) { //can be "90", "180", "270"
606 if (formatContext->rotate) free (formatContext->rotate);
607 formatContext->rotate= mmfile_strdup (tag->value);
608 } else if(!strcasecmp(tag->key, "metadata_block_picture")) {
610 guchar *meta_data = NULL;
612 meta_data = g_base64_decode(tag->value, &len);
613 if (meta_data != NULL) {
614 /* in METADATA_BLOCK_PICTURE,
615 the length of mime type and the length of description are flexible,
616 so, we have to get the length of their for getting correct postion of picture data. */
618 int description_len = 0;
621 unsigned char current_data[DATA_LENGTH] = {0};
623 /* get length of mime_type */
624 memcpy(current_data, meta_data + POS_OF_MIME_LEN, DATA_LENGTH);
625 CONVERT_TO_INT(mime_len, current_data);
627 /* get length of description */
628 current_pos = mime_len + (DATA_LENGTH * 2); /*current position is length of description */
629 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
630 CONVERT_TO_INT(description_len, current_data);
632 /* get length of picture data */
633 current_pos = mime_len + description_len + (DATA_LENGTH * 7); /*current position is length of picture data */
634 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
635 CONVERT_TO_INT(data_len, current_data);
637 /* set the size of art work */
638 formatContext->artworkSize = data_len;
641 current_pos = POS_OF_MIME_LEN + DATA_LENGTH; /*current position is mime type */
642 if (formatContext->artworkMime) mmfile_free (formatContext->artworkMime);
643 formatContext->artworkMime = strndup((const char*)meta_data + current_pos, mime_len);
645 /* set art work data */
646 current_pos = mime_len + description_len + (DATA_LENGTH * 8); /*current position is picture data */
647 if (formatContext->artwork) mmfile_free (formatContext->artwork);
649 formatContext->artwork = mmfile_malloc (data_len);
650 if(formatContext->artwork != NULL)
651 memcpy(formatContext->artwork, meta_data + current_pos, data_len);
656 #ifdef __MMFILE_TEST_MODE__
657 debug_log("Not support metadata. [%s:%s]", tag->key, tag->value);
663 #ifdef __MMFILE_TEST_MODE__
664 mmfile_format_print_tags (formatContext);
669 if (pFormatCtx->title[0]) {
670 if (formatContext->title)
671 free (formatContext->title);
672 formatContext->title = mmfile_strdup (pFormatCtx->title);
674 if (pFormatCtx->author[0]){
675 if (formatContext->author)
676 free (formatContext->author);
677 formatContext->author = mmfile_strdup (pFormatCtx->author);
679 if (pFormatCtx->copyright[0]) {
680 if (formatContext->copyright)
681 free (formatContext->copyright);
682 formatContext->copyright = mmfile_strdup (pFormatCtx->copyright);
684 if (pFormatCtx->comment[0]) {
685 if (formatContext->comment)
686 free (formatContext->comment);
687 formatContext->comment = mmfile_strdup (pFormatCtx->comment);
689 if (pFormatCtx->album[0]) {
690 if (formatContext->album)
691 free (formatContext->album);
692 formatContext->album = mmfile_strdup (pFormatCtx->album);
694 if (pFormatCtx->genre[0]) {
695 if (formatContext->genre)
696 free (formatContext->genre);
697 formatContext->genre = mmfile_strdup (pFormatCtx->genre);
700 if (pFormatCtx->year) {
701 char year[10] = {0,};
702 snprintf (year, 10, "%d", pFormatCtx->year);
704 if (formatContext->year)
705 free (formatContext->year);
706 formatContext->year = mmfile_strdup (year);
709 if (pFormatCtx->track) {
710 char tracknum[10] = {0,};
711 snprintf (tracknum, 10, "%d", pFormatCtx->track);
713 if (formatContext->tagTrackNum)
714 free (formatContext->tagTrackNum);
715 formatContext->tagTrackNum = mmfile_strdup (tracknum);
719 return MMFILE_FORMAT_SUCCESS;
724 int mmfile_format_read_frame_ffmpg (MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
726 AVFormatContext *pFormatCtx = NULL;
727 AVCodecContext *pVideoCodecCtx = NULL;
728 AVCodec *pVideoCodec = NULL;
729 AVFrame *pFrame = NULL;
730 AVFrame *pFrameRGB = NULL;
737 if (NULL == formatContext ||
739 NULL == formatContext->privateFormatData ||
740 formatContext->videoTotalTrackNum <= 0) {
742 debug_error ("invalid param\n");
743 return MMFILE_FORMAT_FAIL;
746 if (formatContext->isdrm == MM_FILE_DRM_PROTECTED) {
747 debug_error ("This is protected drm file\n");
748 return MMFILE_FORMAT_FAIL;
751 pFormatCtx = formatContext->privateFormatData;
753 if (formatContext->videoStreamId != -1) {
754 pVideoCodecCtx = pFormatCtx->streams[formatContext->videoStreamId]->codec;
755 if (NULL == pVideoCodecCtx) {
756 debug_error ("invalid param\n");
757 return MMFILE_FORMAT_FAIL;
760 pVideoCodec = avcodec_find_decoder (pVideoCodecCtx->codec_id);
761 if ( NULL == pVideoCodec ) {
762 debug_error ("error: avcodec_find_decoder failed\n");
763 return MMFILE_FORMAT_FAIL;
766 #ifdef __MMFILE_TEST_MODE__
767 debug_msg ("flag: 0x%08X\n", pVideoCodec->capabilities);
768 // debug_msg (" DRAW_HORIZ_BAND : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND ? 1 : 0);
769 // debug_msg (" DR1 : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_DR1 ? 1 : 0);
770 // debug_msg (" PARSE_ONLY : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_PARSE_ONLY ? 1 : 0);
771 // debug_msg (" TRUNCATED : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_TRUNCATED ? 1 : 0);
772 // debug_msg (" HWACCEL : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_HWACCEL ? 1 : 0);
773 // debug_msg (" DELAY : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_DELAY ? 1 : 0);
774 // debug_msg (" SMALL_LAST_FRAME: %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME ? 1 : 0);
775 // debug_msg (" HWACCEL_VDPAU : %d\n", pVideoCodec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU ? 1 : 0);
778 if (pVideoCodec->capabilities & CODEC_CAP_TRUNCATED) {
779 pVideoCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
782 /*set workaround bug flag*/
783 pVideoCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
784 #ifdef __MMFILE_FFMPEG_V100__
785 /* this is solution for PLM issue P13091703323 */
786 /* If using thread when decoding frame, the result of decoding is not always same.
787 Thumbnail of video content is different with original file when copying file. */
788 pVideoCodecCtx->thread_type = 0;
789 pVideoCodecCtx->thread_count = 0;
790 ret = avcodec_open2 (pVideoCodecCtx, pVideoCodec, NULL);
792 ret = avcodec_open (pVideoCodecCtx, pVideoCodec);
795 debug_error ("error: avcodec_open fail.\n");
796 return MMFILE_FORMAT_FAIL;
799 pFrameRGB = avcodec_alloc_frame ();
802 debug_error ("error: pFrame or pFrameRGB is NULL\n");
803 ret = MMFILE_FORMAT_FAIL;
807 /* search & decode */
808 // seek_ts = formatContext->duration > _SHORT_MEDIA_LIMIT ? seek_ts : 0; /*if short media, seek first key frame*/
809 ret = _get_first_good_video_frame (pFormatCtx, pVideoCodecCtx, formatContext->videoStreamId, &pFrame, formatContext->cdis);
810 if ( ret != MMFILE_FORMAT_SUCCESS ) {
811 debug_error ("error: get key frame\n");
812 ret = MMFILE_FORMAT_FAIL;
816 #ifdef __MMFILE_TEST_MODE__
817 debug_msg ("Video default resolution = [%dx%d]\n", pVideoCodecCtx->coded_width, pVideoCodecCtx->coded_height);
818 debug_msg ("Video coded resolution = [%dx%d]\n", pVideoCodecCtx->width, pVideoCodecCtx->height);
821 /*sometimes, ffmpeg's width/height is wrong*/
822 #if 0 /*coded_width/height sometimes wrong. so use width/height*/
823 width = pVideoCodecCtx->coded_width == 0 ? pVideoCodecCtx->width : pVideoCodecCtx->coded_width;
824 height = pVideoCodecCtx->coded_height == 0 ? pVideoCodecCtx->height : pVideoCodecCtx->coded_height;
826 if((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
827 width = pVideoCodecCtx->coded_width;
828 height = pVideoCodecCtx->coded_height;
830 width = pVideoCodecCtx->width;
831 height = pVideoCodecCtx->height;
834 numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
836 debug_error ("error: avpicture_get_size. [%d x %d]\n", width, height);
837 ret = MMFILE_FORMAT_FAIL;
841 frame->frameData = mmfile_malloc (numBytes);
842 if (NULL == frame->frameData) {
843 debug_error ("error: avpicture_get_size. [%d]\n", numBytes);
844 ret = MMFILE_FORMAT_FAIL;
848 ret = avpicture_fill ((AVPicture *)pFrameRGB, frame->frameData, PIX_FMT_RGB24, width, height);
850 debug_error ("error: avpicture_fill fail. errcode = 0x%08X\n", ret);
851 ret = MMFILE_FORMAT_FAIL;
855 #ifdef __MMFILE_FFMPEG_V085__
856 struct SwsContext *img_convert_ctx = NULL;
858 img_convert_ctx = sws_getContext (width, height, pVideoCodecCtx->pix_fmt,
859 width, height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
861 if (NULL == img_convert_ctx) {
862 debug_error ("failed to get img convet ctx\n");
863 ret = MMFILE_FORMAT_FAIL;
867 ret = sws_scale (img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize,
868 0, height, pFrameRGB->data, pFrameRGB->linesize);
870 debug_error ("failed to convet image\n");
871 ret = MMFILE_FORMAT_FAIL;
872 sws_freeContext(img_convert_ctx);
873 img_convert_ctx = NULL;
877 sws_freeContext(img_convert_ctx);
878 img_convert_ctx = NULL;
880 ret = img_convert ((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pVideoCodecCtx->pix_fmt, width, height);
882 debug_error ("failed to convet image\n");
883 ret = MMFILE_FORMAT_FAIL;
887 frame->frameSize = numBytes;
888 frame->frameWidth = width;
889 frame->frameHeight = height;
890 frame->configLenth = 0;
891 frame->bCompressed = 0; /* false */
893 if (pFrame) av_free (pFrame);
894 if (pFrameRGB) av_free (pFrameRGB);
896 avcodec_close(pVideoCodecCtx);
898 return MMFILE_FORMAT_SUCCESS;
903 if (pVideoCodecCtx) avcodec_close (pVideoCodecCtx);
904 if (frame->frameData) { mmfile_free (frame->frameData); frame->frameData = NULL; }
905 if (pFrame) av_free (pFrame);
906 if (pFrameRGB) av_free (pFrameRGB);
912 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext)
915 AVFormatContext *pFormatCtx = formatContext->privateFormatData;
918 #ifdef __MMFILE_FFMPEG_V100__
919 avformat_close_input(&pFormatCtx);
921 av_close_input_file (pFormatCtx);
923 formatContext->privateFormatData = NULL;
927 return MMFILE_FORMAT_SUCCESS;
931 * return average of difference
933 static unsigned int _diff_memory (const void *s1, const void *s2, unsigned int n)
935 char *s = (char *)s1;
936 char *d = (char *)s2;
941 for (i = 0, ret = 0; i < n; i++) {
944 ret += (tmp < 0 ? -tmp : tmp);
951 int64_t gettime(void)
954 gettimeofday(&tv,NULL);
955 return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
959 #define IS_GOOD_OLD_METHOD
960 #ifdef IS_GOOD_OLD_METHOD
962 * compare with center line.
964 static int _is_good_pgm (unsigned char *buf, int wrap, int xsize, int ysize)
966 #define _MM_CHUNK_NUM 8 /*FIXME*/
967 #define _MM_CHUNK_LIMIT (_MM_CHUNK_NUM / 2)
968 #define _MM_CHUNK_DIFF_LIMIT (_MM_CHUNK_LIMIT * 2 + 1) /*FIXME*/
973 unsigned char *cnt; /*center line of image*/
975 unsigned int sum_diff;
979 step = ysize / _MM_CHUNK_NUM;
980 cnt_offset = (ysize / 2);
981 cnt = buf + cnt_offset * wrap;
983 #ifdef __MMFILE_TEST_MODE__
984 debug_msg ("checking frame. %p, %d, %d, %d\n", buf, wrap, xsize, ysize);
987 /*if too small, always ok return.*/
988 if (ysize < _MM_CHUNK_NUM)
991 for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
992 if (i != cnt_offset) {
995 is_different = _diff_memory (cnt, buf + i * wrap, xsize);
996 point += (is_different == 0 ? 0 : 1);
997 sum_diff += is_different;
999 #ifdef __MMFILE_TEST_MODE__
1000 debug_msg ("check %04d line. %s [%d]\n", i, (is_different == 0 ? "same" : "different"), is_different);
1003 if (point >= _MM_CHUNK_LIMIT) {
1004 if (sum_diff > _MM_CHUNK_DIFF_LIMIT) {
1005 #ifdef __MMFILE_TEST_MODE__
1006 debug_msg ("Good :-)\n");
1010 #ifdef __MMFILE_TEST_MODE__
1011 debug_msg ("Bad :-(\n");
1021 #else // IS_GOOD_OLD_METHOD
1022 /* ToDo : for enhancement */
1023 #endif // IS_GOOD_OLD_METHOD
1028 _get_video_fps (int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
1032 #ifdef __MMFILE_TEST_MODE__
1033 debug_msg ("frame count: %d, dur: %d, num: %d, den: %d\n", frame_cnt, duration, r_frame_rate.num, r_frame_rate.den);
1036 if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
1039 round = (is_roundup != 0 ? 0.50f : 0.00f);
1041 fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
1046 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1047 static void _save_pgm (unsigned char *buf,int wrap, int xsize,int ysize,char *filename)
1052 f = fopen(filename,"w");
1054 fprintf (f,"P5\n%d %d\n%d\n",xsize,ysize,255);
1055 for (i = 0; i < ysize; i++)
1056 fwrite (buf + i * wrap, 1, xsize, f);
1062 #ifdef __MMFILE_TEST_MODE__
1063 static void _dump_av_packet (AVPacket *pkt)
1065 debug_msg ("--------- AV Packet -----------\n");
1066 debug_msg (" pts: %lld\n", pkt->pts);
1067 debug_msg (" dts: %lld\n", pkt->dts);
1068 debug_msg (" data: %p\n", pkt->data);
1069 debug_msg (" size: %d\n", pkt->size);
1070 debug_msg (" stream_index: %d\n", pkt->stream_index);
1071 #ifdef __MMFILE_FFMPEG_V085__
1072 debug_msg (" flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & AV_PKT_FLAG_KEY) ? "Keyframe" : "_");
1074 debug_msg (" flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & PKT_FLAG_KEY) ? "Keyframe" : "_");
1076 debug_msg (" duration: %d\n", pkt->duration);
1077 debug_msg (" destruct: %p\n", pkt->destruct);
1078 debug_msg (" priv: %p\n", pkt->priv);
1079 debug_msg (" pos: %lld\n", pkt->pos);
1080 debug_msg (" convergence_duration: %lld\n", pkt->convergence_duration);
1081 debug_msg ("-------------------------------\n");
1085 static int _get_first_good_video_frame (AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis)
1087 // AVStream *st = NULL;
1090 AVFrame *frame = NULL;
1091 AVFrame *tmp_frame = NULL;
1092 AVFrame *first_frame = NULL;
1094 // long long timestamp;
1095 int stream_id = videoStream;
1098 int i,v, len, got_picture;
1101 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1102 char pgm_name[256] = {0,};
1104 int key_search_limit = 0;
1105 int frame_search_limit = 0;
1107 #define _RETRY_SEARCH_LIMIT 75
1108 #define _KEY_SEARCH_LIMIT (_RETRY_SEARCH_LIMIT*2) /*2 = 1 read. some frame need to read one more*/
1109 #define _FRAME_SEARCH_LIMIT 500
1111 #define _RETRY_SEARCH_LIMIT_CDIS 10
1112 #define _KEY_SEARCH_LIMIT_CDIS (_RETRY_SEARCH_LIMIT*2) /*2 = 1 read. some frame need to read one more*/
1113 #define _FRAME_SEARCH_LIMIT_CDIS 10
1115 first_frame = avcodec_alloc_frame ();
1116 tmp_frame = avcodec_alloc_frame ();
1118 if (!first_frame || !tmp_frame) {
1119 debug_error ("failed to alloc frame.\n");
1120 if (first_frame) av_free (first_frame);
1121 if (tmp_frame) av_free (tmp_frame);
1122 return MMFILE_FORMAT_FAIL;
1125 #ifdef __MMFILE_TEST_MODE__
1126 debug_msg ("frame: 1. %p, 2. %p\n", first_frame, tmp_frame);
1129 #ifdef __MMFILE_FFMPEG_V085__
1130 pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1132 pCodecCtx->hurry_up = 1;
1136 key_search_limit = _KEY_SEARCH_LIMIT_CDIS;
1137 frame_search_limit = _FRAME_SEARCH_LIMIT_CDIS;
1139 key_search_limit = _KEY_SEARCH_LIMIT;
1140 frame_search_limit = _FRAME_SEARCH_LIMIT;
1143 for(i = 0, v = 0, key_detected = 0, frame = first_frame; i < key_search_limit && v < frame_search_limit;) {
1144 av_init_packet (&pkt);
1147 ret = av_read_frame (pFormatCtx, &pkt);
1149 debug_error ("read failed. (maybe EOF or broken)\n");
1152 if (pkt.stream_index == stream_id) {
1154 #ifdef __MMFILE_FFMPEG_V085__
1155 if ((pkt.flags & AV_PKT_FLAG_KEY ) || (key_detected == 1))
1157 if ((pkt.flags & PKT_FLAG_KEY ) || (key_detected == 1))
1160 #ifdef __MMFILE_TEST_MODE__
1161 debug_msg ("video frame: %d, %d, %d\n", retry, i, v);
1162 _dump_av_packet (&pkt);
1167 #ifdef __MMFILE_FFMPEG_V085__
1168 len = avcodec_decode_video2 (pCodecCtx, frame, &got_picture, &pkt);
1170 len = avcodec_decode_video (pCodecCtx, frame, &got_picture, pkt.data, pkt.size);
1173 debug_warning ("Error while decoding frame %dth\n", i);
1174 } else if (got_picture) {
1175 if (frame->key_frame) {
1176 #ifdef __MMFILE_TEST_MODE__
1177 debug_msg ("key frame!\n");
1179 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1180 sprintf (pgm_name, "./key_%d_%d_%d.pgm", retry, i, v);
1181 _save_pgm (frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1186 #ifdef __MMFILE_TEST_MODE__
1190 ret = _is_good_pgm (frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height);
1191 #ifdef __MMFILE_TEST_MODE__
1192 ti = gettime() - ti;
1193 debug_msg ("Elapsed time = %lld\n", ti);
1196 #ifdef __MMFILE_TEST_MODE__
1197 debug_msg ("is good frame.\n");
1201 /*reset video frame count & retry searching*/
1202 #ifdef __MMFILE_TEST_MODE__
1203 debug_warning ("not good fame. retry scanning.\n");
1210 /*set buffer frame*/
1214 if (retry > _RETRY_SEARCH_LIMIT) break;
1217 #ifdef __MMFILE_TEST_MODE__
1218 debug_msg ("skip (not key frame).\n");
1220 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1221 sprintf (pgm_name, "./not_key_%d_%d_%d.pgm", retry, i, v);
1222 _save_pgm (frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1226 #ifdef __MMFILE_TEST_MODE__
1227 debug_msg ("decode not completed.\n");
1234 av_free_packet (&pkt);
1237 /*free pkt after loop breaking*/
1238 if (pkt.data) av_free_packet (&pkt);
1240 #ifdef __MMFILE_TEST_MODE__
1241 debug_msg ("found: %d, retry: %d\n", found, retry);
1244 /*set decode frame to output*/
1246 ret = MMFILE_FORMAT_SUCCESS;
1247 if (retry == 0 || found == retry) {
1248 *pFrame = first_frame;
1249 if (tmp_frame) av_free (tmp_frame);
1251 *pFrame = tmp_frame;
1252 if (first_frame) av_free (first_frame);
1255 ret = MMFILE_FORMAT_FAIL;
1256 if (first_frame) av_free (first_frame);
1257 if (tmp_frame) av_free (tmp_frame);
1260 #ifdef __MMFILE_TEST_MODE__
1261 debug_msg ("out frame: %p\n", *pFrame);
1264 #ifdef __MMFILE_FFMPEG_V085__
1265 pCodecCtx->skip_frame = AVDISCARD_NONE;
1267 pCodecCtx->hurry_up = 0;
1273 static int ConvertVideoCodecEnum (int AVVideoCodecID)
1275 int ret_codecid = 0;
1277 switch (AVVideoCodecID)
1279 case AV_CODEC_ID_NONE:
1280 ret_codecid = MM_VIDEO_CODEC_NONE;
1282 case AV_CODEC_ID_MPEG1VIDEO:
1283 ret_codecid = MM_VIDEO_CODEC_MPEG1;
1285 case AV_CODEC_ID_MPEG2VIDEO: ///< preferred ID for MPEG-1/2 video decoding
1286 case AV_CODEC_ID_MPEG2VIDEO_XVMC:
1287 case AV_CODEC_ID_MPEG2TS:
1288 ret_codecid = MM_VIDEO_CODEC_MPEG2;
1290 case AV_CODEC_ID_H261:
1291 ret_codecid = MM_VIDEO_CODEC_H261;
1293 case AV_CODEC_ID_H263:
1294 ret_codecid = MM_VIDEO_CODEC_H263;
1296 case AV_CODEC_ID_MPEG4:
1297 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1299 case AV_CODEC_ID_MSMPEG4V1:
1300 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1302 case AV_CODEC_ID_MSMPEG4V2:
1303 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1305 case AV_CODEC_ID_MSMPEG4V3:
1306 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1308 case AV_CODEC_ID_WMV1:
1309 ret_codecid = MM_VIDEO_CODEC_WMV;
1311 case AV_CODEC_ID_WMV2:
1312 ret_codecid = MM_VIDEO_CODEC_WMV;
1314 case AV_CODEC_ID_H263P:
1315 ret_codecid = MM_VIDEO_CODEC_H263;
1317 case AV_CODEC_ID_H263I:
1318 ret_codecid = MM_VIDEO_CODEC_H263;
1320 case AV_CODEC_ID_FLV1:
1321 ret_codecid = MM_VIDEO_CODEC_FLV;
1323 case AV_CODEC_ID_H264:
1324 ret_codecid = MM_VIDEO_CODEC_H264;
1326 case AV_CODEC_ID_INDEO2:
1327 case AV_CODEC_ID_INDEO3:
1328 case AV_CODEC_ID_INDEO4:
1329 case AV_CODEC_ID_INDEO5:
1330 ret_codecid = MM_VIDEO_CODEC_INDEO;
1332 case AV_CODEC_ID_THEORA:
1333 ret_codecid = MM_VIDEO_CODEC_THEORA;
1335 case AV_CODEC_ID_CINEPAK:
1336 ret_codecid = MM_VIDEO_CODEC_CINEPAK;
1338 #if (!defined __MMFILE_FFMPEG_V085__ && !defined __MMFILE_LIBAV_VERSION__)
1339 case AV_CODEC_ID_XVID:
1340 ret_codecid = MM_VIDEO_CODEC_XVID;
1343 case AV_CODEC_ID_VC1:
1344 ret_codecid = MM_VIDEO_CODEC_VC1;
1346 case AV_CODEC_ID_WMV3:
1347 ret_codecid = MM_VIDEO_CODEC_WMV;
1349 case AV_CODEC_ID_AVS:
1350 ret_codecid = MM_VIDEO_CODEC_AVS;
1352 case AV_CODEC_ID_RL2:
1353 case AV_CODEC_ID_RV10: // RealVideo 1
1354 case AV_CODEC_ID_RV20: // RealVideo 2
1355 case AV_CODEC_ID_RV30: // RealVideo 3
1356 case AV_CODEC_ID_RV40: // RealVideo 4
1357 ret_codecid = MM_VIDEO_CODEC_REAL;
1359 case AV_CODEC_ID_HEVC:
1360 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1363 ret_codecid = MM_VIDEO_CODEC_NONE;
1371 static int ConvertAudioCodecEnum (int AVAudioCodecID)
1373 int ret_codecid = 0;
1375 switch (AVAudioCodecID)
1377 case AV_CODEC_ID_AMR_NB:
1378 case AV_CODEC_ID_AMR_WB:
1379 ret_codecid = MM_AUDIO_CODEC_AMR;
1381 /* RealAudio codecs*/
1382 case AV_CODEC_ID_RA_144: // RealAudio 1
1383 case AV_CODEC_ID_RA_288: // RealAudio 2
1384 case AV_CODEC_ID_COOK: // RealAudio 6
1385 ret_codecid = MM_AUDIO_CODEC_REAL;
1387 case AV_CODEC_ID_MP2:
1388 ret_codecid = MM_AUDIO_CODEC_MP2;
1390 case AV_CODEC_ID_MP3:
1391 case AV_CODEC_ID_MP3ADU:
1392 case AV_CODEC_ID_MP3ON4:
1393 ret_codecid = MM_AUDIO_CODEC_MP3;
1395 case AV_CODEC_ID_AAC:
1396 ret_codecid = MM_AUDIO_CODEC_AAC;
1398 case AV_CODEC_ID_AC3:
1399 ret_codecid = MM_AUDIO_CODEC_AC3;
1401 case AV_CODEC_ID_VORBIS:
1402 ret_codecid = MM_AUDIO_CODEC_VORBIS;
1404 case AV_CODEC_ID_WMAV1:
1405 case AV_CODEC_ID_WMAV2:
1406 case AV_CODEC_ID_WMAVOICE:
1407 case AV_CODEC_ID_WMAPRO:
1408 case AV_CODEC_ID_WMALOSSLESS:
1409 ret_codecid = MM_AUDIO_CODEC_WMA;
1411 case AV_CODEC_ID_FLAC:
1412 ret_codecid = MM_AUDIO_CODEC_FLAC;
1414 case AV_CODEC_ID_ALAC:
1415 ret_codecid = MM_AUDIO_CODEC_ALAC;
1417 case AV_CODEC_ID_WAVPACK:
1418 ret_codecid = MM_AUDIO_CODEC_WAVE;
1420 case AV_CODEC_ID_ATRAC3:
1421 case AV_CODEC_ID_ATRAC3P:
1422 case AV_CODEC_ID_EAC3:
1423 ret_codecid = MM_AUDIO_CODEC_AC3;
1425 case AV_CODEC_ID_PCM_S8:
1426 case AV_CODEC_ID_PCM_S16BE:
1427 case AV_CODEC_ID_PCM_S24BE:
1428 case AV_CODEC_ID_PCM_S32BE:
1429 ret_codecid = MM_AUDIO_CODEC_PCM;
1432 ret_codecid = MM_AUDIO_CODEC_NONE;
1441 static int getMimeType(int formatId, char *mimeType, int buf_size)
1443 int ret = 0; /*default: success*/
1446 case MM_FILE_FORMAT_3GP:
1447 case MM_FILE_FORMAT_MP4:
1448 snprintf(mimeType, buf_size, "video/3gpp");
1450 case MM_FILE_FORMAT_ASF:
1451 case MM_FILE_FORMAT_WMA:
1452 case MM_FILE_FORMAT_WMV:
1453 snprintf(mimeType, buf_size, "video/x-ms-asf");
1455 case MM_FILE_FORMAT_AVI:
1456 snprintf(mimeType, buf_size, "video/avi");
1458 case MM_FILE_FORMAT_OGG:
1459 snprintf(mimeType, buf_size, "video/ogg");
1461 case MM_FILE_FORMAT_REAL:
1462 snprintf(mimeType, buf_size, "video/vnd.rn-realmedia");
1464 case MM_FILE_FORMAT_AMR:
1465 snprintf(mimeType, buf_size, "audio/AMR");
1467 case MM_FILE_FORMAT_AAC:
1468 snprintf(mimeType, buf_size, "audio/aac");
1470 case MM_FILE_FORMAT_MP3:
1471 snprintf(mimeType, buf_size, "audio/mp3");
1473 case MM_FILE_FORMAT_AIFF:
1474 case MM_FILE_FORMAT_WAV:
1475 snprintf(mimeType, buf_size, "audio/wave");
1477 case MM_FILE_FORMAT_MID:
1478 snprintf(mimeType, buf_size, "audio/midi");
1480 case MM_FILE_FORMAT_MMF:
1481 snprintf(mimeType, buf_size, "audio/mmf");
1483 case MM_FILE_FORMAT_DIVX:
1484 snprintf(mimeType, buf_size, "video/divx");
1486 case MM_FILE_FORMAT_IMELODY:
1487 snprintf(mimeType, buf_size, "audio/iMelody");
1489 case MM_FILE_FORMAT_JPG:
1490 snprintf(mimeType, buf_size, "image/jpeg");
1492 case MM_FILE_FORMAT_AU:
1493 snprintf(mimeType, buf_size, "audio/basic");
1495 case MM_FILE_FORMAT_VOB:
1496 snprintf(mimeType, buf_size, "video/dvd");
1498 case MM_FILE_FORMAT_FLV:
1499 snprintf(mimeType, buf_size, "video/x-flv");
1501 case MM_FILE_FORMAT_QT:
1502 snprintf(mimeType, buf_size, "video/quicktime");
1504 case MM_FILE_FORMAT_MATROSKA:
1505 snprintf(mimeType, buf_size, "video/x-matroska");
1507 case MM_FILE_FORMAT_FLAC:
1508 snprintf(mimeType, buf_size, "audio/x-flac");
1510 case MM_FILE_FORMAT_M2TS:
1511 snprintf(mimeType, buf_size, "video/MP2T");
1513 case MM_FILE_FORMAT_M2PS:
1514 snprintf(mimeType, buf_size, "video/MP2P");
1516 case MM_FILE_FORMAT_M1AUDIO:
1517 snprintf(mimeType, buf_size, "audio/x-mpegaudio");
1519 case MM_FILE_FORMAT_M1VIDEO:
1520 snprintf(mimeType, buf_size, "video/mpeg");
1526 #ifdef __MMFILE_TEST_MODE__
1527 debug_msg ("id: %d, mimetype: %s\n", formatId, mimeType);