|
|
|
@@ -1050,6 +1050,64 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx, |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int cbs_h2645_write_slice_data(CodedBitstreamContext *ctx, |
|
|
|
PutBitContext *pbc, const uint8_t *data, |
|
|
|
size_t data_size, int data_bit_start) |
|
|
|
{ |
|
|
|
size_t rest = data_size - (data_bit_start + 7) / 8; |
|
|
|
const uint8_t *pos = data + data_bit_start / 8; |
|
|
|
|
|
|
|
av_assert0(data_bit_start >= 0 && |
|
|
|
8 * data_size > data_bit_start); |
|
|
|
|
|
|
|
if (data_size * 8 + 8 > put_bits_left(pbc)) |
|
|
|
return AVERROR(ENOSPC); |
|
|
|
|
|
|
|
if (!rest) |
|
|
|
goto rbsp_stop_one_bit; |
|
|
|
|
|
|
|
// First copy the remaining bits of the first byte |
|
|
|
// The above check ensures that we do not accidentally |
|
|
|
// copy beyond the rbsp_stop_one_bit. |
|
|
|
if (data_bit_start % 8) |
|
|
|
put_bits(pbc, 8 - data_bit_start % 8, |
|
|
|
*pos++ & MAX_UINT_BITS(8 - 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 happens normally for CABAC. |
|
|
|
flush_put_bits(pbc); |
|
|
|
memcpy(put_bits_ptr(pbc), pos, rest); |
|
|
|
skip_put_bytes(pbc, rest); |
|
|
|
} else { |
|
|
|
// If not, we have to copy manually. |
|
|
|
// rbsp_stop_one_bit forces us to special-case |
|
|
|
// the last byte. |
|
|
|
uint8_t temp; |
|
|
|
int i; |
|
|
|
|
|
|
|
for (; rest > 4; rest -= 4, pos += 4) |
|
|
|
put_bits32(pbc, AV_RB32(pos)); |
|
|
|
|
|
|
|
for (; rest > 1; rest--, pos++) |
|
|
|
put_bits(pbc, 8, *pos); |
|
|
|
|
|
|
|
rbsp_stop_one_bit: |
|
|
|
temp = rest ? *pos : *pos & MAX_UINT_BITS(8 - data_bit_start % 8); |
|
|
|
|
|
|
|
av_assert0(temp); |
|
|
|
i = ff_ctz(*pos); |
|
|
|
temp = temp >> i; |
|
|
|
i = rest ? (8 - i) : (8 - i - data_bit_start % 8); |
|
|
|
put_bits(pbc, i, temp); |
|
|
|
if (put_bits_count(pbc) % 8) |
|
|
|
put_bits(pbc, 8 - put_bits_count(pbc) % 8, 0); |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, |
|
|
|
CodedBitstreamUnit *unit, |
|
|
|
PutBitContext *pbc) |
|
|
|
@@ -1100,37 +1158,17 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext *ctx, |
|
|
|
case H264_NAL_AUXILIARY_SLICE: |
|
|
|
{ |
|
|
|
H264RawSlice *slice = unit->content; |
|
|
|
GetBitContext gbc; |
|
|
|
int bits_left, end, zeroes; |
|
|
|
|
|
|
|
err = cbs_h264_write_slice_header(ctx, pbc, &slice->header); |
|
|
|
if (err < 0) |
|
|
|
return err; |
|
|
|
|
|
|
|
if (slice->data) { |
|
|
|
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); |
|
|
|
|
|
|
|
// Copy in two-byte blocks, but stop before copying the |
|
|
|
// rbsp_stop_one_bit in the final byte. |
|
|
|
while (get_bits_left(&gbc) > 23) |
|
|
|
put_bits(pbc, 16, get_bits(&gbc, 16)); |
|
|
|
|
|
|
|
bits_left = get_bits_left(&gbc); |
|
|
|
end = get_bits(&gbc, bits_left); |
|
|
|
|
|
|
|
// rbsp_stop_one_bit must be present here. |
|
|
|
av_assert0(end); |
|
|
|
zeroes = ff_ctz(end); |
|
|
|
if (bits_left > zeroes + 1) |
|
|
|
put_bits(pbc, bits_left - zeroes - 1, |
|
|
|
end >> (zeroes + 1)); |
|
|
|
put_bits(pbc, 1, 1); |
|
|
|
while (put_bits_count(pbc) % 8 != 0) |
|
|
|
put_bits(pbc, 1, 0); |
|
|
|
err = cbs_h2645_write_slice_data(ctx, pbc, slice->data, |
|
|
|
slice->data_size, |
|
|
|
slice->data_bit_start); |
|
|
|
if (err < 0) |
|
|
|
return err; |
|
|
|
} else { |
|
|
|
// No slice data - that was just the header. |
|
|
|
// (Bitstream may be unaligned!) |
|
|
|
@@ -1254,37 +1292,17 @@ static int cbs_h265_write_nal_unit(CodedBitstreamContext *ctx, |
|
|
|
case HEVC_NAL_CRA_NUT: |
|
|
|
{ |
|
|
|
H265RawSlice *slice = unit->content; |
|
|
|
GetBitContext gbc; |
|
|
|
int bits_left, end, zeroes; |
|
|
|
|
|
|
|
err = cbs_h265_write_slice_segment_header(ctx, pbc, &slice->header); |
|
|
|
if (err < 0) |
|
|
|
return err; |
|
|
|
|
|
|
|
if (slice->data) { |
|
|
|
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); |
|
|
|
|
|
|
|
// Copy in two-byte blocks, but stop before copying the |
|
|
|
// rbsp_stop_one_bit in the final byte. |
|
|
|
while (get_bits_left(&gbc) > 23) |
|
|
|
put_bits(pbc, 16, get_bits(&gbc, 16)); |
|
|
|
|
|
|
|
bits_left = get_bits_left(&gbc); |
|
|
|
end = get_bits(&gbc, bits_left); |
|
|
|
|
|
|
|
// rbsp_stop_one_bit must be present here. |
|
|
|
av_assert0(end); |
|
|
|
zeroes = ff_ctz(end); |
|
|
|
if (bits_left > zeroes + 1) |
|
|
|
put_bits(pbc, bits_left - zeroes - 1, |
|
|
|
end >> (zeroes + 1)); |
|
|
|
put_bits(pbc, 1, 1); |
|
|
|
while (put_bits_count(pbc) % 8 != 0) |
|
|
|
put_bits(pbc, 1, 0); |
|
|
|
err = cbs_h2645_write_slice_data(ctx, pbc, slice->data, |
|
|
|
slice->data_size, |
|
|
|
slice->data_bit_start); |
|
|
|
if (err < 0) |
|
|
|
return err; |
|
|
|
} else { |
|
|
|
// No slice data - that was just the header. |
|
|
|
} |
|
|
|
|