[FFmpeg-devel] [PATCH] libavformat/aac: Parse ID3 tags between ADTS frames.
wm4
nfxjfg at googlemail.com
Mon Feb 12 23:17:13 EET 2018
On Thu, 1 Feb 2018 18:37:45 -0800
rshaffer at tunein.com wrote:
> From: Richard Shaffer <rshaffer at tunein.com>
>
> While rare, ID3 tags may be inserted between ADTS frames. This change enables
> parsing them and setting the appropriate metadata updated event flag.
> ---
> I have encountered a streaming provider that I must support which does this.
> There are indications that it isn't totally off the wall, and that it does
> happen in the wild:
> * https://www.w3.org/TR/mse-byte-stream-format-mpeg-audio/
> (See specifically sections 3 and 4.)
> * https://github.com/video-dev/hls.js/issues/508
>
> That being said, the providers that do this are in the minority. It seems most
> streaming providers will do one of the following:
> 1. If using .aac segments inside of HLS, use the #EXTINF for text metadata and
> use an ID3 tag at the head of the segment for things like timing metadata.
> 2. If streaming raw AAC over HTTP, use Icy metadata.
>
> Aside from comments on the code, I'd be interested in any opinion about whether
> this is something that should or should not be supported in libavformat.
>
> Thanks,
>
> -Richard
>
> libavformat/aacdec.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 43 insertions(+), 2 deletions(-)
>
> diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c
> index 36d558ff54..5ec706bdc7 100644
> --- a/libavformat/aacdec.c
> +++ b/libavformat/aacdec.c
> @@ -22,8 +22,10 @@
>
> #include "libavutil/intreadwrite.h"
> #include "avformat.h"
> +#include "avio_internal.h"
> #include "internal.h"
> #include "id3v1.h"
> +#include "id3v2.h"
> #include "apetag.h"
>
> #define ADTS_HEADER_SIZE 7
> @@ -116,13 +118,52 @@ static int adts_aac_read_header(AVFormatContext *s)
> return 0;
> }
>
> +static int handle_id3(AVFormatContext *s, AVPacket *pkt)
> +{
> + AVDictionary *metadata = NULL;
> + AVIOContext ioctx;
> + ID3v2ExtraMeta *id3v2_extra_meta = NULL;
> + int ret;
> +
> + ret = av_append_packet(s->pb, pkt, ff_id3v2_tag_len(pkt->data) - pkt->size);
> + if (ret < 0) {
> + av_packet_unref(pkt);
> + return ret;
> + }
> +
> + ffio_init_context(&ioctx, pkt->data, pkt->size, 0, NULL, NULL, NULL, NULL);
> + ff_id3v2_read_dict(&ioctx, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
> + if ((ret = ff_id3v2_parse_priv_dict(&metadata, &id3v2_extra_meta)) < 0)
> + goto error;
> +
> + if (metadata) {
> + if ((ret = av_dict_copy(&s->metadata, metadata, 0)) < 0)
> + goto error;
> + s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
> + }
> +
> +error:
> + av_packet_unref(pkt);
> + ff_id3v2_free_extra_meta(&id3v2_extra_meta);
> + av_dict_free(&metadata);
> +
> + return ret;
> +}
> +
> static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt)
> {
> int ret, fsize;
>
> - ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE);
> + ret = av_get_packet(s->pb, pkt, FFMAX(ID3v2_HEADER_SIZE, ADTS_HEADER_SIZE));
> +
> + if (ret >= ID3v2_HEADER_SIZE && ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) {
> + if ((ret = handle_id3(s, pkt)) >= 0)
> + ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE);
> + }
> +
> if (ret < 0)
> return ret;
> +
> if (ret < ADTS_HEADER_SIZE) {
> av_packet_unref(pkt);
> return AVERROR(EIO);
> @@ -139,7 +180,7 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt)
> return AVERROR_INVALIDDATA;
> }
>
> - ret = av_append_packet(s->pb, pkt, fsize - ADTS_HEADER_SIZE);
> + ret = av_append_packet(s->pb, pkt, fsize - pkt->size);
> if (ret < 0)
> av_packet_unref(pkt);
>
Applied. (I hope this is the most recent version...)
More information about the ffmpeg-devel
mailing list