mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
truehd_core: Switch to in-place modifications
The truehd_core bitstream filter decreases the sizes of the major_sync_info structure (if present), of the substream_directory and of the substreams themselves. As a consequence, there is enough space available in front of the actual substream data for the new header, so that one only needs to modify the header in front of the actual data (which apart from shrinking is left untouched) and the packet's size and buffer pointer (after having made sure that the packet is writable). This and switching to bsf_get_packet_ref also removed the need for having separate packets for in- and output. Even if the input is not writable, there are noticable performance improvements: The average of 10 iterations of processing a file with 262144 runs each (inlcuding about 20 skips per iteration) went down from 5669 to 4362 decicycles. If the input is writable, it goes down to 1363 decicycles. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
This commit is contained in:
parent
836065b27a
commit
5a481b15bd
@ -36,34 +36,33 @@ typedef struct TrueHDCoreContext {
|
||||
MLPHeaderInfo hdr;
|
||||
} TrueHDCoreContext;
|
||||
|
||||
static int truehd_core_filter(AVBSFContext *ctx, AVPacket *out)
|
||||
static int truehd_core_filter(AVBSFContext *ctx, AVPacket *pkt)
|
||||
{
|
||||
TrueHDCoreContext *s = ctx->priv_data;
|
||||
GetBitContext gbc;
|
||||
AccessUnit units[MAX_SUBSTREAMS];
|
||||
AVPacket *in;
|
||||
int ret, i, last_offset = 0;
|
||||
int in_size, out_size;
|
||||
int have_header = 0;
|
||||
int substream_bytes = 0;
|
||||
int end;
|
||||
|
||||
ret = ff_bsf_get_packet(ctx, &in);
|
||||
ret = ff_bsf_get_packet_ref(ctx, pkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (in->size < 4) {
|
||||
if (pkt->size < 4) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
in_size = (AV_RB16(in->data) & 0xFFF) * 2;
|
||||
if (in_size < 4 || in_size > in->size) {
|
||||
in_size = (AV_RB16(pkt->data) & 0xFFF) * 2;
|
||||
if (in_size < 4 || in_size > pkt->size) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = init_get_bits8(&gbc, in->data + 4, in->size - 4);
|
||||
ret = init_get_bits8(&gbc, pkt->data + 4, pkt->size - 4);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
@ -99,27 +98,31 @@ static int truehd_core_filter(AVBSFContext *ctx, AVPacket *out)
|
||||
out_size = end + 4 + last_offset;
|
||||
if (out_size < in_size) {
|
||||
int bpos = 0, reduce = end - have_header * 28 - substream_bytes;
|
||||
uint16_t parity_nibble, dts = AV_RB16(in->data + 2);
|
||||
uint16_t parity_nibble, dts = AV_RB16(pkt->data + 2);
|
||||
uint16_t auheader;
|
||||
uint8_t header[28];
|
||||
|
||||
av_assert1(reduce % 2 == 0);
|
||||
av_assert1(reduce >= 0 && reduce % 2 == 0);
|
||||
|
||||
ret = av_new_packet(out, out_size);
|
||||
if (have_header) {
|
||||
memcpy(header, pkt->data + 4, 28);
|
||||
header[16] = (header[16] & 0x0c) | (FFMIN(s->hdr.num_substreams, 3) << 4);
|
||||
header[17] &= 0x7f;
|
||||
header[25] &= 0xfe;
|
||||
AV_WL16(header + 26, ff_mlp_checksum16(header, 26));
|
||||
}
|
||||
|
||||
pkt->data += reduce;
|
||||
out_size -= reduce;
|
||||
pkt->size = out_size;
|
||||
|
||||
ret = av_packet_make_writable(pkt);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
AV_WB16(out->data + 2, dts);
|
||||
AV_WB16(pkt->data + 2, dts);
|
||||
parity_nibble = dts;
|
||||
out->size -= reduce;
|
||||
parity_nibble ^= out->size / 2;
|
||||
|
||||
if (have_header) {
|
||||
memcpy(out->data + 4, in->data + 4, 28);
|
||||
out->data[16 + 4] = (out->data[16 + 4] & 0x0c) | (FFMIN(s->hdr.num_substreams, 3) << 4);
|
||||
out->data[17 + 4]&= 0x7f;
|
||||
out->data[25 + 4] = out->data[25 + 4] & 0xfe;
|
||||
AV_WL16(out->data + 4 + 26, ff_mlp_checksum16(out->data + 4, 26));
|
||||
}
|
||||
parity_nibble ^= out_size / 2;
|
||||
|
||||
for (i = 0; i < FFMIN(s->hdr.num_substreams, 3); i++) {
|
||||
uint16_t substr_hdr = 0;
|
||||
@ -130,13 +133,13 @@ static int truehd_core_filter(AVBSFContext *ctx, AVPacket *out)
|
||||
substr_hdr |= (units[i].bits[3] << 12);
|
||||
substr_hdr |= units[i].offset;
|
||||
|
||||
AV_WB16(out->data + have_header * 28 + 4 + bpos, substr_hdr);
|
||||
AV_WB16(pkt->data + have_header * 28 + 4 + bpos, substr_hdr);
|
||||
|
||||
parity_nibble ^= substr_hdr;
|
||||
bpos += 2;
|
||||
|
||||
if (units[i].bits[0]) {
|
||||
AV_WB16(out->data + have_header * 28 + 4 + bpos, units[i].optional);
|
||||
AV_WB16(pkt->data + have_header * 28 + 4 + bpos, units[i].optional);
|
||||
|
||||
parity_nibble ^= units[i].optional;
|
||||
bpos += 2;
|
||||
@ -147,22 +150,17 @@ static int truehd_core_filter(AVBSFContext *ctx, AVPacket *out)
|
||||
parity_nibble ^= parity_nibble >> 4;
|
||||
parity_nibble &= 0xF;
|
||||
|
||||
memcpy(out->data + have_header * 28 + 4 + bpos,
|
||||
in->data + 4 + end,
|
||||
out_size - (4 + end));
|
||||
auheader = (parity_nibble ^ 0xF) << 12;
|
||||
auheader |= (out->size / 2) & 0x0fff;
|
||||
AV_WB16(out->data, auheader);
|
||||
auheader |= (out_size / 2) & 0x0fff;
|
||||
AV_WB16(pkt->data, auheader);
|
||||
|
||||
ret = av_packet_copy_props(out, in);
|
||||
} else {
|
||||
av_packet_move_ref(out, in);
|
||||
if (have_header)
|
||||
memcpy(pkt->data + 4, header, 28);
|
||||
}
|
||||
|
||||
fail:
|
||||
if (ret < 0)
|
||||
av_packet_unref(out);
|
||||
av_packet_free(&in);
|
||||
av_packet_unref(pkt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user