matroskadec: add generic metadata support
Originally committed as revision 17331 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
325ace3efc
commit
929e9de7a1
@ -150,6 +150,8 @@ typedef struct {
|
|||||||
char *filename;
|
char *filename;
|
||||||
char *mime;
|
char *mime;
|
||||||
EbmlBin bin;
|
EbmlBin bin;
|
||||||
|
|
||||||
|
AVStream *stream;
|
||||||
} MatroskaAttachement;
|
} MatroskaAttachement;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -177,6 +179,19 @@ typedef struct {
|
|||||||
EbmlList sub;
|
EbmlList sub;
|
||||||
} MatroskaTag;
|
} MatroskaTag;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *type;
|
||||||
|
uint64_t typevalue;
|
||||||
|
uint64_t trackuid;
|
||||||
|
uint64_t chapteruid;
|
||||||
|
uint64_t attachuid;
|
||||||
|
} MatroskaTagTarget;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MatroskaTagTarget target;
|
||||||
|
EbmlList tag;
|
||||||
|
} MatroskaTags;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
uint64_t pos;
|
uint64_t pos;
|
||||||
@ -409,14 +424,23 @@ static EbmlSyntax matroska_simpletag[] = {
|
|||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static EbmlSyntax matroska_tagtargets[] = {
|
||||||
|
{ MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, offsetof(MatroskaTagTarget,type) },
|
||||||
|
{ MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, offsetof(MatroskaTagTarget,typevalue), {.u=50} },
|
||||||
|
{ MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTagTarget,trackuid) },
|
||||||
|
{ MATROSKA_ID_TAGTARGETS_CHAPTERUID,EBML_UINT, 0, offsetof(MatroskaTagTarget,chapteruid) },
|
||||||
|
{ MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, offsetof(MatroskaTagTarget,attachuid) },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
static EbmlSyntax matroska_tag[] = {
|
static EbmlSyntax matroska_tag[] = {
|
||||||
{ MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), 0, {.n=matroska_simpletag} },
|
{ MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTags,tag), {.n=matroska_simpletag} },
|
||||||
{ MATROSKA_ID_TAGTARGETS, EBML_NONE },
|
{ MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, offsetof(MatroskaTags,target), {.n=matroska_tagtargets} },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static EbmlSyntax matroska_tags[] = {
|
static EbmlSyntax matroska_tags[] = {
|
||||||
{ MATROSKA_ID_TAG, EBML_NEST, 0, offsetof(MatroskaDemuxContext,tags), {.n=matroska_tag} },
|
{ MATROSKA_ID_TAG, EBML_NEST, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext,tags), {.n=matroska_tag} },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -474,25 +498,6 @@ static EbmlSyntax matroska_clusters[] = {
|
|||||||
{ 0 }
|
{ 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.
|
* Return: Whether we reached the end of a level in the hierarchy or not.
|
||||||
*/
|
*/
|
||||||
@ -977,24 +982,50 @@ static void matroska_merge_packets(AVPacket *out, AVPacket *in)
|
|||||||
av_free(in);
|
av_free(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void matroska_convert_tags(AVFormatContext *s, EbmlList *list)
|
static void matroska_convert_tag(AVFormatContext *s, EbmlList *list,
|
||||||
|
AVMetadata **metadata, char *prefix)
|
||||||
{
|
{
|
||||||
MatroskaTag *tags = list->elem;
|
MatroskaTag *tags = list->elem;
|
||||||
int i, j;
|
char key[1024];
|
||||||
|
int i;
|
||||||
|
|
||||||
for (i=0; i < list->nb_elem; i++) {
|
for (i=0; i < list->nb_elem; i++) {
|
||||||
for (j=0; j < FF_ARRAY_ELEMS(metadata); j++){
|
if (prefix) snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name);
|
||||||
if (!strcmp(tags[i].name, metadata[j].name)) {
|
else av_strlcpy(key, tags[i].name, sizeof(key));
|
||||||
int *ptr = (int *)((char *)s + metadata[j].offset);
|
av_metadata_set(metadata, key, tags[i].string);
|
||||||
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)
|
if (tags[i].sub.nb_elem)
|
||||||
matroska_convert_tags(s, &tags[i].sub);
|
matroska_convert_tag(s, &tags[i].sub, metadata, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void matroska_convert_tags(AVFormatContext *s)
|
||||||
|
{
|
||||||
|
MatroskaDemuxContext *matroska = s->priv_data;
|
||||||
|
MatroskaTags *tags = matroska->tags.elem;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i=0; i < matroska->tags.nb_elem; i++) {
|
||||||
|
if (tags[i].target.attachuid) {
|
||||||
|
MatroskaAttachement *attachment = matroska->attachments.elem;
|
||||||
|
for (j=0; j<matroska->attachments.nb_elem; j++)
|
||||||
|
if (attachment[j].uid == tags[i].target.attachuid)
|
||||||
|
matroska_convert_tag(s, &tags[i].tag,
|
||||||
|
&attachment[j].stream->metadata, NULL);
|
||||||
|
} else if (tags[i].target.chapteruid) {
|
||||||
|
MatroskaChapter *chapter = matroska->chapters.elem;
|
||||||
|
for (j=0; j<matroska->chapters.nb_elem; j++)
|
||||||
|
if (chapter[j].uid == tags[i].target.chapteruid)
|
||||||
|
matroska_convert_tag(s, &tags[i].tag,
|
||||||
|
&chapter[j].chapter->metadata, NULL);
|
||||||
|
} else if (tags[i].target.trackuid) {
|
||||||
|
MatroskaTrack *track = matroska->tracks.elem;
|
||||||
|
for (j=0; j<matroska->tracks.nb_elem; j++)
|
||||||
|
if (track[j].uid == tags[i].target.trackuid)
|
||||||
|
matroska_convert_tag(s, &tags[i].tag,
|
||||||
|
&track[j].stream->metadata, NULL);
|
||||||
|
} else {
|
||||||
|
matroska_convert_tag(s, &tags[i].tag, &s->metadata, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1109,7 +1140,6 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
matroska->ctx->duration = matroska->duration * matroska->time_scale
|
matroska->ctx->duration = matroska->duration * matroska->time_scale
|
||||||
* 1000 / AV_TIME_BASE;
|
* 1000 / AV_TIME_BASE;
|
||||||
av_metadata_set(&s->metadata, "title", matroska->title);
|
av_metadata_set(&s->metadata, "title", matroska->title);
|
||||||
matroska_convert_tags(s, &matroska->tags);
|
|
||||||
|
|
||||||
tracks = matroska->tracks.elem;
|
tracks = matroska->tracks.elem;
|
||||||
for (i=0; i < matroska->tracks.nb_elem; i++) {
|
for (i=0; i < matroska->tracks.nb_elem; i++) {
|
||||||
@ -1366,6 +1396,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
attachements[j].stream = st;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1403,6 +1434,8 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matroska_convert_tags(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user