X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fasf.c;h=1ac8b5f078905f4421bf78f7ee3cb594a759c1fe;hb=8b3e6ce5f4ab1ebf3a54ff7e0ff440a1a5f842f7;hp=719cae9da53ca7810c8dfe5c10b8d0f4f8049e4b;hpb=5ca7eb36b7353f9e6af05a5a952eead5f6d326dd;p=ffmpeg diff --git a/libavformat/asf.c b/libavformat/asf.c index 719cae9da53..1ac8b5f0789 100644 --- a/libavformat/asf.c +++ b/libavformat/asf.c @@ -19,6 +19,8 @@ */ #include "asf.h" +#include "id3v2.h" +#include "internal.h" const ff_asf_guid ff_asf_header = { 0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C @@ -40,12 +42,6 @@ const ff_asf_guid ff_asf_audio_stream = { 0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B }; -const ff_asf_guid ff_asf_audio_conceal_none = { - // 0x40, 0xa4, 0xf1, 0x49, 0x4ece, 0x11d0, 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 - // New value lifted from avifile - 0x00, 0x57, 0xfb, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b -}; - const ff_asf_guid ff_asf_audio_conceal_spread = { 0x50, 0xCD, 0xC3, 0xBF, 0x8F, 0x61, 0xCF, 0x11, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 }; @@ -176,3 +172,107 @@ const AVMetadataConv ff_asf_metadata_conv[] = { // { "Year" , "date" }, TODO: conversion year<->date { 0 } }; + +/* MSDN claims that this should be "compatible with the ID3 frame, APIC", + * but in reality this is only loosely similar */ +static int asf_read_picture(AVFormatContext *s, int len) +{ + const CodecMime *mime = ff_id3v2_mime_tags; + enum AVCodecID id = AV_CODEC_ID_NONE; + char mimetype[64]; + uint8_t *desc = NULL; + AVStream *st = NULL; + int ret, type, picsize, desc_len; + + /* type + picsize + mime + desc */ + if (len < 1 + 4 + 2 + 2) { + av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len); + return AVERROR_INVALIDDATA; + } + + /* picture type */ + type = avio_r8(s->pb); + len--; + if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) { + av_log(s, AV_LOG_WARNING, "Unknown attached picture type: %d.\n", type); + type = 0; + } + + /* picture data size */ + picsize = avio_rl32(s->pb); + len -= 4; + + /* picture MIME type */ + len -= avio_get_str16le(s->pb, len, mimetype, sizeof(mimetype)); + while (mime->id != AV_CODEC_ID_NONE) { + if (!strncmp(mime->str, mimetype, sizeof(mimetype))) { + id = mime->id; + break; + } + mime++; + } + if (id == AV_CODEC_ID_NONE) { + av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n", + mimetype); + return 0; + } + + if (picsize >= len) { + av_log(s, AV_LOG_ERROR, "Invalid attached picture data size: %d >= %d.\n", + picsize, len); + return AVERROR_INVALIDDATA; + } + + /* picture description */ + desc_len = (len - picsize) * 2 + 1; + desc = av_malloc(desc_len); + if (!desc) + return AVERROR(ENOMEM); + len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len); + + ret = ff_add_attached_pic(s, NULL, s->pb, NULL, picsize); + if (ret < 0) + goto fail; + st = s->streams[s->nb_streams - 1]; + + st->codecpar->codec_id = id; + + if (*desc) { + if (av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + } else + av_freep(&desc); + + if (av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0) < 0) + av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); + + return 0; + +fail: + av_freep(&desc); + return ret; +} + +static int get_id3_tag(AVFormatContext *s, int len) +{ + ID3v2ExtraMeta *id3v2_extra_meta; + + ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len); + if (id3v2_extra_meta) { + ff_id3v2_parse_apic(s, id3v2_extra_meta); + ff_id3v2_parse_chapters(s, id3v2_extra_meta); + ff_id3v2_free_extra_meta(&id3v2_extra_meta); + } + return 0; +} + +int ff_asf_handle_byte_array(AVFormatContext *s, const char *name, + int val_len) +{ + if (!strcmp(name, "WM/Picture")) // handle cover art + return asf_read_picture(s, val_len); + else if (!strcmp(name, "ID3")) // handle ID3 tag + return get_id3_tag(s, val_len); + + return 1; +}