Mercurial > libavformat.hg
comparison matroskadec.c @ 6029:7e9deb9f0234 libavformat
matroskadec: Support webm doctype
Patch by James Zern <jzern at google>
author | conrad |
---|---|
date | Sat, 22 May 2010 01:41:32 +0000 |
parents | b36bdd7213ea |
children | fd82ce3c4e65 |
comparison
equal
deleted
inserted
replaced
6028:d920f5eb9d10 | 6029:7e9deb9f0234 |
---|---|
503 { MATROSKA_ID_TAGS, EBML_NONE }, | 503 { MATROSKA_ID_TAGS, EBML_NONE }, |
504 { MATROSKA_ID_SEEKHEAD, EBML_NONE }, | 504 { MATROSKA_ID_SEEKHEAD, EBML_NONE }, |
505 { 0 } | 505 { 0 } |
506 }; | 506 }; |
507 | 507 |
508 static const char *matroska_doctypes[] = { "matroska", "webm" }; | |
509 | |
508 /* | 510 /* |
509 * Return: Whether we reached the end of a level in the hierarchy or not. | 511 * Return: Whether we reached the end of a level in the hierarchy or not. |
510 */ | 512 */ |
511 static int ebml_level_end(MatroskaDemuxContext *matroska) | 513 static int ebml_level_end(MatroskaDemuxContext *matroska) |
512 { | 514 { |
823 * Autodetecting... | 825 * Autodetecting... |
824 */ | 826 */ |
825 static int matroska_probe(AVProbeData *p) | 827 static int matroska_probe(AVProbeData *p) |
826 { | 828 { |
827 uint64_t total = 0; | 829 uint64_t total = 0; |
828 int len_mask = 0x80, size = 1, n = 1; | 830 int len_mask = 0x80, size = 1, n = 1, i; |
829 static const char probe_data[] = "matroska"; | |
830 | 831 |
831 /* EBML header? */ | 832 /* EBML header? */ |
832 if (AV_RB32(p->buf) != EBML_ID_HEADER) | 833 if (AV_RB32(p->buf) != EBML_ID_HEADER) |
833 return 0; | 834 return 0; |
834 | 835 |
846 | 847 |
847 /* Does the probe data contain the whole header? */ | 848 /* Does the probe data contain the whole header? */ |
848 if (p->buf_size < 4 + size + total) | 849 if (p->buf_size < 4 + size + total) |
849 return 0; | 850 return 0; |
850 | 851 |
851 /* The header must contain the document type 'matroska'. For now, | 852 /* The header should contain a known document type. For now, |
852 * we don't parse the whole header but simply check for the | 853 * we don't parse the whole header but simply check for the |
853 * availability of that array of characters inside the header. | 854 * availability of that array of characters inside the header. |
854 * Not fully fool-proof, but good enough. */ | 855 * Not fully fool-proof, but good enough. */ |
855 for (n = 4+size; n <= 4+size+total-(sizeof(probe_data)-1); n++) | 856 for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) { |
856 if (!memcmp(p->buf+n, probe_data, sizeof(probe_data)-1)) | 857 int probelen = strlen(matroska_doctypes[i]); |
857 return AVPROBE_SCORE_MAX; | 858 for (n = 4+size; n <= 4+size+total-probelen; n++) |
859 if (!memcmp(p->buf+n, matroska_doctypes[i], probelen)) | |
860 return AVPROBE_SCORE_MAX; | |
861 } | |
858 | 862 |
859 return 0; | 863 return 0; |
860 } | 864 } |
861 | 865 |
862 static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, | 866 static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, |
1139 matroska->ctx = s; | 1143 matroska->ctx = s; |
1140 | 1144 |
1141 /* First read the EBML header. */ | 1145 /* First read the EBML header. */ |
1142 if (ebml_parse(matroska, ebml_syntax, &ebml) | 1146 if (ebml_parse(matroska, ebml_syntax, &ebml) |
1143 || ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t) | 1147 || ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t) |
1144 || ebml.id_length > sizeof(uint32_t) || strcmp(ebml.doctype, "matroska") | 1148 || ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 2) { |
1145 || ebml.doctype_version > 2) { | |
1146 av_log(matroska->ctx, AV_LOG_ERROR, | 1149 av_log(matroska->ctx, AV_LOG_ERROR, |
1147 "EBML header using unsupported features\n" | 1150 "EBML header using unsupported features\n" |
1148 "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", | 1151 "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", |
1149 ebml.version, ebml.doctype, ebml.doctype_version); | 1152 ebml.version, ebml.doctype, ebml.doctype_version); |
1153 ebml_free(ebml_syntax, &ebml); | |
1150 return AVERROR_PATCHWELCOME; | 1154 return AVERROR_PATCHWELCOME; |
1151 } | 1155 } |
1156 for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) | |
1157 if (!strcmp(ebml.doctype, matroska_doctypes[i])) | |
1158 break; | |
1159 if (i >= FF_ARRAY_ELEMS(matroska_doctypes)) { | |
1160 av_log(s, AV_LOG_ERROR, "Unknown EBML doctype '%s'\n", ebml.doctype); | |
1161 ebml_free(ebml_syntax, &ebml); | |
1162 return AVERROR_PATCHWELCOME; | |
1163 } | |
1164 av_metadata_set2(&s->metadata, "doctype", ebml.doctype, 0); | |
1152 ebml_free(ebml_syntax, &ebml); | 1165 ebml_free(ebml_syntax, &ebml); |
1153 | 1166 |
1154 /* The next thing is a segment. */ | 1167 /* The next thing is a segment. */ |
1155 if (ebml_parse(matroska, matroska_segments, matroska) < 0) | 1168 if (ebml_parse(matroska, matroska_segments, matroska) < 0) |
1156 return -1; | 1169 return -1; |