From 44015c56a698b3285d186ccb80310cb0b625e12b Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Fri, 8 Aug 2008 23:50:38 +0000 Subject: [PATCH] matroskadec: add basic tags support (metadata) Originally committed as revision 14672 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/matroska.h | 8 ++++- libavformat/matroskadec.c | 66 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 5587c01787..8930e16d3c 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -133,7 +133,13 @@ #define MATROSKA_ID_CUECLUSTERPOSITION 0xF1 /* IDs in the tags master */ -/* TODO */ +#define MATROSKA_ID_TAG 0x7373 +#define MATROSKA_ID_SIMPLETAG 0x67C8 +#define MATROSKA_ID_TAGNAME 0x45A3 +#define MATROSKA_ID_TAGSTRING 0x4487 +#define MATROSKA_ID_TAGLANG 0x447A +#define MATROSKA_ID_TAGDEFAULT 0x44B4 +#define MATROSKA_ID_TAGTARGETS 0x63C0 /* IDs in the seekhead master */ #define MATROSKA_ID_SEEKENTRY 0x4DBB diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index d7a1e39846..89c0d67c36 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -163,6 +163,12 @@ typedef struct { EbmlList pos; } MatroskaIndex; +typedef struct { + char *name; + char *string; + EbmlList sub; +} MatroskaTag; + typedef struct { uint64_t id; uint64_t pos; @@ -188,6 +194,7 @@ typedef struct { EbmlList attachments; EbmlList chapters; EbmlList index; + EbmlList tags; EbmlList seekhead; /* byte position of the segment inside the stream */ @@ -390,7 +397,25 @@ static EbmlSyntax matroska_index[] = { { 0 } }; +static EbmlSyntax matroska_simpletag[] = { + { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, offsetof(MatroskaTag,name) }, + { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, offsetof(MatroskaTag,string) }, + { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTag,sub), {.n=matroska_simpletag} }, + { MATROSKA_ID_TAGLANG, EBML_NONE }, + { MATROSKA_ID_TAGDEFAULT, EBML_NONE }, + { EBML_ID_VOID, EBML_NONE }, + { 0 } +}; + +static EbmlSyntax matroska_tag[] = { + { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), 0, {.n=matroska_simpletag} }, + { MATROSKA_ID_TAGTARGETS, EBML_NONE }, + { EBML_ID_VOID, EBML_NONE }, + { 0 } +}; + static EbmlSyntax matroska_tags[] = { + { MATROSKA_ID_TAG, EBML_NEST, 0, offsetof(MatroskaDemuxContext,tags), {.n=matroska_tag} }, { EBML_ID_VOID, EBML_NONE }, { 0 } }; @@ -448,6 +473,25 @@ static EbmlSyntax matroska_clusters[] = { { 0 } }; +#define SIZE_OFF(x) sizeof(((AVFormatContext*)0)->x),offsetof(AVFormatContext,x) +const struct { + const char name[16]; + int size; + int offset; +} metadata[] = { + { "TITLE", SIZE_OFF(title) }, + { "ARTIST", SIZE_OFF(author) }, + { "WRITTEN_BY", SIZE_OFF(author) }, + { "LEAD_PERFORMER", SIZE_OFF(author) }, + { "COPYRIGHT", SIZE_OFF(copyright) }, + { "COMMENT", SIZE_OFF(comment) }, + { "ALBUM", SIZE_OFF(album) }, + { "DATE_WRITTEN", SIZE_OFF(year) }, + { "DATE_RELEASED", SIZE_OFF(year) }, + { "PART_NUMBER", SIZE_OFF(track) }, + { "GENRE", SIZE_OFF(genre) }, +}; + /* * Return: Whether we reached the end of a level in the hierarchy or not. */ @@ -891,6 +935,27 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size, return -1; } +static void matroska_convert_tags(AVFormatContext *s, EbmlList *list) +{ + MatroskaTag *tags = list->elem; + int i, j; + + for (i=0; i < list->nb_elem; i++) { + for (j=0; j < ARRAY_SIZE(metadata); j++){ + if (!strcmp(tags[i].name, metadata[j].name)) { + int *ptr = (int *)((char *)s + metadata[j].offset); + if (*ptr) continue; + if (metadata[j].size > sizeof(int)) + av_strlcpy((char *)ptr, tags[i].string, metadata[j].size); + else + *ptr = atoi(tags[i].string); + } + } + if (tags[i].sub.nb_elem) + matroska_convert_tags(s, &tags[i].sub); + } +} + static void matroska_execute_seekhead(MatroskaDemuxContext *matroska) { EbmlList *seekhead_list = &matroska->seekhead; @@ -1002,6 +1067,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) if (matroska->title) strncpy(matroska->ctx->title, matroska->title, sizeof(matroska->ctx->title)-1); + matroska_convert_tags(s, &matroska->tags); tracks = matroska->tracks.elem; for (i=0; i < matroska->tracks.nb_elem; i++) {