avcodec/mpegvideo: Use offset instead of pointer for vbv_delay

An offset has the advantage of not needing to be updated
when the buffer is reallocated. Furthermore, the way the pointer
is currently updated is undefined behaviour in case the pointer
is not already set (i.e. when not encoding MPEG-1/2), because
it calculates the nonsense NULL - s->pb.buf.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt 2022-01-26 21:04:53 +01:00
parent 5a04c6a269
commit 24a654c6c9
3 changed files with 9 additions and 10 deletions

View File

@ -465,7 +465,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
(s->picture_number - mpeg12->gop_picture_number) & 0x3ff);
put_bits(&s->pb, 3, s->pict_type);
s->vbv_delay_ptr = s->pb.buf + put_bytes_count(&s->pb, 0);
s->vbv_delay_pos = put_bytes_count(&s->pb, 0);
put_bits(&s->pb, 16, 0xFFFF); /* vbv_delay */
// RAL: Forward f_code also needed for B-frames

View File

@ -432,7 +432,7 @@ typedef struct MpegEncContext {
/* MPEG-1 specific */
int last_mv_dir; ///< last mv_dir, used for B-frame encoding
uint8_t *vbv_delay_ptr; ///< pointer to vbv_delay in the bitstream
int vbv_delay_pos; ///< offset of vbv_delay in the bitstream
/* MPEG-2-specific - I wished not to have to support this mess. */
int progressive_sequence;

View File

@ -1840,8 +1840,9 @@ vbv_retry:
double inbits = avctx->rc_max_rate *
av_q2d(avctx->time_base);
int minbits = s->frame_bits - 8 *
(s->vbv_delay_ptr - s->pb.buf - 1);
(s->vbv_delay_pos - 1);
double bits = s->rc_context.buffer_index + minbits - inbits;
uint8_t *const vbv_delay_ptr = s->pb.buf + s->vbv_delay_pos;
if (bits < 0)
av_log(avctx, AV_LOG_ERROR,
@ -1857,11 +1858,11 @@ vbv_retry:
av_assert0(vbv_delay < 0xFFFF);
s->vbv_delay_ptr[0] &= 0xF8;
s->vbv_delay_ptr[0] |= vbv_delay >> 13;
s->vbv_delay_ptr[1] = vbv_delay >> 5;
s->vbv_delay_ptr[2] &= 0x07;
s->vbv_delay_ptr[2] |= vbv_delay << 3;
vbv_delay_ptr[0] &= 0xF8;
vbv_delay_ptr[0] |= vbv_delay >> 13;
vbv_delay_ptr[1] = vbv_delay >> 5;
vbv_delay_ptr[2] &= 0x07;
vbv_delay_ptr[2] |= vbv_delay << 3;
props = av_cpb_properties_alloc(&props_size);
if (!props)
@ -2721,7 +2722,6 @@ int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t s
&& s->slice_context_count == 1
&& s->pb.buf == s->avctx->internal->byte_buffer) {
int lastgob_pos = s->ptr_lastgob - s->pb.buf;
int vbv_pos = s->vbv_delay_ptr - s->pb.buf;
uint8_t *new_buffer = NULL;
int new_buffer_size = 0;
@ -2744,7 +2744,6 @@ int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t s
s->avctx->internal->byte_buffer_size = new_buffer_size;
rebase_put_bits(&s->pb, new_buffer, new_buffer_size);
s->ptr_lastgob = s->pb.buf + lastgob_pos;
s->vbv_delay_ptr = s->pb.buf + vbv_pos;
}
if (put_bytes_left(&s->pb, 0) < threshold)
return AVERROR(EINVAL);