diff options
Diffstat (limited to 'vp8')
-rw-r--r-- | vp8/common/onyxd.h | 1 | ||||
-rw-r--r-- | vp8/decoder/decodemv.c | 30 | ||||
-rw-r--r-- | vp8/decoder/decodframe.c | 149 | ||||
-rw-r--r-- | vp8/decoder/error_concealment.c | 1 | ||||
-rw-r--r-- | vp8/decoder/onyxd_if.c | 22 | ||||
-rw-r--r-- | vp8/decoder/onyxd_int.h | 4 | ||||
-rw-r--r-- | vp8/decoder/threading.c | 105 | ||||
-rw-r--r-- | vp8/encoder/firstpass.c | 108 | ||||
-rw-r--r-- | vp8/encoder/onyx_if.c | 147 | ||||
-rw-r--r-- | vp8/encoder/onyx_int.h | 6 | ||||
-rw-r--r-- | vp8/encoder/ratectrl.c | 37 |
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; - } } |