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 <libavutil/display.h>
29 #include <libswscale/swscale.h>
32 #include "mm_file_debug.h"
33 #include "mm_file_formats.h"
34 #include "mm_file_utils.h"
35 #include "mm_file_format_ffmpeg.h"
37 static int g_max_analyze_duration = 0;
38 static int g_probesize = 0;
40 #ifdef __MMFILE_TEST_MODE__
41 static void _dump_av_packet(AVPacket *pkt)
43 debug_msg(RELEASE, "--------- AV Packet -----------");
44 debug_msg(RELEASE, " pts: %lld", pkt->pts);
45 debug_msg(RELEASE, " dts: %lld", pkt->dts);
46 debug_msg(RELEASE, " data: %p", pkt->data);
47 debug_msg(RELEASE, " size: %d", pkt->size);
48 debug_msg(RELEASE, " stream_index: %d", pkt->stream_index);
49 debug_msg(RELEASE, " flags: 0x%08X, %s", pkt->flags, (pkt->flags & AV_PKT_FLAG_KEY) ? "Keyframe" : "_");
50 debug_msg(RELEASE, " duration: %lld", pkt->duration);
51 /*debug_msg(RELEASE, " destruct: %p", pkt->destruct);*/
52 /*debug_msg(RELEASE, " priv: %p", pkt->priv);*/
53 debug_msg(RELEASE, " pos: %lld", pkt->pos);
54 debug_msg(RELEASE, "-------------------------------");
58 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, AVFrame **pFrame, int cdis, int videoStreamId);
60 static int __convert_vidio_codec_type(int AVVideoCodecID)
62 switch (AVVideoCodecID) {
63 case AV_CODEC_ID_MPEG1VIDEO:
64 return MM_VIDEO_CODEC_MPEG1;
65 case AV_CODEC_ID_MPEG2VIDEO: /*/< preferred ID for MPEG-1/2 video decoding */
66 case AV_CODEC_ID_MPEG2TS:
67 return MM_VIDEO_CODEC_MPEG2;
68 case AV_CODEC_ID_H261:
69 return MM_VIDEO_CODEC_H261;
70 case AV_CODEC_ID_H263:
71 return MM_VIDEO_CODEC_H263;
72 case AV_CODEC_ID_MPEG4:
73 case AV_CODEC_ID_MSMPEG4V1:
74 case AV_CODEC_ID_MSMPEG4V2:
75 case AV_CODEC_ID_MSMPEG4V3:
76 return MM_VIDEO_CODEC_MPEG4;
77 case AV_CODEC_ID_WMV1:
78 case AV_CODEC_ID_WMV2:
79 return MM_VIDEO_CODEC_WMV;
80 case AV_CODEC_ID_H263P:
81 case AV_CODEC_ID_H263I:
82 return MM_VIDEO_CODEC_H263;
83 case AV_CODEC_ID_FLV1:
84 return MM_VIDEO_CODEC_FLV;
85 case AV_CODEC_ID_H264:
86 return MM_VIDEO_CODEC_H264;
87 case AV_CODEC_ID_INDEO2:
88 case AV_CODEC_ID_INDEO3:
89 case AV_CODEC_ID_INDEO4:
90 case AV_CODEC_ID_INDEO5:
91 return MM_VIDEO_CODEC_INDEO;
92 case AV_CODEC_ID_THEORA:
93 return MM_VIDEO_CODEC_THEORA;
94 case AV_CODEC_ID_CINEPAK:
95 return MM_VIDEO_CODEC_CINEPAK;
97 return MM_VIDEO_CODEC_VC1;
98 case AV_CODEC_ID_WMV3:
99 return MM_VIDEO_CODEC_WMV;
100 case AV_CODEC_ID_AVS:
101 return MM_VIDEO_CODEC_AVS;
102 case AV_CODEC_ID_RL2:
103 case AV_CODEC_ID_RV10: /* RealVideo 1 */
104 case AV_CODEC_ID_RV20: /* RealVideo 2 */
105 case AV_CODEC_ID_RV30: /* RealVideo 3 */
106 case AV_CODEC_ID_RV40: /* RealVideo 4 */
107 return MM_VIDEO_CODEC_REAL;
108 case AV_CODEC_ID_AV1: /* AOMedia Video 1 */
109 return MM_VIDEO_CODEC_AV1;
110 case AV_CODEC_ID_HEVC:
111 return MM_VIDEO_CODEC_MPEG4;
113 case AV_CODEC_ID_VP8:
114 return MM_VIDEO_CODEC_VP8;
115 case AV_CODEC_ID_VP9:
116 return MM_VIDEO_CODEC_VP9;
119 return MM_VIDEO_CODEC_NONE;
123 static int __convert_audio_codec_type(int AVAudioCodecID)
125 switch (AVAudioCodecID) {
126 case AV_CODEC_ID_AMR_NB:
127 case AV_CODEC_ID_AMR_WB:
128 return MM_AUDIO_CODEC_AMR;
129 /* RealAudio codecs*/
130 case AV_CODEC_ID_RA_144: /* RealAudio 1 */
131 case AV_CODEC_ID_RA_288: /* RealAudio 2 */
132 case AV_CODEC_ID_COOK: /* RealAudio 6 */
133 return MM_AUDIO_CODEC_REAL;
134 case AV_CODEC_ID_MP2:
135 return MM_AUDIO_CODEC_MP2;
136 case AV_CODEC_ID_MP3:
137 case AV_CODEC_ID_MP3ADU:
138 case AV_CODEC_ID_MP3ON4:
139 return MM_AUDIO_CODEC_MP3;
140 case AV_CODEC_ID_AAC:
141 return MM_AUDIO_CODEC_AAC;
142 case AV_CODEC_ID_AC3:
143 return MM_AUDIO_CODEC_AC3;
144 case AV_CODEC_ID_VORBIS:
145 return MM_AUDIO_CODEC_VORBIS;
146 case AV_CODEC_ID_WMAV1:
147 case AV_CODEC_ID_WMAV2:
148 case AV_CODEC_ID_WMAVOICE:
149 case AV_CODEC_ID_WMAPRO:
150 case AV_CODEC_ID_WMALOSSLESS:
151 return MM_AUDIO_CODEC_WMA;
152 case AV_CODEC_ID_FLAC:
153 return MM_AUDIO_CODEC_FLAC;
154 case AV_CODEC_ID_ALAC:
155 return MM_AUDIO_CODEC_ALAC;
156 case AV_CODEC_ID_WAVPACK:
157 return MM_AUDIO_CODEC_WAVE;
158 case AV_CODEC_ID_ATRAC3:
159 case AV_CODEC_ID_ATRAC3P:
160 case AV_CODEC_ID_EAC3:
161 return MM_AUDIO_CODEC_AC3;
162 case AV_CODEC_ID_PCM_S8:
163 case AV_CODEC_ID_PCM_S16BE:
164 case AV_CODEC_ID_PCM_S24BE:
165 case AV_CODEC_ID_PCM_S32BE:
166 return MM_AUDIO_CODEC_PCM;
168 return MM_AUDIO_CODEC_NONE;
172 /* plugin manadatory API */
173 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext);
174 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
175 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext);
176 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext);
178 static void __count_stream_num(AVFormatContext *pFormatCtx, MMFileFormatContext *formatContext)
182 formatContext->videoTotalTrackNum = 0;
183 formatContext->audioTotalTrackNum = 0;
185 for (i = 0; i < pFormatCtx->nb_streams; i++) {
186 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
187 debug_msg(RELEASE, "FFMPEG video codec id: 0x%08X", pFormatCtx->streams[i]->codecpar->codec_id);
189 AVPacket pkt = pFormatCtx->streams[i]->attached_pic;
190 if ((pkt.data != NULL) && (pkt.size > 0))
193 /*eventhough codec_id is 0, avformat_find_stream_info() can find proper codec_id. */
194 formatContext->videoTotalTrackNum += 1;
196 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
197 debug_msg(RELEASE, "FFMPEG audio codec id: 0x%08X", pFormatCtx->streams[i]->codecpar->codec_id);
198 formatContext->audioTotalTrackNum += 1;
203 static bool __mmf_mem_open(MMFmemIOHandle **handle, const char *filename)
205 MMFmemIOHandle *memHandle = NULL;
206 char **splitedString = NULL;
208 filename += strlen(MMFILE_MEM_URI);
209 splitedString = g_strsplit(filename, ":", -1);
211 if (g_strv_length(splitedString) < 2) {
212 debug_error(DEBUG, "invalid param");
213 g_strfreev(splitedString);
218 memHandle = g_new0(MMFmemIOHandle, 1);
220 /*memory allocation address changed. memHandle->ptr = (unsigned char*)atoi(splitedString[0]); */
221 memHandle->ptr = (unsigned char *)atoll(splitedString[0]);
222 memHandle->size = atoi(splitedString[1]);
223 memHandle->offset = 0;
224 memHandle->state = 0;
228 g_strfreev(splitedString);
233 static int __mmf_mem_read(void *opaque, uint8_t *buf, int size)
235 MMFmemIOHandle *memHandle = NULL;
236 const unsigned char *c = NULL;
239 mm_file_retvm_if_fails(DEBUG, opaque, MMFILE_UTIL_FAIL);
240 mm_file_retvm_if_fails(DEBUG, buf, MMFILE_UTIL_FAIL);
244 mm_file_retvm_if_fails(DEBUG, memHandle->ptr, MMFILE_UTIL_FAIL);
245 mm_file_retvm_if_fails(DEBUG, memHandle->offset < memHandle->size, MMFILE_UTIL_FAIL);
247 c = memHandle->ptr + memHandle->offset;
249 if (memHandle->state != EOF) {
251 if (len + memHandle->offset > memHandle->size)
252 len = memHandle->size - memHandle->offset;
256 memHandle->offset += len;
258 if (memHandle->offset == memHandle->size)
259 memHandle->state = EOF;
264 static int64_t __mmf_mem_seek(void *opaque, int64_t pos, int whence)
266 MMFmemIOHandle *memHandle = NULL;
267 long long tmp_offset = 0;
269 mm_file_retvm_if_fails(DEBUG, opaque, MMFILE_UTIL_FAIL);
275 tmp_offset = 0 + pos;
278 tmp_offset = memHandle->offset + pos;
281 tmp_offset = memHandle->size + pos;
283 case AVSEEK_SIZE: /*FFMPEG specific*/
284 return memHandle->size;
286 return MMFILE_UTIL_FAIL;
290 mm_file_retvm_if_fails(DEBUG, tmp_offset >= 0 && tmp_offset <= memHandle->size, MMFILE_UTIL_FAIL);
293 memHandle->state = (tmp_offset >= memHandle->size) ? EOF : !EOF;
294 memHandle->offset = (unsigned int) tmp_offset;
300 int mmfile_format_open_ffmpg(MMFileFormatContext *formatContext)
302 AVFormatContext *pFormatCtx = NULL;
303 const AVInputFormat *grab_iformat = NULL;
304 char ffmpegFormatName[MMFILE_FILE_FMT_MAX_LEN] = {0, };
305 AVIOContext *pIOCtx = NULL;
306 MMFmemIOHandle *handle = NULL;
307 uint8_t *avio_ctx_buffer = NULL;
309 formatContext->ReadStream = mmfile_format_read_stream_ffmpg;
310 formatContext->ReadFrame = mmfile_format_read_frame_ffmpg;
311 formatContext->ReadTag = mmfile_format_read_tag_ffmpg;
312 formatContext->Close = mmfile_format_close_ffmpg;
314 debug_msg(RELEASE, "ffmpeg version: %d", avformat_version());
325 #ifdef __MMFILE_TEST_MODE__
326 av_log_set_level(AV_LOG_TRACE);
328 av_log_set_level(AV_LOG_QUIET);
331 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
332 if (mmfile_util_get_ffmpeg_format(formatContext->filesrc->memory.format, ffmpegFormatName) != MMFILE_UTIL_SUCCESS) {
333 debug_error(DEBUG, "error: mmfile_util_get_ffmpeg_format");
334 return MMFILE_FORMAT_FAIL;
337 grab_iformat = av_find_input_format(ffmpegFormatName);
338 mm_file_retvm_if_fails(DEBUG, grab_iformat, MMFILE_UTIL_FAIL);
340 avio_ctx_buffer = av_malloc(MMFILE_AVIO_BUFFER_LEN);
341 mm_file_retvm_if_fails(DEBUG, avio_ctx_buffer, MMFILE_UTIL_FAIL);
343 if (!__mmf_mem_open(&handle, formatContext->uriFileName)) {
344 debug_error(DEBUG, "failed to _mmf_mem_open.");
348 pIOCtx = avio_alloc_context(avio_ctx_buffer, MMFILE_AVIO_BUFFER_LEN, 0, handle, __mmf_mem_read, NULL, __mmf_mem_seek);
350 debug_error(DEBUG, "error: cannot alloc io context");
354 pFormatCtx = avformat_alloc_context();
356 debug_error(DEBUG, "failed to avformat_alloc_context");
360 pFormatCtx->pb = pIOCtx;
362 if (avformat_open_input(&pFormatCtx, "", grab_iformat, NULL) < 0) {
363 debug_error(DEBUG, "error: cannot open %s", formatContext->uriFileName);
367 formatContext->privateFormatData = pFormatCtx;
370 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_FILE) {
371 if (avformat_open_input(&pFormatCtx, formatContext->filesrc->file.path, NULL, NULL) < 0) {
372 debug_error(DEBUG, "error: cannot open %s", formatContext->filesrc->file.path);
376 formatContext->privateFormatData = pFormatCtx;
380 debug_warning(DEBUG, "failed to find av stream. maybe corrupted data.");
384 debug_msg(RELEASE, "number of stream: %d", pFormatCtx->nb_streams);
386 __count_stream_num(pFormatCtx, formatContext);
388 debug_msg(RELEASE, "format: %s (%s)", pFormatCtx->iformat->name, pFormatCtx->iformat->long_name);
389 #ifdef __MMFILE_TEST_MODE__
390 av_dump_format(pFormatCtx, 0, formatContext->filesrc->file.path, 0);
393 return MMFILE_FORMAT_SUCCESS;
395 exception: /* fail to get content information */
396 if (formatContext->filesrc->type == MM_FILE_SRC_TYPE_MEMORY) {
398 av_free(avio_ctx_buffer);
405 avformat_close_input(&pFormatCtx);
407 mmfile_format_close_ffmpg(formatContext);
410 formatContext->privateFormatData = NULL;
412 return MMFILE_FORMAT_FAIL;
415 static int __get_video_fps(int frame_cnt, int duration, AVRational r_frame_rate, int is_roundup)
419 debug_msg(RELEASE, "frame count: %d, dur: %d, num: %d, den: %d", frame_cnt, duration, r_frame_rate.num, r_frame_rate.den);
421 if (duration <= 0 || r_frame_rate.num <= 0 || r_frame_rate.den <= 0)
424 round = (is_roundup != 0 ? 0.50f : 0.00f);
426 fps = (double)frame_cnt / ((double)(duration * r_frame_rate.num) / r_frame_rate.den) + round;
431 static bool __check_uhqa(int sample_rate, enum AVSampleFormat sample_fmt_info)
433 debug_error(RELEASE, "[sample rate %d, sample format %d]", sample_rate, sample_fmt_info);
435 if (sample_rate >= 44100 && sample_fmt_info >= AV_SAMPLE_FMT_S32) {
436 debug_msg(RELEASE, "UHQA CONTENT");
443 int mmfile_format_read_stream_ffmpg(MMFileFormatContext *formatContext)
445 AVFormatContext *pFormatCtx = NULL;
446 AVCodecParameters *pAudioCodecCtx = NULL;
447 AVCodecParameters *pVideoCodecCtx = NULL;
448 MMFileFormatStream *videoStream = NULL;
449 MMFileFormatStream *audioStream = NULL;
452 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
453 mm_file_retvm_if_fails(DEBUG, formatContext->privateFormatData, MMFILE_FORMAT_FAIL);
455 pFormatCtx = formatContext->privateFormatData;
456 pFormatCtx->start_time = -1;
459 * If you could not find codec parameters for stream info,
460 * consider increasing the value for the 'analyzeduration' and 'probesize' options.
463 *@important if data is corrupted, occur segment fault by av_find_stream_info().
464 * - fixed 2009-06-25.
468 * if the content is 8k, the mem-usage in avformat_find_stream_info() is too large, 300MB or more.
469 * so we adjust 'probesize' to reduce memory usage in avformat_find_stream_info().
470 * Please refer to below for detail.
471 * https://ffmpeg.org/ffmpeg-formats.html#Format-Options
473 if (g_max_analyze_duration == 0)
474 g_max_analyze_duration = mmfile_get_int_from_ini(MMFILE_INI_MAXANLDURATION, MMFILE_DEFAULT_MAXANLDURATION);
475 if (g_probesize == 0)
476 g_probesize = mmfile_get_int_from_ini(MMFILE_INI_PROBESIZE, MMFILE_DEFAULT_PROBESIZE);
478 if (formatContext->formatType == MM_FILE_FORMAT_M2TS)
479 pFormatCtx->max_analyze_duration = g_max_analyze_duration; // MPEGTS file timeout set
481 pFormatCtx->probesize = g_probesize; // the size of the data(packet) to probe stream information
483 debug_msg(RELEASE, "max_analyze_duration: %"PRId64", probesize: %"PRId64"", pFormatCtx->max_analyze_duration, pFormatCtx->probesize);
485 if (formatContext->cdis != 1) {
486 if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
487 debug_warning(DEBUG, "failed to find stream info");
492 debug_msg(RELEASE, "FFMPEG: dur %"PRId64", start %"PRId64"", pFormatCtx->duration, pFormatCtx->start_time);
495 *@note asf has long duration bug. and Some content's start time is wrong(negative number).
496 * Generally, mpegts has wrong start time(positive large value). So skip start time for mpegts format.
498 if (pFormatCtx->start_time < 0 || formatContext->formatType == MM_FILE_FORMAT_M2TS) {
499 debug_warning(DEBUG, "Wrong Start time = %"PRId64"", pFormatCtx->start_time);
500 formatContext->duration = (long long)(pFormatCtx->duration) * 1000 / AV_TIME_BASE;
502 formatContext->duration = (long long)(pFormatCtx->duration + pFormatCtx->start_time) * 1000 / AV_TIME_BASE;
505 formatContext->videoStreamId = -1;
506 formatContext->audioStreamId = -1;
507 formatContext->nbStreams = 0;
508 formatContext->videoTotalTrackNum = 0;
509 formatContext->audioTotalTrackNum = 0;
511 for (i = 0; i < pFormatCtx->nb_streams; i++) {
512 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && formatContext->videoStreamId == -1) {
513 videoStream = g_new0(MMFileFormatStream, 1);
515 videoStream->streamType = MMFILE_VIDEO_STREAM;
516 formatContext->streams[MMFILE_VIDEO_STREAM] = videoStream;
517 formatContext->nbStreams += 1;
518 formatContext->videoStreamId = i;
519 formatContext->videoTotalTrackNum += 1;
521 pVideoCodecCtx = pFormatCtx->streams[i]->codecpar;
522 if (pVideoCodecCtx) {
523 videoStream->codecId = __convert_vidio_codec_type(pVideoCodecCtx->codec_id);
524 if (videoStream->codecId == MM_VIDEO_CODEC_NONE) {
525 debug_error(RELEASE, "Proper codec is not found in [%d] stream", i);
526 formatContext->videoStreamId = -1;
527 mmfile_free(videoStream);
528 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
535 * 1. try to get average fps of video stream.
536 * 2. if (1) failed, try to get fps of media container.
538 videoStream->framePerSec = __get_video_fps(pFormatCtx->streams[i]->nb_frames,
539 pFormatCtx->streams[i]->duration,
540 pFormatCtx->streams[i]->time_base,
543 if (videoStream->framePerSec == 0) {
544 if ((int)av_q2d(pFormatCtx->streams[i]->avg_frame_rate) != 0)
545 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->avg_frame_rate);
547 videoStream->framePerSec = av_q2d(pFormatCtx->streams[i]->r_frame_rate);
550 videoStream->width = pVideoCodecCtx->width;
551 videoStream->height = pVideoCodecCtx->height;
552 videoStream->bitRate = pVideoCodecCtx->bit_rate;
554 } else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && formatContext->audioStreamId == -1) {
555 audioStream = g_new0(MMFileFormatStream, 1);
557 audioStream->streamType = MMFILE_AUDIO_STREAM;
558 formatContext->streams[MMFILE_AUDIO_STREAM] = audioStream;
559 formatContext->nbStreams += 1;
560 formatContext->audioStreamId = i;
561 formatContext->audioTotalTrackNum += 1;
563 pAudioCodecCtx = pFormatCtx->streams[i]->codecpar;
564 audioStream->codecId = __convert_audio_codec_type(pAudioCodecCtx->codec_id);
565 audioStream->bitRate = pAudioCodecCtx->bit_rate;
566 audioStream->nbChannel = pAudioCodecCtx->ch_layout.nb_channels;
567 audioStream->samplePerSec = pAudioCodecCtx->sample_rate;
568 audioStream->bitPerSample = pAudioCodecCtx->bits_per_coded_sample;
569 audioStream->is_uhqa = __check_uhqa(audioStream->samplePerSec, pFormatCtx->streams[i]->codecpar->format);
573 if (formatContext->nbStreams == 0) {
574 debug_error(DEBUG, "error: there is no audio and video track");
578 #ifdef __MMFILE_TEST_MODE__
579 mmfile_format_print_contents(formatContext);
582 return MMFILE_FORMAT_SUCCESS;
585 mmfile_free(videoStream);
586 mmfile_free(audioStream);
588 formatContext->streams[MMFILE_VIDEO_STREAM] = NULL;
589 formatContext->streams[MMFILE_AUDIO_STREAM] = NULL;
592 avformat_close_input(&pFormatCtx);
593 formatContext->privateFormatData = NULL;
596 formatContext->audioTotalTrackNum = 0;
597 formatContext->videoTotalTrackNum = 0;
598 formatContext->nbStreams = 0;
600 return MMFILE_FORMAT_FAIL;
603 #define DATA_LENGTH 4
605 static void __fill_picture_in_context(char *value, MMFileFormatContext *formatContext)
608 guchar *meta_data = NULL;
609 int current_pos = DATA_LENGTH;
610 unsigned char current_data[DATA_LENGTH] = {0, };
612 meta_data = g_base64_decode(value, &len);
614 debug_msg(RELEASE, "no picture");
619 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
620 len = (unsigned int)MMFILE_CONVERT_INT(current_data);
622 current_pos += DATA_LENGTH;
623 mmfile_free(formatContext->artworkMime);
624 formatContext->artworkMime = g_strndup((const char *)meta_data + current_pos, len);
626 /* get description */
628 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
629 len = (unsigned int)MMFILE_CONVERT_INT(current_data);
631 /* get picture data */
632 current_pos += len + (DATA_LENGTH * 5);
633 memcpy(current_data, meta_data + current_pos, DATA_LENGTH);
634 len = (unsigned int)MMFILE_CONVERT_INT(current_data);
636 formatContext->artworkSize = len;
638 current_pos += DATA_LENGTH;
639 mmfile_free(formatContext->artwork);
640 formatContext->artwork = g_memdup2(meta_data + current_pos, formatContext->artworkSize);
644 static void __fill_artwork_in_context(AVStream *st, MMFileFormatContext *formatContext)
646 AVPacket pkt = st->attached_pic;
647 int codec_id = st->codecpar->codec_id;
649 if (!pkt.data || pkt.size <= 0)
653 mmfile_free(formatContext->artworkMime);
655 if (codec_id == AV_CODEC_ID_MJPEG)
656 formatContext->artworkMime = g_strdup("image/jpeg");
657 else if (codec_id == AV_CODEC_ID_PNG)
658 formatContext->artworkMime = g_strdup("image/png");
659 else if (codec_id == AV_CODEC_ID_BMP)
660 formatContext->artworkMime = g_strdup("image/bmp");
662 debug_error(DEBUG, "Unknown cover type: 0x%x", codec_id);
665 mmfile_free(formatContext->artwork);
667 formatContext->artworkSize = pkt.size;
668 formatContext->artwork = g_memdup2(pkt.data, pkt.size);
671 static void __fill_rotate_in_context(AVStream *st, MMFileFormatContext *formatContext)
677 for (i = 0; i < st->codecpar->nb_coded_side_data; i++) {
678 const AVPacketSideData *sd = &st->codecpar->coded_side_data[i];
679 if (sd->type == AV_PKT_DATA_DISPLAYMATRIX) {
681 rotate = av_display_rotation_get((const int32_t *)sd->data);
690 if (rotate < 0) // for backward compatibility
692 debug_msg(RELEASE, "Rotate: %f", rotate);
693 mmfile_free(formatContext->rotate);
694 formatContext->rotate = g_strdup_printf("%g", rotate);
697 static void __fill_metainfo_in_context(AVDictionary *metainfo, MMFileFormatContext *formatContext)
699 AVDictionaryEntry *tag = NULL;
701 while ((tag = av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) {
705 if (!g_ascii_strcasecmp(tag->key, "title")) {
706 mmfile_free(formatContext->title);
707 formatContext->title = g_strdup(tag->value);
708 } else if (!g_ascii_strcasecmp(tag->key, "artist")) {
709 mmfile_free(formatContext->artist);
710 formatContext->artist = g_strdup(tag->value);
711 } else if (!g_ascii_strcasecmp(tag->key, "composer")) {
712 mmfile_free(formatContext->composer);
713 formatContext->composer = g_strdup(tag->value);
714 } else if (!g_ascii_strcasecmp(tag->key, "album")) {
715 mmfile_free(formatContext->album);
716 formatContext->album = g_strdup(tag->value);
717 } else if (!g_ascii_strcasecmp(tag->key, "album_artist")) {
718 mmfile_free(formatContext->album_artist);
719 formatContext->album_artist = g_strdup(tag->value);
720 } else if (!g_ascii_strcasecmp(tag->key, "copyright")) {
721 mmfile_free(formatContext->copyright);
722 formatContext->copyright = g_strdup(tag->value);
723 } else if (!g_ascii_strcasecmp(tag->key, "comment")) {
724 mmfile_free(formatContext->comment);
725 formatContext->comment = g_strdup(tag->value);
726 } else if (!g_ascii_strcasecmp(tag->key, "description")) {
727 mmfile_free(formatContext->description);
728 formatContext->description = g_strdup(tag->value);
729 } else if (!g_ascii_strcasecmp(tag->key, "genre")) {
730 mmfile_free(formatContext->genre);
731 formatContext->genre = g_strdup(tag->value);
732 } else if (!g_ascii_strcasecmp(tag->key, "date")) {
733 mmfile_free(formatContext->year);
734 formatContext->year = g_strdup(tag->value);
735 } else if (!g_ascii_strcasecmp(tag->key, "creation_time")) {
736 mmfile_free(formatContext->recDate);
737 formatContext->recDate = g_strdup(tag->value);
738 } else if ((!g_ascii_strcasecmp(tag->key, "track")) || (!g_ascii_strcasecmp(tag->key, "tracknumber"))) {
739 mmfile_free(formatContext->tagTrackNum);
740 formatContext->tagTrackNum = g_strdup(tag->value);
741 } else if (!g_ascii_strcasecmp(tag->key, "lyrics")) {
742 mmfile_free(formatContext->unsyncLyrics);
743 formatContext->unsyncLyrics = g_strdup(tag->value);
744 } else if (!g_ascii_strcasecmp(tag->key, "spherical-video")) {
745 ParseSpatialVideoMetadataFromXMLString(tag->value, formatContext);
746 } else if (!g_ascii_strcasecmp(tag->key, "metadata_block_picture")) {
747 __fill_picture_in_context(tag->value, formatContext);
749 debug_msg(RELEASE, "Not support metadata. [%s:%s]", tag->key, tag->value);
755 int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext)
757 AVFormatContext *pFormatCtx = NULL;
758 unsigned int idx = 0;
760 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
761 mm_file_retvm_if_fails(DEBUG, formatContext->privateFormatData, MMFILE_FORMAT_FAIL);
763 if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4)
764 MMFileUtilGetMetaDataFromMP4(formatContext);
766 if (formatContext->formatType == MM_FILE_FORMAT_MATROSKA)
767 MMFileUtilGetMetaDataFromMKV(formatContext);
769 pFormatCtx = formatContext->privateFormatData;
771 /*metadata extracted by ffmpeg*/
772 for (idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) {
773 AVDictionary *metainfo = NULL;
776 /* Check metadata of normal stream like audio, video, video cover art
777 * (cover art saved in new stream). refer to mov_read_covr() in ffmpeg.
779 if (idx < pFormatCtx->nb_streams) {
780 st = pFormatCtx->streams[idx];
782 metainfo = st->metadata;
783 } else { /*Check metadata of Content */
784 if (pFormatCtx->metadata != NULL) {
785 metainfo = pFormatCtx->metadata;
791 /*refer to mov_read_covr() in ffmpeg.*/
793 __fill_artwork_in_context(st, formatContext);
794 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
795 __fill_rotate_in_context(st, formatContext);
799 __fill_metainfo_in_context(metainfo, formatContext);
801 #ifdef __MMFILE_TEST_MODE__
802 mmfile_format_print_tags(formatContext);
806 return MMFILE_FORMAT_SUCCESS;
809 int mmfile_format_read_frame_ffmpg(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
811 AVFormatContext *pFormatCtx = NULL;
812 AVCodecContext *pVideoCodecCtx = NULL;
813 const AVCodec *pVideoCodec = NULL;
814 AVCodecParameters *pVideoCodecPar = NULL;
815 AVFrame *pFrame = NULL;
816 struct SwsContext *img_convert_ctx = NULL;
823 mm_file_retvm_if_fails(DEBUG, formatContext, MMFILE_FORMAT_FAIL);
824 mm_file_retvm_if_fails(DEBUG, formatContext->privateFormatData, MMFILE_FORMAT_FAIL);
825 mm_file_retvm_if_fails(DEBUG, formatContext->videoTotalTrackNum > 0, MMFILE_FORMAT_FAIL);
826 mm_file_retvm_if_fails(DEBUG, frame, MMFILE_FORMAT_FAIL);
828 pFormatCtx = formatContext->privateFormatData;
830 mm_file_retvm_if_fails(DEBUG, formatContext->videoStreamId != -1, MMFILE_FORMAT_FAIL);
832 pVideoCodecPar = pFormatCtx->streams[formatContext->videoStreamId]->codecpar;
833 mm_file_retvm_if_fails(DEBUG, pVideoCodecPar, MMFILE_FORMAT_FAIL);
835 pVideoCodec = avcodec_find_decoder(pVideoCodecPar->codec_id);
836 mm_file_retvm_if_fails(DEBUG, pVideoCodec, MMFILE_FORMAT_FAIL);
838 pVideoCodecCtx = avcodec_alloc_context3(pVideoCodec);
839 mm_file_retvm_if_fails(DEBUG, pVideoCodecCtx, MMFILE_FORMAT_FAIL);
841 if (avcodec_parameters_to_context(pVideoCodecCtx, pVideoCodecPar) < 0) {
842 debug_error(DEBUG, "error: avcodec_parameters_to_context");
843 avcodec_free_context(&pVideoCodecCtx);
844 return MMFILE_FORMAT_FAIL;
847 debug_msg(RELEASE, "flag: 0x%08X", pVideoCodec->capabilities);
849 debug_msg(RELEASE, " AV_CODEC_CAP_DRAW_HORIZ_BAND : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND));
850 debug_msg(RELEASE, " AV_CODEC_CAP_DR1 : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_DR1));
851 debug_msg(RELEASE, " AV_CODEC_CAP_DELAY : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_DELAY));
852 debug_msg(RELEASE, " AV_CODEC_CAP_SMALL_LAST_FRAME : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME));
853 debug_msg(RELEASE, " AV_CODEC_CAP_EXPERIMENTAL : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_EXPERIMENTAL));
854 debug_msg(RELEASE, " AV_CODEC_CAP_CHANNEL_CONF : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_CHANNEL_CONF));
855 debug_msg(RELEASE, " AV_CODEC_CAP_FRAME_THREADS : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_FRAME_THREADS));
856 debug_msg(RELEASE, " AV_CODEC_CAP_SLICE_THREADS : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_SLICE_THREADS));
857 debug_msg(RELEASE, " AV_CODEC_CAP_PARAM_CHANGE : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_PARAM_CHANGE));
858 debug_msg(RELEASE, " AV_CODEC_CAP_OTHER_THREADS : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_OTHER_THREADS));
859 debug_msg(RELEASE, " AV_CODEC_CAP_VARIABLE_FRAME_SIZE : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE));
860 debug_msg(RELEASE, " AV_CODEC_CAP_AVOID_PROBING : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_AVOID_PROBING));
861 debug_msg(RELEASE, " AV_CODEC_CAP_HARDWARE : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_HARDWARE));
862 debug_msg(RELEASE, " AV_CODEC_CAP_HYBRID : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_HYBRID));
863 debug_msg(RELEASE, " AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE));
864 debug_msg(RELEASE, " AV_CODEC_CAP_ENCODER_FLUSH : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_ENCODER_FLUSH));
865 debug_msg(RELEASE, " AV_CODEC_CAP_ENCODER_RECON_FRAME : %d", (bool)(pVideoCodec->capabilities & AV_CODEC_CAP_ENCODER_RECON_FRAME));
867 /*set workaround bug flag*/
868 pVideoCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
870 /* this is solution for PLM issue P13091703323 */
871 /* If using thread when decoding frame, the result of decoding is not always same.
872 Thumbnail of video content is different with original file when copying file. */
873 pVideoCodecCtx->thread_type = 0;
874 pVideoCodecCtx->thread_count = 0;
875 if (avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL) < 0) {
876 debug_error(DEBUG, "error: avcodec_open fail.");
877 return MMFILE_FORMAT_FAIL;
880 /* search & decode */
881 ret = _get_first_good_video_frame(pFormatCtx, pVideoCodecCtx, &pFrame, formatContext->cdis, formatContext->videoStreamId);
882 if (ret != MMFILE_FORMAT_SUCCESS) {
883 debug_error(DEBUG, "error: get key frame");
887 debug_msg(RELEASE, "Video default resolution = [%dx%d]", pVideoCodecCtx->coded_width, pVideoCodecCtx->coded_height);
888 debug_msg(RELEASE, "Video coded resolution = [%dx%d]", pVideoCodecCtx->width, pVideoCodecCtx->height);
890 if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
891 width = pVideoCodecCtx->coded_width;
892 height = pVideoCodecCtx->coded_height;
894 width = pVideoCodecCtx->width;
895 height = pVideoCodecCtx->height;
898 numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, width, height, 1);
900 debug_error(DEBUG, "error: av_image_get_buffer_size. [%d x %d]", width, height);
904 frame->frameData = av_malloc(numBytes);
905 if (!frame->frameData) {
906 debug_error(DEBUG, "error: av_malloc.");
910 uint8_t *dst_data[4];
913 ret = av_image_fill_arrays(dst_data, dst_linesize, frame->frameData, AV_PIX_FMT_RGB24, width, height, 1);
915 debug_error(DEBUG, "error: av_image_fill_arrays fail. errcode = 0x%08X", ret);
919 img_convert_ctx = sws_getContext(width, height, pVideoCodecCtx->pix_fmt, width, height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
921 if (NULL == img_convert_ctx) {
922 debug_error(DEBUG, "failed to get img convert ctx");
926 ret = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize, 0, height, dst_data, dst_linesize);
928 debug_error(DEBUG, "failed to convert image");
929 sws_freeContext(img_convert_ctx);
930 img_convert_ctx = NULL;
934 sws_freeContext(img_convert_ctx);
935 img_convert_ctx = NULL;
937 frame->frameSize = numBytes;
938 frame->frameWidth = width;
939 frame->frameHeight = height;
940 frame->configLenth = 0;
941 frame->frameDataFree = av_free;
944 av_frame_free(&pFrame);
946 avcodec_free_context(&pVideoCodecCtx);
948 return MMFILE_FORMAT_SUCCESS;
951 avcodec_free_context(&pVideoCodecCtx);
952 av_freep(&frame->frameData);
953 av_frame_free(&pFrame);
955 return MMFILE_FORMAT_FAIL;
960 int mmfile_format_close_ffmpg(MMFileFormatContext *formatContext)
963 AVFormatContext *pFormatCtx = formatContext->privateFormatData;
966 avformat_close_input(&pFormatCtx);
967 formatContext->privateFormatData = NULL;
971 return MMFILE_FORMAT_SUCCESS;
975 * return average of difference
977 static unsigned int _diff_memory(const void *s1, const void *s2, unsigned int n)
979 char *s = (char *)s1;
980 char *d = (char *)s2;
982 unsigned int ret = 0;
985 for (i = 0, ret = 0; i < n; i++) {
988 ret += (tmp < 0 ? -tmp : tmp);
999 * compare with center line.
1001 static bool __is_good_pgm(unsigned char *buf, int wrap, int xsize, int ysize)
1003 #define _MM_CHUNK_NUM 8 /*FIXME*/
1004 #define _MM_CHUNK_LIMIT (_MM_CHUNK_NUM / 2)
1005 #define _MM_CHUNK_DIFF_LIMIT (_MM_CHUNK_LIMIT * 2 + 1) /*FIXME*/
1010 unsigned char *cnt; /*center line of image*/
1012 unsigned int sum_diff;
1016 step = ysize / _MM_CHUNK_NUM;
1017 cnt_offset = (ysize / 2);
1018 cnt = buf + cnt_offset * wrap;
1020 debug_msg(RELEASE, "checking frame. %p, %d, %d, %d", buf, wrap, xsize, ysize);
1022 /*if too small, always ok return.*/
1023 if (ysize < _MM_CHUNK_NUM)
1026 for (point = 0, sum_diff = 0, i = step; i < ysize; i += step) {
1027 if (i == cnt_offset)
1031 is_different = _diff_memory(cnt, buf + i * wrap, xsize);
1032 point += (is_different == 0 ? 0 : 1);
1033 sum_diff += is_different;
1035 debug_msg(RELEASE, "check %04d line. %s [%d]", i, (is_different == 0 ? "same" : "different"), is_different);
1037 if (point < _MM_CHUNK_LIMIT)
1040 if (sum_diff <= _MM_CHUNK_DIFF_LIMIT) {
1041 debug_msg(RELEASE, "Bad :-(");
1045 debug_msg(RELEASE, "Good :-)");
1052 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1053 static void _save_pgm(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
1058 f = fopen(filename, "w");
1060 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
1061 for (i = 0; i < ysize; i++)
1062 fwrite(buf + i * wrap, 1, xsize, f);
1068 static int _get_first_good_video_frame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, AVFrame **pFrame, int cdis, int videoStreamId)
1070 #define _RETRY_SEARCH_LIMIT 250
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 AVPacket *pkt = NULL;
1080 AVFrame *frame = NULL;
1081 AVFrame *tmp_frame = NULL;
1082 AVFrame *first_frame = NULL;
1089 bool key_detected = false;
1090 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1091 char pgm_name[256] = {0, };
1093 int key_search_limit = (cdis == 1) ? _KEY_SEARCH_LIMIT_CDIS : _KEY_SEARCH_LIMIT;
1094 int frame_search_limit = (cdis == 1) ? _FRAME_SEARCH_LIMIT_CDIS : _FRAME_SEARCH_LIMIT;
1096 first_frame = av_frame_alloc();
1097 tmp_frame = av_frame_alloc();
1099 if (!first_frame || !tmp_frame) {
1100 debug_error(DEBUG, "failed to alloc frame.");
1101 av_frame_free(&first_frame);
1102 av_frame_free(&tmp_frame);
1104 return MMFILE_FORMAT_FAIL;
1107 debug_msg(RELEASE, "frame: 1. %p, 2. %p", first_frame, tmp_frame);
1109 pCodecCtx->skip_frame = AVDISCARD_BIDIR;
1110 frame = first_frame;
1112 while (i < key_search_limit && v < frame_search_limit) {
1113 pkt = av_packet_alloc();
1115 debug_error(DEBUG, "packet allocation failed.");
1119 if (av_read_frame(pFormatCtx, pkt) < 0) {
1120 debug_error(DEBUG, "read failed. (maybe EOF or broken)");
1124 if (pkt->stream_index != videoStreamId)
1128 if (!(pkt->flags & AV_PKT_FLAG_KEY) && !key_detected)
1131 #ifdef __MMFILE_TEST_MODE__
1132 _dump_av_packet(pkt);
1135 key_detected = false;
1136 debug_msg(RELEASE, "video frame: %d, %d, %d", retry, i, v);
1138 ret = avcodec_send_packet(pCodecCtx, pkt);
1139 if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
1140 debug_error(RELEASE, "Error while avcodec_send_packet[%2d]", ret);
1144 ret = avcodec_receive_frame(pCodecCtx, frame);
1146 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1147 debug_msg(RELEASE, "decode not completed.");
1148 key_detected = true;
1151 debug_warning(DEBUG, "Error while decoding frame %dth", i);
1155 if (!(frame->flags & AV_FRAME_FLAG_KEY)) {
1156 debug_msg(RELEASE, "skip (not key frame).");
1157 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1158 memset(pgm_name, 0x00, sizeof(pgm_name));
1159 snprintf(pgm_name, sizeof(pgm_name), "./not_key_%d_%d_%d.pgm", retry, i, v);
1160 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1165 debug_msg(RELEASE, "key frame!");
1166 #ifdef MMFILE_FORMAT_DEBUG_DUMP
1167 memset(pgm_name, 0x00, sizeof(pgm_name));
1168 snprintf(pgm_name, sizeof(pgm_name), "./key_%d_%d_%d.pgm", retry, i, v);
1169 _save_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height, pgm_name);
1173 if (__is_good_pgm(frame->data[0], frame->linesize[0], pCodecCtx->width, pCodecCtx->height)) {
1174 debug_msg(RELEASE, "is good frame.");
1178 debug_warning(RELEASE, "not good fame. retry scanning.");
1183 /*set buffer frame*/
1186 if (retry > _RETRY_SEARCH_LIMIT)
1189 av_packet_free(&pkt);
1192 /*free pkt after loop breaking*/
1193 av_packet_free(&pkt);
1195 debug_msg(RELEASE, "found: %d, retry: %d", found, retry);
1197 /*set decode frame to output*/
1199 if (retry == 0 || found == retry) {
1200 *pFrame = first_frame;
1201 av_frame_free(&tmp_frame);
1203 *pFrame = tmp_frame;
1204 av_frame_free(&first_frame);
1207 av_frame_free(&first_frame);
1208 av_frame_free(&tmp_frame);
1211 debug_msg(RELEASE, "out frame: %p", *pFrame);
1213 pCodecCtx->skip_frame = AVDISCARD_NONE;
1215 return (found > 0) ? MMFILE_FORMAT_SUCCESS : MMFILE_FORMAT_FAIL;