matroskadec: split laces parsing

This commit is contained in:
Luca Barbato 2012-09-17 01:58:32 +02:00
parent 117d8c6d1f
commit 2d0e7713f9

View File

@ -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++) {