summaryrefslogtreecommitdiff
path: root/vp8
diff options
context:
space:
mode:
Diffstat (limited to 'vp8')
-rw-r--r--vp8/common/onyxd.h1
-rw-r--r--vp8/decoder/decodemv.c30
-rw-r--r--vp8/decoder/decodframe.c149
-rw-r--r--vp8/decoder/error_concealment.c1
-rw-r--r--vp8/decoder/onyxd_if.c22
-rw-r--r--vp8/decoder/onyxd_int.h4
-rw-r--r--vp8/decoder/threading.c105
-rw-r--r--vp8/encoder/firstpass.c108
-rw-r--r--vp8/encoder/onyx_if.c147
-rw-r--r--vp8/encoder/onyx_int.h6
-rw-r--r--vp8/encoder/ratectrl.c37
11 files changed, 298 insertions, 312 deletions
diff --git a/vp8/common/onyxd.h b/vp8/common/onyxd.h
index d3e5c2fa7..08f1cca80 100644
--- a/vp8/common/onyxd.h
+++ b/vp8/common/onyxd.h
@@ -18,7 +18,6 @@
extern "C"
{
#endif
-#include "vpx/vpx_codec.h"
#include "type_aliases.h"
#include "vpx_scale/yv12config.h"
#include "ppflags.h"
diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c
index 0a7942d89..54547d95c 100644
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -400,18 +400,18 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
/* Clip "next_nearest" so that it does not extend to far out of image */
vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
mb_to_top_edge, mb_to_bottom_edge);
- break;
+ goto propagate_mv;
case NEARESTMV:
mv->as_int = nearest.as_int;
/* Clip "next_nearest" so that it does not extend to far out of image */
vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
mb_to_top_edge, mb_to_bottom_edge);
- break;
+ goto propagate_mv;
case ZEROMV:
mv->as_int = 0;
- break;
+ goto propagate_mv;
case NEWMV:
read_mv(bc, &mv->as_mv, (const MV_CONTEXT *) mvc);
@@ -428,8 +428,30 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
mb_to_right_edge,
mb_to_top_edge,
mb_to_bottom_edge);
- break;
+ propagate_mv: /* same MV throughout */
+#if CONFIG_ERROR_CONCEALMENT
+ if(pbi->ec_enabled)
+ {
+ mi->bmi[ 0].mv.as_int =
+ mi->bmi[ 1].mv.as_int =
+ mi->bmi[ 2].mv.as_int =
+ mi->bmi[ 3].mv.as_int =
+ mi->bmi[ 4].mv.as_int =
+ mi->bmi[ 5].mv.as_int =
+ mi->bmi[ 6].mv.as_int =
+ mi->bmi[ 7].mv.as_int =
+ mi->bmi[ 8].mv.as_int =
+ mi->bmi[ 9].mv.as_int =
+ mi->bmi[10].mv.as_int =
+ mi->bmi[11].mv.as_int =
+ mi->bmi[12].mv.as_int =
+ mi->bmi[13].mv.as_int =
+ mi->bmi[14].mv.as_int =
+ mi->bmi[15].mv.as_int = mv->as_int;
+ }
+#endif
+ break;
default:;
#if CONFIG_DEBUG
assert(0);
diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c
index 9b35ffd66..ddb09703b 100644
--- a/vp8/decoder/decodframe.c
+++ b/vp8/decoder/decodframe.c
@@ -183,6 +183,7 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
unsigned int mb_idx)
{
int eobtotal = 0;
+ int throw_residual = 0;
MB_PREDICTION_MODE mode;
int i;
@@ -203,7 +204,8 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
mode = xd->mode_info_context->mbmi.mode;
- if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV)
+ if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV &&
+ !vp8dx_bool_error(xd->current_bc))
{
/* Special case: Force the loopfilter to skip when eobtotal and
* mb_skip_coeff are zero.
@@ -235,14 +237,21 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
vp8_build_inter_predictors_mb(xd);
}
+ /* When we have independent partitions we can apply residual even
+ * though other partitions within the frame are corrupt.
+ */
+ throw_residual = (!pbi->independent_partitions &&
+ pbi->frame_corrupt_residual);
+ throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
+
#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_enabled &&
- (mb_idx >= pbi->mvs_corrupt_from_mb ||
- vp8dx_bool_error(xd->current_bc)))
+ if (pbi->ec_active &&
+ (mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
{
/* MB with corrupt residuals or corrupt mode/motion vectors.
* Better to use the predictor as reconstruction.
*/
+ pbi->frame_corrupt_residual = 1;
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
vp8_conceal_corrupt_mb(xd);
return;
@@ -376,22 +385,28 @@ decode_mb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mb_row, MACROBLOCKD *xd)
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_enabled &&
- xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
- vp8dx_bool_error(xd->current_bc))
{
- /* We have an intra block with corrupt coefficients, better to
- * conceal with an inter block. Interpolate MVs from neighboring MBs
- *
- * Note that for the first mb with corrupt residual in a frame,
- * we might not discover that before decoding the residual. That
- * happens after this check, and therefore no inter concealment will
- * be done.
- */
- vp8_interpolate_motion(xd,
- mb_row, mb_col,
- pc->mb_rows, pc->mb_cols,
- pc->mode_info_stride);
+ int corrupt_residual = (!pbi->independent_partitions &&
+ pbi->frame_corrupt_residual) ||
+ vp8dx_bool_error(xd->current_bc);
+ if (pbi->ec_active &&
+ xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
+ corrupt_residual)
+ {
+ /* We have an intra block with corrupt coefficients, better to
+ * conceal with an inter block. Interpolate MVs from neighboring
+ * MBs.
+ *
+ * Note that for the first mb with corrupt residual in a frame,
+ * we might not discover that before decoding the residual. That
+ * happens after this check, and therefore no inter concealment
+ * will be done.
+ */
+ vp8_interpolate_motion(xd,
+ mb_row, mb_col,
+ pc->mb_rows, pc->mb_cols,
+ pc->mode_info_stride);
+ }
}
#endif
@@ -495,6 +510,15 @@ static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
#endif
}
+
+static int read_is_valid(const unsigned char *start,
+ size_t len,
+ const unsigned char *end)
+{
+ return (start + len > start && start + len <= end);
+}
+
+
static void setup_token_decoder(VP8D_COMP *pbi,
const unsigned char *cx_data)
{
@@ -510,7 +534,7 @@ static void setup_token_decoder(VP8D_COMP *pbi,
(TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
/* Only update the multi_token_partition field if we are sure the value
* is correct. */
- if (!pbi->ec_enabled || !vp8dx_bool_error(&pbi->bc))
+ if (!pbi->ec_active || !vp8dx_bool_error(&pbi->bc))
pc->multi_token_partition = multi_token_partition;
num_part = 1 << pc->multi_token_partition;
@@ -529,26 +553,42 @@ static void setup_token_decoder(VP8D_COMP *pbi,
for (i = 0; i < num_part; i++)
{
const unsigned char *partition_size_ptr = cx_data + i * 3;
- ptrdiff_t partition_size;
+ ptrdiff_t partition_size, bytes_left;
+
+ bytes_left = user_data_end - partition;
/* Calculate the length of this partition. The last partition
- * size is implicit.
+ * size is implicit. If the partition size can't be read, then
+ * either use the remaining data in the buffer (for EC mode)
+ * or throw an error.
*/
if (i < num_part - 1)
{
- partition_size = read_partition_size(partition_size_ptr);
+ if (read_is_valid(partition_size_ptr, 3, user_data_end))
+ partition_size = read_partition_size(partition_size_ptr);
+ else if (pbi->ec_active)
+ partition_size = bytes_left;
+ else
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated partition size data");
}
else
+ partition_size = bytes_left;
+
+ /* Validate the calculated partition length. If the buffer
+ * described by the partition can't be fully read, then restrict
+ * it to the portion that can be (for EC mode) or throw an error.
+ */
+ if (!read_is_valid(partition, partition_size, user_data_end))
{
- partition_size = user_data_end - partition;
+ if (pbi->ec_active)
+ partition_size = bytes_left;
+ else
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated packet or corrupt partition "
+ "%d length", i + 1);
}
- if (!pbi->ec_enabled && (partition + partition_size > user_data_end
- || partition + partition_size < partition))
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Truncated packet or corrupt partition "
- "%d length", i + 1);
-
if (vp8dx_start_decode(bool_decoder, partition, partition_size))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder %d", i + 1);
@@ -634,6 +674,9 @@ static void init_frame(VP8D_COMP *pbi)
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
}
+
+ if (pbi->decoded_key_frame && pbi->ec_enabled && !pbi->ec_active)
+ pbi->ec_active = 1;
}
xd->left_context = &pc->left_context;
@@ -656,6 +699,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
int mb_row;
int i, j, k, l;
const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
+ int corrupt_tokens = 0;
+ int prev_independent_partitions = pbi->independent_partitions;
if (pbi->input_partition)
{
@@ -669,7 +714,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
if (data_end - data < 3)
{
- if (pbi->ec_enabled)
+ if (pbi->ec_active)
{
/* Declare the missing frame as an inter frame since it will
be handled as an inter frame when we have estimated its
@@ -694,7 +739,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
(data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
data += 3;
- if (!pbi->ec_enabled && (data + first_partition_length_in_bytes > data_end
+ if (!pbi->ec_active && (data + first_partition_length_in_bytes > data_end
|| data + first_partition_length_in_bytes < data))
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition 0 length");
@@ -709,7 +754,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
/* When error concealment is enabled we should only check the sync
* code if we have enough bits available
*/
- if (!pbi->ec_enabled || data + 3 < data_end)
+ if (!pbi->ec_active || data + 3 < data_end)
{
if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
@@ -720,7 +765,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
* if we have enough data. Otherwise we will end up with the wrong
* size.
*/
- if (!pbi->ec_enabled || data + 6 < data_end)
+ if (!pbi->ec_active || data + 6 < data_end)
{
pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
pc->horiz_scale = data[4] >> 6;
@@ -919,7 +964,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_ERROR_CONCEALMENT
/* Assume we shouldn't refresh golden if the bit is missing */
xd->corrupted |= vp8dx_bool_error(bc);
- if (pbi->ec_enabled && xd->corrupted)
+ if (pbi->ec_active && xd->corrupted)
pc->refresh_golden_frame = 0;
#endif
@@ -927,7 +972,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_ERROR_CONCEALMENT
/* Assume we shouldn't refresh altref if the bit is missing */
xd->corrupted |= vp8dx_bool_error(bc);
- if (pbi->ec_enabled && xd->corrupted)
+ if (pbi->ec_active && xd->corrupted)
pc->refresh_alt_ref_frame = 0;
#endif
@@ -957,7 +1002,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_ERROR_CONCEALMENT
/* Assume we should refresh the last frame if the bit is missing */
xd->corrupted |= vp8dx_bool_error(bc);
- if (pbi->ec_enabled && xd->corrupted)
+ if (pbi->ec_active && xd->corrupted)
pc->refresh_last_frame = 1;
#endif
@@ -975,6 +1020,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
}
{
+ pbi->independent_partitions = 1;
+
/* read coef probability tree */
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
@@ -989,6 +1036,9 @@ int vp8_decode_frame(VP8D_COMP *pbi)
*p = (vp8_prob)vp8_read_literal(bc, 8);
}
+ if (k > 0 && *p != pc->fc.coef_probs[i][j][k-1][l])
+ pbi->independent_partitions = 0;
+
}
}
@@ -1015,7 +1065,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
vp8_decode_mode_mvs(pbi);
#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_enabled &&
+ if (pbi->ec_active &&
pbi->mvs_corrupt_from_mb < (unsigned int)pc->mb_cols * pc->mb_rows)
{
/* Motion vectors are missing in this frame. We will try to estimate
@@ -1029,14 +1079,19 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_MULTITHREAD
if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
{
+ int i;
+ pbi->frame_corrupt_residual = 0;
vp8mt_decode_mb_rows(pbi, xd);
vp8_yv12_extend_frame_borders_ptr(&pc->yv12_fb[pc->new_fb_idx]); /*cm->frame_to_show);*/
+ for (i = 0; i < pbi->decoding_thread_count; ++i)
+ corrupt_tokens |= pbi->mb_row_di[i].mbd.corrupted;
}
else
#endif
{
int ibc = 0;
int num_part = 1 << pc->multi_token_partition;
+ pbi->frame_corrupt_residual = 0;
/* Decode the individual macro block */
for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
@@ -1053,17 +1108,26 @@ int vp8_decode_frame(VP8D_COMP *pbi)
decode_mb_row(pbi, pc, mb_row, xd);
}
+ corrupt_tokens |= xd->corrupted;
}
stop_token_decoder(pbi);
/* Collect information about decoder corruption. */
/* 1. Check first boolean decoder for errors. */
- pc->yv12_fb[pc->new_fb_idx].corrupted =
- vp8dx_bool_error(bc);
+ pc->yv12_fb[pc->new_fb_idx].corrupted = vp8dx_bool_error(bc);
/* 2. Check the macroblock information */
- pc->yv12_fb[pc->new_fb_idx].corrupted |=
- xd->corrupted;
+ pc->yv12_fb[pc->new_fb_idx].corrupted |= corrupt_tokens;
+
+ if (!pbi->decoded_key_frame)
+ {
+ if (pc->frame_type == KEY_FRAME &&
+ !pc->yv12_fb[pc->new_fb_idx].corrupted)
+ pbi->decoded_key_frame = 1;
+ else
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
+ "A stream must start with a complete key frame");
+ }
/* vpx_log("Decoder: Frame Decoded, Size Roughly:%d bytes \n",bc->pos+pbi->bc2.pos); */
@@ -1077,6 +1141,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
if (pc->refresh_entropy_probs == 0)
{
vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
+ pbi->independent_partitions = prev_independent_partitions;
}
#ifdef PACKET_TESTING
diff --git a/vp8/decoder/error_concealment.c b/vp8/decoder/error_concealment.c
index 4f8f1a66c..7051bb927 100644
--- a/vp8/decoder/error_concealment.c
+++ b/vp8/decoder/error_concealment.c
@@ -567,7 +567,6 @@ static void interpolate_mvs(MACROBLOCKD *mb,
else
{
mv->as_int = 0;
- mi->bmi[row*4 + col].as_mode = NEW4X4;
mi->mbmi.need_to_clamp_mvs = 0;
}
}
diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c
index 224619480..db6528c80 100644
--- a/vp8/decoder/onyxd_if.c
+++ b/vp8/decoder/onyxd_if.c
@@ -101,9 +101,21 @@ VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
#else
pbi->ec_enabled = 0;
#endif
+ /* Error concealment is activated after a key frame has been
+ * decoded without errors when error concealment is enabled.
+ */
+ pbi->ec_active = 0;
+
+ pbi->decoded_key_frame = 0;
pbi->input_partition = oxcf->input_partition;
+ /* Independent partitions is activated when a frame updates the
+ * token probability table to have equal probabilities over the
+ * PREV_COEF context.
+ */
+ pbi->independent_partitions = 0;
+
return (VP8D_PTR) pbi;
}
@@ -346,11 +358,15 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
/* If error concealment is disabled we won't signal missing frames to
* the decoder.
*/
- if (!pbi->ec_enabled)
+ if (!pbi->ec_active)
{
/* Signal that we have no frame to show. */
cm->show_frame = 0;
+ pbi->num_partitions = 0;
+ if (pbi->input_partition)
+ pbi->common.multi_token_partition = 0;
+
/* Nothing more to do. */
return 0;
}
@@ -379,6 +395,10 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
#endif
pbi->common.error.setjmp = 0;
+ pbi->num_partitions = 0;
+ if (pbi->input_partition)
+ pbi->common.multi_token_partition = 0;
+
/* We do not know if the missing frame(s) was supposed to update
* any of the reference buffers, but we act conservative and
* mark only the last buffer as corrupted.
diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h
index eac57ab35..4ece4312a 100644
--- a/vp8/decoder/onyxd_int.h
+++ b/vp8/decoder/onyxd_int.h
@@ -132,7 +132,11 @@ typedef struct VP8Decompressor
unsigned int mvs_corrupt_from_mb;
#endif
int ec_enabled;
+ int ec_active;
int input_partition;
+ int decoded_key_frame;
+ int independent_partitions;
+ int frame_corrupt_residual;
} VP8D_COMP;
diff --git a/vp8/decoder/threading.c b/vp8/decoder/threading.c
index 1e0330277..fdde04a88 100644
--- a/vp8/decoder/threading.c
+++ b/vp8/decoder/threading.c
@@ -93,6 +93,7 @@ static void setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_D
static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col)
{
int eobtotal = 0;
+ int throw_residual = 0;
int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs;
if (xd->mode_info_context->mbmi.mb_skip_coeff)
@@ -112,7 +113,7 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int m
eobtotal |= (xd->mode_info_context->mbmi.mode == B_PRED ||
xd->mode_info_context->mbmi.mode == SPLITMV);
- if (!eobtotal)
+ if (!eobtotal && !vp8dx_bool_error(xd->current_bc))
{
/* Special case: Force the loopfilter to skip when eobtotal and
* mb_skip_coeff are zero.
@@ -154,14 +155,22 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int m
vp8_build_inter_predictors_mb(xd);
}
+ /* When we have independent partitions we can apply residual even
+ * though other partitions within the frame are corrupt.
+ */
+ throw_residual = (!pbi->independent_partitions &&
+ pbi->frame_corrupt_residual);
+ throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
+
#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_enabled &&
+ if (pbi->ec_active &&
(mb_row * pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb ||
- vp8dx_bool_error(xd->current_bc)))
+ throw_residual))
{
/* MB with corrupt residuals or corrupt mode/motion vectors.
* Better to use the predictor as reconstruction.
*/
+ pbi->frame_corrupt_residual = 1;
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
vp8_conceal_corrupt_mb(xd);
return;
@@ -314,25 +323,32 @@ static THREAD_FUNCTION thread_decoding_proc(void *p_data)
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_enabled &&
- (xd->mode_info_context->mbmi.ref_frame ==
- INTRA_FRAME) &&
- vp8dx_bool_error(xd->current_bc))
{
- /* We have an intra block with corrupt coefficients,
- * better to conceal with an inter block.
- * Interpolate MVs from neighboring MBs
- *
- * Note that for the first mb with corrupt residual
- * in a frame, we might not discover that before
- * decoding the residual. That happens after this
- * check, and therefore no inter concealment will be
- * done.
- */
- vp8_interpolate_motion(xd,
- mb_row, mb_col,
- pc->mb_rows, pc->mb_cols,
- pc->mode_info_stride);
+ int corrupt_residual =
+ (!pbi->independent_partitions &&
+ pbi->frame_corrupt_residual) ||
+ vp8dx_bool_error(xd->current_bc);
+ if (pbi->ec_active &&
+ (xd->mode_info_context->mbmi.ref_frame ==
+ INTRA_FRAME) &&
+ corrupt_residual)
+ {
+ /* We have an intra block with corrupt
+ * coefficients, better to conceal with an inter
+ * block.
+ * Interpolate MVs from neighboring MBs
+ *
+ * Note that for the first mb with corrupt
+ * residual in a frame, we might not discover
+ * that before decoding the residual. That
+ * happens after this check, and therefore no
+ * inter concealment will be done.
+ */
+ vp8_interpolate_motion(xd,
+ mb_row, mb_col,
+ pc->mb_rows, pc->mb_cols,
+ pc->mode_info_stride);
+ }
}
#endif
@@ -355,9 +371,19 @@ static THREAD_FUNCTION thread_decoding_proc(void *p_data)
xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
+ if (xd->mode_info_context->mbmi.ref_frame !=
+ INTRA_FRAME)
+ {
+ /* propagate errors from reference frames */
+ xd->corrupted |= pc->yv12_fb[ref_fb_idx].corrupted;
+ }
+
vp8_build_uvmvs(xd, pc->full_pixel);
decode_macroblock(pbi, xd, mb_row, mb_col);
+ /* check if the boolean decoder has suffered an error */
+ xd->corrupted |= vp8dx_bool_error(xd->current_bc);
+
if (pbi->common.filter_level)
{
int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
@@ -803,23 +829,28 @@ void vp8mt_decode_mb_rows( VP8D_COMP *pbi, MACROBLOCKD *xd)
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
#if CONFIG_ERROR_CONCEALMENT
- if (pbi->ec_enabled &&
- (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
- vp8dx_bool_error(xd->current_bc))
{
- /* We have an intra block with corrupt coefficients, better
- * to conceal with an inter block. Interpolate MVs from
- * neighboring MBs
- *
- * Note that for the first mb with corrupt residual in a
- * frame, we might not discover that before decoding the
- * residual. That happens after this check, and therefore no
- * inter concealment will be done.
- */
- vp8_interpolate_motion(xd,
- mb_row, mb_col,
- pc->mb_rows, pc->mb_cols,
- pc->mode_info_stride);
+ int corrupt_residual = (!pbi->independent_partitions &&
+ pbi->frame_corrupt_residual) ||
+ vp8dx_bool_error(xd->current_bc);
+ if (pbi->ec_active &&
+ (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
+ corrupt_residual)
+ {
+ /* We have an intra block with corrupt coefficients,
+ * better to conceal with an inter block. Interpolate
+ * MVs from neighboring MBs
+ *
+ * Note that for the first mb with corrupt residual in a
+ * frame, we might not discover that before decoding the
+ * residual. That happens after this check, and
+ * therefore no inter concealment will be done.
+ */
+ vp8_interpolate_motion(xd,
+ mb_row, mb_col,
+ pc->mb_rows, pc->mb_cols,
+ pc->mode_info_stride);
+ }
}
#endif
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
index a4730a796..9cdc1e5bf 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -357,58 +357,33 @@ static int frame_max_bits(VP8_COMP *cpi)
int max_bits;
// For CBR we need to also consider buffer fullness.
+ // If we are running below the optimal level then we need to gradually tighten up on max_bits.
if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
{
- max_bits = 2 * cpi->av_per_frame_bandwidth;
- max_bits -= cpi->buffered_av_per_frame_bandwidth;
- max_bits *= ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0);
- }
- // VBR
- else
- {
- // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
- max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
- }
-
- // Trap case where we are out of bits
- if (max_bits < 0)
- max_bits = 0;
+ double buffer_fullness_ratio = (double)cpi->buffer_level / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.optimal_buffer_level);
- return max_bits;
-}
+ // For CBR base this on the target average bits per frame plus the maximum sedction rate passed in by the user
+ max_bits = (int)(cpi->av_per_frame_bandwidth * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
+ // If our buffer is below the optimum level
+ if (buffer_fullness_ratio < 1.0)
+ {
+ // The lower of max_bits / 4 or cpi->av_per_frame_bandwidth / 4.
+ int min_max_bits = ((cpi->av_per_frame_bandwidth >> 2) < (max_bits >> 2)) ? cpi->av_per_frame_bandwidth >> 2 : max_bits >> 2;
-static int gf_group_max_bits(VP8_COMP *cpi)
-{
- // Max allocation for a golden frame group
- int max_bits;
+ max_bits = (int)(max_bits * buffer_fullness_ratio);
- // For CBR we need to also consider buffer fullness.
- if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- max_bits = cpi->av_per_frame_bandwidth * cpi->baseline_gf_interval;
- if (max_bits > cpi->oxcf.optimal_buffer_level)
- {
- max_bits -= cpi->oxcf.optimal_buffer_level;
- max_bits += cpi->buffer_level;
+ if (max_bits < min_max_bits)
+ max_bits = min_max_bits; // Lowest value we will set ... which should allow the buffer to refil.
}
- else
- {
- max_bits -= (cpi->buffered_av_per_frame_bandwidth
- - cpi->av_per_frame_bandwidth)
- * cpi->baseline_gf_interval;
- }
-
- max_bits *= ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0);
}
+ // VBR
else
{
// For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
- max_bits *= cpi->baseline_gf_interval;
}
-
// Trap case where we are out of bits
if (max_bits < 0)
max_bits = 0;
@@ -887,8 +862,6 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_
double correction_factor;
double corr_high;
double speed_correction = 1.0;
- double rolling_ratio;
-
double pow_highq = 0.90;
double pow_lowq = 0.40;
@@ -898,8 +871,10 @@ static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_
target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs);
// Calculate a corrective factor based on a rolling ratio of bits spent vs target bits
- if ((cpi->rolling_target_bits > 0.0) && (cpi->active_worst_quality < cpi->worst_quality))
+ if ((cpi->rolling_target_bits > 0) && (cpi->active_worst_quality < cpi->worst_quality))
{
+ double rolling_ratio;
+
rolling_ratio = (double)cpi->rolling_actual_bits / (double)cpi->rolling_target_bits;
//if ( cpi->twopass.est_max_qcorrection_factor > rolling_ratio )
@@ -1626,7 +1601,7 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
double abs_mv_in_out_accumulator = 0.0;
double mod_err_per_mb_accumulator = 0.0;
- int max_group_bits;
+ int max_bits = frame_max_bits(cpi); // Max for a single frame
unsigned int allow_alt_ref =
cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames;
@@ -1988,9 +1963,8 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
// Clip cpi->twopass.gf_group_bits based on user supplied data rate
// variability limit (cpi->oxcf.two_pass_vbrmax_section)
- max_group_bits = gf_group_max_bits(cpi);
- if (cpi->twopass.gf_group_bits > max_group_bits)
- cpi->twopass.gf_group_bits = max_group_bits;
+ if (cpi->twopass.gf_group_bits > max_bits * cpi->baseline_gf_interval)
+ cpi->twopass.gf_group_bits = max_bits * cpi->baseline_gf_interval;
// Reset the file position
reset_fpf_position(cpi, start_pos);
@@ -2090,6 +2064,13 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
}
}
+ // Apply an additional limit for CBR
+ if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+ {
+ if (cpi->twopass.gf_bits > (cpi->buffer_level >> 1))
+ cpi->twopass.gf_bits = cpi->buffer_level >> 1;
+ }
+
// Dont allow a negative value for gf_bits
if (gf_bits < 0)
gf_bits = 0;
@@ -2126,6 +2107,10 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
if (cpi->twopass.gf_group_bits < 0)
cpi->twopass.gf_group_bits = 0;
+ // This condition could fail if there are two kfs very close together
+ // despite (MIN_GF_INTERVAL) and would cause a devide by 0 in the
+ // calculation of cpi->twopass.alt_extra_bits.
+ if ( cpi->baseline_gf_interval >= 3 )
{
#if NEW_BOOST
int boost = (cpi->source_alt_ref_pending)
@@ -2133,19 +2118,24 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
#else
int boost = cpi->gfu_boost;
#endif
- // Set aside some bits for a mid gf sequence boost
- if ((boost > 150) && (cpi->baseline_gf_interval > 5))
+ if ( boost >= 150 )
{
- int pct_extra = (boost - 100) / 50;
- pct_extra = (pct_extra > 10) ? 10 : pct_extra;
+ int pct_extra;
- cpi->twopass.mid_gf_extra_bits =
+ pct_extra = (boost - 100) / 50;
+ pct_extra = (pct_extra > 20) ? 20 : pct_extra;
+
+ cpi->twopass.alt_extra_bits =
(cpi->twopass.gf_group_bits * pct_extra) / 100;
- cpi->twopass.gf_group_bits -= cpi->twopass.mid_gf_extra_bits;
+ cpi->twopass.gf_group_bits -= cpi->twopass.alt_extra_bits;
+ cpi->twopass.alt_extra_bits /=
+ ((cpi->baseline_gf_interval-1)>>1);
}
else
- cpi->twopass.mid_gf_extra_bits = 0;
+ cpi->twopass.alt_extra_bits = 0;
}
+ else
+ cpi->twopass.alt_extra_bits = 0;
}
// Adjustment to estimate_max_q based on a measure of complexity of the section
@@ -2225,9 +2215,12 @@ static void assign_std_frame_bits(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
target_frame_size += cpi->min_frame_bandwidth; // Add in the minimum number of bits that is set aside for every frame.
- // Special case for the frame that lies half way between two gfs
- if (cpi->common.frames_since_golden == cpi->baseline_gf_interval / 2)
- target_frame_size += cpi->twopass.mid_gf_extra_bits;
+ // Every other frame gets a few extra bits
+ if ( (cpi->common.frames_since_golden & 0x01) &&
+ (cpi->frames_till_gf_update_due > 0) )
+ {
+ target_frame_size += cpi->twopass.alt_extra_bits;
+ }
cpi->per_frame_bandwidth = target_frame_size; // Per frame bit target for this frame
}
@@ -2570,8 +2563,11 @@ static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
&& lookup_next_frame_stats(cpi, &next_frame) != EOF)
{
// Normal scene cut check
- if (test_candidate_kf(cpi, &last_frame, this_frame, &next_frame))
+ if ( ( i >= MIN_GF_INTERVAL ) &&
+ test_candidate_kf(cpi, &last_frame, this_frame, &next_frame) )
+ {
break;
+ }
// How fast is prediction quality decaying
loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index 3f7b86854..ff9a64172 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -1460,7 +1460,6 @@ static void init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->rolling_actual_bits = cpi->av_per_frame_bandwidth;
cpi->long_rolling_target_bits = cpi->av_per_frame_bandwidth;
cpi->long_rolling_actual_bits = cpi->av_per_frame_bandwidth;
- cpi->buffered_av_per_frame_bandwidth = cpi->av_per_frame_bandwidth;
cpi->total_actual_bits = 0;
cpi->total_target_vs_actual = 0;
@@ -1556,7 +1555,7 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
break;
}
- if (cpi->pass == 0 && cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER)
+ if (cpi->pass == 0)
cpi->auto_worst_q = 1;
cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
@@ -3198,116 +3197,6 @@ void loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm)
}
-
-static void update_buffer_level(VP8_COMP *cpi)
-{
- int64_t tmp;
-
- /* Update the buffered average bitrate.
- *
- * The buffered average bitrate tracks the bitrate over the buffer
- * window. Here we simulate taking a frame of average size out
- * of the buffer, and putting in the new frame just encoded.
- * It is calculated accordingly:
- *
- * A = Average Bits Per Frame In The Buffer
- * P = New Frame Size
- * N = Number of bits in the buffer
- *
- * We recalculate the average as so:
- * (N-A)*A + A*P A * (N - A + P)
- * A' = ------------- = ---------------
- * N N
- *
- * This is modeled after a the standard algorithm for a moving
- * average with fixed weighting (eg A' = ((N-1)*A + 1*P) / N). This makes
- * the step response nonlinear but consistent with expected behavior --
- * when A is large, the model adapts more quickly, since there are
- * fewer frames in the buffer and conversely when A is small there
- * will be more frames in the buffer so the average will adapt
- * slowly.
- *
- * TODO(jkoleszar): This may give poor step response in some situations,
- * for example motion following a long static section. It might be
- * worth experimenting more with weighting by av_per_frame_bandwidth
- * rather than buffered_av_per_frame_bandwidth or using a more accurate
- * algorithm to get faster response. Current testing showed worse results
- * with that setting though.
- *
- */
-
- /* Guard against buffered_av_per_frame_bandwidth falling to 0. Should
- * never happen, but without this check, it would be irrecoverable.
- */
- if(cpi->buffered_av_per_frame_bandwidth == 0)
- cpi->buffered_av_per_frame_bandwidth = 1;
-
- tmp = cpi->oxcf.maximum_buffer_size
- - cpi->buffered_av_per_frame_bandwidth
- + cpi->projected_frame_size;
- tmp *= cpi->buffered_av_per_frame_bandwidth;
- cpi->buffered_av_per_frame_bandwidth = tmp
- / cpi->oxcf.maximum_buffer_size;
-
- if(cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
- {
- /* In CBR mode, buffer level is synthesized from the buffered
- * average per-frame bandwidth to get the response characteristics
- * of that model, rather than using the unbounded (wrt buffer size)
- * bits_off_target. ie, the long term average bitrate doesn't
- * matter in CBR mode. If the clip is consistently undershooting
- * because it is very static, for example, you don't want to blow
- * your short term bitrate budget trying to the the long term spend
- * up to the target when you hit a motion section.
- *
- * Instead, the ratio of buffered_av_per_frame_bandwidth to the
- * target av_per_frame_bandwidth is taken, scaled by
- * maximum_buffer_size and centered around optimal_buffer_level,
- * which presents the expected behavior of buffer_level for the other
- * parts of the rate control code which handle the targeting.
- *
- * Note that this only happens after the starting_buffer_level
- * has passed, to give the model a chance to stabilize.
- */
- if(cpi->total_actual_bits > cpi->oxcf.starting_buffer_level)
- {
- tmp = (int64_t)cpi->buffered_av_per_frame_bandwidth
- * cpi->oxcf.maximum_buffer_size
- / cpi->av_per_frame_bandwidth;
- cpi->buffer_level = cpi->oxcf.maximum_buffer_size
- - tmp
- + cpi->oxcf.optimal_buffer_level;
- }
- else
- cpi->buffer_level = cpi->oxcf.optimal_buffer_level;
-
- /* Accumulate recent overshoot error.
- *
- * If this frame is larger than the target, then accumulate
- * that error to apply as a damping factor later. Only care about
- * recent overshoot, so this value decays by (N-P)/N
- */
- if(cpi->total_actual_bits > cpi->oxcf.starting_buffer_level)
- {
- int64_t decayed_overshoot;
-
- decayed_overshoot = cpi->accumulated_overshoot;
- decayed_overshoot *= (cpi->oxcf.maximum_buffer_size
- - cpi->projected_frame_size);
- decayed_overshoot /= cpi->oxcf.maximum_buffer_size;
- cpi->accumulated_overshoot = decayed_overshoot;
-
- cpi->accumulated_overshoot +=
- (cpi->projected_frame_size > cpi->av_per_frame_bandwidth)
- ? cpi->projected_frame_size - cpi->av_per_frame_bandwidth
- : 0;
- }
- }
- else
- cpi->buffer_level = cpi->bits_off_target;
-}
-
-
static void encode_frame_to_data_rate
(
VP8_COMP *cpi,
@@ -3553,8 +3442,7 @@ static void encode_frame_to_data_rate
// For CBR if the buffer reaches its maximum level then we can no longer
// save up bits for later frames so we might as well use them up
// on the current frame.
- if (cpi->pass == 2
- && (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+ if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
(cpi->buffer_level >= cpi->oxcf.optimal_buffer_level) && cpi->buffered_mode)
{
int Adjustment = cpi->active_worst_quality / 4; // Max adjustment is 1/4
@@ -3645,10 +3533,6 @@ static void encode_frame_to_data_rate
}
else
{
- if(cpi->pass != 2)
- Q = cpi->auto_worst_q?
- cpi->active_worst_quality:cpi->avg_frame_qindex;
-
cpi->active_best_quality = inter_minq[Q];
// For the constant/constrained quality mode we dont want
@@ -3950,17 +3834,15 @@ static void encode_frame_to_data_rate
(cpi->active_worst_quality < cpi->worst_quality) &&
(cpi->projected_frame_size > frame_over_shoot_limit))
{
- /* step down active_worst_quality such that the corresponding
- * active_best_quality will be equal to the current
- * active_worst_quality + 1. Once the limit on active_best_quality
- * is reached, active_worst_quality will equal worst_quality.
- */
- int i;
+ int over_size_percent = ((cpi->projected_frame_size - frame_over_shoot_limit) * 100) / frame_over_shoot_limit;
- for(i=cpi->active_worst_quality; i<cpi->worst_quality; i++)
- if(inter_minq[i] >= cpi->active_worst_quality + 1)
- break;
- cpi->active_worst_quality = i;
+ // If so is there any scope for relaxing it
+ while ((cpi->active_worst_quality < cpi->worst_quality) && (over_size_percent > 0))
+ {
+ cpi->active_worst_quality++;
+ top_index = cpi->active_worst_quality;
+ over_size_percent = (int)(over_size_percent * 0.96); // Assume 1 qstep = about 4% on frame size.
+ }
// If we have updated the active max Q do not call vp8_update_rate_correction_factors() this loop.
active_worst_qchanged = TRUE;
@@ -4348,9 +4230,10 @@ static void encode_frame_to_data_rate
// Update the buffer level variable.
// Non-viewable frames are a special case and are treated as pure overhead.
- if ( cm->show_frame )
- cpi->bits_off_target += cpi->av_per_frame_bandwidth;
- cpi->bits_off_target -= cpi->projected_frame_size;
+ if ( !cm->show_frame )
+ cpi->bits_off_target -= cpi->projected_frame_size;
+ else
+ cpi->bits_off_target += cpi->av_per_frame_bandwidth - cpi->projected_frame_size;
// Rolling monitors of whether we are over or underspending used to help regulate min and Max Q in two pass.
cpi->rolling_target_bits = ((cpi->rolling_target_bits * 3) + cpi->this_frame_target + 2) / 4;
@@ -4364,7 +4247,7 @@ static void encode_frame_to_data_rate
// Debug stats
cpi->total_target_vs_actual += (cpi->this_frame_target - cpi->projected_frame_size);
- update_buffer_level(cpi);
+ cpi->buffer_level = cpi->bits_off_target;
// Update bits left to the kf and gf groups to account for overshoot or undershoot on these frames
if (cm->frame_type == KEY_FRAME)
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index 0d347e363..f75f6cb57 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -348,10 +348,6 @@ typedef struct VP8_COMP
int per_frame_bandwidth; // Current section per frame bandwidth target
int av_per_frame_bandwidth; // Average frame size target for clip
int min_frame_bandwidth; // Minimum allocation that should be used for any frame
- int buffered_av_per_frame_bandwidth; // Average bitrate over the last buffer
- int buffered_av_per_frame_bandwidth_rem; // Average bitrate remainder
- int accumulated_overshoot; // Accumulated # of bits spent > target
-
int inter_frame_target;
double output_frame_rate;
int64_t last_time_stamp_seen;
@@ -556,7 +552,7 @@ typedef struct VP8_COMP
int gf_group_bits; // Projected Bits available for a group of frames including 1 GF or ARF
int gf_bits; // Bits for the golden frame or ARF - 2 pass only
- int mid_gf_extra_bits; // A few extra bits for the frame half way between two gfs.
+ int alt_extra_bits;
double est_max_qcorrection_factor;
} twopass;
diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c
index 769c91adb..46e1d9dd9 100644
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -608,7 +608,7 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
int min_frame_target;
int Adjustment;
- min_frame_target = 1;
+ min_frame_target = 0;
if (cpi->pass == 2)
{
@@ -617,11 +617,9 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
if (min_frame_target < (cpi->av_per_frame_bandwidth >> 5))
min_frame_target = cpi->av_per_frame_bandwidth >> 5;
}
- else
- {
- if (min_frame_target < cpi->per_frame_bandwidth / 4)
- min_frame_target = cpi->per_frame_bandwidth / 4;
- }
+ else if (min_frame_target < cpi->per_frame_bandwidth / 4)
+ min_frame_target = cpi->per_frame_bandwidth / 4;
+
// Special alt reference frame case
if (cpi->common.refresh_alt_ref_frame)
@@ -1114,33 +1112,6 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
}
}
-
- if (cpi->pass==0
- && cpi->common.refresh_golden_frame
- && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
- int64_t adjust;
-
- /*
- frames_in_buffer = cpi->oxcf.maximum_buffer_size
- / cpi->av_per_frame_bandwidth;
- gf_in_buffer = frames_in_buffer /
- cpi->frames_till_gf_update_due;
- overshoot_per_gf = cpi->accumulated_overshoot / gf_in_buffer;
-
- */
-
- adjust = cpi->accumulated_overshoot;
- adjust *= cpi->frames_till_gf_update_due + 1;
- adjust *= cpi->av_per_frame_bandwidth;
- adjust /= cpi->oxcf.maximum_buffer_size;
-
- if (adjust > (cpi->this_frame_target - min_frame_target))
- adjust = (cpi->this_frame_target - min_frame_target);
- else if (adjust < 0)
- adjust = 0;
-
- cpi->this_frame_target -= adjust;
- }
}