diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c index b985cb1b7fa88def67d7fdef3e1e658e809b6701..0b58b0eaae809272ec0dd99d3be2f12370aa80cc 100644 --- a/vp8/vp8_cx_iface.c +++ b/vp8/vp8_cx_iface.c @@ -1238,6 +1238,7 @@ static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] = {1, 30}, /* g_timebase */ 0, /* g_error_resilient */ + 0, /* g_frame_parallel_decoding */ VPX_RC_ONE_PASS, /* g_pass */ diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h index 46ae2f0f44f21690baffccd24c7a911aa764aa15..d757c398ebf781fd7d6145ddb04b1556cf08fadd 100644 --- a/vp9/common/vp9_onyx.h +++ b/vp9/common/vp9_onyx.h @@ -165,6 +165,12 @@ extern "C" */ unsigned int error_resilient_mode; + /* Bitfield defining the parallel decoding mode where the + * decoding in successive frames may be conducted in parallel + * just by decoding the frame headers. + */ + unsigned int frame_parallel_decoding_mode; + int arnr_max_frames; int arnr_strength; int arnr_type; diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index 4e2fa379922d05b0d3fbe36f169be22fa7cb5d52..cbabfa3da6e967d2be969455b3214dc898d1c4ba 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -277,6 +277,7 @@ typedef struct VP9Common { #endif int error_resilient_mode; + int frame_parallel_decoding_mode; } VP9_COMMON; static int get_free_fb(VP9_COMMON *cm) { diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index 31ae257dc3a183def4b89eb1d5c3b98c55b7f899..76fb817dfd88c11e3c7cfc008a4e83f188482fa5 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -791,7 +791,8 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, if (mbmi->mode != ZEROMV) { vp9_find_best_ref_mvs(xd, - pbi->common.error_resilient_mode ? + pbi->common.error_resilient_mode || + pbi->common.frame_parallel_decoding_mode ? 0 : xd->pre.y_buffer, recon_y_stride, mbmi->ref_mvs[ref_frame], @@ -851,7 +852,8 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, if (mbmi->mode != ZEROMV) { vp9_find_best_ref_mvs(xd, - pbi->common.error_resilient_mode ? + pbi->common.error_resilient_mode || + pbi->common.frame_parallel_decoding_mode ? 0 : xd->second_pre.y_buffer, recon_y_stride, mbmi->ref_mvs[mbmi->second_ref_frame], diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 10bcbf953002851db23276c06803bb6b59a3ce9b..936251a6adb3157fc7f344dd034a99b0b486036a 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -1624,7 +1624,13 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc); } - pc->refresh_entropy_probs = vp9_read_bit(&header_bc); + if (!pc->error_resilient_mode) { + pc->refresh_entropy_probs = vp9_read_bit(&header_bc); + pc->frame_parallel_decoding_mode = vp9_read_bit(&header_bc); + } else { + pc->refresh_entropy_probs = 0; + pc->frame_parallel_decoding_mode = 1; + } pc->frame_context_idx = vp9_read_literal(&header_bc, NUM_FRAME_CONTEXTS_LG2); vpx_memcpy(&pc->fc, &pc->frame_contexts[pc->frame_context_idx], sizeof(pc->fc)); @@ -1771,10 +1777,12 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { "A stream must start with a complete key frame"); } - if (!pc->error_resilient_mode) + if (!pc->error_resilient_mode && + !pc->frame_parallel_decoding_mode) vp9_adapt_coef_probs(pc); if (pc->frame_type != KEY_FRAME) { - if (!pc->error_resilient_mode) { + if (!pc->error_resilient_mode && + !pc->frame_parallel_decoding_mode) { vp9_adapt_mode_probs(pc); vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv); vp9_adapt_mode_context(&pbi->common); diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 34d27d1beb2fe846078c04a4aa1f31a21bc86e30..23a5b93c57acc7c2811c8ea918a2a3791a3e8f7e 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -1833,7 +1833,11 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, #endif } - vp9_write_bit(&header_bc, pc->refresh_entropy_probs); + if (!pc->error_resilient_mode) { + vp9_write_bit(&header_bc, pc->refresh_entropy_probs); + vp9_write_bit(&header_bc, pc->frame_parallel_decoding_mode); + } + vp9_write_literal(&header_bc, pc->frame_context_idx, NUM_FRAME_CONTEXTS_LG2); @@ -2023,9 +2027,6 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, * final packing pass */ // if (!cpi->dummy_packing) vp9_zero(cpi->NMVcount); write_modes(cpi, &residual_bc); - - if (!cpi->common.error_resilient_mode) - vp9_adapt_mode_context(&cpi->common); } vp9_stop_encode(&residual_bc); diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index a14165752bb73b28ff7991c7e00a310666222ffe..d1c48e14cbc39d9289cfd23cfb2f08dbecad5fdf 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -2824,6 +2824,12 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, } cm->error_resilient_mode = (cpi->oxcf.error_resilient_mode != 0); + cm->frame_parallel_decoding_mode = + (cpi->oxcf.frame_parallel_decoding_mode != 0); + if (cm->error_resilient_mode) { + cm->frame_parallel_decoding_mode = 1; + cm->refresh_entropy_probs = 0; + } } // Test code for new segment features @@ -3449,7 +3455,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, vp9_copy(cpi->common.fc.hybrid_coef_counts_16x16, cpi->hybrid_coef_counts_16x16); vp9_copy(cpi->common.fc.coef_counts_32x32, cpi->coef_counts_32x32); - if (!cpi->common.error_resilient_mode) + if (!cpi->common.error_resilient_mode && + !cpi->common.frame_parallel_decoding_mode) vp9_adapt_coef_probs(&cpi->common); if (cpi->common.frame_type != KEY_FRAME) { vp9_copy(cpi->common.fc.sb_ymode_counts, cpi->sb_ymode_count); @@ -3462,12 +3469,13 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, #if CONFIG_COMP_INTERINTRA_PRED vp9_copy(cpi->common.fc.interintra_counts, cpi->interintra_count); #endif - if (!cpi->common.error_resilient_mode) - vp9_adapt_mode_probs(&cpi->common); - cpi->common.fc.NMVcount = cpi->NMVcount; - if (!cpi->common.error_resilient_mode) + if (!cpi->common.error_resilient_mode && + !cpi->common.frame_parallel_decoding_mode) { + vp9_adapt_mode_probs(&cpi->common); + vp9_adapt_mode_context(&cpi->common); vp9_adapt_nmv_probs(&cpi->common, cpi->mb.e_mbd.allow_high_precision_mv); + } } #if CONFIG_COMP_INTERINTRA_PRED if (cm->frame_type != KEY_FRAME) diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 8710475bda53b9cb2b15c5cd243dde7de2d23c70..2f52f02972a1c119412078aa4e81b8f1d6840da1 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -3179,7 +3179,8 @@ static void setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x, // Candidate refinement carried out at encoder and decoder vp9_find_best_ref_mvs(xd, - cpi->common.error_resilient_mode ? + cpi->common.error_resilient_mode || + cpi->common.frame_parallel_decoding_mode ? 0 : y_buffer[frame_type], yv12->y_stride, mbmi->ref_mvs[frame_type], diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 0c82d067cec3ac5e39a25df0bcd198acb68858dc..75df0e0372248e4239b54596479897306db7e2f0 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -314,6 +314,7 @@ static vpx_codec_err_t set_vp8e_config(VP9_CONFIG *oxcf, #endif oxcf->error_resilient_mode = cfg.g_error_resilient; + oxcf->frame_parallel_decoding_mode = cfg.g_frame_parallel_decoding; /* printf("Current VP9 Settings: \n"); printf("target_bandwidth: %d\n", oxcf->target_bandwidth); @@ -342,6 +343,8 @@ static vpx_codec_err_t set_vp8e_config(VP9_CONFIG *oxcf, printf("Version: %d\n", oxcf->Version); printf("encode_breakout: %d\n", oxcf->encode_breakout); printf("error resilient: %d\n", oxcf->error_resilient_mode); + printf("frame parallel detokenization: %d\n", + oxcf->frame_parallel_decoding_mode); */ return VPX_CODEC_OK; } @@ -1034,6 +1037,7 @@ static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] = { {1, 30}, /* g_timebase */ 0, /* g_error_resilient */ + 0, /* g_frame_parallel_decoding */ VPX_RC_ONE_PASS, /* g_pass */ diff --git a/vpx/vpx_encoder.h b/vpx/vpx_encoder.h index ffdbc0644f794b157edf597715f8efc138e0f21a..2ec09bdd4b2b25a956c6b8231b14bff06e8849a0 100644 --- a/vpx/vpx_encoder.h +++ b/vpx/vpx_encoder.h @@ -334,6 +334,12 @@ extern "C" { */ vpx_codec_er_flags_t g_error_resilient; + /*!\brief Enable frame parallel decoding mode + * This value should be 1 to encode in a way that enables frame parallel + * decoding. Otherwise make it 0. + */ + unsigned int g_frame_parallel_decoding; + /*!\brief Multi-pass Encoding Mode * diff --git a/vpxenc.c b/vpxenc.c index d53d9db57a32f7c63844f5df3a3152510c4d5654..e6f935174fccc0a13119f5923254530160c3b8a7 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -993,12 +993,20 @@ static const arg_def_t timebase = ARG_DEF(NULL, "timebase", 1, "Output timestamp precision (fractional seconds)"); static const arg_def_t error_resilient = ARG_DEF(NULL, "error-resilient", 1, "Enable error resiliency features"); +#if CONFIG_VP9_ENCODER +static const arg_def_t frame_parallel_decoding = ARG_DEF( + NULL, "frame-parallel", 1, "Enable frame parallel decodability features"); +#endif static const arg_def_t lag_in_frames = ARG_DEF(NULL, "lag-in-frames", 1, "Max number of frames to lag"); static const arg_def_t *global_args[] = { &use_yv12, &use_i420, &usage, &threads, &profile, - &width, &height, &stereo_mode, &timebase, &framerate, &error_resilient, + &width, &height, &stereo_mode, &timebase, &framerate, + &error_resilient, +#if CONFIG_VP9_ENCODER + &frame_parallel_decoding, +#endif &lag_in_frames, NULL }; @@ -1882,6 +1890,10 @@ static int parse_stream_params(struct global_config *global, validate_positive_rational(arg.name, &config->cfg.g_timebase); } else if (arg_match(&arg, &error_resilient, argi)) config->cfg.g_error_resilient = arg_parse_uint(&arg); +#if CONFIG_VP9_ENCODER + else if (arg_match(&arg, &frame_parallel_decoding, argi)) + config->cfg.g_frame_parallel_decoding = arg_parse_uint(&arg); +#endif else if (arg_match(&arg, &lag_in_frames, argi)) config->cfg.g_lag_in_frames = arg_parse_uint(&arg); else if (arg_match(&arg, &dropframe_thresh, argi)) @@ -2062,6 +2074,9 @@ static void show_stream_config(struct stream_state *stream, SHOW(g_timebase.num); SHOW(g_timebase.den); SHOW(g_error_resilient); +#if CONFIG_VP9_ENCODER + SHOW(g_frame_parallel_decoding); +#endif SHOW(g_pass); SHOW(g_lag_in_frames); SHOW(rc_dropframe_thresh);