|
|
|
@ -1749,89 +1749,40 @@ static void matroska_clear_queue(MatroskaDemuxContext *matroska) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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, |
|
|
|
|
int64_t cluster_pos) |
|
|
|
|
static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, |
|
|
|
|
int size, int type, |
|
|
|
|
uint32_t **lace_buf, int *laces) |
|
|
|
|
{ |
|
|
|
|
uint64_t timecode = AV_NOPTS_VALUE; |
|
|
|
|
MatroskaTrack *track; |
|
|
|
|
int res = 0; |
|
|
|
|
AVStream *st; |
|
|
|
|
AVPacket *pkt; |
|
|
|
|
int16_t block_time; |
|
|
|
|
uint32_t *lace_size = NULL; |
|
|
|
|
int n, flags, laces = 0; |
|
|
|
|
uint64_t num; |
|
|
|
|
|
|
|
|
|
if ((n = matroska_ebmlnum_uint(matroska, data, size, &num)) < 0) { |
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, "EBML block data error\n"); |
|
|
|
|
return n; |
|
|
|
|
} |
|
|
|
|
data += n; |
|
|
|
|
size -= n; |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
track = matroska_find_track_by_num(matroska, num); |
|
|
|
|
if (!track || !track->stream) { |
|
|
|
|
av_log(matroska->ctx, AV_LOG_INFO, |
|
|
|
|
"Invalid stream %"PRIu64" or size %u\n", num, size); |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} else if (size <= 3) |
|
|
|
|
*lace_buf[0] = size; |
|
|
|
|
return 0; |
|
|
|
|
st = track->stream; |
|
|
|
|
if (st->discard >= AVDISCARD_ALL) |
|
|
|
|
return res; |
|
|
|
|
if (duration == AV_NOPTS_VALUE) |
|
|
|
|
duration = track->default_duration / matroska->time_scale; |
|
|
|
|
|
|
|
|
|
block_time = AV_RB16(data); |
|
|
|
|
data += 2; |
|
|
|
|
flags = *data++; |
|
|
|
|
size -= 3; |
|
|
|
|
if (is_keyframe == -1) |
|
|
|
|
is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0; |
|
|
|
|
|
|
|
|
|
if (cluster_time != (uint64_t)-1 |
|
|
|
|
&& (block_time >= 0 || cluster_time >= -block_time)) { |
|
|
|
|
timecode = cluster_time + block_time; |
|
|
|
|
if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE |
|
|
|
|
&& timecode < track->end_timecode) |
|
|
|
|
is_keyframe = 0; /* overlapping subtitles are not key frame */ |
|
|
|
|
if (is_keyframe) |
|
|
|
|
av_add_index_entry(st, cluster_pos, timecode, 0,0,AVINDEX_KEYFRAME); |
|
|
|
|
track->end_timecode = FFMAX(track->end_timecode, timecode+duration); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (matroska->skip_to_keyframe && track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { |
|
|
|
|
if (!is_keyframe || timecode < matroska->skip_to_timecode) |
|
|
|
|
return res; |
|
|
|
|
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; |
|
|
|
|
assert(size > 0); |
|
|
|
|
*laces = *data + 1; |
|
|
|
|
data += 1; |
|
|
|
|
size -= 1; |
|
|
|
|
lace_size = av_mallocz(laces * sizeof(int)); |
|
|
|
|
lace_size = av_mallocz(*laces * sizeof(int)); |
|
|
|
|
if (!lace_size) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
switch ((flags & 0x06) >> 1) { |
|
|
|
|
switch (type) { |
|
|
|
|
case 0x1: /* Xiph lacing */ { |
|
|
|
|
uint8_t temp; |
|
|
|
|
uint32_t total = 0; |
|
|
|
|
for (n = 0; res == 0 && n < laces - 1; n++) { |
|
|
|
|
for (n = 0; res == 0 && n < *laces - 1; n++) { |
|
|
|
|
while (1) { |
|
|
|
|
if (size == 0) { |
|
|
|
|
res = -1; |
|
|
|
|
res = AVERROR_EOF; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
temp = *data; |
|
|
|
@ -1845,34 +1796,36 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, |
|
|
|
|
} |
|
|
|
|
if (size <= total) { |
|
|
|
|
res = AVERROR_INVALIDDATA; |
|
|
|
|
goto end; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
lace_size[n] = size - total; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case 0x2: /* fixed-size lacing */ |
|
|
|
|
if (size != (size / laces) * size) { |
|
|
|
|
if (size != (size / *laces) * size) { |
|
|
|
|
res = AVERROR_INVALIDDATA; |
|
|
|
|
goto end; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
for (n = 0; n < laces; n++) |
|
|
|
|
lace_size[n] = size / laces; |
|
|
|
|
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; |
|
|
|
|
goto end; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
data += n; |
|
|
|
|
size -= n; |
|
|
|
|
total = lace_size[0] = num; |
|
|
|
|
for (n = 1; res == 0 && n < laces - 1; n++) { |
|
|
|
|
for (n = 1; res == 0 && n < *laces - 1; n++) { |
|
|
|
|
int64_t snum; |
|
|
|
|
int r; |
|
|
|
|
r = matroska_ebmlnum_sint(matroska, data, size, &snum); |
|
|
|
@ -1880,7 +1833,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, |
|
|
|
|
av_log(matroska->ctx, AV_LOG_INFO, |
|
|
|
|
"EBML block data error\n"); |
|
|
|
|
res = r; |
|
|
|
|
goto end; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
data += r; |
|
|
|
|
size -= r; |
|
|
|
@ -1889,14 +1842,80 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, |
|
|
|
|
} |
|
|
|
|
if (size <= total) { |
|
|
|
|
res = AVERROR_INVALIDDATA; |
|
|
|
|
goto end; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
lace_size[laces - 1] = size - total; |
|
|
|
|
lace_size[*laces - 1] = size - total; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
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, |
|
|
|
|
int64_t cluster_pos) |
|
|
|
|
{ |
|
|
|
|
uint64_t timecode = AV_NOPTS_VALUE; |
|
|
|
|
MatroskaTrack *track; |
|
|
|
|
int res = 0; |
|
|
|
|
AVStream *st; |
|
|
|
|
AVPacket *pkt; |
|
|
|
|
int16_t block_time; |
|
|
|
|
uint32_t *lace_size = NULL; |
|
|
|
|
int n, flags, laces = 0; |
|
|
|
|
uint64_t num; |
|
|
|
|
|
|
|
|
|
if ((n = matroska_ebmlnum_uint(matroska, data, size, &num)) < 0) { |
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, "EBML block data error\n"); |
|
|
|
|
return n; |
|
|
|
|
} |
|
|
|
|
data += n; |
|
|
|
|
size -= n; |
|
|
|
|
|
|
|
|
|
track = matroska_find_track_by_num(matroska, num); |
|
|
|
|
if (!track || !track->stream) { |
|
|
|
|
av_log(matroska->ctx, AV_LOG_INFO, |
|
|
|
|
"Invalid stream %"PRIu64" or size %u\n", num, size); |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} else if (size <= 3) |
|
|
|
|
return 0; |
|
|
|
|
st = track->stream; |
|
|
|
|
if (st->discard >= AVDISCARD_ALL) |
|
|
|
|
return res; |
|
|
|
|
if (duration == AV_NOPTS_VALUE) |
|
|
|
|
duration = track->default_duration / matroska->time_scale; |
|
|
|
|
|
|
|
|
|
block_time = AV_RB16(data); |
|
|
|
|
data += 2; |
|
|
|
|
flags = *data++; |
|
|
|
|
size -= 3; |
|
|
|
|
if (is_keyframe == -1) |
|
|
|
|
is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0; |
|
|
|
|
|
|
|
|
|
if (cluster_time != (uint64_t)-1 |
|
|
|
|
&& (block_time >= 0 || cluster_time >= -block_time)) { |
|
|
|
|
timecode = cluster_time + block_time; |
|
|
|
|
if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE |
|
|
|
|
&& timecode < track->end_timecode) |
|
|
|
|
is_keyframe = 0; /* overlapping subtitles are not key frame */ |
|
|
|
|
if (is_keyframe) |
|
|
|
|
av_add_index_entry(st, cluster_pos, timecode, 0,0,AVINDEX_KEYFRAME); |
|
|
|
|
track->end_timecode = FFMAX(track->end_timecode, timecode+duration); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (matroska->skip_to_keyframe && track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { |
|
|
|
|
if (!is_keyframe || timecode < matroska->skip_to_timecode) |
|
|
|
|
return res; |
|
|
|
|
matroska->skip_to_keyframe = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1, |
|
|
|
|
&lace_size, &laces); |
|
|
|
|
|
|
|
|
|
if (res == 0) { |
|
|
|
|
for (n = 0; n < laces; n++) { |
|
|
|
|