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 <libswscale/swscale.h>
30 #include "mm_file_debug.h"
31 #include "mm_file_formats.h"
32 #include "mm_file_utils.h"
33 #include "mm_file_format_ffmpeg.h"
36 #define _SHORT_MEDIA_LIMIT 2000 /* under X seconds duration*/
38 /* internal functions */
39 static int _is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize);
40 #ifdef MMFILE_FORMAT_DEBUG_DUMP
41 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename);
43 #ifdef __MMFILE_TEST_MODE__
44 static void _dump_av_packet(AVPacket *pkt);
47 static int _get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup);
48 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis);
50 static int ConvertVideoCodecEnum(int AVVideoCodecID);
51 static int ConvertAudioCodecEnum(int AVAudioCodecID);
53 /* plugin manadatory API */
54 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext);
55 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
56 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext);
57 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext);
58 static int getMimeType(int formatId, char *mimeType, int buf_size);
60 static int _mmf_mem_read(void *opaque, uint8_t *buf, int size);
61 static int64_t _mmf_mem_seek(void *opaque, int64_t pos, int whence);
70 static int _mmf_mem_open(MMFmemIOHandle **handle, const char *filename)
72 MMFmemIOHandle *memHandle = NULL;
73 char **splitedString = NULL;
75 filename += strlen(MMFILE_MEM_URI);
77 splitedString = mmfile_strsplit(filename, ":");
78 if (splitedString == NULL) {
79 debug_error(DEBUG, "invalid param\n");
80 return MMFILE_IO_FAILED;
83 if (!splitedString[0] || !splitedString[1]) {
84 debug_error(DEBUG, "invalid param\n");
88 memHandle = mmfile_malloc(sizeof(MMFmemIOHandle));
90 debug_error(DEBUG, "error: mmfile_malloc memHandle\n");
94 memHandle->ptr = (unsigned char *)atoll(splitedString[0]); /*memory allocation address changed. memHandle->ptr = (unsigned char*)atoi(splitedString[0]); */
95 memHandle->size = atoi(splitedString[1]);
96 memHandle->offset = 0;
102 mmfile_strfreev(splitedString);
105 return MMFILE_IO_SUCCESS;
110 mmfile_strfreev(splitedString);
113 return MMFILE_IO_FAILED;
116 static int _mmf_mem_read(void *opaque, uint8_t *buf, int size)
118 MMFmemIOHandle *memHandle = NULL;
119 const unsigned char *c = NULL;
122 if (!opaque || !buf) {
123 debug_error(DEBUG, "invalid para\n");
124 return MMFILE_UTIL_FAIL;
129 if (!memHandle->ptr) {
130 debug_error(DEBUG, "invalid para\n");
131 return MMFILE_UTIL_FAIL;
134 if (memHandle->offset >= memHandle->size) {
135 /* for some file formats last file read */
136 debug_error(DEBUG, "File Read is beyond the file Size\n");
137 return MMFILE_UTIL_FAIL;
141 c = memHandle->ptr + memHandle->offset;
143 if (memHandle->state != EOF) {
145 if (len + memHandle->offset > memHandle->size) {
146 len = memHandle->size - memHandle->offset;
152 memHandle->offset += len;
154 if (memHandle->offset == memHandle->size) {
155 memHandle->state = EOF;
161 static int64_t _mmf_mem_seek(void *opaque, int64_t pos, int whence)
163 MMFmemIOHandle *memHandle = NULL;
164 long long tmp_offset = 0;
167 debug_error(DEBUG, "invalid para\n");
168 return MMFILE_UTIL_FAIL;
175 tmp_offset = 0 + pos;
178 tmp_offset = memHandle->offset + pos;
181 tmp_offset = memHandle->size + pos;
183 case AVSEEK_SIZE: /*FFMPEG specific*/
184 return memHandle->size;
186 return MMFILE_UTIL_FAIL;
190 if (tmp_offset < 0 && tmp_offset > memHandle->size) {
191 debug_error(DEBUG, "invalid file offset\n");
192 return MMFILE_UTIL_FAIL;
196 memHandle->state = (tmp_offset >= memHandle->size) ? EOF : !EOF;
197 memHandle->offset = (unsigned int) tmp_offset;
203 int mmfile_format_open_ffmpg(MMFileFormatContext *formatContext)
205 AVFormatContext *pFormatCtx = NULL;
206 AVInputFormat *grab_iformat = NULL;
209 char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0, };
210 char mimeType[MMFILE_MIMETYPE_MAX_LEN] = {0, };
211 AVIOContext *pIOCtx = NULL;
212 MMFmemIOHandle *handle = NULL;
213 uint8_t *avio_ctx_buffer = NULL;
215 formatContext->ReadStream = mmfile_format_read_stream_ffmpg;
216 formatContext->ReadFrame = mmfile_format_read_frame_ffmpg;
217 formatContext->ReadTag = mmfile_format_read_tag_ffmpg;
218 formatContext->Close = mmfile_format_close_ffmpg;
220 debug_msg(RELEASE, "ffmpeg version: %d\n", avformat_version());
231 #ifdef __MMFILE_TEST_MODE__
232 av_log_set_level(AV_LOG_DEBUG);
234 av_log_set_level(AV_LOG_QUIET);
239 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
240 if (getMimeType(formatContext->filesrc->memory.format, mimeType, MMFILE_MIMETYPE_MAX_LEN) < 0) {
241 debug_error(DEBUG, "error: Error in MIME Type finding\n");
242 return MMFILE_FORMAT_FAIL;
245 memset(ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
247 ret = mmfile_util_get_ffmpeg_format(mimeType, ffmpegFormatName);
249 if (MMFILE_UTIL_SUCCESS != ret) {
250 debug_error(DEBUG, "error: mmfile_util_get_ffmpeg_format\n");
251 return MMFILE_FORMAT_FAIL;
254 grab_iformat = av_find_input_format(ffmpegFormatName);
256 if (NULL == grab_iformat) {
257 debug_error(DEBUG, "error: cannot find format\n");
261 avio_ctx_buffer = av_malloc(MMFILE_AVIO_BUFFER_LEN);
262 if (avio_ctx_buffer == NULL) {
263 debug_error(DEBUG, "error: cannot alloc avio_ctx_buffert\n");
267 ret = _mmf_mem_open(&handle, formatContext->uriFileName);
268 if (ret != MMFILE_IO_SUCCESS) {
269 debug_warning(DEBUG, "failed to _mmf_mem_open.\n");
273 pIOCtx = avio_alloc_context(avio_ctx_buffer, MMFILE_AVIO_BUFFER_LEN, 0, handle, _mmf_mem_read, NULL, _mmf_mem_seek);
274 if (pIOCtx == NULL) {
275 debug_error(DEBUG, "error: cannot alloc io context\n");
279 pFormatCtx = avformat_alloc_context();
280 if (pFormatCtx == NULL) {
281 debug_warning(DEBUG, "failed to avformat_alloc_context\n");
285 pFormatCtx->pb = pIOCtx;
287 ret = avformat_open_input(&pFormatCtx, "", grab_iformat, NULL);
289 debug_error(DEBUG, "error: cannot open %s %d\n", formatContext->uriFileName, ret);
293 formatContext->privateFormatData = pFormatCtx;
296 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_FILE) {
298 ret = avformat_open_input(&pFormatCtx, formatContext->filesrc->file.path, NULL, NULL);
300 debug_error(DEBUG, "error: cannot open %s %d\n", formatContext->filesrc->file.path, ret);
304 formatContext->privateFormatData = pFormatCtx;
307 if (!pFormatCtx/* || !(pFormatCtx->nb_streams > 0)*/) {
308 debug_warning(DEBUG, "failed to find av stream. maybe corrupted data.\n");
312 debug_msg(RELEASE, "number of stream: %d\n", pFormatCtx->nb_streams);
314 formatContext->videoTotalTrackNum = 0;
315 formatContext->audioTotalTrackNum = 0;
317 for (i = 0; i < pFormatCtx->nb_streams; i++) {
318 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
319 debug_msg(RELEASE, "FFMPEG video codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
321 AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
322 if ((pkt.data != NULL) && (pkt.size > 0))
325 /*eventhough codec_id is 0, avformat_find_stream_info() can find proper codec_id. */
326 formatContext->videoTotalTrackNum += 1;
328 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
329 debug_msg(RELEASE, "FFMPEG audio codec id: 0x%08X\n", pFormatCtx->streams[i]->codec->codec_id);
330 formatContext->audioTotalTrackNum += 1;
334 debug_msg(RELEASE, "format: %s (%s)\n", pFormatCtx->iformat->name, pFormatCtx->iformat->long_name);
335 #ifdef __MMFILE_TEST_MODE__
336 av_dump_format(pFormatCtx, 0, formatContext->filesrc->file.path, 0);
339 return MMFILE_FORMAT_SUCCESS;
341 exception: /* fail to get content information */
342 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
344 av_free(avio_ctx_buffer);
350 avformat_close_input(&pFormatCtx);
352 mmfile_format_close_ffmpg(formatContext);
355 formatContext->privateFormatData = NULL;
357 return MMFILE_FORMAT_FAIL;
360 static bool __check_uhqa(int sample_rate, enum AVSampleFormat sample_fmt_info)
364 debug_error(RELEASE, "[sample rate %d, sample format %d]", sample_rate, sample_fmt_info);
366 if ((sample_rate >= 44100) && (sample_fmt_info >= AV_SAMPLE_FMT_S32)) {
367 debug_msg(RELEASE, "UHQA CONTENT");
377 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext)
379 AVFormatContext *pFormatCtx = NULL;
380 AVCodecContext *pAudioCodecCtx = NULL;
381 AVCodecContext *pVideoCodecCtx = NULL;
383 MMFileFormatStream *videoStream = NULL;
384 MMFileFormatStream *audioStream = NULL;
387 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
388 debug_error(DEBUG, "invalid param\n");
389 return MMFILE_FORMAT_FAIL;
392 pFormatCtx = formatContext->privateFormatData;
393 pFormatCtx->start_time = -1;
396 *@important if data is corrupted, occur segment fault by av_find_stream_info().
397 * - fixed 2009-06-25.
399 if (formatContext->cdis != 1)
400 ret = avformat_find_stream_info(pFormatCtx, NULL);
405 debug_warning(DEBUG, "failed to find stream info. errcode = %d\n", ret);
409 debug_msg(RELEASE, "FFMPEG: dur %lld, start %lld\n", pFormatCtx->duration, pFormatCtx->start_time);
412 *@note asf has long duration bug. and Some content's start time is wrong(negative number).
414 if (pFormatCtx->start_time < 0) {
415 debug_warning(DEBUG, "Wrong Start time = %lld\n", pFormatCtx->start_time);
416 formatContext->duration = (long long)(pFormatCtx->duration) * 1000 / AV_TIME_BASE;
418 formatContext->duration = (long long)(pFormatCtx->duration + pFormatCtx->start_time) * 1000 / AV_TIME_BASE;
421 formatContext->videoStreamId = -1;
422 formatContext->audioStreamId = -1;
423 formatContext->nbStreams = 0;
424 formatContext->videoTotalTrackNum = 0;
425 formatContext->audioTotalTrackNum = 0;
428 for (i = 0; i < pFormatCtx->nb_streams; i++) {
429 if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
430 if (formatContext->videoStreamId == -1) {
431 videoStream = mmfile_malloc(sizeof(MMFileFormatStream));
432 if (NULL == videoStream) {
433 debug_error(DEBUG, "mmfile_malloc error\n");
437 videoStream->streamType = MMFILE_VIDEO_STREAM;
438 formatContext->streams[MMFILE_VIDEO_STREAM] = videoStream;
439 formatContext->nbStreams += 1;
440 formatContext->videoStreamId = i;
441 formatContext->videoTotalTrackNum += 1;
443 pVideoCodecCtx = pFormatCtx->streams[i]->codec;
444 if (pVideoCodecCtx) {
445 videoStream->codecId = ConvertVideoCodecEnum(pVideoCodecCtx->codec_id);
446 if (videoStream->codecId == MM_VIDEO_CODEC_NONE) {
447 debug_error(RELEASE, "Proper codec is not found in [%d] stream", i);
448 formatContext->videoStreamId = -1;
449 mmfile_free(videoStream);
450 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
457 * 1. try to get average fps of video stream.
458 * 2. if (1) failed, try to get fps of media container.
460 videoStream->framePerSec = _get_video_fps(pFormatCtx->streams[i]->nb_frames,
461 pFormatCtx->streams[i]->duration,
462 pFormatCtx->streams[i]->time_base,
465 if (videoStream->framePerSec == 0) {
466 #ifndef __MMFILE_LIBAV_VERSION__
467 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->r_frame_rate);
469 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->avg_frame_rate);
473 videoStream->width = pVideoCodecCtx->width;
474 videoStream->height = pVideoCodecCtx->height;
475 videoStream->bitRate = pVideoCodecCtx->bit_rate;
479 else if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
480 if (formatContext->audioStreamId == -1) {
481 audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
482 if (NULL == audioStream) {
483 debug_error(DEBUG, "mmfile_malloc error\n");
487 audioStream->streamType = MMFILE_AUDIO_STREAM;
488 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
489 formatContext->nbStreams += 1;
490 formatContext->audioStreamId = i;
491 formatContext->audioTotalTrackNum += 1;
493 pAudioCodecCtx = pFormatCtx->streams[i]->codec;
494 if (pAudioCodecCtx) {
495 audioStream->codecId = ConvertAudioCodecEnum(pAudioCodecCtx->codec_id);
496 audioStream->bitRate = pAudioCodecCtx->bit_rate;
497 audioStream->nbChannel = pAudioCodecCtx->channels;
498 audioStream->samplePerSec = pAudioCodecCtx->sample_rate;
499 if (audioStream->codecId == MM_AUDIO_CODEC_FLAC)
500 audioStream->bitPerSample = pAudioCodecCtx->bits_per_raw_sample;
502 audioStream->bitPerSample = pAudioCodecCtx->bits_per_coded_sample;
503 audioStream->is_uhqa = __check_uhqa(audioStream->samplePerSec, pFormatCtx->streams[i]->codec->sample_fmt);
509 if (formatContext->nbStreams == 0) {
510 debug_error(DEBUG, "error: there is no audio and video track\n");
514 #ifdef __MMFILE_TEST_MODE__
515 mmfile_format_print_contents(formatContext);
518 return MMFILE_FORMAT_SUCCESS;
522 mmfile_free(videoStream);
523 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
527 mmfile_free(audioStream);
528 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
532 avformat_close_input(&pFormatCtx);
533 formatContext->privateFormatData = NULL;
536 formatContext->audioTotalTrackNum = 0;
537 formatContext->videoTotalTrackNum = 0;
538 formatContext->nbStreams = 0;
540 return MMFILE_FORMAT_FAIL;
543 #define DATA_LENGTH 4
544 #define POS_OF_MIME_LEN DATA_LENGTH
545 #define CONVERT_TO_INT(dest, src) {dest = 0; dest |= (0 | src[0] << 24) | (0 | src[1] << 16) | (0 | src[2] << 8) | (0 | src[3]); }
548 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext)
550 AVFormatContext *pFormatCtx = NULL;
552 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
553 debug_error(DEBUG, "invalid param\n");
554 return MMFILE_FORMAT_FAIL;
557 pFormatCtx = formatContext->privateFormatData;
559 if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4) {
560 MMFileUtilGetMetaDataFromMP4(formatContext);
563 /*metadata extracted by ffmpeg*/
564 unsigned int idx = 0;
566 if (pFormatCtx != NULL) {
567 for (idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) {
568 AVDictionary *metainfo = NULL;
571 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. */
572 st = pFormatCtx->streams[idx];
574 metainfo = st->metadata;
575 } else { /*Check metadata of Content */
576 if (pFormatCtx->metadata != NULL) {
577 metainfo = pFormatCtx->metadata;
583 /*refer to mov_read_covr() in ffmpeg.*/
585 AVPacket pkt = st->attached_pic;
586 int codec_id = st->codec->codec_id;
588 if ((pkt.data != NULL) && (pkt.size > 0)) {
590 if (formatContext->artworkMime) mmfile_free(formatContext->artworkMime);
592 if (codec_id == AV_CODEC_ID_MJPEG)
593 formatContext->artworkMime = mmfile_strdup("image/jpeg");
594 else if (codec_id == AV_CODEC_ID_PNG)
595 formatContext->artworkMime = mmfile_strdup("image/png");
596 else if (codec_id == AV_CODEC_ID_BMP)
597 formatContext->artworkMime = mmfile_strdup("image/bmp");
599 debug_error(DEBUG, "Unknown cover type: 0x%x\n", codec_id);
602 if (formatContext->artwork) mmfile_free(formatContext->artwork);
604 formatContext->artworkSize = pkt.size;
605 formatContext->artwork = mmfile_malloc(pkt.size);
606 if (formatContext->artwork != NULL)
607 memcpy(formatContext->artwork, pkt.data, pkt.size);
611 if (metainfo != NULL) {
612 AVDictionaryEntry *tag = NULL;
613 while ((tag = av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) {
614 if (tag->key != NULL) {
615 if (!strcasecmp(tag->key, "title")) {
616 if (formatContext->title) free(formatContext->title);
617 formatContext->title = mmfile_strdup(tag->value);
618 } else if (!strcasecmp(tag->key, "artist")) {
619 if (formatContext->artist) free(formatContext->artist);
620 formatContext->artist = mmfile_strdup(tag->value);
621 } else if (!strcasecmp(tag->key, "composer")) {
622 if (formatContext->composer) free(formatContext->composer);
623 formatContext->composer = mmfile_strdup(tag->value);
624 } else if (!strcasecmp(tag->key, "album")) {
625 if (formatContext->album) free(formatContext->album);
626 formatContext->album = mmfile_strdup(tag->value);
627 } else if (!strcasecmp(tag->key, "album_artist")) {
628 if (formatContext->album_artist) free(formatContext->album_artist);
629 formatContext->album_artist = mmfile_strdup(tag->value);
630 } else if (!strcasecmp(tag->key, "copyright")) {
631 if (formatContext->copyright) free(formatContext->copyright);
632 formatContext->copyright = mmfile_strdup(tag->value);
633 } else if (!strcasecmp(tag->key, "comment")) {
634 if (formatContext->comment) free(formatContext->comment);
635 formatContext->comment = mmfile_strdup(tag->value);
636 } else if (!strcasecmp(tag->key, "description")) {
637 if (formatContext->description) free(formatContext->description);
638 formatContext->description = mmfile_strdup(tag->value);
639 } else if (!strcasecmp(tag->key, "genre")) {
640 if (formatContext->genre) free(formatContext->genre);
641 formatContext->genre = mmfile_strdup(tag->value);
642 } else if (!strcasecmp(tag->key, "date")) {
643 if (formatContext->year) free(formatContext->year);
644 formatContext->year = mmfile_strdup(tag->value);
645 } else if (!strcasecmp(tag->key, "creation_time")) {
646 if (formatContext->recDate) free(formatContext->recDate);
647 formatContext->recDate = mmfile_strdup(tag->value);
648 } else if ((!strcasecmp(tag->key, "track")) || (!strcasecmp(tag->key, "tracknumber"))) {
649 if (formatContext->tagTrackNum) free(formatContext->tagTrackNum);
650 formatContext->tagTrackNum = mmfile_strdup(tag->value);
651 } else if (!strcasecmp(tag->key, "lyrics")) {
652 if (formatContext->unsyncLyrics) free(formatContext->unsyncLyrics);
653 formatContext->unsyncLyrics = mmfile_strdup(tag->value);
654 } else if (!strcasecmp(tag->key, "rotate")) { /*can be "90", "180", "270" */
655 if (formatContext->rotate) free(formatContext->rotate);
656 formatContext->rotate = mmfile_strdup(tag->value);
657 } else if (!strcasecmp(tag->key, "metadata_block_picture")) {
659 guchar *meta_data = NULL;
661 meta_data = g_base64_decode(tag->value, &len);
662 if (meta_data != NULL) {
663 /* in METADATA_BLOCK_PICTURE,
664 the length of mime type and the length of description are flexible,
665 so, we have to get the length of their for getting correct postion of picture data. */
667 int description_len = 0;
670 unsigned char current_data[DATA_LENGTH] = {0};
672 /* get length of mime_type */
673 memcpy(current_data, meta_data + POS_OF_MIME_LEN, DATA_LENGTH);
674 CONVERT_TO_INT(mime_len, current_data);
676 /* get length of description */
677 current_pos = mime_len + (DATA_LENGTH * 2); /*current position is length of description */
678 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
679 CONVERT_TO_INT(description_len, current_data);
681 /* get length of picture data */
682 current_pos = mime_len + description_len + (DATA_LENGTH * 7); /*current position is length of picture data */
683 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
684 CONVERT_TO_INT(data_len, current_data);
686 /* set the size of art work */
687 formatContext->artworkSize = data_len;
690 current_pos = POS_OF_MIME_LEN + DATA_LENGTH; /*current position is mime type */
691 if (formatContext->artworkMime) mmfile_free(formatContext->artworkMime);
692 formatContext->artworkMime = strndup((const char *)meta_data + current_pos, mime_len);
694 /* set art work data */
695 current_pos = mime_len + description_len + (DATA_LENGTH * 8); /*current position is picture data */
696 if (formatContext->artwork) mmfile_free(formatContext->artwork);
698 formatContext->artwork = mmfile_malloc(data_len);
699 if (formatContext->artwork != NULL)
700 memcpy(formatContext->artwork, meta_data + current_pos, data_len);
705 debug_log(RELEASE, "Not support metadata. [%s:%s]", tag->key, tag->value);
710 #ifdef __MMFILE_TEST_MODE__
711 mmfile_format_print_tags(formatContext);
716 return MMFILE_FORMAT_SUCCESS;
721 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
723 AVFormatContext *pFormatCtx = NULL;
724 AVCodecContext *pVideoCodecCtx = NULL;
725 AVCodec *pVideoCodec = NULL;
726 AVFrame *pFrame = NULL;
727 AVFrame *pFrameRGB = NULL;
734 if (NULL == formatContext ||
736 NULL == formatContext->privateFormatData ||
737 formatContext->videoTotalTrackNum <= 0) {
739 debug_error(DEBUG, "invalid param\n");
740 return MMFILE_FORMAT_FAIL;
743 pFormatCtx = formatContext->privateFormatData;
745 if (formatContext->videoStreamId != -1) {
746 pVideoCodecCtx = pFormatCtx->streams[formatContext->videoStreamId]->codec;
747 if (NULL == pVideoCodecCtx) {
748 debug_error(DEBUG, "invalid param\n");
749 return MMFILE_FORMAT_FAIL;
752 pVideoCodec = avcodec_find_decoder(pVideoCodecCtx->codec_id);
753 if (NULL == pVideoCodec) {
754 debug_error(DEBUG, "error: avcodec_find_decoder failed\n");
755 return MMFILE_FORMAT_FAIL;
758 debug_msg(RELEASE, "flag: 0x%08X\n", pVideoCodec->capabilities);
759 /* debug_msg(RELEASE, " DRAW_HORIZ_BAND : %d\n", pVideoCodec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND ? 1 : 0); */
760 /* debug_msg(RELEASE, " DR1 : %d\n", pVideoCodec->capabilities & CODEC_CAP_DR1 ? 1 : 0); */
761 /* debug_msg(RELEASE, " PARSE_ONLY : %d\n", pVideoCodec->capabilities & CODEC_CAP_PARSE_ONLY ? 1 : 0); */
762 /* debug_msg(RELEASE, " TRUNCATED : %d\n", pVideoCodec->capabilities & CODEC_CAP_TRUNCATED ? 1 : 0); */
763 /* debug_msg(RELEASE, " HWACCEL : %d\n", pVideoCodec->capabilities & CODEC_CAP_HWACCEL ? 1 : 0); */
764 /* debug_msg(RELEASE, " DELAY : %d\n", pVideoCodec->capabilities & CODEC_CAP_DELAY ? 1 : 0); */
765 /* debug_msg(RELEASE, " SMALL_LAST_FRAME: %d\n", pVideoCodec->capabilities & CODEC_CAP_SMALL_LAST_FRAME ? 1 : 0); */
766 /* debug_msg(RELEASE, " HWACCEL_VDPAU : %d\n", pVideoCodec->capabilities & CODEC_CAP_HWACCEL_VDPAU ? 1 : 0); */
768 if (pVideoCodec->capabilities & CODEC_CAP_TRUNCATED) {
769 pVideoCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
772 /*set workaround bug flag*/
773 pVideoCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
775 /* this is solution for PLM issue P13091703323 */
776 /* If using thread when decoding frame, the result of decoding is not always same.
777 Thumbnail of video content is different with original file when copying file. */
778 pVideoCodecCtx->thread_type = 0;
779 pVideoCodecCtx->thread_count = 0;
780 ret = avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL);
782 debug_error(DEBUG, "error: avcodec_open fail.\n");
783 return MMFILE_FORMAT_FAIL;
786 pFrameRGB = av_frame_alloc();
789 debug_error(DEBUG, "error: pFrame or pFrameRGB is NULL\n");
790 ret = MMFILE_FORMAT_FAIL;
794 /* search & decode */
795 /* seek_ts = formatContext->duration > _SHORT_MEDIA_LIMIT ? seek_ts : 0; */ /*if short media, seek first key frame*/
796 ret = _get_first_good_video_frame(pFormatCtx, pVideoCodecCtx, formatContext->videoStreamId, &pFrame, formatContext->cdis);
797 if (ret != MMFILE_FORMAT_SUCCESS) {
798 debug_error(DEBUG, "error: get key frame\n");
799 ret = MMFILE_FORMAT_FAIL;
803 debug_msg(RELEASE, "Video default resolution = [%dx%d]\n", pVideoCodecCtx->coded_width, pVideoCodecCtx->coded_height);
804 debug_msg(RELEASE, "Video coded resolution = [%dx%d]\n", pVideoCodecCtx->width, pVideoCodecCtx->height);
806 /*sometimes, ffmpeg's width/height is wrong*/
807 #if 0 /*coded_width/height sometimes wrong. so use width/height*/
808 width = pVideoCodecCtx->coded_width == 0 ? pVideoCodecCtx->width : pVideoCodecCtx->coded_width;
809 height = pVideoCodecCtx->coded_height == 0 ? pVideoCodecCtx->height : pVideoCodecCtx->coded_height;
811 if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
812 width = pVideoCodecCtx->coded_width;
813 height = pVideoCodecCtx->coded_height;
815 width = pVideoCodecCtx->width;
816 height = pVideoCodecCtx->height;
819 numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, width, height);
821 debug_error(DEBUG, "error: avpicture_get_size. [%d x %d]\n", width, height);
822 ret = MMFILE_FORMAT_FAIL;
826 frame->frameData = mmfile_malloc(numBytes);
827 if (NULL == frame->frameData) {
828 debug_error(DEBUG, "error: avpicture_get_size. [%d]\n", numBytes);
829 ret = MMFILE_FORMAT_FAIL;
833 ret = avpicture_fill((AVPicture *)pFrameRGB, frame->frameData, AV_PIX_FMT_RGB24, width, height);
835 debug_error(DEBUG, "error: avpicture_fill fail. errcode = 0x%08X\n", ret);
836 ret = MMFILE_FORMAT_FAIL;
840 struct SwsContext *img_convert_ctx = NULL;
842 img_convert_ctx = sws_getContext(width, height, pVideoCodecCtx->pix_fmt, width, height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
844 if (NULL == img_convert_ctx) {
845 debug_error(DEBUG, "failed to get img convet ctx\n");
846 ret = MMFILE_FORMAT_FAIL;
850 ret = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize, 0, height, pFrameRGB->data, pFrameRGB->linesize);
852 debug_error(DEBUG, "failed to convet image\n");
853 ret = MMFILE_FORMAT_FAIL;
854 sws_freeContext(img_convert_ctx);
855 img_convert_ctx = NULL;
859 sws_freeContext(img_convert_ctx);
860 img_convert_ctx = NULL;
862 frame->frameSize = numBytes;
863 frame->frameWidth = width;
864 frame->frameHeight = height;
865 frame->configLenth = 0;
866 frame->bCompressed = 0; /* false */
868 if (pFrame) av_free(pFrame);
869 if (pFrameRGB) av_free(pFrameRGB);
871 avcodec_close(pVideoCodecCtx);
873 return MMFILE_FORMAT_SUCCESS;
878 if (pVideoCodecCtx) avcodec_close(pVideoCodecCtx);
879 if (frame->frameData) {
880 mmfile_free(frame->frameData);
881 frame->frameData = NULL;
883 if (pFrame) av_free(pFrame);
884 if (pFrameRGB) av_free(pFrameRGB);
890 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext)
893 AVFormatContext *pFormatCtx = formatContext->privateFormatData;
896 avformat_close_input(&pFormatCtx);
897 formatContext->privateFormatData = NULL;
901 return MMFILE_FORMAT_SUCCESS;
905 * return average of difference
907 static unsigned int _diff_memory(const void *s1, const void *s2, unsigned int n)
909 char *s = (char *)s1;
910 char *d = (char *)s2;
912 unsigned int ret = 0;
915 for (i = 0, ret = 0; i < n; i++) {
918 ret += (tmp < 0 ? -tmp : tmp);
928 int64_t gettime(void)
931 gettimeofday(&tv, NULL);
932 return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
936 #define IS_GOOD_OLD_METHOD
937 #ifdef IS_GOOD_OLD_METHOD
939 * compare with center line.
941 static int _is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize)
943 #define _MM_CHUNK_NUM 8 /*FIXME*/
944 #define _MM_CHUNK_LIMIT (_MM_CHUNK_NUM / 2)
945 #define _MM_CHUNK_DIFF_LIMIT (_MM_CHUNK_LIMIT * 2 + 1) /*FIXME*/
950 unsigned char *cnt; /*center line of image*/
952 unsigned int sum_diff;
956 step = ysize / _MM_CHUNK_NUM;
957 cnt_offset = (ysize / 2);
958 cnt = buf + cnt_offset * wrap;
960 debug_msg(RELEASE, "checking frame. %p, %d, %d, %d\n", buf, wrap, xsize, ysize);
962 /*if too small, always ok return.*/
963 if (ysize < _MM_CHUNK_NUM)
966 for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
967 if (i != cnt_offset) {
970 is_different = _diff_memory(cnt, buf + i * wrap, xsize);
971 point += (is_different == 0 ? 0 : 1);
972 sum_diff += is_different;
974 debug_msg(RELEASE, "check %04d line. %s [%d]\n", i, (is_different == 0 ? "same" : "different"), is_different);
976 if (point >= _MM_CHUNK_LIMIT) {
977 if (sum_diff > _MM_CHUNK_DIFF_LIMIT) {
978 debug_msg(RELEASE, "Good :-)\n");
981 debug_msg(RELEASE, "Bad :-(\n");
990 #else /* IS_GOOD_OLD_METHOD */
991 /* ToDo : for enhancement */
992 #endif /* IS_GOOD_OLD_METHOD */
997 _get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
1001 debug_msg(RELEASE, "frame count: %d, dur: %d, num: %d, den: %d\n", frame_cnt, duration, r_frame_rate.num, r_frame_rate.den);
1003 if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
1006 round = (is_roundup != 0 ? 0.50f : 0.00f);
1008 fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
1013 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1014 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
1019 f = fopen(filename, "w");
1021 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
1022 for (i = 0; i < ysize; i++)
1023 fwrite(buf + i * wrap, 1, xsize, f);
1029 #ifdef __MMFILE_TEST_MODE__
1030 static void _dump_av_packet(AVPacket *pkt)
1032 debug_msg(RELEASE, "--------- AV Packet -----------\n");
1033 debug_msg(RELEASE, " pts: %lld\n", pkt->pts);
1034 debug_msg(RELEASE, " dts: %lld\n", pkt->dts);
1035 debug_msg(RELEASE, " data: %p\n", pkt->data);
1036 debug_msg(RELEASE, " size: %d\n", pkt->size);
1037 debug_msg(RELEASE, " stream_index: %d\n", pkt->stream_index);
1038 debug_msg(RELEASE, " flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & AV_PKT_FLAG_KEY) ? "Keyframe" : "_");
1039 debug_msg(RELEASE, " duration: %d\n", pkt->duration);
1040 /*debug_msg(RELEASE, " destruct: %p\n", pkt->destruct);*/
1041 /*debug_msg(RELEASE, " priv: %p\n", pkt->priv);*/
1042 debug_msg(RELEASE, " pos: %lld\n", pkt->pos);
1043 debug_msg(RELEASE, " convergence_duration: %lld\n", pkt->convergence_duration);
1044 debug_msg(RELEASE, "-------------------------------\n");
1048 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis)
1050 /* AVStream *st = NULL; */
1053 AVFrame *frame = NULL;
1054 AVFrame *tmp_frame = NULL;
1055 AVFrame *first_frame = NULL;
1057 /* long long timestamp; */
1058 /*int stream_id = videoStream;*/
1061 int i, v, len, got_picture;
1064 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1065 char pgm_name[256] = {0, };
1067 int key_search_limit = 0;
1068 int frame_search_limit = 0;
1070 #define _RETRY_SEARCH_LIMIT 75
1071 #define _KEY_SEARCH_LIMIT (_RETRY_SEARCH_LIMIT*2) /*2 = 1 read. some frame need to read one more*/
1072 #define _FRAME_SEARCH_LIMIT 500
1074 #define _RETRY_SEARCH_LIMIT_CDIS 10
1075 #define _KEY_SEARCH_LIMIT_CDIS (_RETRY_SEARCH_LIMIT*2) /*2 = 1 read. some frame need to read one more*/
1076 #define _FRAME_SEARCH_LIMIT_CDIS 10
1078 first_frame = av_frame_alloc();
1079 tmp_frame = av_frame_alloc();
1081 if (!first_frame || !tmp_frame) {
1082 debug_error(DEBUG, "failed to alloc frame.\n");
1083 if (first_frame) av_free(first_frame);
1084 if (tmp_frame) av_free(tmp_frame);
1085 return MMFILE_FORMAT_FAIL;
1088 debug_msg(RELEASE, "frame: 1. %p, 2. %p\n", first_frame, tmp_frame);
1090 pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1093 key_search_limit = _KEY_SEARCH_LIMIT_CDIS;
1094 frame_search_limit = _FRAME_SEARCH_LIMIT_CDIS;
1096 key_search_limit = _KEY_SEARCH_LIMIT;
1097 frame_search_limit = _FRAME_SEARCH_LIMIT;
1100 for (i = 0, v = 0, key_detected = 0, frame = first_frame; i < key_search_limit && v < frame_search_limit;) {
1101 av_init_packet(&pkt);
1104 ret = av_read_frame(pFormatCtx, &pkt);
1106 debug_error(DEBUG, "read failed. (maybe EOF or broken)\n");
1109 if (avcodec_get_type(pFormatCtx->streams[pkt.stream_index]->codec->codec_id) == AVMEDIA_TYPE_VIDEO) {
1111 if ((pkt.flags & AV_PKT_FLAG_KEY) || (key_detected == 1))
1113 debug_msg(RELEASE, "video frame: %d, %d, %d\n", retry, i, v);
1114 #ifdef __MMFILE_TEST_MODE__
1115 _dump_av_packet(&pkt);
1121 len = avcodec_decode_video2(pCodecCtx, frame, &got_picture, &pkt);
1123 debug_warning(DEBUG, "Error while decoding frame %dth\n", i);
1124 } else if (got_picture) {
1125 if (frame->key_frame) {
1126 debug_msg(RELEASE, "key frame!\n");
1127 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1128 memset(pgm_name, 0x00, sizeof(pgm_name));
1129 snprintf(pgm_name, sizeof(pgm_name), "./key_%d_%d_%d.pgm", retry, i, v);
1130 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1135 #ifdef __MMFILE_TEST_MODE__
1139 ret = _is_good_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height);
1140 #ifdef __MMFILE_TEST_MODE__
1141 ti = gettime() - ti;
1142 debug_msg(RELEASE, "Elapsed time = %lld\n", ti);
1145 debug_msg(RELEASE, "is good frame.\n");
1148 /*reset video frame count & retry searching*/
1149 debug_warning(RELEASE, "not good fame. retry scanning.\n");
1155 /*set buffer frame*/
1159 if (retry > _RETRY_SEARCH_LIMIT) break;
1162 debug_msg(RELEASE, "skip (not key frame).\n");
1163 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1164 memset(pgm_name, 0x00, sizeof(pgm_name));
1165 snprintf(pgm_name, sizeof(pgm_name), "./not_key_%d_%d_%d.pgm", retry, i, v);
1166 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1170 debug_msg(RELEASE, "decode not completed.\n");
1176 av_free_packet(&pkt);
1179 /*free pkt after loop breaking*/
1180 if (pkt.data) av_free_packet(&pkt);
1182 debug_msg(RELEASE, "found: %d, retry: %d\n", found, retry);
1184 /*set decode frame to output*/
1186 ret = MMFILE_FORMAT_SUCCESS;
1187 if (retry == 0 || found == retry) {
1188 *pFrame = first_frame;
1189 if (tmp_frame) av_free(tmp_frame);
1191 *pFrame = tmp_frame;
1192 if (first_frame) av_free(first_frame);
1195 ret = MMFILE_FORMAT_FAIL;
1196 if (first_frame) av_free(first_frame);
1197 if (tmp_frame) av_free(tmp_frame);
1200 debug_msg(RELEASE, "out frame: %p\n", *pFrame);
1202 pCodecCtx->skip_frame = AVDISCARD_NONE;
1207 static int ConvertVideoCodecEnum(int AVVideoCodecID)
1209 int ret_codecid = 0;
1211 switch (AVVideoCodecID) {
1212 case AV_CODEC_ID_NONE:
1213 ret_codecid = MM_VIDEO_CODEC_NONE;
1215 case AV_CODEC_ID_MPEG1VIDEO:
1216 ret_codecid = MM_VIDEO_CODEC_MPEG1;
1218 case AV_CODEC_ID_MPEG2VIDEO: /*/< preferred ID for MPEG-1/2 video decoding */
1219 case AV_CODEC_ID_MPEG2VIDEO_XVMC:
1220 case AV_CODEC_ID_MPEG2TS:
1221 ret_codecid = MM_VIDEO_CODEC_MPEG2;
1223 case AV_CODEC_ID_H261:
1224 ret_codecid = MM_VIDEO_CODEC_H261;
1226 case AV_CODEC_ID_H263:
1227 ret_codecid = MM_VIDEO_CODEC_H263;
1229 case AV_CODEC_ID_MPEG4:
1230 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1232 case AV_CODEC_ID_MSMPEG4V1:
1233 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1235 case AV_CODEC_ID_MSMPEG4V2:
1236 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1238 case AV_CODEC_ID_MSMPEG4V3:
1239 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1241 case AV_CODEC_ID_WMV1:
1242 ret_codecid = MM_VIDEO_CODEC_WMV;
1244 case AV_CODEC_ID_WMV2:
1245 ret_codecid = MM_VIDEO_CODEC_WMV;
1247 case AV_CODEC_ID_H263P:
1248 ret_codecid = MM_VIDEO_CODEC_H263;
1250 case AV_CODEC_ID_H263I:
1251 ret_codecid = MM_VIDEO_CODEC_H263;
1253 case AV_CODEC_ID_FLV1:
1254 ret_codecid = MM_VIDEO_CODEC_FLV;
1256 case AV_CODEC_ID_H264:
1257 ret_codecid = MM_VIDEO_CODEC_H264;
1259 case AV_CODEC_ID_INDEO2:
1260 case AV_CODEC_ID_INDEO3:
1261 case AV_CODEC_ID_INDEO4:
1262 case AV_CODEC_ID_INDEO5:
1263 ret_codecid = MM_VIDEO_CODEC_INDEO;
1265 case AV_CODEC_ID_THEORA:
1266 ret_codecid = MM_VIDEO_CODEC_THEORA;
1268 case AV_CODEC_ID_CINEPAK:
1269 ret_codecid = MM_VIDEO_CODEC_CINEPAK;
1271 case AV_CODEC_ID_VC1:
1272 ret_codecid = MM_VIDEO_CODEC_VC1;
1274 case AV_CODEC_ID_WMV3:
1275 ret_codecid = MM_VIDEO_CODEC_WMV;
1277 case AV_CODEC_ID_AVS:
1278 ret_codecid = MM_VIDEO_CODEC_AVS;
1280 case AV_CODEC_ID_RL2:
1281 case AV_CODEC_ID_RV10: /* RealVideo 1 */
1282 case AV_CODEC_ID_RV20: /* RealVideo 2 */
1283 case AV_CODEC_ID_RV30: /* RealVideo 3 */
1284 case AV_CODEC_ID_RV40: /* RealVideo 4 */
1285 ret_codecid = MM_VIDEO_CODEC_REAL;
1287 #ifdef __MMFILE_LIBAV_VERSION__
1288 case AV_CODEC_ID_HEVC:
1289 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1293 ret_codecid = MM_VIDEO_CODEC_NONE;
1301 static int ConvertAudioCodecEnum(int AVAudioCodecID)
1303 int ret_codecid = 0;
1305 switch (AVAudioCodecID) {
1306 case AV_CODEC_ID_AMR_NB:
1307 case AV_CODEC_ID_AMR_WB:
1308 ret_codecid = MM_AUDIO_CODEC_AMR;
1310 /* RealAudio codecs*/
1311 case AV_CODEC_ID_RA_144: /* RealAudio 1 */
1312 case AV_CODEC_ID_RA_288: /* RealAudio 2 */
1313 case AV_CODEC_ID_COOK: /* RealAudio 6 */
1314 ret_codecid = MM_AUDIO_CODEC_REAL;
1316 case AV_CODEC_ID_MP2:
1317 ret_codecid = MM_AUDIO_CODEC_MP2;
1319 case AV_CODEC_ID_MP3:
1320 case AV_CODEC_ID_MP3ADU:
1321 case AV_CODEC_ID_MP3ON4:
1322 ret_codecid = MM_AUDIO_CODEC_MP3;
1324 case AV_CODEC_ID_AAC:
1325 ret_codecid = MM_AUDIO_CODEC_AAC;
1327 case AV_CODEC_ID_AC3:
1328 ret_codecid = MM_AUDIO_CODEC_AC3;
1330 case AV_CODEC_ID_VORBIS:
1331 ret_codecid = MM_AUDIO_CODEC_VORBIS;
1333 case AV_CODEC_ID_WMAV1:
1334 case AV_CODEC_ID_WMAV2:
1335 case AV_CODEC_ID_WMAVOICE:
1336 case AV_CODEC_ID_WMAPRO:
1337 case AV_CODEC_ID_WMALOSSLESS:
1338 ret_codecid = MM_AUDIO_CODEC_WMA;
1340 case AV_CODEC_ID_FLAC:
1341 ret_codecid = MM_AUDIO_CODEC_FLAC;
1343 case AV_CODEC_ID_ALAC:
1344 ret_codecid = MM_AUDIO_CODEC_ALAC;
1346 case AV_CODEC_ID_WAVPACK:
1347 ret_codecid = MM_AUDIO_CODEC_WAVE;
1349 case AV_CODEC_ID_ATRAC3:
1350 case AV_CODEC_ID_ATRAC3P:
1351 case AV_CODEC_ID_EAC3:
1352 ret_codecid = MM_AUDIO_CODEC_AC3;
1354 case AV_CODEC_ID_PCM_S8:
1355 case AV_CODEC_ID_PCM_S16BE:
1356 case AV_CODEC_ID_PCM_S24BE:
1357 case AV_CODEC_ID_PCM_S32BE:
1358 ret_codecid = MM_AUDIO_CODEC_PCM;
1361 ret_codecid = MM_AUDIO_CODEC_NONE;
1370 static int getMimeType(int formatId, char *mimeType, int buf_size)
1372 int ret = 0; /*default: success*/
1375 case MM_FILE_FORMAT_3GP:
1376 case MM_FILE_FORMAT_MP4:
1377 snprintf(mimeType, buf_size, "video/3gpp");
1379 case MM_FILE_FORMAT_ASF:
1380 case MM_FILE_FORMAT_WMA:
1381 case MM_FILE_FORMAT_WMV:
1382 snprintf(mimeType, buf_size, "video/x-ms-asf");
1384 case MM_FILE_FORMAT_AVI:
1385 snprintf(mimeType, buf_size, "video/avi");
1387 case MM_FILE_FORMAT_OGG:
1388 snprintf(mimeType, buf_size, "video/ogg");
1390 case MM_FILE_FORMAT_REAL:
1391 snprintf(mimeType, buf_size, "video/vnd.rn-realmedia");
1393 case MM_FILE_FORMAT_AMR:
1394 snprintf(mimeType, buf_size, "audio/AMR");
1396 case MM_FILE_FORMAT_AAC:
1397 snprintf(mimeType, buf_size, "audio/aac");
1399 case MM_FILE_FORMAT_MP3:
1400 snprintf(mimeType, buf_size, "audio/mp3");
1402 case MM_FILE_FORMAT_AIFF:
1403 case MM_FILE_FORMAT_WAV:
1404 snprintf(mimeType, buf_size, "audio/wave");
1406 case MM_FILE_FORMAT_MID:
1407 snprintf(mimeType, buf_size, "audio/midi");
1409 case MM_FILE_FORMAT_MMF:
1410 snprintf(mimeType, buf_size, "audio/mmf");
1412 case MM_FILE_FORMAT_DIVX:
1413 snprintf(mimeType, buf_size, "video/divx");
1415 case MM_FILE_FORMAT_IMELODY:
1416 snprintf(mimeType, buf_size, "audio/iMelody");
1418 case MM_FILE_FORMAT_JPG:
1419 snprintf(mimeType, buf_size, "image/jpeg");
1421 case MM_FILE_FORMAT_AU:
1422 snprintf(mimeType, buf_size, "audio/basic");
1424 case MM_FILE_FORMAT_VOB:
1425 snprintf(mimeType, buf_size, "video/dvd");
1427 case MM_FILE_FORMAT_FLV:
1428 snprintf(mimeType, buf_size, "video/x-flv");
1430 case MM_FILE_FORMAT_QT:
1431 snprintf(mimeType, buf_size, "video/quicktime");
1433 case MM_FILE_FORMAT_MATROSKA:
1434 snprintf(mimeType, buf_size, "video/x-matroska");
1436 case MM_FILE_FORMAT_FLAC:
1437 snprintf(mimeType, buf_size, "audio/x-flac");
1439 case MM_FILE_FORMAT_M2TS:
1440 snprintf(mimeType, buf_size, "video/MP2T");
1442 case MM_FILE_FORMAT_M2PS:
1443 snprintf(mimeType, buf_size, "video/MP2P");
1445 case MM_FILE_FORMAT_M1AUDIO:
1446 snprintf(mimeType, buf_size, "audio/x-mpegaudio");
1448 case MM_FILE_FORMAT_M1VIDEO:
1449 snprintf(mimeType, buf_size, "video/mpeg");
1455 debug_msg(RELEASE, "id: %d, mimetype: %s\n", formatId, mimeType);