matroskadec: split frame parsing
This commit is contained in:
parent
2d0e7713f9
commit
c831ebf616
@ -1855,6 +1855,141 @@ static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
|
||||||
|
MatroskaTrack *track,
|
||||||
|
AVStream *st,
|
||||||
|
uint8_t *data, int size,
|
||||||
|
uint64_t timecode, uint64_t duration,
|
||||||
|
int64_t pos)
|
||||||
|
{
|
||||||
|
int a = st->codec->block_align;
|
||||||
|
int sps = track->audio.sub_packet_size;
|
||||||
|
int cfs = track->audio.coded_framesize;
|
||||||
|
int h = track->audio.sub_packet_h;
|
||||||
|
int y = track->audio.sub_packet_cnt;
|
||||||
|
int w = track->audio.frame_size;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
if (!track->audio.pkt_cnt) {
|
||||||
|
if (track->audio.sub_packet_cnt == 0)
|
||||||
|
track->audio.buf_timecode = timecode;
|
||||||
|
if (st->codec->codec_id == AV_CODEC_ID_RA_288) {
|
||||||
|
if (size < cfs * h / 2) {
|
||||||
|
av_log(matroska->ctx, AV_LOG_ERROR,
|
||||||
|
"Corrupt int4 RM-style audio packet size\n");
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
for (x=0; x<h/2; x++)
|
||||||
|
memcpy(track->audio.buf+x*2*w+y*cfs,
|
||||||
|
data+x*cfs, cfs);
|
||||||
|
} else if (st->codec->codec_id == AV_CODEC_ID_SIPR) {
|
||||||
|
if (size < w) {
|
||||||
|
av_log(matroska->ctx, AV_LOG_ERROR,
|
||||||
|
"Corrupt sipr RM-style audio packet size\n");
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
memcpy(track->audio.buf + y*w, data, w);
|
||||||
|
} else {
|
||||||
|
if (size < sps * w / sps) {
|
||||||
|
av_log(matroska->ctx, AV_LOG_ERROR,
|
||||||
|
"Corrupt generic RM-style audio packet size\n");
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
for (x=0; x<w/sps; x++)
|
||||||
|
memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++track->audio.sub_packet_cnt >= h) {
|
||||||
|
if (st->codec->codec_id == AV_CODEC_ID_SIPR)
|
||||||
|
ff_rm_reorder_sipr_data(track->audio.buf, h, w);
|
||||||
|
track->audio.sub_packet_cnt = 0;
|
||||||
|
track->audio.pkt_cnt = h*w / a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (track->audio.pkt_cnt) {
|
||||||
|
AVPacket *pkt = av_mallocz(sizeof(AVPacket));
|
||||||
|
av_new_packet(pkt, a);
|
||||||
|
memcpy(pkt->data, track->audio.buf
|
||||||
|
+ a * (h*w / a - track->audio.pkt_cnt--), a);
|
||||||
|
pkt->pts = track->audio.buf_timecode;
|
||||||
|
track->audio.buf_timecode = AV_NOPTS_VALUE;
|
||||||
|
pkt->pos = pos;
|
||||||
|
pkt->stream_index = st->index;
|
||||||
|
dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int matroska_parse_frame(MatroskaDemuxContext *matroska,
|
||||||
|
MatroskaTrack *track,
|
||||||
|
AVStream *st,
|
||||||
|
uint8_t *data, int pkt_size,
|
||||||
|
uint64_t timecode, uint64_t duration,
|
||||||
|
int64_t pos, int is_keyframe)
|
||||||
|
{
|
||||||
|
MatroskaTrackEncoding *encodings = track->encodings.elem;
|
||||||
|
uint8_t *pkt_data = data;
|
||||||
|
int offset = 0, res;
|
||||||
|
AVPacket *pkt;
|
||||||
|
|
||||||
|
if (encodings && encodings->scope & 1) {
|
||||||
|
res = matroska_decode_buffer(&pkt_data, &pkt_size, track);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st->codec->codec_id == AV_CODEC_ID_PRORES)
|
||||||
|
offset = 8;
|
||||||
|
|
||||||
|
pkt = av_mallocz(sizeof(AVPacket));
|
||||||
|
/* XXX: prevent data copy... */
|
||||||
|
if (av_new_packet(pkt, pkt_size + offset) < 0) {
|
||||||
|
av_free(pkt);
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st->codec->codec_id == AV_CODEC_ID_PRORES) {
|
||||||
|
uint8_t *buf = pkt->data;
|
||||||
|
bytestream_put_be32(&buf, pkt_size);
|
||||||
|
bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f'));
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pkt->data + offset, pkt_data, pkt_size);
|
||||||
|
|
||||||
|
if (pkt_data != data)
|
||||||
|
av_free(pkt_data);
|
||||||
|
|
||||||
|
pkt->flags = is_keyframe;
|
||||||
|
pkt->stream_index = st->index;
|
||||||
|
|
||||||
|
if (track->ms_compat)
|
||||||
|
pkt->dts = timecode;
|
||||||
|
else
|
||||||
|
pkt->pts = timecode;
|
||||||
|
pkt->pos = pos;
|
||||||
|
if (st->codec->codec_id == AV_CODEC_ID_TEXT)
|
||||||
|
pkt->convergence_duration = duration;
|
||||||
|
else if (track->type != MATROSKA_TRACK_TYPE_SUBTITLE)
|
||||||
|
pkt->duration = duration;
|
||||||
|
|
||||||
|
if (st->codec->codec_id == AV_CODEC_ID_SSA)
|
||||||
|
matroska_fix_ass_packet(matroska, pkt, duration);
|
||||||
|
|
||||||
|
if (matroska->prev_pkt &&
|
||||||
|
timecode != AV_NOPTS_VALUE &&
|
||||||
|
matroska->prev_pkt->pts == timecode &&
|
||||||
|
matroska->prev_pkt->stream_index == st->index &&
|
||||||
|
st->codec->codec_id == AV_CODEC_ID_SSA)
|
||||||
|
matroska_merge_packets(matroska->prev_pkt, pkt);
|
||||||
|
else {
|
||||||
|
dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
|
||||||
|
matroska->prev_pkt = pkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
|
static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
|
||||||
int size, int64_t pos, uint64_t cluster_time,
|
int size, int64_t pos, uint64_t cluster_time,
|
||||||
uint64_t duration, int is_keyframe,
|
uint64_t duration, int is_keyframe,
|
||||||
@ -1864,7 +1999,6 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
|
|||||||
MatroskaTrack *track;
|
MatroskaTrack *track;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
AVPacket *pkt;
|
|
||||||
int16_t block_time;
|
int16_t block_time;
|
||||||
uint32_t *lace_size = NULL;
|
uint32_t *lace_size = NULL;
|
||||||
int n, flags, laces = 0;
|
int n, flags, laces = 0;
|
||||||
@ -1917,139 +2051,33 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
|
|||||||
res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1,
|
res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1,
|
||||||
&lace_size, &laces);
|
&lace_size, &laces);
|
||||||
|
|
||||||
if (res == 0) {
|
if (res)
|
||||||
for (n = 0; n < laces; n++) {
|
goto end;
|
||||||
if ((st->codec->codec_id == AV_CODEC_ID_RA_288 ||
|
|
||||||
st->codec->codec_id == AV_CODEC_ID_COOK ||
|
|
||||||
st->codec->codec_id == AV_CODEC_ID_SIPR ||
|
|
||||||
st->codec->codec_id == AV_CODEC_ID_ATRAC3) &&
|
|
||||||
st->codec->block_align && track->audio.sub_packet_size) {
|
|
||||||
int a = st->codec->block_align;
|
|
||||||
int sps = track->audio.sub_packet_size;
|
|
||||||
int cfs = track->audio.coded_framesize;
|
|
||||||
int h = track->audio.sub_packet_h;
|
|
||||||
int y = track->audio.sub_packet_cnt;
|
|
||||||
int w = track->audio.frame_size;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
if (!track->audio.pkt_cnt) {
|
for (n = 0; n < laces; n++) {
|
||||||
if (track->audio.sub_packet_cnt == 0)
|
if ((st->codec->codec_id == AV_CODEC_ID_RA_288 ||
|
||||||
track->audio.buf_timecode = timecode;
|
st->codec->codec_id == AV_CODEC_ID_COOK ||
|
||||||
if (st->codec->codec_id == AV_CODEC_ID_RA_288) {
|
st->codec->codec_id == AV_CODEC_ID_SIPR ||
|
||||||
if (size < cfs * h / 2) {
|
st->codec->codec_id == AV_CODEC_ID_ATRAC3) &&
|
||||||
av_log(matroska->ctx, AV_LOG_ERROR,
|
st->codec->block_align && track->audio.sub_packet_size) {
|
||||||
"Corrupt int4 RM-style audio packet size\n");
|
|
||||||
res = AVERROR_INVALIDDATA;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
for (x=0; x<h/2; x++)
|
|
||||||
memcpy(track->audio.buf+x*2*w+y*cfs,
|
|
||||||
data+x*cfs, cfs);
|
|
||||||
} else if (st->codec->codec_id == AV_CODEC_ID_SIPR) {
|
|
||||||
if (size < w) {
|
|
||||||
av_log(matroska->ctx, AV_LOG_ERROR,
|
|
||||||
"Corrupt sipr RM-style audio packet size\n");
|
|
||||||
res = AVERROR_INVALIDDATA;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
memcpy(track->audio.buf + y*w, data, w);
|
|
||||||
} else {
|
|
||||||
if (size < sps * w / sps) {
|
|
||||||
av_log(matroska->ctx, AV_LOG_ERROR,
|
|
||||||
"Corrupt generic RM-style audio packet size\n");
|
|
||||||
res = AVERROR_INVALIDDATA;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
for (x=0; x<w/sps; x++)
|
|
||||||
memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++track->audio.sub_packet_cnt >= h) {
|
res = matroska_parse_rm_audio(matroska, track, st, data, size,
|
||||||
if (st->codec->codec_id == AV_CODEC_ID_SIPR)
|
timecode, duration, pos);
|
||||||
ff_rm_reorder_sipr_data(track->audio.buf, h, w);
|
if (res)
|
||||||
track->audio.sub_packet_cnt = 0;
|
goto end;
|
||||||
track->audio.pkt_cnt = h*w / a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (track->audio.pkt_cnt) {
|
|
||||||
pkt = av_mallocz(sizeof(AVPacket));
|
|
||||||
av_new_packet(pkt, a);
|
|
||||||
memcpy(pkt->data, track->audio.buf
|
|
||||||
+ a * (h*w / a - track->audio.pkt_cnt--), a);
|
|
||||||
pkt->pts = track->audio.buf_timecode;
|
|
||||||
track->audio.buf_timecode = AV_NOPTS_VALUE;
|
|
||||||
pkt->pos = pos;
|
|
||||||
pkt->stream_index = st->index;
|
|
||||||
dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MatroskaTrackEncoding *encodings = track->encodings.elem;
|
|
||||||
uint32_t pkt_size = lace_size[n];
|
|
||||||
uint8_t *pkt_data = data;
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
if (encodings && encodings->scope & 1) {
|
} else {
|
||||||
res = matroska_decode_buffer(&pkt_data, &pkt_size, track);
|
res = matroska_parse_frame(matroska, track, st, data, lace_size[n],
|
||||||
if (res < 0)
|
timecode, duration,
|
||||||
break;
|
pos, !n? is_keyframe : 0);
|
||||||
}
|
if (res)
|
||||||
|
goto end;
|
||||||
if (st->codec->codec_id == AV_CODEC_ID_PRORES)
|
|
||||||
offset = 8;
|
|
||||||
|
|
||||||
pkt = av_mallocz(sizeof(AVPacket));
|
|
||||||
/* XXX: prevent data copy... */
|
|
||||||
if (av_new_packet(pkt, pkt_size + offset) < 0) {
|
|
||||||
av_free(pkt);
|
|
||||||
res = AVERROR(ENOMEM);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (st->codec->codec_id == AV_CODEC_ID_PRORES) {
|
|
||||||
uint8_t *buf = pkt->data;
|
|
||||||
bytestream_put_be32(&buf, pkt_size);
|
|
||||||
bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f'));
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(pkt->data + offset, pkt_data, pkt_size);
|
|
||||||
|
|
||||||
if (pkt_data != data)
|
|
||||||
av_free(pkt_data);
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
pkt->flags = is_keyframe;
|
|
||||||
pkt->stream_index = st->index;
|
|
||||||
|
|
||||||
if (track->ms_compat)
|
|
||||||
pkt->dts = timecode;
|
|
||||||
else
|
|
||||||
pkt->pts = timecode;
|
|
||||||
pkt->pos = pos;
|
|
||||||
if (st->codec->codec_id == AV_CODEC_ID_TEXT)
|
|
||||||
pkt->convergence_duration = duration;
|
|
||||||
else if (track->type != MATROSKA_TRACK_TYPE_SUBTITLE)
|
|
||||||
pkt->duration = duration;
|
|
||||||
|
|
||||||
if (st->codec->codec_id == AV_CODEC_ID_SSA)
|
|
||||||
matroska_fix_ass_packet(matroska, pkt, duration);
|
|
||||||
|
|
||||||
if (matroska->prev_pkt &&
|
|
||||||
timecode != AV_NOPTS_VALUE &&
|
|
||||||
matroska->prev_pkt->pts == timecode &&
|
|
||||||
matroska->prev_pkt->stream_index == st->index &&
|
|
||||||
st->codec->codec_id == AV_CODEC_ID_SSA)
|
|
||||||
matroska_merge_packets(matroska->prev_pkt, pkt);
|
|
||||||
else {
|
|
||||||
dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
|
|
||||||
matroska->prev_pkt = pkt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timecode != AV_NOPTS_VALUE)
|
|
||||||
timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
|
|
||||||
data += lace_size[n];
|
|
||||||
size -= lace_size[n];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (timecode != AV_NOPTS_VALUE)
|
||||||
|
timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
|
||||||
|
data += lace_size[n];
|
||||||
|
size -= lace_size[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user