comparison matroskadec.c @ 3702:b4f34511ccd3 libavformat

matroskadec: add basic tags support (metadata)
author aurel
date Fri, 08 Aug 2008 23:50:38 +0000
parents 4aef467adb6b
children b337fe64a31f
comparison
equal deleted inserted replaced
3701:5cf9918994ed 3702:b4f34511ccd3
162 uint64_t time; 162 uint64_t time;
163 EbmlList pos; 163 EbmlList pos;
164 } MatroskaIndex; 164 } MatroskaIndex;
165 165
166 typedef struct { 166 typedef struct {
167 char *name;
168 char *string;
169 EbmlList sub;
170 } MatroskaTag;
171
172 typedef struct {
167 uint64_t id; 173 uint64_t id;
168 uint64_t pos; 174 uint64_t pos;
169 } MatroskaSeekhead; 175 } MatroskaSeekhead;
170 176
171 typedef struct { 177 typedef struct {
186 char *title; 192 char *title;
187 EbmlList tracks; 193 EbmlList tracks;
188 EbmlList attachments; 194 EbmlList attachments;
189 EbmlList chapters; 195 EbmlList chapters;
190 EbmlList index; 196 EbmlList index;
197 EbmlList tags;
191 EbmlList seekhead; 198 EbmlList seekhead;
192 199
193 /* byte position of the segment inside the stream */ 200 /* byte position of the segment inside the stream */
194 offset_t segment_start; 201 offset_t segment_start;
195 202
388 { MATROSKA_ID_POINTENTRY, EBML_NEST, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext,index), {.n=matroska_index_entry} }, 395 { MATROSKA_ID_POINTENTRY, EBML_NEST, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext,index), {.n=matroska_index_entry} },
389 { EBML_ID_VOID, EBML_NONE }, 396 { EBML_ID_VOID, EBML_NONE },
390 { 0 } 397 { 0 }
391 }; 398 };
392 399
400 static EbmlSyntax matroska_simpletag[] = {
401 { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, offsetof(MatroskaTag,name) },
402 { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, offsetof(MatroskaTag,string) },
403 { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTag,sub), {.n=matroska_simpletag} },
404 { MATROSKA_ID_TAGLANG, EBML_NONE },
405 { MATROSKA_ID_TAGDEFAULT, EBML_NONE },
406 { EBML_ID_VOID, EBML_NONE },
407 { 0 }
408 };
409
410 static EbmlSyntax matroska_tag[] = {
411 { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), 0, {.n=matroska_simpletag} },
412 { MATROSKA_ID_TAGTARGETS, EBML_NONE },
413 { EBML_ID_VOID, EBML_NONE },
414 { 0 }
415 };
416
393 static EbmlSyntax matroska_tags[] = { 417 static EbmlSyntax matroska_tags[] = {
418 { MATROSKA_ID_TAG, EBML_NEST, 0, offsetof(MatroskaDemuxContext,tags), {.n=matroska_tag} },
394 { EBML_ID_VOID, EBML_NONE }, 419 { EBML_ID_VOID, EBML_NONE },
395 { 0 } 420 { 0 }
396 }; 421 };
397 422
398 static EbmlSyntax matroska_seekhead_entry[] = { 423 static EbmlSyntax matroska_seekhead_entry[] = {
444 }; 469 };
445 470
446 static EbmlSyntax matroska_clusters[] = { 471 static EbmlSyntax matroska_clusters[] = {
447 { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster} }, 472 { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster} },
448 { 0 } 473 { 0 }
474 };
475
476 #define SIZE_OFF(x) sizeof(((AVFormatContext*)0)->x),offsetof(AVFormatContext,x)
477 const struct {
478 const char name[16];
479 int size;
480 int offset;
481 } metadata[] = {
482 { "TITLE", SIZE_OFF(title) },
483 { "ARTIST", SIZE_OFF(author) },
484 { "WRITTEN_BY", SIZE_OFF(author) },
485 { "LEAD_PERFORMER", SIZE_OFF(author) },
486 { "COPYRIGHT", SIZE_OFF(copyright) },
487 { "COMMENT", SIZE_OFF(comment) },
488 { "ALBUM", SIZE_OFF(album) },
489 { "DATE_WRITTEN", SIZE_OFF(year) },
490 { "DATE_RELEASED", SIZE_OFF(year) },
491 { "PART_NUMBER", SIZE_OFF(track) },
492 { "GENRE", SIZE_OFF(genre) },
449 }; 493 };
450 494
451 /* 495 /*
452 * Return: Whether we reached the end of a level in the hierarchy or not. 496 * Return: Whether we reached the end of a level in the hierarchy or not.
453 */ 497 */
889 failed: 933 failed:
890 av_free(pkt_data); 934 av_free(pkt_data);
891 return -1; 935 return -1;
892 } 936 }
893 937
938 static void matroska_convert_tags(AVFormatContext *s, EbmlList *list)
939 {
940 MatroskaTag *tags = list->elem;
941 int i, j;
942
943 for (i=0; i < list->nb_elem; i++) {
944 for (j=0; j < ARRAY_SIZE(metadata); j++){
945 if (!strcmp(tags[i].name, metadata[j].name)) {
946 int *ptr = (int *)((char *)s + metadata[j].offset);
947 if (*ptr) continue;
948 if (metadata[j].size > sizeof(int))
949 av_strlcpy((char *)ptr, tags[i].string, metadata[j].size);
950 else
951 *ptr = atoi(tags[i].string);
952 }
953 }
954 if (tags[i].sub.nb_elem)
955 matroska_convert_tags(s, &tags[i].sub);
956 }
957 }
958
894 static void matroska_execute_seekhead(MatroskaDemuxContext *matroska) 959 static void matroska_execute_seekhead(MatroskaDemuxContext *matroska)
895 { 960 {
896 EbmlList *seekhead_list = &matroska->seekhead; 961 EbmlList *seekhead_list = &matroska->seekhead;
897 MatroskaSeekhead *seekhead = seekhead_list->elem; 962 MatroskaSeekhead *seekhead = seekhead_list->elem;
898 uint32_t level_up = matroska->level_up; 963 uint32_t level_up = matroska->level_up;
1000 matroska->ctx->duration = matroska->duration * matroska->time_scale 1065 matroska->ctx->duration = matroska->duration * matroska->time_scale
1001 * 1000 / AV_TIME_BASE; 1066 * 1000 / AV_TIME_BASE;
1002 if (matroska->title) 1067 if (matroska->title)
1003 strncpy(matroska->ctx->title, matroska->title, 1068 strncpy(matroska->ctx->title, matroska->title,
1004 sizeof(matroska->ctx->title)-1); 1069 sizeof(matroska->ctx->title)-1);
1070 matroska_convert_tags(s, &matroska->tags);
1005 1071
1006 tracks = matroska->tracks.elem; 1072 tracks = matroska->tracks.elem;
1007 for (i=0; i < matroska->tracks.nb_elem; i++) { 1073 for (i=0; i < matroska->tracks.nb_elem; i++) {
1008 MatroskaTrack *track = &tracks[i]; 1074 MatroskaTrack *track = &tracks[i];
1009 enum CodecID codec_id = CODEC_ID_NONE; 1075 enum CodecID codec_id = CODEC_ID_NONE;