Mercurial > libavformat.hg
comparison matroskadec.c @ 3633:7a44217312bb libavformat
matroskadec: use generic ebml parser to parse ebml header
author | aurel |
---|---|
date | Tue, 05 Aug 2008 00:40:02 +0000 |
parents | a43869dda583 |
children | f206f746ff61 |
comparison
equal
deleted
inserted
replaced
3632:a43869dda583 | 3633:7a44217312bb |
---|---|
78 int size; | 78 int size; |
79 uint8_t *data; | 79 uint8_t *data; |
80 int64_t pos; | 80 int64_t pos; |
81 } EbmlBin; | 81 } EbmlBin; |
82 | 82 |
83 typedef struct { | |
84 uint64_t version; | |
85 uint64_t max_size; | |
86 uint64_t id_length; | |
87 char *doctype; | |
88 uint64_t doctype_version; | |
89 } Ebml; | |
90 | |
83 typedef struct Track { | 91 typedef struct Track { |
84 MatroskaTrackType type; | 92 MatroskaTrackType type; |
85 | 93 |
86 /* Unique track number and track ID. stream_index is the index that | 94 /* Unique track number and track ID. stream_index is the index that |
87 * the calling app uses for this track. */ | 95 * the calling app uses for this track. */ |
201 AVStream *skip_to_stream; | 209 AVStream *skip_to_stream; |
202 } MatroskaDemuxContext; | 210 } MatroskaDemuxContext; |
203 | 211 |
204 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x)) | 212 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x)) |
205 | 213 |
214 static EbmlSyntax ebml_header[] = { | |
215 { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml,version), {.u=EBML_VERSION} }, | |
216 { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml,max_size), {.u=8} }, | |
217 { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, offsetof(Ebml,id_length), {.u=4} }, | |
218 { EBML_ID_DOCTYPE, EBML_STR, 0, offsetof(Ebml,doctype), {.s="(none)"} }, | |
219 { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, offsetof(Ebml,doctype_version), {.u=1} }, | |
220 { EBML_ID_EBMLVERSION, EBML_NONE }, | |
221 { EBML_ID_DOCTYPEVERSION, EBML_NONE }, | |
222 { EBML_ID_VOID, EBML_NONE }, | |
223 { 0 } | |
224 }; | |
225 | |
226 static EbmlSyntax ebml_syntax[] = { | |
227 { EBML_ID_HEADER, EBML_NEST, 0, 0, {.n=ebml_header} }, | |
228 { 0 } | |
229 }; | |
230 | |
206 /* | 231 /* |
207 * The first few functions handle EBML file parsing. The rest | 232 * The first few functions handle EBML file parsing. The rest |
208 * is the document interpretation. Matroska really just is a | 233 * is the document interpretation. Matroska really just is a |
209 * EBML file. | 234 * EBML file. |
210 */ | 235 */ |
690 *num = INT64_MAX; | 715 *num = INT64_MAX; |
691 else | 716 else |
692 *num = unum - ((1LL << ((7 * res) - 1)) - 1); | 717 *num = unum - ((1LL << ((7 * res) - 1)) - 1); |
693 | 718 |
694 return res; | 719 return res; |
695 } | |
696 | |
697 /* | |
698 * Read an EBML header. | |
699 * 0 is success, < 0 is failure. | |
700 */ | |
701 | |
702 static int | |
703 ebml_read_header (MatroskaDemuxContext *matroska, | |
704 char **doctype, | |
705 int *version) | |
706 { | |
707 uint32_t id; | |
708 int level_up, res = 0; | |
709 | |
710 /* default init */ | |
711 if (doctype) | |
712 *doctype = NULL; | |
713 if (version) | |
714 *version = 1; | |
715 | |
716 if (!(id = ebml_peek_id(matroska, &level_up)) || | |
717 level_up != 0 || id != EBML_ID_HEADER) { | |
718 av_log(matroska->ctx, AV_LOG_ERROR, | |
719 "This is not an EBML file (id=0x%x/0x%x)\n", id, EBML_ID_HEADER); | |
720 return AVERROR_INVALIDDATA; | |
721 } | |
722 if ((res = ebml_read_master(matroska, &id)) < 0) | |
723 return res; | |
724 | |
725 while (res == 0) { | |
726 if (!(id = ebml_peek_id(matroska, &level_up))) | |
727 return AVERROR(EIO); | |
728 | |
729 /* end-of-header */ | |
730 if (level_up) | |
731 break; | |
732 | |
733 switch (id) { | |
734 /* is our read version uptodate? */ | |
735 case EBML_ID_EBMLREADVERSION: { | |
736 uint64_t num; | |
737 | |
738 if ((res = ebml_read_uint(matroska, &id, &num)) < 0) | |
739 return res; | |
740 if (num > EBML_VERSION) { | |
741 av_log(matroska->ctx, AV_LOG_ERROR, | |
742 "EBML version %"PRIu64" (> %d) is not supported\n", | |
743 num, EBML_VERSION); | |
744 return AVERROR_INVALIDDATA; | |
745 } | |
746 break; | |
747 } | |
748 | |
749 /* we only handle 8 byte lengths at max */ | |
750 case EBML_ID_EBMLMAXSIZELENGTH: { | |
751 uint64_t num; | |
752 | |
753 if ((res = ebml_read_uint(matroska, &id, &num)) < 0) | |
754 return res; | |
755 if (num > sizeof(uint64_t)) { | |
756 av_log(matroska->ctx, AV_LOG_ERROR, | |
757 "Integers of size %"PRIu64" (> %zd) not supported\n", | |
758 num, sizeof(uint64_t)); | |
759 return AVERROR_INVALIDDATA; | |
760 } | |
761 break; | |
762 } | |
763 | |
764 /* we handle 4 byte IDs at max */ | |
765 case EBML_ID_EBMLMAXIDLENGTH: { | |
766 uint64_t num; | |
767 | |
768 if ((res = ebml_read_uint(matroska, &id, &num)) < 0) | |
769 return res; | |
770 if (num > sizeof(uint32_t)) { | |
771 av_log(matroska->ctx, AV_LOG_ERROR, | |
772 "IDs of size %"PRIu64" (> %zu) not supported\n", | |
773 num, sizeof(uint32_t)); | |
774 return AVERROR_INVALIDDATA; | |
775 } | |
776 break; | |
777 } | |
778 | |
779 case EBML_ID_DOCTYPE: { | |
780 char *text; | |
781 | |
782 if ((res = ebml_read_ascii(matroska, &id, &text)) < 0) | |
783 return res; | |
784 if (doctype) { | |
785 if (*doctype) | |
786 av_free(*doctype); | |
787 *doctype = text; | |
788 } else | |
789 av_free(text); | |
790 break; | |
791 } | |
792 | |
793 case EBML_ID_DOCTYPEREADVERSION: { | |
794 uint64_t num; | |
795 | |
796 if ((res = ebml_read_uint(matroska, &id, &num)) < 0) | |
797 return res; | |
798 if (version) | |
799 *version = num; | |
800 break; | |
801 } | |
802 | |
803 default: | |
804 av_log(matroska->ctx, AV_LOG_INFO, | |
805 "Unknown data type 0x%x in EBML header", id); | |
806 /* pass-through */ | |
807 | |
808 case EBML_ID_VOID: | |
809 /* we ignore these two, as they don't tell us anything we | |
810 * care about */ | |
811 case EBML_ID_EBMLVERSION: | |
812 case EBML_ID_DOCTYPEVERSION: | |
813 res = ebml_read_skip (matroska); | |
814 break; | |
815 } | |
816 } | |
817 | |
818 return 0; | |
819 } | 720 } |
820 | 721 |
821 | 722 |
822 static int | 723 static int |
823 matroska_find_track_by_num (MatroskaDemuxContext *matroska, | 724 matroska_find_track_by_num (MatroskaDemuxContext *matroska, |
2498 static int | 2399 static int |
2499 matroska_read_header (AVFormatContext *s, | 2400 matroska_read_header (AVFormatContext *s, |
2500 AVFormatParameters *ap) | 2401 AVFormatParameters *ap) |
2501 { | 2402 { |
2502 MatroskaDemuxContext *matroska = s->priv_data; | 2403 MatroskaDemuxContext *matroska = s->priv_data; |
2503 char *doctype; | 2404 int last_level, res = 0; |
2504 int version, last_level, res = 0; | 2405 Ebml ebml = { 0 }; |
2505 uint32_t id; | 2406 uint32_t id; |
2506 | 2407 |
2507 matroska->ctx = s; | 2408 matroska->ctx = s; |
2508 | 2409 |
2509 /* First read the EBML header. */ | 2410 /* First read the EBML header. */ |
2510 doctype = NULL; | 2411 if (ebml_parse(matroska, ebml_syntax, &ebml, 0, 1) |
2511 if ((res = ebml_read_header(matroska, &doctype, &version)) < 0) | 2412 || ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t) |
2512 return res; | 2413 || ebml.id_length > sizeof(uint32_t) || strcmp(ebml.doctype, "matroska") |
2513 if ((doctype == NULL) || strcmp(doctype, "matroska")) { | 2414 || ebml.doctype_version > 2) { |
2514 av_log(matroska->ctx, AV_LOG_ERROR, | 2415 av_log(matroska->ctx, AV_LOG_ERROR, |
2515 "Wrong EBML doctype ('%s' != 'matroska').\n", | 2416 "EBML header using unsupported features\n" |
2516 doctype ? doctype : "(none)"); | 2417 "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", |
2517 if (doctype) | 2418 ebml.version, ebml.doctype, ebml.doctype_version); |
2518 av_free(doctype); | |
2519 return AVERROR_NOFMT; | 2419 return AVERROR_NOFMT; |
2520 } | 2420 } |
2521 av_free(doctype); | 2421 ebml_free(ebml_syntax, &ebml); |
2522 if (version > 2) { | |
2523 av_log(matroska->ctx, AV_LOG_ERROR, | |
2524 "Matroska demuxer version 2 too old for file version %d\n", | |
2525 version); | |
2526 return AVERROR_NOFMT; | |
2527 } | |
2528 | 2422 |
2529 /* The next thing is a segment. */ | 2423 /* The next thing is a segment. */ |
2530 while (1) { | 2424 while (1) { |
2531 if (!(id = ebml_peek_id(matroska, &last_level))) | 2425 if (!(id = ebml_peek_id(matroska, &last_level))) |
2532 return AVERROR(EIO); | 2426 return AVERROR(EIO); |