Compare commits

...

7 Commits

Author SHA1 Message Date
John Koleszar
20307c70ae Update CHANGELOG for v0.9.7-p1
Change-Id: I5490a9cad2d6752832b6bf4ec1835c06a45eeb9b
2011-08-15 17:02:45 -04:00
Stefan Holmer
99d870a472 Don't set the bmi mode when doing error concealment
Since the block will be interpreted as an inter block, the mode will
be interpreted as a motion vector, resulting in bad concealment.

Change-Id: Ifcc685ae1cc883492bce6dbd61e418d91a89b053
2011-08-15 11:46:04 -04:00
John Koleszar
5e562c77db Generate libvpx_srcs.txt from current configuration
To get a list of files that the libvpx library depends on in the current
configuration, run:

  $ make target=libs libvpx_srcs.txt

Change-Id: I68a69648ecf212f0fe29c325297728ac2a9393d9
2011-08-12 14:59:22 -04:00
John Koleszar
e96131705a Revert "Improved 1-pass CBR rate control"
This reverts commit b5ea2fbc2c. Further
testing showed noticable keyframe popping in some cases, reverting this
for now to give time for a proper fix.

Conflicts:

	vp8/encoder/onyx_if.c
	vp8/encoder/ratectrl.c

Change-Id: I159f53d1bf0e24c035754ab3ded8ccfd58fd04af
2011-08-12 14:51:36 -04:00
John Koleszar
a4c2211ea3 Propagate macroblock MV to subblocks for error concealment
EC expects the subblock MVs to be populated, but
f1d6cc79e4 removed this code. This
commit restores it, protected by CONFIG_ERROR_CONCEALMENT. May move this
to the EC code more directly in the future.

Change-Id: I44f8f985720cb9a1bf222e59143f9e69abf56ad2
2011-08-12 14:49:35 -04:00
Stefan Holmer
a609be5633 Disable error concealment until first key frame is decoded
When error concealment is enabled the first key frame must
be successfully received before error concealment is activated.
Error concealment will be activated when the delta following
delta frame is received.

Also fixed a couple of bugs related to error tracking in
multi-threading. And avoiding decoding corrupt residual
when we have multiple non-resilient partitions.

Change-Id: I45c4bb296e2f05f57624aef500a874faf431a60d
2011-08-12 14:49:34 -04:00
John Koleszar
cdae03a4eb Fix potential OOB read with Error Concealment
This patch fixes an OOB read when error concealment is enabled and the
partition sizes are corrupt. The partition size read from the bitstream
was not being validated in EC mode.

Change-Id: Ia81dfd4bce1ab29ee78e42320abe52cee8318974
2011-08-12 14:49:34 -04:00
13 changed files with 311 additions and 302 deletions

View File

@@ -1,3 +1,33 @@
2011-08-15 v0.9.7-p1 "Cayuga" patch 1
This is an incremental bugfix release against Cayuga. All users of that
release are strongly encouraged to upgrade.
- Fix potential OOB reads (cdae03a)
An unbounded out of bounds read was discovered when the
decoder was requested to perform error concealment (new in
Cayuga) given a frame with corrupt partition sizes.
A bounded out of bounds read was discovered affecting all
versions of libvpx. Given an multipartition input frame that
is truncated between the mode/mv partition and the first
residiual paritition (in the block of partition offsets), up
to 3 extra bytes could have been read from the source buffer.
The code will not take any action regardless of the contents
of these undefined bytes, as the truncated buffer is detected
immediately following the read based on the calculated
starting position of the coefficient partition.
- Fix potential error concealment crash when the very first frame
is missing or corrupt (a609be5)
- Fix significant artifacts in error concealment (a4c2211, 99d870a)
- Revert 1-pass CBR rate control changes (e961317)
Further testing showed this change produced undesirable visual
artifacts, rolling back for now.
2011-08-02 v0.9.7 "Cayuga" 2011-08-02 v0.9.7 "Cayuga"
Our third named release, focused on a faster, higher quality, encoder. Our third named release, focused on a faster, higher quality, encoder.

View File

@@ -132,6 +132,14 @@ CODEC_SRCS=$(call enabled,CODEC_SRCS)
INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(CODEC_SRCS) INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(CODEC_SRCS)
INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(call enabled,CODEC_EXPORTS) INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(call enabled,CODEC_EXPORTS)
# Generate a list of all enabled sources, in particular for exporting to gyp
# based build systems.
libvpx_srcs.txt:
@echo " [CREATE] $@"
@echo $(CODEC_SRCS) | xargs -n1 echo | sort -u > $@
ifeq ($(CONFIG_EXTERNAL_BUILD),yes) ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
ifeq ($(CONFIG_MSVS),yes) ifeq ($(CONFIG_MSVS),yes)

View File

@@ -18,7 +18,6 @@
extern "C" extern "C"
{ {
#endif #endif
#include "vpx/vpx_codec.h"
#include "type_aliases.h" #include "type_aliases.h"
#include "vpx_scale/yv12config.h" #include "vpx_scale/yv12config.h"
#include "ppflags.h" #include "ppflags.h"

View File

@@ -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 */ /* 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, vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
mb_to_top_edge, mb_to_bottom_edge); mb_to_top_edge, mb_to_bottom_edge);
break; goto propagate_mv;
case NEARESTMV: case NEARESTMV:
mv->as_int = nearest.as_int; mv->as_int = nearest.as_int;
/* Clip "next_nearest" so that it does not extend to far out of image */ /* 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, vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
mb_to_top_edge, mb_to_bottom_edge); mb_to_top_edge, mb_to_bottom_edge);
break; goto propagate_mv;
case ZEROMV: case ZEROMV:
mv->as_int = 0; mv->as_int = 0;
break; goto propagate_mv;
case NEWMV: case NEWMV:
read_mv(bc, &mv->as_mv, (const MV_CONTEXT *) mvc); 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_right_edge,
mb_to_top_edge, mb_to_top_edge,
mb_to_bottom_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:; default:;
#if CONFIG_DEBUG #if CONFIG_DEBUG
assert(0); assert(0);

View File

@@ -183,6 +183,7 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
unsigned int mb_idx) unsigned int mb_idx)
{ {
int eobtotal = 0; int eobtotal = 0;
int throw_residual = 0;
MB_PREDICTION_MODE mode; MB_PREDICTION_MODE mode;
int i; int i;
@@ -203,7 +204,8 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
mode = xd->mode_info_context->mbmi.mode; 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 /* Special case: Force the loopfilter to skip when eobtotal and
* mb_skip_coeff are zero. * mb_skip_coeff are zero.
@@ -235,14 +237,21 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
vp8_build_inter_predictors_mb(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 CONFIG_ERROR_CONCEALMENT
if (pbi->ec_enabled && if (pbi->ec_active &&
(mb_idx >= pbi->mvs_corrupt_from_mb || (mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
vp8dx_bool_error(xd->current_bc)))
{ {
/* MB with corrupt residuals or corrupt mode/motion vectors. /* MB with corrupt residuals or corrupt mode/motion vectors.
* Better to use the predictor as reconstruction. * Better to use the predictor as reconstruction.
*/ */
pbi->frame_corrupt_residual = 1;
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff)); vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
vp8_conceal_corrupt_mb(xd); vp8_conceal_corrupt_mb(xd);
return; return;
@@ -376,23 +385,29 @@ 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; xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
#if CONFIG_ERROR_CONCEALMENT #if CONFIG_ERROR_CONCEALMENT
if (pbi->ec_enabled && {
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 && xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
vp8dx_bool_error(xd->current_bc)) corrupt_residual)
{ {
/* We have an intra block with corrupt coefficients, better to /* We have an intra block with corrupt coefficients, better to
* conceal with an inter block. Interpolate MVs from neighboring MBs * conceal with an inter block. Interpolate MVs from neighboring
* MBs.
* *
* Note that for the first mb with corrupt residual in a frame, * Note that for the first mb with corrupt residual in a frame,
* we might not discover that before decoding the residual. That * we might not discover that before decoding the residual. That
* happens after this check, and therefore no inter concealment will * happens after this check, and therefore no inter concealment
* be done. * will be done.
*/ */
vp8_interpolate_motion(xd, vp8_interpolate_motion(xd,
mb_row, mb_col, mb_row, mb_col,
pc->mb_rows, pc->mb_cols, pc->mb_rows, pc->mb_cols,
pc->mode_info_stride); pc->mode_info_stride);
} }
}
#endif #endif
update_blockd_bmi(xd); update_blockd_bmi(xd);
@@ -495,6 +510,15 @@ static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
#endif #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, static void setup_token_decoder(VP8D_COMP *pbi,
const unsigned char *cx_data) 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); (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
/* Only update the multi_token_partition field if we are sure the value /* Only update the multi_token_partition field if we are sure the value
* is correct. */ * 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; pc->multi_token_partition = multi_token_partition;
num_part = 1 << pc->multi_token_partition; num_part = 1 << pc->multi_token_partition;
@@ -529,25 +553,41 @@ static void setup_token_decoder(VP8D_COMP *pbi,
for (i = 0; i < num_part; i++) for (i = 0; i < num_part; i++)
{ {
const unsigned char *partition_size_ptr = cx_data + i * 3; 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 /* 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) if (i < num_part - 1)
{ {
if (read_is_valid(partition_size_ptr, 3, user_data_end))
partition_size = read_partition_size(partition_size_ptr); 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 else
{ partition_size = bytes_left;
partition_size = user_data_end - partition;
}
if (!pbi->ec_enabled && (partition + partition_size > user_data_end /* Validate the calculated partition length. If the buffer
|| partition + partition_size < partition)) * 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))
{
if (pbi->ec_active)
partition_size = bytes_left;
else
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition " "Truncated packet or corrupt partition "
"%d length", i + 1); "%d length", i + 1);
}
if (vp8dx_start_decode(bool_decoder, partition, partition_size)) if (vp8dx_start_decode(bool_decoder, partition, partition_size))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
@@ -634,6 +674,9 @@ static void init_frame(VP8D_COMP *pbi)
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8); xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16); 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; xd->left_context = &pc->left_context;
@@ -656,6 +699,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
int mb_row; int mb_row;
int i, j, k, l; int i, j, k, l;
const int *const mb_feature_data_bits = vp8_mb_feature_data_bits; 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) if (pbi->input_partition)
{ {
@@ -669,7 +714,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
if (data_end - data < 3) if (data_end - data < 3)
{ {
if (pbi->ec_enabled) if (pbi->ec_active)
{ {
/* Declare the missing frame as an inter frame since it will /* Declare the missing frame as an inter frame since it will
be handled as an inter frame when we have estimated its 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[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
data += 3; 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)) || data + first_partition_length_in_bytes < data))
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition 0 length"); "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 /* When error concealment is enabled we should only check the sync
* code if we have enough bits available * 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) if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM, 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 * if we have enough data. Otherwise we will end up with the wrong
* size. * 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->Width = (data[3] | (data[4] << 8)) & 0x3fff;
pc->horiz_scale = data[4] >> 6; pc->horiz_scale = data[4] >> 6;
@@ -919,7 +964,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_ERROR_CONCEALMENT #if CONFIG_ERROR_CONCEALMENT
/* Assume we shouldn't refresh golden if the bit is missing */ /* Assume we shouldn't refresh golden if the bit is missing */
xd->corrupted |= vp8dx_bool_error(bc); xd->corrupted |= vp8dx_bool_error(bc);
if (pbi->ec_enabled && xd->corrupted) if (pbi->ec_active && xd->corrupted)
pc->refresh_golden_frame = 0; pc->refresh_golden_frame = 0;
#endif #endif
@@ -927,7 +972,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_ERROR_CONCEALMENT #if CONFIG_ERROR_CONCEALMENT
/* Assume we shouldn't refresh altref if the bit is missing */ /* Assume we shouldn't refresh altref if the bit is missing */
xd->corrupted |= vp8dx_bool_error(bc); xd->corrupted |= vp8dx_bool_error(bc);
if (pbi->ec_enabled && xd->corrupted) if (pbi->ec_active && xd->corrupted)
pc->refresh_alt_ref_frame = 0; pc->refresh_alt_ref_frame = 0;
#endif #endif
@@ -957,7 +1002,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
#if CONFIG_ERROR_CONCEALMENT #if CONFIG_ERROR_CONCEALMENT
/* Assume we should refresh the last frame if the bit is missing */ /* Assume we should refresh the last frame if the bit is missing */
xd->corrupted |= vp8dx_bool_error(bc); xd->corrupted |= vp8dx_bool_error(bc);
if (pbi->ec_enabled && xd->corrupted) if (pbi->ec_active && xd->corrupted)
pc->refresh_last_frame = 1; pc->refresh_last_frame = 1;
#endif #endif
@@ -975,6 +1020,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
} }
{ {
pbi->independent_partitions = 1;
/* read coef probability tree */ /* read coef probability tree */
for (i = 0; i < BLOCK_TYPES; i++) for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++) 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); *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); vp8_decode_mode_mvs(pbi);
#if CONFIG_ERROR_CONCEALMENT #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) 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 /* 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 CONFIG_MULTITHREAD
if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION) if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
{ {
int i;
pbi->frame_corrupt_residual = 0;
vp8mt_decode_mb_rows(pbi, xd); vp8mt_decode_mb_rows(pbi, xd);
vp8_yv12_extend_frame_borders_ptr(&pc->yv12_fb[pc->new_fb_idx]); /*cm->frame_to_show);*/ 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 else
#endif #endif
{ {
int ibc = 0; int ibc = 0;
int num_part = 1 << pc->multi_token_partition; int num_part = 1 << pc->multi_token_partition;
pbi->frame_corrupt_residual = 0;
/* Decode the individual macro block */ /* Decode the individual macro block */
for (mb_row = 0; mb_row < pc->mb_rows; mb_row++) 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); decode_mb_row(pbi, pc, mb_row, xd);
} }
corrupt_tokens |= xd->corrupted;
} }
stop_token_decoder(pbi); stop_token_decoder(pbi);
/* Collect information about decoder corruption. */ /* Collect information about decoder corruption. */
/* 1. Check first boolean decoder for errors. */ /* 1. Check first boolean decoder for errors. */
pc->yv12_fb[pc->new_fb_idx].corrupted = pc->yv12_fb[pc->new_fb_idx].corrupted = vp8dx_bool_error(bc);
vp8dx_bool_error(bc);
/* 2. Check the macroblock information */ /* 2. Check the macroblock information */
pc->yv12_fb[pc->new_fb_idx].corrupted |= pc->yv12_fb[pc->new_fb_idx].corrupted |= corrupt_tokens;
xd->corrupted;
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); */ /* 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) if (pc->refresh_entropy_probs == 0)
{ {
vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc)); vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
pbi->independent_partitions = prev_independent_partitions;
} }
#ifdef PACKET_TESTING #ifdef PACKET_TESTING

View File

@@ -567,7 +567,6 @@ static void interpolate_mvs(MACROBLOCKD *mb,
else else
{ {
mv->as_int = 0; mv->as_int = 0;
mi->bmi[row*4 + col].as_mode = NEW4X4;
mi->mbmi.need_to_clamp_mvs = 0; mi->mbmi.need_to_clamp_mvs = 0;
} }
} }

View File

@@ -101,9 +101,21 @@ VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
#else #else
pbi->ec_enabled = 0; pbi->ec_enabled = 0;
#endif #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; 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; 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 /* If error concealment is disabled we won't signal missing frames to
* the decoder. * the decoder.
*/ */
if (!pbi->ec_enabled) if (!pbi->ec_active)
{ {
/* Signal that we have no frame to show. */ /* Signal that we have no frame to show. */
cm->show_frame = 0; cm->show_frame = 0;
pbi->num_partitions = 0;
if (pbi->input_partition)
pbi->common.multi_token_partition = 0;
/* Nothing more to do. */ /* Nothing more to do. */
return 0; return 0;
} }
@@ -379,6 +395,10 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
#endif #endif
pbi->common.error.setjmp = 0; 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 /* We do not know if the missing frame(s) was supposed to update
* any of the reference buffers, but we act conservative and * any of the reference buffers, but we act conservative and
* mark only the last buffer as corrupted. * mark only the last buffer as corrupted.

View File

@@ -132,7 +132,11 @@ typedef struct VP8Decompressor
unsigned int mvs_corrupt_from_mb; unsigned int mvs_corrupt_from_mb;
#endif #endif
int ec_enabled; int ec_enabled;
int ec_active;
int input_partition; int input_partition;
int decoded_key_frame;
int independent_partitions;
int frame_corrupt_residual;
} VP8D_COMP; } VP8D_COMP;

View File

@@ -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) static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col)
{ {
int eobtotal = 0; int eobtotal = 0;
int throw_residual = 0;
int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs; int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs;
if (xd->mode_info_context->mbmi.mb_skip_coeff) 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 || eobtotal |= (xd->mode_info_context->mbmi.mode == B_PRED ||
xd->mode_info_context->mbmi.mode == SPLITMV); 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 /* Special case: Force the loopfilter to skip when eobtotal and
* mb_skip_coeff are zero. * 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); 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 CONFIG_ERROR_CONCEALMENT
if (pbi->ec_enabled && if (pbi->ec_active &&
(mb_row * pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb || (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. /* MB with corrupt residuals or corrupt mode/motion vectors.
* Better to use the predictor as reconstruction. * Better to use the predictor as reconstruction.
*/ */
pbi->frame_corrupt_residual = 1;
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff)); vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
vp8_conceal_corrupt_mb(xd); vp8_conceal_corrupt_mb(xd);
return; return;
@@ -314,26 +323,33 @@ static THREAD_FUNCTION thread_decoding_proc(void *p_data)
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3; xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
#if CONFIG_ERROR_CONCEALMENT #if CONFIG_ERROR_CONCEALMENT
if (pbi->ec_enabled && {
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 == (xd->mode_info_context->mbmi.ref_frame ==
INTRA_FRAME) && INTRA_FRAME) &&
vp8dx_bool_error(xd->current_bc)) corrupt_residual)
{ {
/* We have an intra block with corrupt coefficients, /* We have an intra block with corrupt
* better to conceal with an inter block. * coefficients, better to conceal with an inter
* block.
* Interpolate MVs from neighboring MBs * Interpolate MVs from neighboring MBs
* *
* Note that for the first mb with corrupt residual * Note that for the first mb with corrupt
* in a frame, we might not discover that before * residual in a frame, we might not discover
* decoding the residual. That happens after this * that before decoding the residual. That
* check, and therefore no inter concealment will be * happens after this check, and therefore no
* done. * inter concealment will be done.
*/ */
vp8_interpolate_motion(xd, vp8_interpolate_motion(xd,
mb_row, mb_col, mb_row, mb_col,
pc->mb_rows, pc->mb_cols, pc->mb_rows, pc->mb_cols,
pc->mode_info_stride); pc->mode_info_stride);
} }
}
#endif #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.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; 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); vp8_build_uvmvs(xd, pc->full_pixel);
decode_macroblock(pbi, xd, mb_row, mb_col); 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) if (pbi->common.filter_level)
{ {
int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED && int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
@@ -803,24 +829,29 @@ void vp8mt_decode_mb_rows( VP8D_COMP *pbi, MACROBLOCKD *xd)
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3; xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
#if CONFIG_ERROR_CONCEALMENT #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 int corrupt_residual = (!pbi->independent_partitions &&
* to conceal with an inter block. Interpolate MVs from pbi->frame_corrupt_residual) ||
* neighboring MBs 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 * Note that for the first mb with corrupt residual in a
* frame, we might not discover that before decoding the * frame, we might not discover that before decoding the
* residual. That happens after this check, and therefore no * residual. That happens after this check, and
* inter concealment will be done. * therefore no inter concealment will be done.
*/ */
vp8_interpolate_motion(xd, vp8_interpolate_motion(xd,
mb_row, mb_col, mb_row, mb_col,
pc->mb_rows, pc->mb_cols, pc->mb_rows, pc->mb_cols,
pc->mode_info_stride); pc->mode_info_stride);
} }
}
#endif #endif

