summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux_mkv.c116
1 files changed, 61 insertions, 55 deletions
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 5f41cdbab6..e2569cae0b 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -2047,9 +2047,36 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track,
}
}
-static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
- uint64_t block_duration, bool keyframe,
- bool simpleblock)
+struct block_info {
+ uint64_t length;
+ uint64_t duration;
+ bool simple, keyframe;
+ uint8_t *data;
+};
+
+static void reset_block(struct block_info *block)
+{
+ free(block->data);
+ *block = (struct block_info){0};
+ block->keyframe = true;
+}
+
+static int read_block(demuxer_t *demuxer, struct block_info *block)
+{
+ stream_t *s = demuxer->stream;
+
+ block->length = ebml_read_length(s, NULL);
+ if (block->length > 500000000)
+ return -1;
+ free(block->data);
+ block->data = malloc(block->length + AV_LZO_INPUT_PADDING);
+ demuxer->filepos = stream_tell(s);
+ if (stream_read(s, block->data, block->length) != (int) block->length)
+ return -1;
+ return 0;
+}
+
+static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
{
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
mkv_track_t *track = NULL;
@@ -2061,6 +2088,10 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
int i, num, tmp, use_this_block = 1;
double current_pts;
int16_t time;
+ uint8_t *block = block_info->data;
+ uint64_t length = block_info->length;
+ bool keyframe = block_info->keyframe;
+ uint64_t block_duration = block_info->duration;
/* first byte(s): track num */
num = ebml_read_vlen_uint(block, &tmp);
@@ -2071,7 +2102,7 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length,
length -= tmp + 2;
old_length = length;
flags = block[0];
- if (simpleblock)
+ if (block_info->simple)
keyframe = flags & 0x80;
if (demux_mkv_read_block_lacing(block, &length, &laces, &lace_size))
return 0;
@@ -2187,51 +2218,36 @@ 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;
+ struct block_info block = {0};
+ reset_block(&block);
while (1) {
while (stream_tell(s) < mkv_d->cluster_end) {
- uint64_t block_duration = 0, block_length = 0;
- bool keyframe = true;
- uint8_t *block = NULL;
+ reset_block(&block);
while (stream_tell(s) < mkv_d->blockgroup_end) {
switch (ebml_read_id(s, NULL)) {
case MATROSKA_ID_BLOCKDURATION:
- block_duration = ebml_read_uint(s, NULL);
- if (block_duration == EBML_UINT_INVALID) {
- free(block);
- return 0;
- }
- block_duration *= mkv_d->tc_scale;
+ block.duration = ebml_read_uint(s, NULL);
+ if (block.duration == EBML_UINT_INVALID)
+ goto find_next_cluster;
+ block.duration *= mkv_d->tc_scale;
break;
case MATROSKA_ID_BLOCK:
- block_length = ebml_read_length(s, NULL);
- free(block);
- if (block_length > 500000000)
- return 0;
- block = malloc(block_length + AV_LZO_INPUT_PADDING);
- demuxer->filepos = stream_tell(s);
- if (stream_read(s, block, block_length) !=
- (int) block_length) {
- free(block);
- return 0;
- }
+ if (read_block(demuxer, &block) < 0)
+ goto find_next_cluster;
break;
case MATROSKA_ID_REFERENCEBLOCK:;
int64_t num = ebml_read_int(s, NULL);
- if (num == EBML_INT_INVALID) {
- free(block);
- return 0;
- }
+ if (num == EBML_INT_INVALID)
+ goto find_next_cluster;
if (num)
- keyframe = false;
+ block.keyframe = false;
break;
case EBML_ID_INVALID:
- free(block);
- ebml_resync_cluster(s);
goto find_next_cluster;
default:
@@ -2241,13 +2257,12 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
}
}
- if (block) {
- int res = handle_block(demuxer, block, block_length,
- block_duration, keyframe, false);
- free(block);
+ if (block.data) {
+ int res = handle_block(demuxer, &block);
+ reset_block(&block);
if (res < 0)
- return 0;
- if (res)
+ goto find_next_cluster;
+ if (res > 0)
return 1;
}
@@ -2257,7 +2272,7 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
case MATROSKA_ID_TIMECODE:;
uint64_t num = ebml_read_uint(s, NULL);
if (num == EBML_UINT_INVALID)
- return 0;
+ goto find_next_cluster;
mkv_d->cluster_tc = num * mkv_d->tc_scale;
add_cluster_position(demuxer, mkv_d->cluster_start, num);
break;
@@ -2268,23 +2283,14 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
break;
case MATROSKA_ID_SIMPLEBLOCK:;
- int res;
- block_length = ebml_read_length(s, NULL);
- if (block_length > 500000000)
- return 0;
- block = malloc(block_length);
- demuxer->filepos = stream_tell(s);
- if (stream_read(s, block, block_length) !=
- (int) block_length) {
- free(block);
- return 0;
- }
- res = handle_block(demuxer, block, block_length,
- block_duration, false, true);
- free(block);
+ block.simple = true;
+ if (read_block(demuxer, &block) < 0)
+ goto find_next_cluster;
+ int res = handle_block(demuxer, &block);
+ reset_block(&block);
if (res < 0)
- return 0;
- else if (res)
+ goto find_next_cluster;
+ if (res > 0)
return 1;
break;
@@ -2293,7 +2299,6 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
goto next_cluster;
case EBML_ID_INVALID:
- ebml_resync_cluster(s);
goto find_next_cluster;
default: ;
@@ -2305,6 +2310,7 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
}
find_next_cluster:
+ reset_block(&block);
mkv_d->cluster_end = mkv_d->blockgroup_end = 0;
for (;;) {
mkv_d->cluster_start = stream_tell(s);