On Monday, May 27, 2013, Sean McGovern <[email protected]> wrote: > This allows handling matroska files with errors. > Fixes test4.mkv and test7.mkv from the official Matroska test suite, > and by extension Bugzilla #62. > > Based on a patch by Reimar Doffinger <[email protected]> > --- > Corrected as per Anton's instructions. > --- > libavformat/matroskadec.c | 47 +++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 43 insertions(+), 4 deletions(-) > > diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c > index 3b801e0..0e5c261 100644 > --- a/libavformat/matroskadec.c > +++ b/libavformat/matroskadec.c > @@ -557,6 +557,35 @@ static EbmlSyntax matroska_clusters_incremental[] = { > > static const char *const matroska_doctypes[] = { "matroska", "webm" }; > > +static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) > +{ > + AVIOContext *pb = matroska->ctx->pb; > + uint32_t id; > + matroska->current_id = 0; > + matroska->num_levels = 0; > + > + /* seek to next position to resync from */ > + if (avio_seek(pb, last_pos + 1, SEEK_SET) < 0) > + goto eof; > + > + id = avio_rb32(pb); > + > + // try to find a toplevel element > + while (!pb->eof_reached) { > + if (id == MATROSKA_ID_INFO || id == MATROSKA_ID_TRACKS || > + id == MATROSKA_ID_CUES || id == MATROSKA_ID_TAGS || > + id == MATROSKA_ID_SEEKHEAD || id == MATROSKA_ID_ATTACHMENTS || > + id == MATROSKA_ID_CLUSTER || id == MATROSKA_ID_CHAPTERS) { > + matroska->current_id = id; > + return 0; > + } > + id = (id << 8) | avio_r8(pb); > + } > +eof: > + matroska->done = 1; > + return AVERROR_EOF; > +} > + > /* > * Return: Whether we reached the end of a level in the hierarchy or not. > */ > @@ -1362,6 +1391,7 @@ static int matroska_read_header(AVFormatContext *s) > MatroskaChapter *chapters; > MatroskaTrack *tracks; > uint64_t max_start = 0; > + int64_t pos; > Ebml ebml = { 0 }; > AVStream *st; > int i, j, res; > @@ -1392,8 +1422,16 @@ static int matroska_read_header(AVFormatContext *s) > ebml_free(ebml_syntax, &ebml); > > /* The next thing is a segment. */ > - if ((res = ebml_parse(matroska, matroska_segments, matroska)) < 0) > - return res; > + pos = avio_tell(matroska->ctx->pb); > + res = ebml_parse(matroska, matroska_segments, matroska); > + // try resyncing until we find a EBML_STOP type element. > + while (res != 1) { > + res = matroska_resync(matroska, pos); > + if (res < 0) > + return res; > + pos = avio_tell(matroska->ctx->pb); > + res = ebml_parse(matroska, matroska_segment, matroska); > + } > matroska_execute_seekhead(matroska); > > if (!matroska->time_scale) > @@ -2188,7 +2226,6 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska) > pos); > } > ebml_free(matroska_cluster, &cluster); > - if (res < 0) matroska->done = 1; > return res; > } > > @@ -2198,9 +2235,11 @@ static int matroska_read_packet(AVFormatContext *s, AVPacket *pkt) > int ret = 0; > > while (!ret && matroska_deliver_packet(matroska, pkt)) { > + int64_t pos = avio_tell(matroska->ctx->pb); > if (matroska->done) > return AVERROR_EOF; > - ret = matroska_parse_cluster(matroska); > + if (matroska_parse_cluster(matroska) < 0) > + ret = matroska_resync(matroska, pos); > } > > if (ret == AVERROR_INVALIDDATA && pkt->data) { > -- >
Ping! -- Sean McG. _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
