aboutsummaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorLuca Barbato2012-09-17 01:58:32 +0200
committerLuca Barbato2012-09-19 20:34:14 +0200
commit2d0e7713f992c0d6f5bb9e5fb8112afba8b3e8b9 (patch)
tree5bcffeb45add73715ad33cec46c6165190f151e8 /libavformat
parent117d8c6d1f1c187ffc6098d9618457e00534e013 (diff)
matroskadec: split laces parsing
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/matroskadec.c197
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++) {