From c2bf06f63e6080503ff19db10ef892252e441156 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 11 Apr 2013 20:31:58 +0200 Subject: demux_mkv: simplify cluster reading code The end positions of the current cluster and block were managed by tracking their size and how much of them were read, instead of just using the absolute end positions. I'm not sure about the reasons why this code was originally written this way. One obvious concern is reading from pipes and such, but the stream layers hides this. stream_tell(s) works even when reading from pipes. It's also a fast call, and doesn't involve the stream implementation or syscalls. Keeping track of the cluster/block end is simpler and there's no reason why this wouldn't work. --- demux/demux_mkv.c | 56 ++++++++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 32 deletions(-) (limited to 'demux/demux_mkv.c') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 6dd84b20c9..77abbab85f 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -156,8 +156,8 @@ typedef struct mkv_demuxer { uint64_t tc_scale, cluster_tc; uint64_t cluster_start; - uint64_t cluster_size; - uint64_t blockgroup_size; + uint64_t cluster_end; + uint64_t blockgroup_end; mkv_index_t *indexes; int num_indexes; @@ -2187,19 +2187,17 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) { mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; stream_t *s = demuxer->stream; - uint64_t l; - int il, tmp; while (1) { - while (mkv_d->cluster_size > 0) { + while (stream_tell(s) < mkv_d->cluster_end) { uint64_t block_duration = 0, block_length = 0; bool keyframe = true; uint8_t *block = NULL; - while (mkv_d->blockgroup_size > 0) { - switch (ebml_read_id(s, &il)) { + while (stream_tell(s) < mkv_d->blockgroup_end) { + switch (ebml_read_id(s, NULL)) { case MATROSKA_ID_BLOCKDURATION: - block_duration = ebml_read_uint(s, &l); + block_duration = ebml_read_uint(s, NULL); if (block_duration == EBML_UINT_INVALID) { free(block); return 0; @@ -2208,7 +2206,7 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) break; case MATROSKA_ID_BLOCK: - block_length = ebml_read_length(s, &tmp); + block_length = ebml_read_length(s, NULL); free(block); if (block_length > 500000000) return 0; @@ -2219,11 +2217,10 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) free(block); return 0; } - l = tmp + block_length; break; case MATROSKA_ID_REFERENCEBLOCK:; - int64_t num = ebml_read_int(s, &l); + int64_t num = ebml_read_int(s, NULL); if (num == EBML_INT_INVALID) { free(block); return 0; @@ -2238,12 +2235,10 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) goto find_next_cluster; default: - if (ebml_read_skip_or_resync_cluster(s, &l) != 0) + if (ebml_read_skip_or_resync_cluster(s, NULL) != 0) goto find_next_cluster; break; } - mkv_d->blockgroup_size -= l + il; - mkv_d->cluster_size -= l + il; } if (block) { @@ -2256,10 +2251,10 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) return 1; } - if (mkv_d->cluster_size > 0) { - switch (ebml_read_id(s, &il)) { + if (stream_tell(s) < mkv_d->cluster_end) { + switch (ebml_read_id(s, NULL)) { case MATROSKA_ID_TIMECODE:; - uint64_t num = ebml_read_uint(s, &l); + uint64_t num = ebml_read_uint(s, NULL); if (num == EBML_UINT_INVALID) return 0; mkv_d->cluster_tc = num * mkv_d->tc_scale; @@ -2267,13 +2262,13 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) break; case MATROSKA_ID_BLOCKGROUP: - mkv_d->blockgroup_size = ebml_read_length(s, &tmp); - l = tmp; + mkv_d->blockgroup_end = ebml_read_length(s, NULL); + mkv_d->blockgroup_end += stream_tell(s); break; case MATROSKA_ID_SIMPLEBLOCK:; int res; - block_length = ebml_read_length(s, &tmp); + block_length = ebml_read_length(s, NULL); if (block_length > 500000000) return 0; block = malloc(block_length); @@ -2283,17 +2278,13 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) free(block); return 0; } - l = tmp + block_length; res = handle_block(demuxer, block, block_length, block_duration, false, true); free(block); - mkv_d->cluster_size -= l + il; if (res < 0) return 0; else if (res) return 1; - else - mkv_d->cluster_size += l + il; break; case EBML_ID_INVALID: @@ -2301,25 +2292,26 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) goto find_next_cluster; default: ; - if (ebml_read_skip_or_resync_cluster(s, &l) != 0) + if (ebml_read_skip_or_resync_cluster(s, NULL) != 0) goto find_next_cluster; break; } - mkv_d->cluster_size -= l + il; } } find_next_cluster: + mkv_d->cluster_end = mkv_d->blockgroup_end = 0; for (;;) { - uint32_t id = ebml_read_id(s, &il); + mkv_d->cluster_start = stream_tell(s); + uint32_t id = ebml_read_id(s, NULL); if (id == MATROSKA_ID_CLUSTER) break; if (s->eof) return 0; ebml_read_skip_or_resync_cluster(s, NULL); } - mkv_d->cluster_start = stream_tell(s) - il; - mkv_d->cluster_size = ebml_read_length(s, NULL); + mkv_d->cluster_end = ebml_read_length(s, NULL); + mkv_d->cluster_end += stream_tell(s); } return 0; @@ -2345,7 +2337,7 @@ static int create_index_until(struct demuxer *demuxer, uint64_t timecode) if ((int64_t) max_filepos > cur_filepos) stream_seek(s, max_filepos); else - stream_seek(s, cur_filepos + mkv_d->cluster_size); + stream_seek(s, mkv_d->cluster_end); mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] creating index until TC %" PRIu64 "\n", timecode); /* parse all the clusters upto target_filepos */ @@ -2430,7 +2422,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, seek_pos = prev_target; } - mkv_d->cluster_size = mkv_d->blockgroup_size = 0; + mkv_d->cluster_end = mkv_d->blockgroup_end = 0; stream_seek(demuxer->stream, seek_pos); } return index; @@ -2510,7 +2502,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, if (!index) return; - mkv_d->cluster_size = mkv_d->blockgroup_size = 0; + mkv_d->cluster_end = mkv_d->blockgroup_end = 0; stream_seek(s, index->filepos); if (demuxer->video->id >= 0) -- cgit v1.2.3