# HG changeset patch # User aurel # Date 1217896836 0 # Node ID 1990951ffa35b4b5ce7166b2d0f5e380b2dda71b # Parent 1dfa03e34d5b5f26ff8475be98012950380fca50 matroskadec: use generic parser to parse seekhead diff -r 1dfa03e34d5b -r 1990951ffa35 matroskadec.c --- a/matroskadec.c Tue Aug 05 00:40:33 2008 +0000 +++ b/matroskadec.c Tue Aug 05 00:40:36 2008 +0000 @@ -163,6 +163,11 @@ EbmlList pos; } MatroskaIndex; +typedef struct { + uint64_t id; + uint64_t pos; +} MatroskaSeekhead; + typedef struct MatroskaLevel { uint64_t start; uint64_t length; @@ -184,6 +189,7 @@ EbmlList attachments; EbmlList chapters; EbmlList index; + EbmlList seekhead; /* num_streams is the number of streams that av_new_stream() was called * for ( = that are available to the calling program). */ @@ -388,6 +394,19 @@ { 0 } }; +static EbmlSyntax matroska_seekhead_entry[] = { + { MATROSKA_ID_SEEKID, EBML_UINT, 0, offsetof(MatroskaSeekhead,id) }, + { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, offsetof(MatroskaSeekhead,pos), {.u=-1} }, + { EBML_ID_VOID, EBML_NONE }, + { 0 } +}; + +static EbmlSyntax matroska_seekhead[] = { + { MATROSKA_ID_SEEKENTRY, EBML_NEST, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext,seekhead), {.n=matroska_seekhead_entry} }, + { EBML_ID_VOID, EBML_NONE }, + { 0 } +}; + /* * The first few functions handle EBML file parsing. The rest * is the document interpretation. Matroska really just is a @@ -1316,86 +1335,32 @@ static int matroska_parse_seekhead (MatroskaDemuxContext *matroska) { - int res = 0; - uint32_t id; - - av_log(matroska->ctx, AV_LOG_DEBUG, "parsing seekhead...\n"); - - while (res == 0) { - if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { - res = AVERROR(EIO); - break; - } else if (matroska->level_up) { - matroska->level_up--; - break; - } - - switch (id) { - case MATROSKA_ID_SEEKENTRY: { - uint32_t seek_id = 0, peek_id_cache = 0; - uint64_t seek_pos = (uint64_t) -1, t; - int dummy_level = 0; - - if ((res = ebml_read_master(matroska, &id)) < 0) - break; - - while (res == 0) { - if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { - res = AVERROR(EIO); - break; - } else if (matroska->level_up) { - matroska->level_up--; - break; - } - - switch (id) { - case MATROSKA_ID_SEEKID: - res = ebml_read_uint(matroska, &id, &t); - seek_id = t; - break; + return ebml_parse(matroska, matroska_seekhead, matroska, MATROSKA_ID_SEEKHEAD, 0); +} - case MATROSKA_ID_SEEKPOSITION: - res = ebml_read_uint(matroska, &id, &seek_pos); - break; - - default: - av_log(matroska->ctx, AV_LOG_INFO, - "Unknown seekhead ID 0x%x\n", id); - /* fall-through */ - - case EBML_ID_VOID: - res = ebml_read_skip(matroska); - break; - } +static void +matroska_execute_seekhead(MatroskaDemuxContext *matroska) +{ + EbmlList *seekhead_list = &matroska->seekhead; + MatroskaSeekhead *seekhead = seekhead_list->elem; + uint32_t peek_id_cache = matroska->peek_id; + uint32_t level_up = matroska->level_up; + offset_t before_pos = url_ftell(matroska->ctx->pb); + int dummy_level = 0; + MatroskaLevel level; + uint32_t id; + int i, res; - if (matroska->level_up) { - matroska->level_up--; - break; - } - } - - if (!seek_id || seek_pos == (uint64_t) -1) { - av_log(matroska->ctx, AV_LOG_INFO, - "Incomplete seekhead entry (0x%x/%"PRIu64")\n", - seek_id, seek_pos); - break; - } - - switch (seek_id) { - case MATROSKA_ID_CUES: - case MATROSKA_ID_TAGS: { - uint32_t level_up = matroska->level_up; - offset_t before_pos; - MatroskaLevel level; - - /* remember the peeked ID and the current position */ - peek_id_cache = matroska->peek_id; - before_pos = url_ftell(matroska->ctx->pb); + for (i=0; inb_elem; i++) { + if (seekhead[i].pos <= before_pos + || seekhead[i].id == MATROSKA_ID_SEEKHEAD + || seekhead[i].id == MATROSKA_ID_CLUSTER) + continue; /* seek */ - if ((res = ebml_read_seek(matroska, seek_pos + - matroska->segment_start)) < 0) - goto finish; + if (ebml_read_seek(matroska, + seekhead[i].pos+matroska->segment_start) < 0) + continue; /* we don't want to lose our seekhead level, so we add * a dummy. This is a crude hack. */ @@ -1403,7 +1368,7 @@ av_log(matroska->ctx, AV_LOG_INFO, "Max EBML element depth (%d) reached, " "cannot parse further.\n", EBML_MAX_DEPTH); - return AVERROR_UNKNOWN; + break; } level.start = 0; @@ -1416,11 +1381,11 @@ if (!(id = ebml_peek_id (matroska, &matroska->level_up))) goto finish; - if (id != seek_id) { + if (id != seekhead[i].id) { av_log(matroska->ctx, AV_LOG_INFO, "We looked for ID=0x%x but got " "ID=0x%x (pos=%"PRIu64")", - seek_id, id, seek_pos + + (int)seekhead[i].id, id, seekhead[i].pos + matroska->segment_start); goto finish; } @@ -1451,42 +1416,12 @@ if (length == (uint64_t)-1) break; } + } /* seek back */ - if ((res = ebml_read_seek(matroska, before_pos)) < 0) - return res; + ebml_read_seek(matroska, before_pos); matroska->peek_id = peek_id_cache; matroska->level_up = level_up; - break; - } - - default: - av_log(matroska->ctx, AV_LOG_INFO, - "Ignoring seekhead entry for ID=0x%x\n", - seek_id); - break; - } - - break; - } - - default: - av_log(matroska->ctx, AV_LOG_INFO, - "Unknown seekhead ID 0x%x\n", id); - /* fall-through */ - - case EBML_ID_VOID: - res = ebml_read_skip(matroska); - break; - } - - if (matroska->level_up) { - matroska->level_up--; - break; - } - } - - return res; } static int @@ -1667,8 +1602,6 @@ /* file index (if seekable, seek to Cues/Tags to parse it) */ case MATROSKA_ID_SEEKHEAD: { - if ((res = ebml_read_master(matroska, &id)) < 0) - break; res = matroska_parse_seekhead(matroska); break; } @@ -1705,6 +1638,7 @@ break; } } + matroska_execute_seekhead(matroska); /* Have we found a cluster? */ if (ebml_peek_id(matroska, NULL) == MATROSKA_ID_CLUSTER) {