cbs_mpeg2: Improve performance of writing slices

Instead of using a combination of bitreader and -writer for copying data,
one can byte-align the (obsolete and removed) bitreader to improve performance.
One can even use memcpy in the normal case.
This improved the time needed for writing the slicedata from 33618 to
2370 decicycles when tested on a video originating from a DVD (4194394
runs).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@googlemail.com>
Signed-off-by: Mark Thompson <sw@jkqxz.net>
This commit is contained in:
Andreas Rheinhardt 2018-11-04 05:48:40 +01:00 committed by Mark Thompson
parent 252e79663d
commit 6df9020f45

View File

@ -264,8 +264,6 @@ static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx,
PutBitContext *pbc) PutBitContext *pbc)
{ {
MPEG2RawSlice *slice = unit->content; MPEG2RawSlice *slice = unit->content;
GetBitContext gbc;
size_t bits_left;
int err; int err;
err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header); err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header);
@ -273,21 +271,38 @@ static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx,
return err; return err;
if (slice->data) { if (slice->data) {
size_t rest = slice->data_size - (slice->data_bit_start + 7) / 8;
uint8_t *pos = slice->data + slice->data_bit_start / 8;
av_assert0(slice->data_bit_start >= 0 &&
8 * slice->data_size > slice->data_bit_start);
if (slice->data_size * 8 + 8 > put_bits_left(pbc)) if (slice->data_size * 8 + 8 > put_bits_left(pbc))
return AVERROR(ENOSPC); return AVERROR(ENOSPC);
init_get_bits(&gbc, slice->data, slice->data_size * 8); // First copy the remaining bits of the first byte
skip_bits_long(&gbc, slice->data_bit_start); if (slice->data_bit_start % 8)
put_bits(pbc, 8 - slice->data_bit_start % 8,
*pos++ & MAX_UINT_BITS(8 - slice->data_bit_start % 8));
while (get_bits_left(&gbc) > 15) if (put_bits_count(pbc) % 8 == 0) {
put_bits(pbc, 16, get_bits(&gbc, 16)); // If the writer is aligned at this point,
// memcpy can be used to improve performance.
// This is the normal case.
flush_put_bits(pbc);
memcpy(put_bits_ptr(pbc), pos, rest);
skip_put_bytes(pbc, rest);
} else {
// If not, we have to copy manually:
for (; rest > 3; rest -= 4, pos += 4)
put_bits32(pbc, AV_RB32(pos));
bits_left = get_bits_left(&gbc); for (; rest; rest--, pos++)
put_bits(pbc, bits_left, get_bits(&gbc, bits_left)); put_bits(pbc, 8, *pos);
// Align with zeroes. // Align with zeros
while (put_bits_count(pbc) % 8 != 0) put_bits(pbc, 8 - put_bits_count(pbc) % 8, 0);
put_bits(pbc, 1, 0); }
} }
return 0; return 0;