From: jiyong.min Date: Tue, 27 Aug 2019 02:08:10 +0000 (+0900) Subject: Improve 'mmfile_format_read_tag_ffmpg' function X-Git-Tag: accepted/tizen/unified/20190904.224430~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F09%2F212809%2F4;p=platform%2Fcore%2Fmultimedia%2Flibmm-fileinfo.git Improve 'mmfile_format_read_tag_ffmpg' function Change-Id: I2edf99b08d29631d0363e1ce3493004ad99bfa21 --- diff --git a/formats/ffmpeg/mm_file_format_ffmpeg.c b/formats/ffmpeg/mm_file_format_ffmpeg.c index 9ad513c..e7c5bf7 100755 --- a/formats/ffmpeg/mm_file_format_ffmpeg.c +++ b/formats/ffmpeg/mm_file_format_ffmpeg.c @@ -546,6 +546,150 @@ exception: #define POS_OF_MIME_LEN DATA_LENGTH #define CONVERT_TO_INT(dest, src) {dest = 0; dest |= (0 | src[0] << 24) | (0 | src[1] << 16) | (0 | src[2] << 8) | (0 | src[3]); } +static void __fill_picture_in_context(char *value, MMFileFormatContext *formatContext) +{ + gsize len = 0; + guchar *meta_data = NULL; + + meta_data = g_base64_decode(value, &len); + if (!meta_data) { + debug_log(RELEASE, "no picture"); + return; + } + + /* in METADATA_BLOCK_PICTURE, + the length of mime type and the length of description are flexible, + so, we have to get the length of their for getting correct postion of picture data. */ + int mime_len = 0; + int description_len = 0; + int data_len = 0; + int current_pos = 0; + unsigned char current_data[DATA_LENGTH] = {0}; + + /* get length of mime_type */ + memcpy(current_data, meta_data + POS_OF_MIME_LEN, DATA_LENGTH); + CONVERT_TO_INT(mime_len, current_data); + + /* get length of description */ + current_pos = mime_len + (DATA_LENGTH * 2); /*current position is length of description */ + memcpy(current_data, meta_data + current_pos, DATA_LENGTH); + CONVERT_TO_INT(description_len, current_data); + + /* get length of picture data */ + current_pos = mime_len + description_len + (DATA_LENGTH * 7); /*current position is length of picture data */ + memcpy(current_data, meta_data + current_pos, DATA_LENGTH); + CONVERT_TO_INT(data_len, current_data); + + /* set the size of art work */ + formatContext->artworkSize = data_len; + + /* set mime type */ + current_pos = POS_OF_MIME_LEN + DATA_LENGTH; /*current position is mime type */ + mmfile_free(formatContext->artworkMime); + formatContext->artworkMime = strndup((const char *)meta_data + current_pos, mime_len); + + /* set art work data */ + current_pos = mime_len + description_len + (DATA_LENGTH * 8); /*current position is picture data */ + mmfile_free(formatContext->artwork); + + formatContext->artwork = mmfile_malloc(data_len); + if (formatContext->artwork) + memcpy(formatContext->artwork, meta_data + current_pos, data_len); + + g_free(meta_data); +} + +static void __fill_artwork_in_context(AVStream *st, MMFileFormatContext *formatContext) +{ + AVPacket pkt = st->attached_pic; + int codec_id = st->codecpar->codec_id; + + if (!pkt.data || pkt.size <= 0) { + return; + } + + /*Set mime type*/ + mmfile_free(formatContext->artworkMime); + + if (codec_id == AV_CODEC_ID_MJPEG) + formatContext->artworkMime = mmfile_strdup("image/jpeg"); + else if (codec_id == AV_CODEC_ID_PNG) + formatContext->artworkMime = mmfile_strdup("image/png"); + else if (codec_id == AV_CODEC_ID_BMP) + formatContext->artworkMime = mmfile_strdup("image/bmp"); + else + debug_error(DEBUG, "Unknown cover type: 0x%x\n", codec_id); + + /*Copy artwork*/ + mmfile_free(formatContext->artwork); + + formatContext->artworkSize = pkt.size; + formatContext->artwork = mmfile_malloc(pkt.size); + if (formatContext->artwork) + memcpy(formatContext->artwork, pkt.data, pkt.size); +} + +static void __fill_metainfo_in_context(AVDictionary *metainfo, MMFileFormatContext *formatContext) +{ + AVDictionaryEntry *tag = NULL; + + while ((tag = av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) { + if (!tag->key) { + continue; + } + + if (!g_ascii_strcasecmp(tag->key, "title")) { + MMFILE_SAFE_FREE(formatContext->title); + formatContext->title = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "artist")) { + MMFILE_SAFE_FREE(formatContext->artist); + formatContext->artist = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "composer")) { + MMFILE_SAFE_FREE(formatContext->composer); + formatContext->composer = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "album")) { + MMFILE_SAFE_FREE(formatContext->album); + formatContext->album = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "album_artist")) { + MMFILE_SAFE_FREE(formatContext->album_artist); + formatContext->album_artist = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "copyright")) { + MMFILE_SAFE_FREE(formatContext->copyright); + formatContext->copyright = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "comment")) { + MMFILE_SAFE_FREE(formatContext->comment); + formatContext->comment = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "description")) { + MMFILE_SAFE_FREE(formatContext->description); + formatContext->description = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "genre")) { + MMFILE_SAFE_FREE(formatContext->genre); + formatContext->genre = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "date")) { + MMFILE_SAFE_FREE(formatContext->year); + formatContext->year = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "creation_time")) { + MMFILE_SAFE_FREE(formatContext->recDate); + formatContext->recDate = mmfile_strdup(tag->value); + } else if ((!g_ascii_strcasecmp(tag->key, "track")) || (!g_ascii_strcasecmp(tag->key, "tracknumber"))) { + MMFILE_SAFE_FREE(formatContext->tagTrackNum); + formatContext->tagTrackNum = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "lyrics")) { + MMFILE_SAFE_FREE(formatContext->unsyncLyrics); + formatContext->unsyncLyrics = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "rotate")) { /*can be "90", "180", "270" */ + MMFILE_SAFE_FREE(formatContext->rotate); + formatContext->rotate = mmfile_strdup(tag->value); + } else if (!g_ascii_strcasecmp(tag->key, "spherical-video")) { + ParseSpatialVideoMetadataFromXMLString(tag->value, formatContext); + } else if (!g_ascii_strcasecmp(tag->key, "metadata_block_picture")) { + __fill_picture_in_context(tag->value, formatContext); + } else { + debug_log(RELEASE, "Not support metadata. [%s:%s]", tag->key, tag->value); + } + } +} + EXPORT_API int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext) { @@ -557,6 +701,10 @@ int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext) } pFormatCtx = formatContext->privateFormatData; + if (!pFormatCtx) { + debug_warning(DEBUG, "No format information"); + return MMFILE_FORMAT_SUCCESS; + } if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4) { MMFileUtilGetMetaDataFromMP4(formatContext); @@ -569,156 +717,35 @@ int mmfile_format_read_tag_ffmpg(MMFileFormatContext *formatContext) /*metadata extracted by ffmpeg*/ unsigned int idx = 0; - if (pFormatCtx != NULL) { - for (idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) { - AVDictionary *metainfo = NULL; - AVStream *st = NULL; - - 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. */ - st = pFormatCtx->streams[idx]; - if (st != NULL) - metainfo = st->metadata; - } else { /*Check metadata of Content */ - if (pFormatCtx->metadata != NULL) { - metainfo = pFormatCtx->metadata; - } else { - continue; - } + for (idx = 0; idx < pFormatCtx->nb_streams + 1; idx++) { + AVDictionary *metainfo = NULL; + AVStream *st = NULL; + + /* Check metadata of normal stream like audio, video, video cover art + * (cover art saved in new stream). refer to mov_read_covr() in ffmpeg. + */ + if (idx < pFormatCtx->nb_streams) { + st = pFormatCtx->streams[idx]; + if (st != NULL) + metainfo = st->metadata; + } else { /*Check metadata of Content */ + if (pFormatCtx->metadata != NULL) { + metainfo = pFormatCtx->metadata; + } else { + continue; } + } - /*refer to mov_read_covr() in ffmpeg.*/ - if (st != NULL) { - AVPacket pkt = st->attached_pic; - int codec_id = st->codecpar->codec_id; - - if ((pkt.data != NULL) && (pkt.size > 0)) { - /*Set mime type*/ - mmfile_free(formatContext->artworkMime); - - if (codec_id == AV_CODEC_ID_MJPEG) - formatContext->artworkMime = mmfile_strdup("image/jpeg"); - else if (codec_id == AV_CODEC_ID_PNG) - formatContext->artworkMime = mmfile_strdup("image/png"); - else if (codec_id == AV_CODEC_ID_BMP) - formatContext->artworkMime = mmfile_strdup("image/bmp"); - else - debug_error(DEBUG, "Unknown cover type: 0x%x\n", codec_id); - - /*Copy artwork*/ - mmfile_free(formatContext->artwork); + /*refer to mov_read_covr() in ffmpeg.*/ + if (st) + __fill_artwork_in_context(st, formatContext); - formatContext->artworkSize = pkt.size; - formatContext->artwork = mmfile_malloc(pkt.size); - if (formatContext->artwork != NULL) - memcpy(formatContext->artwork, pkt.data, pkt.size); - } - } + if (metainfo) + __fill_metainfo_in_context(metainfo, formatContext); - if (metainfo != NULL) { - AVDictionaryEntry *tag = NULL; - while ((tag = av_dict_get(metainfo, "", tag, AV_DICT_IGNORE_SUFFIX))) { - if (tag->key != NULL) { - if (!g_ascii_strcasecmp(tag->key, "title")) { - if (formatContext->title) free(formatContext->title); - formatContext->title = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "artist")) { - if (formatContext->artist) free(formatContext->artist); - formatContext->artist = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "composer")) { - if (formatContext->composer) free(formatContext->composer); - formatContext->composer = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "album")) { - if (formatContext->album) free(formatContext->album); - formatContext->album = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "album_artist")) { - if (formatContext->album_artist) free(formatContext->album_artist); - formatContext->album_artist = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "copyright")) { - if (formatContext->copyright) free(formatContext->copyright); - formatContext->copyright = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "comment")) { - if (formatContext->comment) free(formatContext->comment); - formatContext->comment = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "description")) { - if (formatContext->description) free(formatContext->description); - formatContext->description = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "genre")) { - if (formatContext->genre) free(formatContext->genre); - formatContext->genre = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "date")) { - if (formatContext->year) free(formatContext->year); - formatContext->year = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "creation_time")) { - if (formatContext->recDate) free(formatContext->recDate); - formatContext->recDate = mmfile_strdup(tag->value); - } else if ((!g_ascii_strcasecmp(tag->key, "track")) || (!g_ascii_strcasecmp(tag->key, "tracknumber"))) { - if (formatContext->tagTrackNum) free(formatContext->tagTrackNum); - formatContext->tagTrackNum = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "lyrics")) { - if (formatContext->unsyncLyrics) free(formatContext->unsyncLyrics); - formatContext->unsyncLyrics = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "rotate")) { /*can be "90", "180", "270" */ - if (formatContext->rotate) free(formatContext->rotate); - formatContext->rotate = mmfile_strdup(tag->value); - } else if (!g_ascii_strcasecmp(tag->key, "spherical-video")) { - ParseSpatialVideoMetadataFromXMLString(tag->value, formatContext); - } else if (!g_ascii_strcasecmp(tag->key, "metadata_block_picture")) { - gsize len = 0; - guchar *meta_data = NULL; - - meta_data = g_base64_decode(tag->value, &len); - if (meta_data != NULL) { - /* in METADATA_BLOCK_PICTURE, - the length of mime type and the length of description are flexible, - so, we have to get the length of their for getting correct postion of picture data. */ - int mime_len = 0; - int description_len = 0; - int data_len = 0; - int current_pos = 0; - unsigned char current_data[DATA_LENGTH] = {0}; - - /* get length of mime_type */ - memcpy(current_data, meta_data + POS_OF_MIME_LEN, DATA_LENGTH); - CONVERT_TO_INT(mime_len, current_data); - - /* get length of description */ - current_pos = mime_len + (DATA_LENGTH * 2); /*current position is length of description */ - memcpy(current_data, meta_data + current_pos, DATA_LENGTH); - CONVERT_TO_INT(description_len, current_data); - - /* get length of picture data */ - current_pos = mime_len + description_len + (DATA_LENGTH * 7); /*current position is length of picture data */ - memcpy(current_data, meta_data + current_pos, DATA_LENGTH); - CONVERT_TO_INT(data_len, current_data); - - /* set the size of art work */ - formatContext->artworkSize = data_len; - - /* set mime type */ - current_pos = POS_OF_MIME_LEN + DATA_LENGTH; /*current position is mime type */ - mmfile_free(formatContext->artworkMime); - formatContext->artworkMime = strndup((const char *)meta_data + current_pos, mime_len); - - /* set art work data */ - current_pos = mime_len + description_len + (DATA_LENGTH * 8); /*current position is picture data */ - mmfile_free(formatContext->artwork); - - formatContext->artwork = mmfile_malloc(data_len); - if (formatContext->artwork != NULL) - memcpy(formatContext->artwork, meta_data + current_pos, data_len); - - g_free(meta_data); - } - } else { - debug_log(RELEASE, "Not support metadata. [%s:%s]", tag->key, tag->value); - } - } - } - } #ifdef __MMFILE_TEST_MODE__ - mmfile_format_print_tags(formatContext); + mmfile_format_print_tags(formatContext); #endif - } } return MMFILE_FORMAT_SUCCESS; diff --git a/utils/include/mm_file_utils.h b/utils/include/mm_file_utils.h index ec10dab..6d9679e 100755 --- a/utils/include/mm_file_utils.h +++ b/utils/include/mm_file_utils.h @@ -46,6 +46,8 @@ extern "C" { #define MMFILE_IO_SUCCESS MMFILE_UTIL_SUCCESS #define CAST_MM_HANDLE(x) (MMHandleType)(x) +#define MMFILE_SAFE_FREE(src) {if (src) {free(src); src = NULL; } } + #ifndef TRUE #define TRUE (1 == 1) #endif