diff options
author | Thomas Bernard <miniupnp@free.fr> | 2016-06-07 00:25:38 +0200 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2016-06-13 20:58:43 +0200 |
commit | 836f3555a8def29001d7c917d1574a7938d2357b (patch) | |
tree | 9a901be8bb8f6842df253434a93db75a71f90a8a | |
parent | 4879841d1529e1919fc07f613ecd1a0f65b9d456 (diff) | |
download | ffmpeg-836f3555a8def29001d7c917d1574a7938d2357b.tar.gz |
avformat/au: Read MetaData from AU Sun audio file header
recognize title= album= artist= genre= track=
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r-- | libavformat/au.c | 70 |
1 files changed, 68 insertions, 2 deletions
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); |