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/imgutils.h>
28 #include <libswscale/swscale.h>
31 #include "mm_file_debug.h"
32 #include "mm_file_formats.h"
33 #include "mm_file_utils.h"
34 #include "mm_file_format_ffmpeg.h"
37 #define _SHORT_MEDIA_LIMIT 2000 /* under X seconds duration*/
39 /* internal functions */
40 static int _is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize);
41 #ifdef MMFILE_FORMAT_DEBUG_DUMP
42 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename);
44 #ifdef __MMFILE_TEST_MODE__
45 static void _dump_av_packet(AVPacket *pkt);
48 static int _get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup);
49 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis);
51 static int ConvertVideoCodecEnum(int AVVideoCodecID);
52 static int ConvertAudioCodecEnum(int AVAudioCodecID);
54 /* plugin manadatory API */
55 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext);
56 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
57 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext);
58 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext);
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 void __count_stream_num(AVFormatContext *pFormatCtx, MMFileFormatContext *formatContext)
74 formatContext->videoTotalTrackNum = 0;
75 formatContext->audioTotalTrackNum = 0;
77 for (i = 0; i < pFormatCtx->nb_streams; i++) {
78 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
79 debug_msg(RELEASE, "FFMPEG video codec id: 0x%08X\n", pFormatCtx->streams[i]->codecpar->codec_id);
81 AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
82 if ((pkt.data != NULL) && (pkt.size > 0))
85 /*eventhough codec_id is 0, avformat_find_stream_info() can find proper codec_id. */
86 formatContext->videoTotalTrackNum += 1;
88 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
89 debug_msg(RELEASE, "FFMPEG audio codec id: 0x%08X\n", pFormatCtx->streams[i]->codecpar->codec_id);
90 formatContext->audioTotalTrackNum += 1;
95 static int _mmf_mem_open(MMFmemIOHandle **handle, const char *filename)
97 MMFmemIOHandle *memHandle = NULL;
98 char **splitedString = NULL;
100 filename += strlen(MMFILE_MEM_URI);
102 splitedString = mmfile_strsplit(filename, ":");
103 if (splitedString == NULL) {
104 debug_error(DEBUG, "invalid param\n");
105 return MMFILE_IO_FAILED;
108 if (!splitedString[0] || !splitedString[1]) {
109 debug_error(DEBUG, "invalid param\n");
113 memHandle = mmfile_malloc(sizeof(MMFmemIOHandle));
115 debug_error(DEBUG, "error: mmfile_malloc memHandle\n");
119 memHandle->ptr = (unsigned char *)atoll(splitedString[0]); /*memory allocation address changed. memHandle->ptr = (unsigned char*)atoi(splitedString[0]); */
120 memHandle->size = atoi(splitedString[1]);
121 memHandle->offset = 0;
122 memHandle->state = 0;
127 mmfile_strfreev(splitedString);
130 return MMFILE_IO_SUCCESS;
135 mmfile_strfreev(splitedString);
138 return MMFILE_IO_FAILED;
141 static int _mmf_mem_read(void *opaque, uint8_t *buf, int size)
143 MMFmemIOHandle *memHandle = NULL;
144 const unsigned char *c = NULL;
147 if (!opaque || !buf) {
148 debug_error(DEBUG, "invalid para\n");
149 return MMFILE_UTIL_FAIL;
154 if (!memHandle->ptr) {
155 debug_error(DEBUG, "invalid para\n");
156 return MMFILE_UTIL_FAIL;
159 if (memHandle->offset >= memHandle->size) {
160 /* for some file formats last file read */
161 debug_error(DEBUG, "File Read is beyond the file Size\n");
162 return MMFILE_UTIL_FAIL;
166 c = memHandle->ptr + memHandle->offset;
168 if (memHandle->state != EOF) {
170 if (len + memHandle->offset > memHandle->size) {
171 len = memHandle->size - memHandle->offset;
177 memHandle->offset += len;
179 if (memHandle->offset == memHandle->size) {
180 memHandle->state = EOF;
186 static int64_t _mmf_mem_seek(void *opaque, int64_t pos, int whence)
188 MMFmemIOHandle *memHandle = NULL;
189 long long tmp_offset = 0;
192 debug_error(DEBUG, "invalid para\n");
193 return MMFILE_UTIL_FAIL;
200 tmp_offset = 0 + pos;
203 tmp_offset = memHandle->offset + pos;
206 tmp_offset = memHandle->size + pos;
208 case AVSEEK_SIZE: /*FFMPEG specific*/
209 return memHandle->size;
211 return MMFILE_UTIL_FAIL;
215 if (tmp_offset < 0 && tmp_offset > memHandle->size) {
216 debug_error(DEBUG, "invalid file offset\n");
217 return MMFILE_UTIL_FAIL;
221 memHandle->state = (tmp_offset >= memHandle->size) ? EOF : !EOF;
222 memHandle->offset = (unsigned int) tmp_offset;
228 int mmfile_format_open_ffmpg(MMFileFormatContext *formatContext)
230 AVFormatContext *pFormatCtx = NULL;
231 AVInputFormat *grab_iformat = NULL;
233 char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0, };
234 char mimeType[MMFILE_MIMETYPE_MAX_LEN] = {0, };
235 AVIOContext *pIOCtx = NULL;
236 MMFmemIOHandle *handle = NULL;
237 uint8_t *avio_ctx_buffer = NULL;
239 formatContext->ReadStream = mmfile_format_read_stream_ffmpg;
240 formatContext->ReadFrame = mmfile_format_read_frame_ffmpg;
241 formatContext->ReadTag = mmfile_format_read_tag_ffmpg;
242 formatContext->Close = mmfile_format_close_ffmpg;
244 debug_msg(RELEASE, "ffmpeg version: %d\n", avformat_version());
255 #ifdef __MMFILE_TEST_MODE__
256 av_log_set_level(AV_LOG_DEBUG);
258 av_log_set_level(AV_LOG_QUIET);
263 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
264 if (mmfile_util_get_mimetype(formatContext->filesrc->memory.format, mimeType, MMFILE_MIMETYPE_MAX_LEN) < 0) {
265 debug_error(DEBUG, "error: Error in MIME Type finding\n");
266 return MMFILE_FORMAT_FAIL;
269 memset(ffmpegFormatName, 0x00, MMFILE_FILE_FMT_MAX_LEN);
271 ret = mmfile_util_get_ffmpeg_format(mimeType, ffmpegFormatName);
272 if (MMFILE_UTIL_SUCCESS != ret) {
273 debug_error(DEBUG, "error: mmfile_util_get_ffmpeg_format\n");
274 return MMFILE_FORMAT_FAIL;
277 grab_iformat = av_find_input_format(ffmpegFormatName);
279 if (NULL == grab_iformat) {
280 debug_error(DEBUG, "error: cannot find format\n");
284 avio_ctx_buffer = av_malloc(MMFILE_AVIO_BUFFER_LEN);
285 if (avio_ctx_buffer == NULL) {
286 debug_error(DEBUG, "error: cannot alloc avio_ctx_buffert\n");
290 ret = _mmf_mem_open(&handle, formatContext->uriFileName);
291 if (ret != MMFILE_IO_SUCCESS) {
292 debug_warning(DEBUG, "failed to _mmf_mem_open.\n");
296 pIOCtx = avio_alloc_context(avio_ctx_buffer, MMFILE_AVIO_BUFFER_LEN, 0, handle, _mmf_mem_read, NULL, _mmf_mem_seek);
297 if (pIOCtx == NULL) {
298 debug_error(DEBUG, "error: cannot alloc io context\n");
302 pFormatCtx = avformat_alloc_context();
303 if (pFormatCtx == NULL) {
304 debug_warning(DEBUG, "failed to avformat_alloc_context\n");
308 pFormatCtx->pb = pIOCtx;
310 ret = avformat_open_input(&pFormatCtx, "", grab_iformat, NULL);
312 debug_error(DEBUG, "error: cannot open %s %d\n", formatContext->uriFileName, ret);
316 formatContext->privateFormatData = pFormatCtx;
319 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_FILE) {
321 ret = avformat_open_input(&pFormatCtx, formatContext->filesrc->file.path, NULL, NULL);
323 debug_error(DEBUG, "error: cannot open %s %d\n", formatContext->filesrc->file.path, ret);
327 formatContext->privateFormatData = pFormatCtx;
330 if (!pFormatCtx/* || !(pFormatCtx->nb_streams > 0)*/) {
331 debug_warning(DEBUG, "failed to find av stream. maybe corrupted data.\n");
335 debug_msg(RELEASE, "number of stream: %d\n", pFormatCtx->nb_streams);
337 __count_stream_num(pFormatCtx, formatContext);
339 debug_msg(RELEASE, "format: %s (%s)\n", pFormatCtx->iformat->name, pFormatCtx->iformat->long_name);
340 #ifdef __MMFILE_TEST_MODE__
341 av_dump_format(pFormatCtx, 0, formatContext->filesrc->file.path, 0);
344 return MMFILE_FORMAT_SUCCESS;
346 exception: /* fail to get content information */
347 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
349 av_free(avio_ctx_buffer);
356 avformat_close_input(&pFormatCtx);
358 mmfile_format_close_ffmpg(formatContext);
361 formatContext->privateFormatData = NULL;
363 return MMFILE_FORMAT_FAIL;
366 static bool __check_uhqa(int sample_rate, enum AVSampleFormat sample_fmt_info)
370 debug_error(RELEASE, "[sample rate %d, sample format %d]", sample_rate, sample_fmt_info);
372 if ((sample_rate >= 44100) && (sample_fmt_info >= AV_SAMPLE_FMT_S32)) {
373 debug_msg(RELEASE, "UHQA CONTENT");
383 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext)
385 AVFormatContext *pFormatCtx = NULL;
386 AVCodecParameters *pAudioCodecCtx = NULL;
387 AVCodecParameters *pVideoCodecCtx = NULL;
389 MMFileFormatStream *videoStream = NULL;
390 MMFileFormatStream *audioStream = NULL;
394 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
395 debug_error(DEBUG, "invalid param\n");
396 return MMFILE_FORMAT_FAIL;
399 pFormatCtx = formatContext->privateFormatData;
400 pFormatCtx->start_time = -1;
403 *@important if data is corrupted, occur segment fault by av_find_stream_info().
404 * - fixed 2009-06-25.
406 if (formatContext->formatType == MM_FILE_FORMAT_M2TS)
407 pFormatCtx->max_analyze_duration = 100000; // MPEGTS file timeout set
409 if (formatContext->cdis != 1)
410 ret = avformat_find_stream_info(pFormatCtx, NULL);
415 debug_warning(DEBUG, "failed to find stream info. errcode = %d\n", ret);
419 debug_msg(RELEASE, "FFMPEG: dur %"PRId64", start %"PRId64"\n", pFormatCtx->duration, pFormatCtx->start_time);
422 *@note asf has long duration bug. and Some content's start time is wrong(negative number).
423 * Generally, mpegts has wrong start time(positive large value). So skip start time for mpegts format.
425 if (pFormatCtx->start_time < 0 || formatContext->formatType == MM_FILE_FORMAT_M2TS) {
426 debug_warning(DEBUG, "Wrong Start time = %"PRId64"\n", pFormatCtx->start_time);
427 formatContext->duration = (long long)(pFormatCtx->duration) * 1000 / AV_TIME_BASE;
429 formatContext->duration = (long long)(pFormatCtx->duration + pFormatCtx->start_time) * 1000 / AV_TIME_BASE;
432 formatContext->videoStreamId = -1;
433 formatContext->audioStreamId = -1;
434 formatContext->nbStreams = 0;
435 formatContext->videoTotalTrackNum = 0;
436 formatContext->audioTotalTrackNum = 0;
438 for (i = 0; i < pFormatCtx->nb_streams; i++) {
439 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
440 if (formatContext->videoStreamId == -1) {
441 videoStream = mmfile_malloc(sizeof(MMFileFormatStream));
442 if (NULL == videoStream) {
443 debug_error(DEBUG, "mmfile_malloc error\n");
447 videoStream->streamType = MMFILE_VIDEO_STREAM;
448 formatContext->streams[MMFILE_VIDEO_STREAM] = videoStream;
449 formatContext->nbStreams += 1;
450 formatContext->videoStreamId = i;
451 formatContext->videoTotalTrackNum += 1;
453 pVideoCodecCtx = pFormatCtx->streams[i]->codecpar;
454 if (pVideoCodecCtx) {
455 videoStream->codecId = ConvertVideoCodecEnum(pVideoCodecCtx->codec_id);
456 if (videoStream->codecId == MM_VIDEO_CODEC_NONE) {
457 debug_error(RELEASE, "Proper codec is not found in [%d] stream", i);
458 formatContext->videoStreamId = -1;
459 mmfile_free(videoStream);
460 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
467 * 1. try to get average fps of video stream.
468 * 2. if (1) failed, try to get fps of media container.
470 videoStream->framePerSec = _get_video_fps(pFormatCtx->streams[i]->nb_frames,
471 pFormatCtx->streams[i]->duration,
472 pFormatCtx->streams[i]->time_base,
475 if (videoStream->framePerSec == 0) {
476 #ifndef __MMFILE_LIBAV_VERSION__
477 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->r_frame_rate);
479 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->avg_frame_rate);
483 videoStream->width = pVideoCodecCtx->width;
484 videoStream->height = pVideoCodecCtx->height;
485 videoStream->bitRate = pVideoCodecCtx->bit_rate;
488 } else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
489 if (formatContext->audioStreamId == -1) {
490 audioStream = mmfile_malloc(sizeof(MMFileFormatStream));
491 if (NULL == audioStream) {
492 debug_error(DEBUG, "mmfile_malloc error\n");
496 audioStream->streamType = MMFILE_AUDIO_STREAM;
497 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
498 formatContext->nbStreams += 1;
499 formatContext->audioStreamId = i;
500 formatContext->audioTotalTrackNum += 1;
502 pAudioCodecCtx = pFormatCtx->streams[i]->codecpar;
503 if (pAudioCodecCtx) {
504 audioStream->codecId = ConvertAudioCodecEnum(pAudioCodecCtx->codec_id);
505 audioStream->bitRate = pAudioCodecCtx->bit_rate;
506 audioStream->nbChannel = pAudioCodecCtx->channels;
507 audioStream->samplePerSec = pAudioCodecCtx->sample_rate;
509 if (audioStream->codecId == MM_AUDIO_CODEC_FLAC)
510 audioStream->bitPerSample = pAudioCodecCtx->bits_per_raw_sample;
513 audioStream->bitPerSample = pAudioCodecCtx->bits_per_coded_sample;
514 audioStream->is_uhqa = __check_uhqa(audioStream->samplePerSec, pFormatCtx->streams[i]->codecpar->format);
520 if (formatContext->nbStreams == 0) {
521 debug_error(DEBUG, "error: there is no audio and video track\n");
525 #ifdef __MMFILE_TEST_MODE__
526 mmfile_format_print_contents(formatContext);
529 return MMFILE_FORMAT_SUCCESS;
532 mmfile_free(videoStream);
533 mmfile_free(audioStream);
535 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
536 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
539 avformat_close_input(&pFormatCtx);
540 formatContext->privateFormatData = NULL;
543 formatContext->audioTotalTrackNum = 0;
544 formatContext->videoTotalTrackNum = 0;
545 formatContext->nbStreams = 0;
547 return MMFILE_FORMAT_FAIL;
550 #define DATA_LENGTH 4
551 #define POS_OF_MIME_LEN DATA_LENGTH
552 #define CONVERT_TO_INT(dest, src) {dest = 0; dest |= (0 | src[0] << 24) | (0 | src[1] << 16) | (0 | src[2] << 8) | (0 | src[3]); }
554 static void __fill_picture_in_context(char *value, MMFileFormatContext *formatContext)
557 guchar *meta_data = NULL;
559 meta_data = g_base64_decode(value, &len);
561 debug_log(RELEASE, "no picture");
565 /* in METADATA_BLOCK_PICTURE,
566 the length of mime type and the length of description are flexible,
567 so, we have to get the length of their for getting correct postion of picture data. */
569 int description_len = 0;
572 unsigned char current_data[DATA_LENGTH] = {0};
574 /* get length of mime_type */
575 memcpy(current_data, meta_data + POS_OF_MIME_LEN, DATA_LENGTH);
576 CONVERT_TO_INT(mime_len, current_data);
578 /* get length of description */
579 current_pos = mime_len + (DATA_LENGTH * 2); /*current position is length of description */
580 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
581 CONVERT_TO_INT(description_len, current_data);
583 /* get length of picture data */
584 current_pos = mime_len + description_len + (DATA_LENGTH * 7); /*current position is length of picture data */
585 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
586 CONVERT_TO_INT(data_len, current_data);
588 /* set the size of art work */
589 formatContext->artworkSize = data_len;
592 current_pos = POS_OF_MIME_LEN + DATA_LENGTH; /*current position is mime type */
593 mmfile_free(formatContext->artworkMime);
594 formatContext->artworkMime = strndup((const char *)meta_data + current_pos, mime_len);
596 /* set art work data */
597 current_pos = mime_len + description_len + (DATA_LENGTH * 8); /*current position is picture data */
598 mmfile_free(formatContext->artwork);
600 formatContext->artwork = mmfile_malloc(data_len);
601 if (formatContext->artwork)
602 memcpy(formatContext->artwork, meta_data + current_pos, data_len);
607 static void __fill_artwork_in_context(AVStream *st, MMFileFormatContext *formatContext)
609 AVPacket pkt = st->attached_pic;
610 int codec_id = st->codecpar->codec_id;
612 if (!pkt.data || pkt.size <= 0) {
617 mmfile_free(formatContext->artworkMime);
619 if (codec_id == AV_CODEC_ID_MJPEG)
620 formatContext->artworkMime = mmfile_strdup("image/jpeg");
621 else if (codec_id == AV_CODEC_ID_PNG)
622 formatContext->artworkMime = mmfile_strdup("image/png");
623 else if (codec_id == AV_CODEC_ID_BMP)
624 formatContext->artworkMime = mmfile_strdup("image/bmp");
626 debug_error(DEBUG, "Unknown cover type: 0x%x\n", codec_id);
629 mmfile_free(formatContext->artwork);
631 formatContext->artworkSize = pkt.size;
632 formatContext->artwork = mmfile_malloc(pkt.size);
633 if (formatContext->artwork)
634 memcpy(formatContext->artwork, pkt.data, pkt.size);
637 static void __fill_metainfo_in_context(AVDictionary *metainfo, MMFileFormatContext *formatContext)
639 AVDictionaryEntry *tag = NULL;
641 while ((tag = av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) {
646 if (!g_ascii_strcasecmp(tag->key, "title")) {
647 MMFILE_SAFE_FREE(formatContext->title);
648 formatContext->title = mmfile_strdup(tag->value);
649 } else if (!g_ascii_strcasecmp(tag->key, "artist")) {
650 MMFILE_SAFE_FREE(formatContext->artist);
651 formatContext->artist = mmfile_strdup(tag->value);
652 } else if (!g_ascii_strcasecmp(tag->key, "composer")) {
653 MMFILE_SAFE_FREE(formatContext->composer);
654 formatContext->composer = mmfile_strdup(tag->value);
655 } else if (!g_ascii_strcasecmp(tag->key, "album")) {
656 MMFILE_SAFE_FREE(formatContext->album);
657 formatContext->album = mmfile_strdup(tag->value);
658 } else if (!g_ascii_strcasecmp(tag->key, "album_artist")) {
659 MMFILE_SAFE_FREE(formatContext->album_artist);
660 formatContext->album_artist = mmfile_strdup(tag->value);
661 } else if (!g_ascii_strcasecmp(tag->key, "copyright")) {
662 MMFILE_SAFE_FREE(formatContext->copyright);
663 formatContext->copyright = mmfile_strdup(tag->value);
664 } else if (!g_ascii_strcasecmp(tag->key, "comment")) {
665 MMFILE_SAFE_FREE(formatContext->comment);
666 formatContext->comment = mmfile_strdup(tag->value);
667 } else if (!g_ascii_strcasecmp(tag->key, "description")) {
668 MMFILE_SAFE_FREE(formatContext->description);
669 formatContext->description = mmfile_strdup(tag->value);
670 } else if (!g_ascii_strcasecmp(tag->key, "genre")) {
671 MMFILE_SAFE_FREE(formatContext->genre);
672 formatContext->genre = mmfile_strdup(tag->value);
673 } else if (!g_ascii_strcasecmp(tag->key, "date")) {
674 MMFILE_SAFE_FREE(formatContext->year);
675 formatContext->year = mmfile_strdup(tag->value);
676 } else if (!g_ascii_strcasecmp(tag->key, "creation_time")) {
677 MMFILE_SAFE_FREE(formatContext->recDate);
678 formatContext->recDate = mmfile_strdup(tag->value);
679 } else if ((!g_ascii_strcasecmp(tag->key, "track")) || (!g_ascii_strcasecmp(tag->key, "tracknumber"))) {
680 MMFILE_SAFE_FREE(formatContext->tagTrackNum);
681 formatContext->tagTrackNum = mmfile_strdup(tag->value);
682 } else if (!g_ascii_strcasecmp(tag->key, "lyrics")) {
683 MMFILE_SAFE_FREE(formatContext->unsyncLyrics);
684 formatContext->unsyncLyrics = mmfile_strdup(tag->value);
685 } else if (!g_ascii_strcasecmp(tag->key, "rotate")) { /*can be "90", "180", "270" */
686 MMFILE_SAFE_FREE(formatContext->rotate);
687 formatContext->rotate = mmfile_strdup(tag->value);
688 } else if (!g_ascii_strcasecmp(tag->key, "spherical-video")) {
689 ParseSpatialVideoMetadataFromXMLString(tag->value, formatContext);
690 } else if (!g_ascii_strcasecmp(tag->key, "metadata_block_picture")) {
691 __fill_picture_in_context(tag->value, formatContext);
693 debug_log(RELEASE, "Not support metadata. [%s:%s]", tag->key, tag->value);
699 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext)
701 AVFormatContext *pFormatCtx = NULL;
703 if (NULL == formatContext || NULL == formatContext->privateFormatData) {
704 debug_error(DEBUG, "invalid param\n");
705 return MMFILE_FORMAT_FAIL;
708 pFormatCtx = formatContext->privateFormatData;
710 debug_warning(DEBUG, "No format information");
711 return MMFILE_FORMAT_SUCCESS;
714 if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4) {
715 MMFileUtilGetMetaDataFromMP4(formatContext);
718 if (formatContext->formatType == MM_FILE_FORMAT_MATROSKA) {
719 MMFileUtilGetMetaDataFromMKV(formatContext);
722 /*metadata extracted by ffmpeg*/
723 unsigned int idx = 0;
725 for (idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) {
726 AVDictionary *metainfo = NULL;
729 /* Check metadata of normal stream like audio, video, video cover art
730 * (cover art saved in new stream). refer to mov_read_covr() in ffmpeg.
732 if (idx < pFormatCtx->nb_streams) {
733 st = pFormatCtx->streams[idx];
735 metainfo = st->metadata;
736 } else { /*Check metadata of Content */
737 if (pFormatCtx->metadata != NULL) {
738 metainfo = pFormatCtx->metadata;
744 /*refer to mov_read_covr() in ffmpeg.*/
746 __fill_artwork_in_context(st, formatContext);
749 __fill_metainfo_in_context(metainfo, formatContext);
751 #ifdef __MMFILE_TEST_MODE__
752 mmfile_format_print_tags(formatContext);
756 return MMFILE_FORMAT_SUCCESS;
761 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
763 AVFormatContext *pFormatCtx = NULL;
764 AVCodecContext *pVideoCodecCtx = NULL;
765 AVCodec *pVideoCodec = NULL;
766 AVCodecParameters *pVideoCodecPar = NULL;
767 AVFrame *pFrame = NULL;
774 if (NULL == formatContext ||
776 NULL == formatContext->privateFormatData ||
777 formatContext->videoTotalTrackNum <= 0) {
779 debug_error(DEBUG, "invalid param\n");
780 return MMFILE_FORMAT_FAIL;
783 pFormatCtx = formatContext->privateFormatData;
785 if (formatContext->videoStreamId != -1) {
786 pVideoCodecPar = pFormatCtx->streams[formatContext->videoStreamId]->codecpar;
787 if (NULL == pVideoCodecPar) {
788 debug_error(DEBUG, "invalid param\n");
789 return MMFILE_FORMAT_FAIL;
792 pVideoCodec = avcodec_find_decoder(pVideoCodecPar->codec_id);
793 if (NULL == pVideoCodec) {
794 debug_error(DEBUG, "error: avcodec_find_decoder failed\n");
795 return MMFILE_FORMAT_FAIL;
798 pVideoCodecCtx = avcodec_alloc_context3(pVideoCodec);
799 if (NULL == pVideoCodecCtx) {
800 debug_error(DEBUG, "error: avcodec_alloc_context3 failed\n");
801 return MMFILE_FORMAT_FAIL;
804 ret = avcodec_parameters_to_context(pVideoCodecCtx, pVideoCodecPar);
806 debug_error(DEBUG, "error: avcodec_parameters_to_context\n");
807 avcodec_free_context(&pVideoCodecCtx);
808 return MMFILE_FORMAT_FAIL;
811 debug_msg(RELEASE, "flag: 0x%08X\n", pVideoCodec->capabilities);
812 /* debug_msg(RELEASE, " DRAW_HORIZ_BAND : %d\n", pVideoCodec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND ? 1 : 0); */
813 /* debug_msg(RELEASE, " DR1 : %d\n", pVideoCodec->capabilities & CODEC_CAP_DR1 ? 1 : 0); */
814 /* debug_msg(RELEASE, " PARSE_ONLY : %d\n", pVideoCodec->capabilities & CODEC_CAP_PARSE_ONLY ? 1 : 0); */
815 /* debug_msg(RELEASE, " TRUNCATED : %d\n", pVideoCodec->capabilities & CODEC_CAP_TRUNCATED ? 1 : 0); */
816 /* debug_msg(RELEASE, " HWACCEL : %d\n", pVideoCodec->capabilities & CODEC_CAP_HWACCEL ? 1 : 0); */
817 /* debug_msg(RELEASE, " DELAY : %d\n", pVideoCodec->capabilities & CODEC_CAP_DELAY ? 1 : 0); */
818 /* debug_msg(RELEASE, " SMALL_LAST_FRAME: %d\n", pVideoCodec->capabilities & CODEC_CAP_SMALL_LAST_FRAME ? 1 : 0); */
819 /* debug_msg(RELEASE, " HWACCEL_VDPAU : %d\n", pVideoCodec->capabilities & CODEC_CAP_HWACCEL_VDPAU ? 1 : 0); */
821 if (pVideoCodec->capabilities & CODEC_CAP_TRUNCATED) {
822 pVideoCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
825 /*set workaround bug flag*/
826 pVideoCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
828 /* this is solution for PLM issue P13091703323 */
829 /* If using thread when decoding frame, the result of decoding is not always same.
830 Thumbnail of video content is different with original file when copying file. */
831 pVideoCodecCtx->thread_type = 0;
832 pVideoCodecCtx->thread_count = 0;
833 ret = avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL);
835 debug_error(DEBUG, "error: avcodec_open fail.\n");
836 return MMFILE_FORMAT_FAIL;
839 /* search & decode */
840 /* seek_ts = formatContext->duration > _SHORT_MEDIA_LIMIT ? seek_ts : 0; */ /*if short media, seek first key frame*/
841 ret = _get_first_good_video_frame(pFormatCtx, pVideoCodecCtx, formatContext->videoStreamId, &pFrame, formatContext->cdis);
842 if (ret != MMFILE_FORMAT_SUCCESS) {
843 debug_error(DEBUG, "error: get key frame\n");
844 ret = MMFILE_FORMAT_FAIL;
848 debug_msg(RELEASE, "Video default resolution = [%dx%d]\n", pVideoCodecCtx->coded_width, pVideoCodecCtx->coded_height);
849 debug_msg(RELEASE, "Video coded resolution = [%dx%d]\n", pVideoCodecCtx->width, pVideoCodecCtx->height);
851 /*sometimes, ffmpeg's width/height is wrong*/
852 #if 0 /*coded_width/height sometimes wrong. so use width/height*/
853 width = pVideoCodecCtx->coded_width == 0 ? pVideoCodecCtx->width : pVideoCodecCtx->coded_width;
854 height = pVideoCodecCtx->coded_height == 0 ? pVideoCodecCtx->height : pVideoCodecCtx->coded_height;
856 if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
857 width = pVideoCodecCtx->coded_width;
858 height = pVideoCodecCtx->coded_height;
860 width = pVideoCodecCtx->width;
861 height = pVideoCodecCtx->height;
864 numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, width, height, 1);
866 debug_error(DEBUG, "error: av_image_get_buffer_size. [%d x %d]\n", width, height);
867 ret = MMFILE_FORMAT_FAIL;
871 frame->frameData = mmfile_malloc(numBytes);
872 if (NULL == frame->frameData) {
873 debug_error(DEBUG, "error: mmfile_malloc. [%d]\n", numBytes);
874 ret = MMFILE_FORMAT_FAIL;
878 uint8_t *dst_data[4];
881 ret = av_image_fill_arrays(dst_data, dst_linesize, frame->frameData, AV_PIX_FMT_RGB24, width, height, 1);
883 debug_error(DEBUG, "error: avpicture_fill fail. errcode = 0x%08X\n", ret);
884 ret = MMFILE_FORMAT_FAIL;
888 struct SwsContext *img_convert_ctx = NULL;
890 img_convert_ctx = sws_getContext(width, height, pVideoCodecCtx->pix_fmt, width, height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
892 if (NULL == img_convert_ctx) {
893 debug_error(DEBUG, "failed to get img convet ctx\n");
894 ret = MMFILE_FORMAT_FAIL;
898 ret = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize, 0, height, dst_data, dst_linesize);
900 debug_error(DEBUG, "failed to convet image\n");
901 ret = MMFILE_FORMAT_FAIL;
902 sws_freeContext(img_convert_ctx);
903 img_convert_ctx = NULL;
907 sws_freeContext(img_convert_ctx);
908 img_convert_ctx = NULL;
910 frame->frameSize = numBytes;
911 frame->frameWidth = width;
912 frame->frameHeight = height;
913 frame->configLenth = 0;
914 frame->bCompressed = 0; /* false */
916 if (pFrame) av_frame_free(&pFrame);
918 avcodec_free_context(&pVideoCodecCtx);
920 return MMFILE_FORMAT_SUCCESS;
925 if (pVideoCodecCtx) avcodec_free_context(&pVideoCodecCtx);
927 mmfile_free(frame->frameData);
929 if (pFrame) av_frame_free(&pFrame);
936 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext)
939 AVFormatContext *pFormatCtx = formatContext->privateFormatData;
942 avformat_close_input(&pFormatCtx);
943 formatContext->privateFormatData = NULL;
947 return MMFILE_FORMAT_SUCCESS;
951 * return average of difference
953 static unsigned int _diff_memory(const void *s1, const void *s2, unsigned int n)
955 char *s = (char *)s1;
956 char *d = (char *)s2;
958 unsigned int ret = 0;
961 for (i = 0, ret = 0; i < n; i++) {
964 ret += (tmp < 0 ? -tmp : tmp);
974 int64_t gettime(void)
977 gettimeofday(&tv, NULL);
978 return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
982 #define IS_GOOD_OLD_METHOD
983 #ifdef IS_GOOD_OLD_METHOD
985 * compare with center line.
987 static int _is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize)
989 #define _MM_CHUNK_NUM 8 /*FIXME*/
990 #define _MM_CHUNK_LIMIT (_MM_CHUNK_NUM / 2)
991 #define _MM_CHUNK_DIFF_LIMIT (_MM_CHUNK_LIMIT * 2 + 1) /*FIXME*/
996 unsigned char *cnt; /*center line of image*/
998 unsigned int sum_diff;
1002 step = ysize / _MM_CHUNK_NUM;
1003 cnt_offset = (ysize / 2);
1004 cnt = buf + cnt_offset * wrap;
1006 debug_msg(RELEASE, "checking frame. %p, %d, %d, %d\n", buf, wrap, xsize, ysize);
1008 /*if too small, always ok return.*/
1009 if (ysize < _MM_CHUNK_NUM)
1012 for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
1013 if (i != cnt_offset) {
1016 is_different = _diff_memory(cnt, buf + i * wrap, xsize);
1017 point += (is_different == 0 ? 0 : 1);
1018 sum_diff += is_different;
1020 debug_msg(RELEASE, "check %04d line. %s [%d]\n", i, (is_different == 0 ? "same" : "different"), is_different);
1022 if (point >= _MM_CHUNK_LIMIT) {
1023 if (sum_diff > _MM_CHUNK_DIFF_LIMIT) {
1024 debug_msg(RELEASE, "Good :-)\n");
1027 debug_msg(RELEASE, "Bad :-(\n");
1036 #else /* IS_GOOD_OLD_METHOD */
1037 /* ToDo : for enhancement */
1038 #endif /* IS_GOOD_OLD_METHOD */
1043 _get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
1047 debug_msg(RELEASE, "frame count: %d, dur: %d, num: %d, den: %d\n", frame_cnt, duration, r_frame_rate.num, r_frame_rate.den);
1049 if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
1052 round = (is_roundup != 0 ? 0.50f : 0.00f);
1054 fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
1059 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1060 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
1065 f = fopen(filename, "w");
1067 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
1068 for (i = 0; i < ysize; i++)
1069 fwrite(buf + i * wrap, 1, xsize, f);
1075 #ifdef __MMFILE_TEST_MODE__
1076 static void _dump_av_packet(AVPacket *pkt)
1078 debug_msg(RELEASE, "--------- AV Packet -----------\n");
1079 debug_msg(RELEASE, " pts: %lld\n", pkt->pts);
1080 debug_msg(RELEASE, " dts: %lld\n", pkt->dts);
1081 debug_msg(RELEASE, " data: %p\n", pkt->data);
1082 debug_msg(RELEASE, " size: %d\n", pkt->size);
1083 debug_msg(RELEASE, " stream_index: %d\n", pkt->stream_index);
1084 debug_msg(RELEASE, " flags: 0x%08X, %s\n", pkt->flags, (pkt->flags & AV_PKT_FLAG_KEY) ? "Keyframe" : "_");
1085 debug_msg(RELEASE, " duration: %lld\n", pkt->duration);
1086 /*debug_msg(RELEASE, " destruct: %p\n", pkt->destruct);*/
1087 /*debug_msg(RELEASE, " priv: %p\n", pkt->priv);*/
1088 debug_msg(RELEASE, " pos: %lld\n", pkt->pos);
1089 debug_msg(RELEASE, "-------------------------------\n");
1093 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame **pFrame, int cdis)
1095 /* AVStream *st = NULL; */
1098 AVFrame *frame = NULL;
1099 AVFrame *tmp_frame = NULL;
1100 AVFrame *first_frame = NULL;
1102 /* long long timestamp; */
1103 /*int stream_id = videoStream;*/
1109 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1110 char pgm_name[256] = {0, };
1112 int key_search_limit = 0;
1113 int frame_search_limit = 0;
1115 #define _RETRY_SEARCH_LIMIT 250
1116 #define _KEY_SEARCH_LIMIT (_RETRY_SEARCH_LIMIT*2) /*2 = 1 read. some frame need to read one more*/
1117 #define _FRAME_SEARCH_LIMIT 500
1119 #define _RETRY_SEARCH_LIMIT_CDIS 10
1120 #define _KEY_SEARCH_LIMIT_CDIS (_RETRY_SEARCH_LIMIT*2) /*2 = 1 read. some frame need to read one more*/
1121 #define _FRAME_SEARCH_LIMIT_CDIS 10
1123 first_frame = av_frame_alloc();
1124 tmp_frame = av_frame_alloc();
1126 if (!first_frame || !tmp_frame) {
1127 debug_error(DEBUG, "failed to alloc frame.\n");
1128 if (first_frame) av_frame_free(&first_frame);
1129 if (tmp_frame) av_frame_free(&tmp_frame);
1130 return MMFILE_FORMAT_FAIL;
1133 debug_msg(RELEASE, "frame: 1. %p, 2. %p\n", first_frame, tmp_frame);
1135 pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1138 key_search_limit = _KEY_SEARCH_LIMIT_CDIS;
1139 frame_search_limit = _FRAME_SEARCH_LIMIT_CDIS;
1141 key_search_limit = _KEY_SEARCH_LIMIT;
1142 frame_search_limit = _FRAME_SEARCH_LIMIT;
1145 for (i = 0, v = 0, key_detected = 0, frame = first_frame; i < key_search_limit && v < frame_search_limit;) {
1146 av_init_packet(&pkt);
1148 ret = av_read_frame(pFormatCtx, &pkt);
1150 debug_error(DEBUG, "read failed. (maybe EOF or broken)\n");
1154 if (avcodec_get_type(pFormatCtx->streams[pkt.stream_index]->codecpar->codec_id) == AVMEDIA_TYPE_VIDEO) {
1156 if ((pkt.flags & AV_PKT_FLAG_KEY) || (key_detected == 1)) {
1157 debug_msg(RELEASE, "video frame: %d, %d, %d\n", retry, i, v);
1158 #ifdef __MMFILE_TEST_MODE__
1159 _dump_av_packet(&pkt);
1165 len = avcodec_send_packet(pCodecCtx, &pkt);
1166 if (len < 0 && len != AVERROR(EAGAIN) && len != AVERROR_EOF) {
1167 debug_error(RELEASE, "Error while avcodec_send_packet[%2d]", len);
1171 len = avcodec_receive_frame(pCodecCtx, frame);
1172 if (len < 0 && len != AVERROR(EAGAIN) && len != AVERROR_EOF) {
1173 debug_warning(DEBUG, "Error while decoding frame %dth\n", i);
1174 } else if (len >= 0) {
1175 if (frame->key_frame) {
1176 debug_msg(RELEASE, "key frame!\n");
1177 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1178 memset(pgm_name, 0x00, sizeof(pgm_name));
1179 snprintf(pgm_name, sizeof(pgm_name), "./key_%d_%d_%d.pgm", retry, i, v);
1180 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1185 #ifdef __MMFILE_TEST_MODE__
1189 ret = _is_good_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height);
1190 #ifdef __MMFILE_TEST_MODE__
1191 ti = gettime() - ti;
1192 debug_msg(RELEASE, "Elapsed time = %lld\n", ti);
1195 debug_msg(RELEASE, "is good frame.\n");
1199 /*reset video frame count & retry searching*/
1200 debug_warning(RELEASE, "not good fame. retry scanning.\n");
1205 /*set buffer frame*/
1209 if (retry > _RETRY_SEARCH_LIMIT) break;
1212 debug_msg(RELEASE, "skip (not key frame).\n");
1213 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1214 memset(pgm_name, 0x00, sizeof(pgm_name));
1215 snprintf(pgm_name, sizeof(pgm_name), "./not_key_%d_%d_%d.pgm", retry, i, v);
1216 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1220 debug_msg(RELEASE, "decode not completed.\n");
1226 av_packet_unref(&pkt);
1229 /*free pkt after loop breaking*/
1230 av_packet_unref(&pkt);
1232 debug_msg(RELEASE, "found: %d, retry: %d\n", found, retry);
1234 /*set decode frame to output*/
1236 ret = MMFILE_FORMAT_SUCCESS;
1237 if (retry == 0 || found == retry) {
1238 *pFrame = first_frame;
1239 if (tmp_frame) av_frame_free(&tmp_frame);
1241 *pFrame = tmp_frame;
1242 if (first_frame) av_frame_free(&first_frame);
1245 ret = MMFILE_FORMAT_FAIL;
1246 if (first_frame) av_frame_free(&first_frame);
1247 if (tmp_frame) av_frame_free(&tmp_frame);
1250 debug_msg(RELEASE, "out frame: %p\n", *pFrame);
1252 pCodecCtx->skip_frame = AVDISCARD_NONE;
1257 static int ConvertVideoCodecEnum(int AVVideoCodecID)
1259 int ret_codecid = 0;
1261 switch (AVVideoCodecID) {
1262 case AV_CODEC_ID_NONE:
1263 ret_codecid = MM_VIDEO_CODEC_NONE;
1265 case AV_CODEC_ID_MPEG1VIDEO:
1266 ret_codecid = MM_VIDEO_CODEC_MPEG1;
1268 case AV_CODEC_ID_MPEG2VIDEO: /*/< preferred ID for MPEG-1/2 video decoding */
1269 case AV_CODEC_ID_MPEG2VIDEO_XVMC:
1270 case AV_CODEC_ID_MPEG2TS:
1271 ret_codecid = MM_VIDEO_CODEC_MPEG2;
1273 case AV_CODEC_ID_H261:
1274 ret_codecid = MM_VIDEO_CODEC_H261;
1276 case AV_CODEC_ID_H263:
1277 ret_codecid = MM_VIDEO_CODEC_H263;
1279 case AV_CODEC_ID_MPEG4:
1280 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1282 case AV_CODEC_ID_MSMPEG4V1:
1283 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1285 case AV_CODEC_ID_MSMPEG4V2:
1286 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1288 case AV_CODEC_ID_MSMPEG4V3:
1289 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1291 case AV_CODEC_ID_WMV1:
1292 ret_codecid = MM_VIDEO_CODEC_WMV;
1294 case AV_CODEC_ID_WMV2:
1295 ret_codecid = MM_VIDEO_CODEC_WMV;
1297 case AV_CODEC_ID_H263P:
1298 ret_codecid = MM_VIDEO_CODEC_H263;
1300 case AV_CODEC_ID_H263I:
1301 ret_codecid = MM_VIDEO_CODEC_H263;
1303 case AV_CODEC_ID_FLV1:
1304 ret_codecid = MM_VIDEO_CODEC_FLV;
1306 case AV_CODEC_ID_H264:
1307 ret_codecid = MM_VIDEO_CODEC_H264;
1309 case AV_CODEC_ID_INDEO2:
1310 case AV_CODEC_ID_INDEO3:
1311 case AV_CODEC_ID_INDEO4:
1312 case AV_CODEC_ID_INDEO5:
1313 ret_codecid = MM_VIDEO_CODEC_INDEO;
1315 case AV_CODEC_ID_THEORA:
1316 ret_codecid = MM_VIDEO_CODEC_THEORA;
1318 case AV_CODEC_ID_CINEPAK:
1319 ret_codecid = MM_VIDEO_CODEC_CINEPAK;
1321 case AV_CODEC_ID_VC1:
1322 ret_codecid = MM_VIDEO_CODEC_VC1;
1324 case AV_CODEC_ID_WMV3:
1325 ret_codecid = MM_VIDEO_CODEC_WMV;
1327 case AV_CODEC_ID_AVS:
1328 ret_codecid = MM_VIDEO_CODEC_AVS;
1330 case AV_CODEC_ID_RL2:
1331 case AV_CODEC_ID_RV10: /* RealVideo 1 */
1332 case AV_CODEC_ID_RV20: /* RealVideo 2 */
1333 case AV_CODEC_ID_RV30: /* RealVideo 3 */
1334 case AV_CODEC_ID_RV40: /* RealVideo 4 */
1335 ret_codecid = MM_VIDEO_CODEC_REAL;
1337 #ifdef __MMFILE_LIBAV_VERSION__
1338 case AV_CODEC_ID_HEVC:
1339 ret_codecid = MM_VIDEO_CODEC_MPEG4;
1342 #ifdef USE_PRODUCT_FEATURE
1343 case AV_CODEC_ID_VP8:
1344 ret_codecid = MM_VIDEO_CODEC_VP8;
1346 case AV_CODEC_ID_VP9:
1347 ret_codecid = MM_VIDEO_CODEC_VP9;
1351 ret_codecid = MM_VIDEO_CODEC_NONE;
1359 static int ConvertAudioCodecEnum(int AVAudioCodecID)
1361 int ret_codecid = 0;
1363 switch (AVAudioCodecID) {
1364 case AV_CODEC_ID_AMR_NB:
1365 case AV_CODEC_ID_AMR_WB:
1366 ret_codecid = MM_AUDIO_CODEC_AMR;
1368 /* RealAudio codecs*/
1369 case AV_CODEC_ID_RA_144: /* RealAudio 1 */
1370 case AV_CODEC_ID_RA_288: /* RealAudio 2 */
1371 case AV_CODEC_ID_COOK: /* RealAudio 6 */
1372 ret_codecid = MM_AUDIO_CODEC_REAL;
1374 case AV_CODEC_ID_MP2:
1375 ret_codecid = MM_AUDIO_CODEC_MP2;
1377 case AV_CODEC_ID_MP3:
1378 case AV_CODEC_ID_MP3ADU:
1379 case AV_CODEC_ID_MP3ON4:
1380 ret_codecid = MM_AUDIO_CODEC_MP3;
1382 case AV_CODEC_ID_AAC:
1383 ret_codecid = MM_AUDIO_CODEC_AAC;
1385 case AV_CODEC_ID_AC3:
1386 ret_codecid = MM_AUDIO_CODEC_AC3;
1388 case AV_CODEC_ID_VORBIS:
1389 ret_codecid = MM_AUDIO_CODEC_VORBIS;
1391 case AV_CODEC_ID_WMAV1:
1392 case AV_CODEC_ID_WMAV2:
1393 case AV_CODEC_ID_WMAVOICE:
1394 case AV_CODEC_ID_WMAPRO:
1395 case AV_CODEC_ID_WMALOSSLESS:
1396 ret_codecid = MM_AUDIO_CODEC_WMA;
1398 case AV_CODEC_ID_FLAC:
1399 ret_codecid = MM_AUDIO_CODEC_FLAC;
1401 case AV_CODEC_ID_ALAC:
1402 ret_codecid = MM_AUDIO_CODEC_ALAC;
1404 case AV_CODEC_ID_WAVPACK:
1405 ret_codecid = MM_AUDIO_CODEC_WAVE;
1407 case AV_CODEC_ID_ATRAC3:
1408 case AV_CODEC_ID_ATRAC3P:
1409 case AV_CODEC_ID_EAC3:
1410 ret_codecid = MM_AUDIO_CODEC_AC3;
1412 case AV_CODEC_ID_PCM_S8:
1413 case AV_CODEC_ID_PCM_S16BE:
1414 case AV_CODEC_ID_PCM_S24BE:
1415 case AV_CODEC_ID_PCM_S32BE:
1416 ret_codecid = MM_AUDIO_CODEC_PCM;
1419 ret_codecid = MM_AUDIO_CODEC_NONE;