PutBitContext *pbc)
{
MPEG2RawSlice *slice = unit->content;
- GetBitContext gbc;
- size_t bits_left;
int err;
err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header);
return err;
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))
return AVERROR(ENOSPC);
- init_get_bits(&gbc, slice->data, slice->data_size * 8);
- skip_bits_long(&gbc, slice->data_bit_start);
-
- while (get_bits_left(&gbc) > 15)
- put_bits(pbc, 16, get_bits(&gbc, 16));
+ // First copy the remaining bits of the first byte
+ 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));
+
+ if (put_bits_count(pbc) % 8 == 0) {
+ // 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);
- put_bits(pbc, bits_left, get_bits(&gbc, bits_left));
+ for (; rest; rest--, pos++)
+ put_bits(pbc, 8, *pos);
- // Align with zeroes.
- while (put_bits_count(pbc) % 8 != 0)
- put_bits(pbc, 1, 0);
+ // Align with zeros
+ put_bits(pbc, 8 - put_bits_count(pbc) % 8, 0);
+ }
}
return 0;