Attached patch solves the overshoots the encoder has.
From 5e4e428fdf3fcc58431b80947dc399dfacb82724 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov <rpehliva...@obe.tv> Date: Wed, 6 Apr 2016 11:51:24 +0100 Subject: [PATCH] vc2enc: prevent bitrate overshoots
The rounding caused by the size scaler wasn't compensated for and the slice sizes grew beyond what is allowed per frame. Signed-off-by: Rostislav Pehlivanov <rpehliva...@obe.tv> --- libavcodec/vc2enc.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index 577d49d..fdbd0d4 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -167,6 +167,7 @@ typedef struct VC2EncContext { int chroma_y_shift; /* Rate control stuff */ + int frame_max_bytes; int slice_max_bytes; int slice_min_bytes; int q_ceil; @@ -718,7 +719,7 @@ static int calc_slice_sizes(VC2EncContext *s) for (i = 0; i < s->num_x*s->num_y; i++) { SliceArgs *args = &enc_args[i]; - bytes_left += s->slice_max_bytes - args->bytes; + bytes_left += args->bytes; for (j = 0; j < slice_redist_range; j++) { if (args->bytes > bytes_top[j]) { bytes_top[j] = args->bytes; @@ -728,8 +729,10 @@ static int calc_slice_sizes(VC2EncContext *s) } } + bytes_left = s->frame_max_bytes - bytes_left; + /* Second pass - distribute leftover bytes */ - while (1) { + while (bytes_left > 0) { int distributed = 0; for (i = 0; i < slice_redist_range; i++) { SliceArgs *args; @@ -992,12 +995,12 @@ static av_cold int vc2_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet) { int ret = 0; - int sig_size = 256; + int slice_ceil, sig_size = 256; VC2EncContext *s = avctx->priv_data; const char aux_data[] = LIBAVCODEC_IDENT; const int aux_data_size = sizeof(aux_data); const int header_size = 100 + aux_data_size; - int64_t max_frame_bytes, r_bitrate = avctx->bit_rate >> (s->interlaced); + int64_t r_bitrate = avctx->bit_rate >> (s->interlaced); s->avctx = avctx; s->size_scaler = 2; @@ -1006,18 +1009,21 @@ static av_cold int vc2_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, s->next_parse_offset = 0; /* Rate control */ - max_frame_bytes = (av_rescale(r_bitrate, s->avctx->time_base.num, - s->avctx->time_base.den) >> 3) - header_size; - s->slice_max_bytes = av_rescale(max_frame_bytes, 1, s->num_x*s->num_y); + s->frame_max_bytes = (av_rescale(r_bitrate, s->avctx->time_base.num, + s->avctx->time_base.den) >> 3) - header_size; + s->slice_max_bytes = slice_ceil = av_rescale(s->frame_max_bytes, 1, s->num_x*s->num_y); /* Find an appropriate size scaler */ while (sig_size > 255) { int r_size = SSIZE_ROUND(s->slice_max_bytes); + if (r_size > slice_ceil) { + s->slice_max_bytes -= r_size - slice_ceil; + r_size = SSIZE_ROUND(s->slice_max_bytes); + } sig_size = r_size/s->size_scaler; /* Signalled slize size */ s->size_scaler <<= 1; } - s->slice_max_bytes = SSIZE_ROUND(s->slice_max_bytes); s->slice_min_bytes = s->slice_max_bytes - s->slice_max_bytes*(s->tolerance/100.0f); ret = encode_frame(s, avpkt, frame, aux_data, header_size, s->interlaced); -- 2.8.0.rc3
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel