diff options
author | Luca Barbato | 2012-09-17 01:58:32 +0200 |
---|---|---|
committer | Luca Barbato | 2012-09-19 20:34:14 +0200 |
commit | 2d0e7713f992c0d6f5bb9e5fb8112afba8b3e8b9 (patch) | |
tree | 5bcffeb45add73715ad33cec46c6165190f151e8 /libavformat | |
parent | 117d8c6d1f1c187ffc6098d9618457e00534e013 (diff) |
matroskadec: split laces parsing
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/matroskadec.c | 197 |
1 files changed, 108 insertions, 89 deletions
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index c00ebaac8e..2de1d48334 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1749,6 +1749,112 @@ static void matroska_clear_queue(MatroskaDemuxContext *matroska) } } +static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, + int size, int type, + uint32_t **lace_buf, int *laces) +{ + int res = 0, n; + uint8_t *data = *buf; + uint32_t *lace_size; + + if (!type) { + *laces = 1; + *lace_buf = av_mallocz(sizeof(int)); + if (!*lace_buf) + return AVERROR(ENOMEM); + + *lace_buf[0] = size; + return 0; + } + + assert(size > 0); + *laces = *data + 1; + data += 1; + size -= 1; + lace_size = av_mallocz(*laces * sizeof(int)); + if (!lace_size) + return AVERROR(ENOMEM); + + switch (type) { + case 0x1: /* Xiph lacing */ { + uint8_t temp; + uint32_t total = 0; + for (n = 0; res == 0 && n < *laces - 1; n++) { + while (1) { + if (size == 0) { + res = AVERROR_EOF; + break; + } + temp = *data; + lace_size[n] += temp; + data += 1; + size -= 1; + if (temp != 0xff) + break; + } + total += lace_size[n]; + } + if (size <= total) { + res = AVERROR_INVALIDDATA; + break; + } + + lace_size[n] = size - total; + break; + } + + case 0x2: /* fixed-size lacing */ + if (size != (size / *laces) * size) { + res = AVERROR_INVALIDDATA; + break; + } + for (n = 0; n < *laces; n++) + lace_size[n] = size / *laces; + break; + + case 0x3: /* EBML lacing */ { + uint64_t num; + uint32_t total; + n = matroska_ebmlnum_uint(matroska, data, size, &num); + if (n < 0) { + av_log(matroska->ctx, AV_LOG_INFO, + "EBML block data error\n"); + res = n; + break; + } + data += n; + size -= n; + total = lace_size[0] = num; + for (n = 1; res == 0 && n < *laces - 1; n++) { + int64_t snum; + int r; + r = matroska_ebmlnum_sint(matroska, data, size, &snum); + if (r < 0) { + av_log(matroska->ctx, AV_LOG_INFO, + "EBML block data error\n"); + res = r; + break; + } + data += r; + size -= r; + lace_size[n] = lace_size[n - 1] + snum; + total += lace_size[n]; + } + if (size <= total) { + res = AVERROR_INVALIDDATA; + break; + } + lace_size[*laces - 1] = size - total; + break; + } + } + + *buf = data; + *lace_buf = lace_size; + + return res; +} + static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size, int64_t pos, uint64_t cluster_time, uint64_t duration, int is_keyframe, @@ -1808,95 +1914,8 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, matroska->skip_to_keyframe = 0; } - switch ((flags & 0x06) >> 1) { - case 0x0: /* no lacing */ - laces = 1; - lace_size = av_mallocz(sizeof(int)); - lace_size[0] = size; - break; - - case 0x1: /* Xiph lacing */ - case 0x2: /* fixed-size lacing */ - case 0x3: /* EBML lacing */ - assert(size>0); // size <=3 is checked before size-=3 above - laces = (*data) + 1; - data += 1; - size -= 1; - lace_size = av_mallocz(laces * sizeof(int)); - - switch ((flags & 0x06) >> 1) { - case 0x1: /* Xiph lacing */ { - uint8_t temp; - uint32_t total = 0; - for (n = 0; res == 0 && n < laces - 1; n++) { - while (1) { - if (size == 0) { - res = -1; - break; - } - temp = *data; - lace_size[n] += temp; - data += 1; - size -= 1; - if (temp != 0xff) - break; - } - total += lace_size[n]; - } - if (size <= total) { - res = AVERROR_INVALIDDATA; - goto end; - } - lace_size[n] = size - total; - break; - } - - case 0x2: /* fixed-size lacing */ - if (size != (size / laces) * size) { - res = AVERROR_INVALIDDATA; - goto end; - } - for (n = 0; n < laces; n++) - lace_size[n] = size / laces; - break; - - case 0x3: /* EBML lacing */ { - uint32_t total; - n = matroska_ebmlnum_uint(matroska, data, size, &num); - if (n < 0) { - av_log(matroska->ctx, AV_LOG_INFO, - "EBML block data error\n"); - res = n; - goto end; - } - data += n; - size -= n; - total = lace_size[0] = num; - for (n = 1; res == 0 && n < laces - 1; n++) { - int64_t snum; - int r; - r = matroska_ebmlnum_sint(matroska, data, size, &snum); - if (r < 0) { - av_log(matroska->ctx, AV_LOG_INFO, - "EBML block data error\n"); - res = r; - goto end; - } - data += r; - size -= r; - lace_size[n] = lace_size[n - 1] + snum; - total += lace_size[n]; - } - if (size <= total) { - res = AVERROR_INVALIDDATA; - goto end; - } - lace_size[laces - 1] = size - total; - break; - } - } - break; - } + res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1, + &lace_size, &laces); if (res == 0) { for (n = 0; n < laces; n++) { |