View File

@@ -357,11 +357,25 @@ static int frame_max_bits(VP8_COMP *cpi)
int max_bits; int max_bits;
// For CBR we need to also consider buffer fullness. // 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) if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
{ {
max_bits = 2 * cpi->av_per_frame_bandwidth; double buffer_fullness_ratio = (double)cpi->buffer_level / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.optimal_buffer_level);
max_bits -= cpi->buffered_av_per_frame_bandwidth;
max_bits *= ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0); // 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;
max_bits = (int)(max_bits * buffer_fullness_ratio);
if (max_bits < min_max_bits)
max_bits = min_max_bits; // Lowest value we will set ... which should allow the buffer to refil.
}
} }
// VBR // VBR
else else
@@ -377,45 +391,6 @@ static int frame_max_bits(VP8_COMP *cpi)
return max_bits; return max_bits;
} }
static int gf_group_max_bits(VP8_COMP *cpi)
{
// Max allocation for a golden frame group
int max_bits;
// 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;
}
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);
}
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;
return max_bits;
}
void vp8_init_first_pass(VP8_COMP *cpi) void vp8_init_first_pass(VP8_COMP *cpi)
{ {
zero_stats(cpi->twopass.total_stats); zero_stats(cpi->twopass.total_stats);
@@ -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 abs_mv_in_out_accumulator = 0.0;
double mod_err_per_mb_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 = unsigned int allow_alt_ref =
cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames; 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 // Clip cpi->twopass.gf_group_bits based on user supplied data rate
// variability limit (cpi->oxcf.two_pass_vbrmax_section) // variability limit (cpi->oxcf.two_pass_vbrmax_section)
max_group_bits = gf_group_max_bits(cpi); if (cpi->twopass.gf_group_bits > max_bits * cpi->baseline_gf_interval)
if (cpi->twopass.gf_group_bits > max_group_bits) cpi->twopass.gf_group_bits = max_bits * cpi->baseline_gf_interval;
cpi->twopass.gf_group_bits = max_group_bits;
// Reset the file position // Reset the file position
reset_fpf_position(cpi, start_pos); 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 // Dont allow a negative value for gf_bits
if (gf_bits < 0) if (gf_bits < 0)
gf_bits = 0; gf_bits = 0;

View File

@@ -1460,7 +1460,6 @@ static void init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->rolling_actual_bits = cpi->av_per_frame_bandwidth; cpi->rolling_actual_bits = cpi->av_per_frame_bandwidth;
cpi->long_rolling_target_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->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_actual_bits = 0;
cpi->total_target_vs_actual = 0; cpi->total_target_vs_actual = 0;
@@ -1556,7 +1555,7 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
break; break;
} }
if (cpi->pass == 0 && cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) if (cpi->pass == 0)
cpi->auto_worst_q = 1; cpi->auto_worst_q = 1;
cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q]; 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 static void encode_frame_to_data_rate
( (
VP8_COMP *cpi, 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 // 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 // save up bits for later frames so we might as well use them up
// on the current frame. // on the current frame.
if (cpi->pass == 2 if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
&& (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
(cpi->buffer_level >= cpi->oxcf.optimal_buffer_level) && cpi->buffered_mode) (cpi->buffer_level >= cpi->oxcf.optimal_buffer_level) && cpi->buffered_mode)
{ {
int Adjustment = cpi->active_worst_quality / 4; // Max adjustment is 1/4 int Adjustment = cpi->active_worst_quality / 4; // Max adjustment is 1/4
@@ -3645,10 +3533,6 @@ static void encode_frame_to_data_rate
} }
else 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]; cpi->active_best_quality = inter_minq[Q];
// For the constant/constrained quality mode we dont want // 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->active_worst_quality < cpi->worst_quality) &&
(cpi->projected_frame_size > frame_over_shoot_limit)) (cpi->projected_frame_size > frame_over_shoot_limit))
{ {
/* step down active_worst_quality such that the corresponding int over_size_percent = ((cpi->projected_frame_size - frame_over_shoot_limit) * 100) / frame_over_shoot_limit;
* 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;
for(i=cpi->active_worst_quality; i<cpi->worst_quality; i++) // If so is there any scope for relaxing it
if(inter_minq[i] >= cpi->active_worst_quality + 1) while ((cpi->active_worst_quality < cpi->worst_quality) && (over_size_percent > 0))
break; {
cpi->active_worst_quality = i; 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. // If we have updated the active max Q do not call vp8_update_rate_correction_factors() this loop.
active_worst_qchanged = TRUE; active_worst_qchanged = TRUE;
@@ -4348,9 +4230,10 @@ static void encode_frame_to_data_rate
// Update the buffer level variable. // Update the buffer level variable.
// Non-viewable frames are a special case and are treated as pure overhead. // Non-viewable frames are a special case and are treated as pure overhead.
if ( cm->show_frame ) if ( !cm->show_frame )
cpi->bits_off_target += cpi->av_per_frame_bandwidth;
cpi->bits_off_target -= cpi->projected_frame_size; 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. // 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; 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 // Debug stats
cpi->total_target_vs_actual += (cpi->this_frame_target - cpi->projected_frame_size); 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 // Update bits left to the kf and gf groups to account for overshoot or undershoot on these frames
if (cm->frame_type == KEY_FRAME) if (cm->frame_type == KEY_FRAME)

View File

@@ -348,10 +348,6 @@ typedef struct VP8_COMP
int per_frame_bandwidth; // Current section per frame bandwidth target int per_frame_bandwidth; // Current section per frame bandwidth target
int av_per_frame_bandwidth; // Average frame size target for clip 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 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; int inter_frame_target;
double output_frame_rate; double output_frame_rate;
int64_t last_time_stamp_seen; int64_t last_time_stamp_seen;

View File

@@ -608,7 +608,7 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
int min_frame_target; int min_frame_target;
int Adjustment; int Adjustment;
min_frame_target = 1; min_frame_target = 0;
if (cpi->pass == 2) 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)) if (min_frame_target < (cpi->av_per_frame_bandwidth >> 5))
min_frame_target = cpi->av_per_frame_bandwidth >> 5; min_frame_target = cpi->av_per_frame_bandwidth >> 5;
} }
else else if (min_frame_target < cpi->per_frame_bandwidth / 4)
{
if (min_frame_target < cpi->per_frame_bandwidth / 4)
min_frame_target = cpi->per_frame_bandwidth / 4; min_frame_target = cpi->per_frame_bandwidth / 4;
}
// Special alt reference frame case // Special alt reference frame case
if (cpi->common.refresh_alt_ref_frame) 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;
}
} }