From e5929fdf62a6e96d8f258a4040160f4a841a58c7 Mon Sep 17 00:00:00 2001 From: Aurelien Jacobs Date: Tue, 5 Aug 2008 00:40:15 +0000 Subject: [PATCH] matroskadec: use generic parser to parse index Originally committed as revision 14557 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/matroskadec.c | 223 ++++++++------------------------------ 1 file changed, 47 insertions(+), 176 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 9555c41273..b3f8b6d77a 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -158,17 +158,21 @@ typedef struct MatroskaSubtitleTrack { sizeof(MatroskaAudioTrack), \ sizeof(MatroskaSubtitleTrack))) +typedef struct { + uint64_t track; + uint64_t pos; +} MatroskaIndexPos; + +typedef struct { + uint64_t time; + EbmlList pos; +} MatroskaIndex; + typedef struct MatroskaLevel { uint64_t start; uint64_t length; } MatroskaLevel; -typedef struct MatroskaDemuxIndex { - uint64_t pos; /* of the corresponding *cluster*! */ - uint16_t track; /* reference to 'num' */ - uint64_t time; /* in nanoseconds */ -} MatroskaDemuxIndex; - typedef struct MatroskaDemuxContext { AVFormatContext *ctx; @@ -179,6 +183,7 @@ typedef struct MatroskaDemuxContext { /* timescale in the file */ int64_t time_scale; + EbmlList index; /* num_streams is the number of streams that av_new_stream() was called * for ( = that are available to the calling program). */ @@ -201,10 +206,6 @@ typedef struct MatroskaDemuxContext { int index_parsed; int done; - /* The index for seeking. */ - int num_indexes; - MatroskaDemuxIndex *index; - /* What to skip before effectively reading a packet. */ int skip_to_keyframe; AVStream *skip_to_stream; @@ -229,6 +230,26 @@ static EbmlSyntax ebml_syntax[] = { { 0 } }; +static EbmlSyntax matroska_index_pos[] = { + { MATROSKA_ID_CUETRACK, EBML_UINT, 0, offsetof(MatroskaIndexPos,track) }, + { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, offsetof(MatroskaIndexPos,pos) }, + { EBML_ID_VOID, EBML_NONE }, + { 0 } +}; + +static EbmlSyntax matroska_index_entry[] = { + { MATROSKA_ID_CUETIME, EBML_UINT, 0, offsetof(MatroskaIndex,time) }, + { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex,pos), {.n=matroska_index_pos} }, + { EBML_ID_VOID, EBML_NONE }, + { 0 } +}; + +static EbmlSyntax matroska_index[] = { + { MATROSKA_ID_POINTENTRY, EBML_NEST, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext,index), {.n=matroska_index_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 @@ -1731,159 +1752,7 @@ matroska_parse_tracks (MatroskaDemuxContext *matroska) static int matroska_parse_index (MatroskaDemuxContext *matroska) { - int res = 0; - uint32_t id; - MatroskaDemuxIndex idx; - - av_log(matroska->ctx, AV_LOG_DEBUG, "parsing index...\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) { - /* one single index entry ('point') */ - case MATROSKA_ID_POINTENTRY: - if ((res = ebml_read_master(matroska, &id)) < 0) - break; - - /* in the end, we hope to fill one entry with a - * timestamp, a file position and a tracknum */ - idx.pos = (uint64_t) -1; - idx.time = (uint64_t) -1; - idx.track = (uint16_t) -1; - - 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) { - /* one single index entry ('point') */ - case MATROSKA_ID_CUETIME: { - uint64_t time; - if ((res = ebml_read_uint(matroska, &id, - &time)) < 0) - break; - idx.time = time * matroska->time_scale; - break; - } - - /* position in the file + track to which it - * belongs */ - case MATROSKA_ID_CUETRACKPOSITION: - 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) { - /* track number */ - case MATROSKA_ID_CUETRACK: { - uint64_t num; - if ((res = ebml_read_uint(matroska, - &id, &num)) < 0) - break; - idx.track = num; - break; - } - - /* position in file */ - case MATROSKA_ID_CUECLUSTERPOSITION: { - uint64_t num; - if ((res = ebml_read_uint(matroska, - &id, &num)) < 0) - break; - idx.pos = num+matroska->segment_start; - break; - } - - default: - av_log(matroska->ctx, AV_LOG_INFO, - "Unknown entry 0x%x in " - "CuesTrackPositions\n", id); - /* fall-through */ - - case EBML_ID_VOID: - res = ebml_read_skip(matroska); - break; - } - - if (matroska->level_up) { - matroska->level_up--; - break; - } - } - - break; - - default: - av_log(matroska->ctx, AV_LOG_INFO, - "Unknown entry 0x%x in cuespoint " - "index\n", id); - /* fall-through */ - - case EBML_ID_VOID: - res = ebml_read_skip(matroska); - break; - } - - if (matroska->level_up) { - matroska->level_up--; - break; - } - } - - /* so let's see if we got what we wanted */ - if (idx.pos != (uint64_t) -1 && - idx.time != (uint64_t) -1 && - idx.track != (uint16_t) -1) { - if (matroska->num_indexes % 32 == 0) { - /* re-allocate bigger index */ - matroska->index = - av_realloc(matroska->index, - (matroska->num_indexes + 32) * - sizeof(MatroskaDemuxIndex)); - } - matroska->index[matroska->num_indexes] = idx; - matroska->num_indexes++; - } - break; - - default: - av_log(matroska->ctx, AV_LOG_INFO, - "Unknown entry 0x%x in cues header\n", id); - /* fall-through */ - - case EBML_ID_VOID: - res = ebml_read_skip(matroska); - break; - } - - if (matroska->level_up) { - matroska->level_up--; - break; - } - } - - return res; + return ebml_parse(matroska, matroska_index, matroska, MATROSKA_ID_CUES, 0); } static int @@ -2036,8 +1905,6 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) } /* read master + parse */ - if ((res = ebml_read_master(matroska, &id)) < 0) - goto finish; switch (id) { case MATROSKA_ID_CUES: if (!(res = matroska_parse_index(matroska)) || @@ -2047,6 +1914,8 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska) } break; case MATROSKA_ID_TAGS: + if ((res = ebml_read_master(matroska, &id)) < 0) + goto finish; if (!(res = matroska_parse_metadata(matroska)) || url_feof(matroska->ctx->pb)) { matroska->metadata_parsed = 1; @@ -2403,7 +2272,9 @@ matroska_read_header (AVFormatContext *s, AVFormatParameters *ap) { MatroskaDemuxContext *matroska = s->priv_data; - int last_level, res = 0; + EbmlList *index_list; + MatroskaIndex *index; + int i, j, last_level, res = 0; Ebml ebml = { 0 }; uint32_t id; @@ -2475,8 +2346,6 @@ matroska_read_header (AVFormatContext *s, /* stream index */ case MATROSKA_ID_CUES: { if (!matroska->index_parsed) { - if ((res = ebml_read_master(matroska, &id)) < 0) - break; res = matroska_parse_index(matroska); } else res = ebml_read_skip(matroska); @@ -2745,15 +2614,18 @@ matroska_read_header (AVFormatContext *s, res = 0; } - if (matroska->index_parsed) { - int i; - for (i=0; inum_indexes; i++) { - MatroskaDemuxIndex *idx = &matroska->index[i]; + index_list = &matroska->index; + index = index_list->elem; + for (i=0; inb_elem; i++) { + EbmlList *pos_list = &index[i].pos; + MatroskaIndexPos *pos = pos_list->elem; + for (j=0; jnb_elem; j++) { MatroskaTrack *track = matroska_find_track_by_num(matroska, - idx->track); + pos[j].track); if (track && track->stream) av_add_index_entry(track->stream, - idx->pos, idx->time/AV_TIME_BASE, + pos[j].pos + matroska->segment_start, + index[i].time*matroska->time_scale/AV_TIME_BASE, 0, 0, AVINDEX_KEYFRAME); } } @@ -3209,8 +3081,6 @@ matroska_read_close (AVFormatContext *s) MatroskaDemuxContext *matroska = s->priv_data; int n = 0; - av_free(matroska->index); - matroska_clear_queue(matroska); for (n = 0; n < matroska->num_tracks; n++) { @@ -3226,6 +3096,7 @@ matroska_read_close (AVFormatContext *s) av_free(track); } + ebml_free(matroska_index, matroska); return 0; }