Commit 7087fc95 authored by Andreas Rheinhardt's avatar Andreas Rheinhardt Committed by James Almer

avformat/matroskadec: Reuse positions

Up until now, avio_tell was used multiple times in ebml_parse and its
subroutines, although the result of these calls can usually be simply
derived from the result of earlier calls to avio_tell. This has been
changed. Unnecessary calls to avio_tell in ebml_parse are avoided now.

Furthermore, there has been a slight change in the output of some error
messages relating to elements exceeding their containing master element:
The reported position of the element now points to the first byte of the
element ID and no longer to the first byte of the element's payload.
Signed-off-by: 's avatarAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
parent 3ed2755b
...@@ -976,7 +976,8 @@ static int ebml_read_ascii(AVIOContext *pb, int size, char **str) ...@@ -976,7 +976,8 @@ static int ebml_read_ascii(AVIOContext *pb, int size, char **str)
* Read the next element as binary data. * Read the next element as binary data.
* 0 is success, < 0 or NEEDS_CHECKING is failure. * 0 is success, < 0 or NEEDS_CHECKING is failure.
*/ */
static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin) static int ebml_read_binary(AVIOContext *pb, int length,
int64_t pos, EbmlBin *bin)
{ {
int ret; int ret;
...@@ -987,7 +988,7 @@ static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin) ...@@ -987,7 +988,7 @@ static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin)
bin->data = bin->buf->data; bin->data = bin->buf->data;
bin->size = length; bin->size = length;
bin->pos = avio_tell(pb); bin->pos = pos;
if ((ret = avio_read(pb, bin->data, length)) != length) { if ((ret = avio_read(pb, bin->data, length)) != length) {
av_buffer_unref(&bin->buf); av_buffer_unref(&bin->buf);
bin->data = NULL; bin->data = NULL;
...@@ -1003,9 +1004,9 @@ static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin) ...@@ -1003,9 +1004,9 @@ static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin)
* are supposed to be sub-elements which can be read separately. * are supposed to be sub-elements which can be read separately.
* 0 is success, < 0 is failure. * 0 is success, < 0 is failure.
*/ */
static int ebml_read_master(MatroskaDemuxContext *matroska, uint64_t length) static int ebml_read_master(MatroskaDemuxContext *matroska,
uint64_t length, int64_t pos)
{ {
AVIOContext *pb = matroska->ctx->pb;
MatroskaLevel *level; MatroskaLevel *level;
if (matroska->num_levels >= EBML_MAX_DEPTH) { if (matroska->num_levels >= EBML_MAX_DEPTH) {
...@@ -1015,7 +1016,7 @@ static int ebml_read_master(MatroskaDemuxContext *matroska, uint64_t length) ...@@ -1015,7 +1016,7 @@ static int ebml_read_master(MatroskaDemuxContext *matroska, uint64_t length)
} }
level = &matroska->levels[matroska->num_levels++]; level = &matroska->levels[matroska->num_levels++];
level->start = avio_tell(pb); level->start = pos;
level->length = length; level->length = length;
return 0; return 0;
...@@ -1173,7 +1174,7 @@ static int ebml_parse(MatroskaDemuxContext *matroska, ...@@ -1173,7 +1174,7 @@ static int ebml_parse(MatroskaDemuxContext *matroska,
AVIOContext *pb = matroska->ctx->pb; AVIOContext *pb = matroska->ctx->pb;
uint32_t id; uint32_t id;
uint64_t length; uint64_t length;
int64_t pos = avio_tell(pb); int64_t pos = avio_tell(pb), pos_alt;
int res, update_pos = 1, level_check; int res, update_pos = 1, level_check;
void *newelem; void *newelem;
MatroskaLevel1Element *level1_elem; MatroskaLevel1Element *level1_elem;
...@@ -1201,8 +1202,11 @@ static int ebml_parse(MatroskaDemuxContext *matroska, ...@@ -1201,8 +1202,11 @@ static int ebml_parse(MatroskaDemuxContext *matroska,
return res; return res;
} }
matroska->current_id = id | 1 << 7 * res; matroska->current_id = id | 1 << 7 * res;
} else pos_alt = pos + res;
pos -= (av_log2(matroska->current_id) + 7) / 8; } else {
pos_alt = pos;
pos -= (av_log2(matroska->current_id) + 7) / 8;
}
id = matroska->current_id; id = matroska->current_id;
...@@ -1247,14 +1251,15 @@ static int ebml_parse(MatroskaDemuxContext *matroska, ...@@ -1247,14 +1251,15 @@ static int ebml_parse(MatroskaDemuxContext *matroska,
length, max_lengths[syntax->type], syntax->type); length, max_lengths[syntax->type], syntax->type);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
pos_alt += res;
if (matroska->num_levels > 0) { if (matroska->num_levels > 0) {
MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1]; MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1];
AVIOContext *pb = matroska->ctx->pb;
int64_t pos = avio_tell(pb);
if (length != EBML_UNKNOWN_LENGTH && if (length != EBML_UNKNOWN_LENGTH &&
level->length != EBML_UNKNOWN_LENGTH) { level->length != EBML_UNKNOWN_LENGTH) {
uint64_t elem_end = pos + length, uint64_t elem_end = pos_alt + length,
level_end = level->start + level->length; level_end = level->start + level->length;
if (elem_end < level_end) { if (elem_end < level_end) {
...@@ -1309,14 +1314,14 @@ static int ebml_parse(MatroskaDemuxContext *matroska, ...@@ -1309,14 +1314,14 @@ static int ebml_parse(MatroskaDemuxContext *matroska,
res = ebml_read_ascii(pb, length, data); res = ebml_read_ascii(pb, length, data);
break; break;
case EBML_BIN: case EBML_BIN:
res = ebml_read_binary(pb, length, data); res = ebml_read_binary(pb, length, pos_alt, data);
break; break;
case EBML_LEVEL1: case EBML_LEVEL1:
case EBML_NEST: case EBML_NEST:
if ((res = ebml_read_master(matroska, length)) < 0) if ((res = ebml_read_master(matroska, length, pos_alt)) < 0)
return res; return res;
if (id == MATROSKA_ID_SEGMENT) if (id == MATROSKA_ID_SEGMENT)
matroska->segment_start = avio_tell(matroska->ctx->pb); matroska->segment_start = pos_alt;
if (id == MATROSKA_ID_CUES) if (id == MATROSKA_ID_CUES)
matroska->cues_parsing_deferred = 0; matroska->cues_parsing_deferred = 0;
if (syntax->type == EBML_LEVEL1 && if (syntax->type == EBML_LEVEL1 &&
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment