From 836f3555a8def29001d7c917d1574a7938d2357b Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 7 Jun 2016 00:25:38 +0200 Subject: avformat/au: Read MetaData from AU Sun audio file header recognize title= album= artist= genre= track= Signed-off-by: Michael Niedermayer --- libavformat/au.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) (limited to 'libavformat/au.c') diff --git a/libavformat/au.c b/libavformat/au.c index 4a0400b01e..f70f827201 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -66,6 +66,72 @@ static int au_probe(AVProbeData *p) return 0; } +static int au_read_annotation(AVFormatContext *s, int size) +{ + static const char * keys[] = { + "title", + "artist", + "album", + "track", + "genre", + NULL }; + AVIOContext *pb = s->pb; + enum { PARSE_KEY, PARSE_VALUE, PARSE_FINISHED } state = PARSE_KEY; + char c; + AVBPrint bprint; + char * key = NULL; + char * value = NULL; + int i; + + av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); + + while (size-- > 0) { + c = avio_r8(pb); + switch(state) { + case PARSE_KEY: + if (c == '\0') { + state = PARSE_FINISHED; + } else if (c == '=') { + av_bprint_finalize(&bprint, &key); + av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); + state = PARSE_VALUE; + } else { + av_bprint_chars(&bprint, c, 1); + } + break; + case PARSE_VALUE: + if (c == '\0' || c == '\n') { + if (av_bprint_finalize(&bprint, &value) != 0) { + av_log(s, AV_LOG_ERROR, "Memory error while parsing AU metadata.\n"); + } else { + av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); + for (i = 0; keys[i] != NULL && key != NULL; i++) { + if (av_strcasecmp(keys[i], key) == 0) { + av_dict_set(&(s->metadata), keys[i], value, AV_DICT_DONT_STRDUP_VAL); + av_freep(&key); + value = NULL; + } + } + } + av_freep(&key); + av_freep(&value); + state = (c == '\0') ? PARSE_FINISHED : PARSE_KEY; + } else { + av_bprint_chars(&bprint, c, 1); + } + break; + case PARSE_FINISHED: + break; + default: + /* should never happen */ + av_assert0(0); + } + } + av_bprint_finalize(&bprint, NULL); + av_freep(&key); + return 0; +} + #define BLOCK_SIZE 1024 static int au_read_header(AVFormatContext *s) @@ -94,8 +160,8 @@ static int au_read_header(AVFormatContext *s) channels = avio_rb32(pb); if (size > 24) { - /* skip unused data */ - avio_skip(pb, size - 24); + /* parse annotation field to get metadata */ + au_read_annotation(s, size - 24); } codec = ff_codec_get_id(codec_au_tags, id); -- cgit v1.2.3