diff options
Diffstat (limited to 'vp9')
-rw-r--r-- | vp9/common/vp9_idct.h | 3 | ||||
-rw-r--r-- | vp9/encoder/vp9_encodeframe.c | 67 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 4 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 4 | ||||
-rw-r--r-- | vp9/encoder/vp9_mcomp.c | 6 | ||||
-rw-r--r-- | vp9/encoder/vp9_mcomp.h | 4 | ||||
-rw-r--r-- | vp9/encoder/vp9_pickmode.c | 12 | ||||
-rw-r--r-- | vp9/encoder/vp9_ratectrl.c | 80 | ||||
-rw-r--r-- | vp9/encoder/vp9_rdopt.c | 8 | ||||
-rw-r--r-- | vp9/encoder/vp9_speed_features.h | 2 | ||||
-rw-r--r-- | vp9/encoder/vp9_svc_layercontext.c | 2 | ||||
-rw-r--r-- | vp9/encoder/x86/vp9_dct32x32_sse2.c | 3 | ||||
-rw-r--r-- | vp9/vp9_dx_iface.c | 98 |
13 files changed, 131 insertions, 162 deletions
diff --git a/vp9/common/vp9_idct.h b/vp9/common/vp9_idct.h index ceca7951b..d86877622 100644 --- a/vp9/common/vp9_idct.h +++ b/vp9/common/vp9_idct.h @@ -33,9 +33,6 @@ extern "C" { #define pair_set_epi16(a, b) \ _mm_set_epi16(b, a, b, a, b, a, b, a) -#define pair_set_epi32(a, b) \ - _mm_set_epi32(b, a, b, a) - // Constants: // for (int i = 1; i< 32; ++i) // printf("static const int cospi_%d_64 = %.0f;\n", i, diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index ef1d4e60e..87051d56b 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -3063,6 +3063,23 @@ static void encode_frame_internal(VP9_COMP *cpi) { #endif } +static INTERP_FILTER get_interp_filter( + const int64_t threshes[SWITCHABLE_FILTER_CONTEXTS], int is_alt_ref) { + if (!is_alt_ref && + threshes[EIGHTTAP_SMOOTH] > threshes[EIGHTTAP] && + threshes[EIGHTTAP_SMOOTH] > threshes[EIGHTTAP_SHARP] && + threshes[EIGHTTAP_SMOOTH] > threshes[SWITCHABLE - 1]) { + return EIGHTTAP_SMOOTH; + } else if (threshes[EIGHTTAP_SHARP] > threshes[EIGHTTAP] && + threshes[EIGHTTAP_SHARP] > threshes[SWITCHABLE - 1]) { + return EIGHTTAP_SHARP; + } else if (threshes[EIGHTTAP] > threshes[SWITCHABLE - 1]) { + return EIGHTTAP; + } else { + return SWITCHABLE; + } +} + void vp9_encode_frame(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; RD_OPT *const rd_opt = &cpi->rd; @@ -3098,59 +3115,41 @@ void vp9_encode_frame(VP9_COMP *cpi) { // that for subsequent frames. // It does the same analysis for transform size selection also. const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi); - const int64_t *mode_thresh = rd_opt->prediction_type_threshes[frame_type]; - const int64_t *filter_thresh = rd_opt->filter_threshes[frame_type]; + int64_t *const mode_thrs = rd_opt->prediction_type_threshes[frame_type]; + int64_t *const filter_thrs = rd_opt->filter_threshes[frame_type]; + int *const tx_thrs = rd_opt->tx_select_threshes[frame_type]; + const int is_alt_ref = frame_type == ALTREF_FRAME; /* prediction (compound, single or hybrid) mode selection */ - if (frame_type == ALTREF_FRAME || !cm->allow_comp_inter_inter) + if (is_alt_ref || !cm->allow_comp_inter_inter) cm->reference_mode = SINGLE_REFERENCE; - else if (mode_thresh[COMPOUND_REFERENCE] > mode_thresh[SINGLE_REFERENCE] && - mode_thresh[COMPOUND_REFERENCE] > - mode_thresh[REFERENCE_MODE_SELECT] && + else if (mode_thrs[COMPOUND_REFERENCE] > mode_thrs[SINGLE_REFERENCE] && + mode_thrs[COMPOUND_REFERENCE] > + mode_thrs[REFERENCE_MODE_SELECT] && check_dual_ref_flags(cpi) && cpi->static_mb_pct == 100) cm->reference_mode = COMPOUND_REFERENCE; - else if (mode_thresh[SINGLE_REFERENCE] > mode_thresh[REFERENCE_MODE_SELECT]) + else if (mode_thrs[SINGLE_REFERENCE] > mode_thrs[REFERENCE_MODE_SELECT]) cm->reference_mode = SINGLE_REFERENCE; else cm->reference_mode = REFERENCE_MODE_SELECT; - if (cm->interp_filter == SWITCHABLE) { - if (frame_type != ALTREF_FRAME && - filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP] && - filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[EIGHTTAP_SHARP] && - filter_thresh[EIGHTTAP_SMOOTH] > filter_thresh[SWITCHABLE - 1]) { - cm->interp_filter = EIGHTTAP_SMOOTH; - } else if (filter_thresh[EIGHTTAP_SHARP] > filter_thresh[EIGHTTAP] && - filter_thresh[EIGHTTAP_SHARP] > filter_thresh[SWITCHABLE - 1]) { - cm->interp_filter = EIGHTTAP_SHARP; - } else if (filter_thresh[EIGHTTAP] > filter_thresh[SWITCHABLE - 1]) { - cm->interp_filter = EIGHTTAP; - } - } + if (cm->interp_filter == SWITCHABLE) + cm->interp_filter = get_interp_filter(filter_thrs, is_alt_ref); encode_frame_internal(cpi); - for (i = 0; i < REFERENCE_MODES; ++i) { - const int diff = (int) (rd_opt->comp_pred_diff[i] / cm->MBs); - rd_opt->prediction_type_threshes[frame_type][i] += diff; - rd_opt->prediction_type_threshes[frame_type][i] >>= 1; - } + for (i = 0; i < REFERENCE_MODES; ++i) + mode_thrs[i] = (mode_thrs[i] + rd_opt->comp_pred_diff[i] / cm->MBs) / 2; - for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) { - const int64_t diff = rd_opt->filter_diff[i] / cm->MBs; - rd_opt->filter_threshes[frame_type][i] = - (rd_opt->filter_threshes[frame_type][i] + diff) / 2; - } + for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) + filter_thrs[i] = (filter_thrs[i] + rd_opt->filter_diff[i] / cm->MBs) / 2; for (i = 0; i < TX_MODES; ++i) { int64_t pd = rd_opt->tx_select_diff[i]; - int diff; if (i == TX_MODE_SELECT) pd -= RDCOST(cpi->mb.rdmult, cpi->mb.rddiv, 2048 * (TX_SIZES - 1), 0); - diff = (int) (pd / cm->MBs); - rd_opt->tx_select_threshes[frame_type][i] += diff; - rd_opt->tx_select_threshes[frame_type][i] /= 2; + tx_thrs[i] = (tx_thrs[i] + (int)(pd / cm->MBs)) / 2; } if (cm->reference_mode == REFERENCE_MODE_SELECT) { diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index a9a9695de..cc2c552a7 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2061,7 +2061,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cm->lf.mode_ref_delta_update = 0; // Initialize cpi->mv_step_param to default based on max resolution. - cpi->mv_step_param = vp9_init_search_range(cpi, max_mv_def); + cpi->mv_step_param = vp9_init_search_range(sf, max_mv_def); // Initialize cpi->max_mv_magnitude and cpi->mv_step_param if appropriate. if (sf->auto_mv_step_size) { if (frame_is_intra_only(cm)) { @@ -2073,7 +2073,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, // Allow mv_steps to correspond to twice the max mv magnitude found // in the previous frame, capped by the default max_mv_magnitude based // on resolution. - cpi->mv_step_param = vp9_init_search_range(cpi, MIN(max_mv_def, 2 * + cpi->mv_step_param = vp9_init_search_range(sf, MIN(max_mv_def, 2 * cpi->max_mv_magnitude)); cpi->max_mv_magnitude = 0; } diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 5867fb3fc..efa320f3f 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -2402,8 +2402,8 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { const double progress = (double)(cpi->twopass.stats_in - cpi->twopass.stats_in_start) / (cpi->twopass.stats_in_end - cpi->twopass.stats_in_start); - const int bits_used = progress * rc->this_frame_target + - (1.0 - progress) * rc->projected_frame_size; + const int bits_used = (int)(progress * rc->this_frame_target + + (1.0 - progress) * rc->projected_frame_size); #endif cpi->twopass.bits_left -= bits_used; diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c index 15afa1ab5..43c8ab868 100644 --- a/vp9/encoder/vp9_mcomp.c +++ b/vp9/encoder/vp9_mcomp.c @@ -51,7 +51,7 @@ void vp9_set_mv_search_range(MACROBLOCK *x, const MV *mv) { x->mv_row_max = row_max; } -int vp9_init_search_range(VP9_COMP *cpi, int size) { +int vp9_init_search_range(const SPEED_FEATURES *sf, int size) { int sr = 0; // Minimum search size no matter what the passed in value. @@ -60,8 +60,8 @@ int vp9_init_search_range(VP9_COMP *cpi, int size) { while ((size << sr) < MAX_FULL_PEL_VAL) sr++; - sr += cpi->sf.reduce_first_step_size; - sr = MIN(sr, (cpi->sf.max_step_search_steps - 2)); + sr += sf->reduce_first_step_size; + sr = MIN(sr, (sf->max_step_search_steps - 2)); return sr; } diff --git a/vp9/encoder/vp9_mcomp.h b/vp9/encoder/vp9_mcomp.h index 1f524f1f6..827957d62 100644 --- a/vp9/encoder/vp9_mcomp.h +++ b/vp9/encoder/vp9_mcomp.h @@ -62,7 +62,9 @@ int vp9_get_mvpred_av_var(const MACROBLOCK *x, int use_mvcost); struct VP9_COMP; -int vp9_init_search_range(struct VP9_COMP *cpi, int size); +struct SPEED_FEATURES; + +int vp9_init_search_range(const struct SPEED_FEATURES *sf, int size); // Runs sequence of diamond searches in smaller steps for RD int vp9_full_pixel_diamond(const struct VP9_COMP *cpi, MACROBLOCK *x, diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c index e750a53b6..adaa04447 100644 --- a/vp9/encoder/vp9_pickmode.c +++ b/vp9/encoder/vp9_pickmode.c @@ -161,10 +161,16 @@ static void model_rd_for_sb_y(VP9_COMP *cpi, BLOCK_SIZE bsize, struct macroblock_plane *const p = &x->plane[0]; struct macroblockd_plane *const pd = &xd->plane[0]; - int var = cpi->fn_ptr[bsize].vf(p->src.buf, p->src.stride, - pd->dst.buf, pd->dst.stride, &sse); + unsigned int var = cpi->fn_ptr[bsize].vf(p->src.buf, p->src.stride, + pd->dst.buf, pd->dst.stride, &sse); - vp9_model_rd_from_var_lapndz(sse + var, 1 << num_pels_log2_lookup[bsize], + // TODO(jingning) This is a temporary solution to account for frames with + // light changes. Need to customize the rate-distortion modeling for non-RD + // mode decision. + if ((sse >> 3) > var) + sse = var; + + vp9_model_rd_from_var_lapndz(var + sse, 1 << num_pels_log2_lookup[bsize], pd->dequant[1] >> 3, &rate, &dist); *out_rate_sum = rate; *out_dist_sum = dist << 3; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 985743d88..fe43f3a07 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -45,11 +45,9 @@ // Tables relating active max Q to active min Q static int kf_low_motion_minq[QINDEX_RANGE]; static int kf_high_motion_minq[QINDEX_RANGE]; -static int gf_low_motion_minq[QINDEX_RANGE]; -static int gf_high_motion_minq[QINDEX_RANGE]; +static int arfgf_low_motion_minq[QINDEX_RANGE]; +static int arfgf_high_motion_minq[QINDEX_RANGE]; static int inter_minq[QINDEX_RANGE]; -static int afq_low_motion_minq[QINDEX_RANGE]; -static int afq_high_motion_minq[QINDEX_RANGE]; static int gf_high = 2000; static int gf_low = 400; static int kf_high = 5000; @@ -81,13 +79,11 @@ void vp9_rc_init_minq_luts() { for (i = 0; i < QINDEX_RANGE; i++) { const double maxq = vp9_convert_qindex_to_q(i); - kf_low_motion_minq[i] = get_minq_index(maxq, 0.000001, -0.0004, 0.15); + kf_low_motion_minq[i] = get_minq_index(maxq, 0.000001, -0.0004, 0.125); kf_high_motion_minq[i] = get_minq_index(maxq, 0.000002, -0.0012, 0.50); - gf_low_motion_minq[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.32); - gf_high_motion_minq[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.50); - afq_low_motion_minq[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.33); - afq_high_motion_minq[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.55); - inter_minq[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.75); + arfgf_low_motion_minq[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.30); + arfgf_high_motion_minq[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.50); + inter_minq[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.90); } } @@ -548,7 +544,7 @@ static int rc_pick_q_and_bounds_one_pass_cbr(const VP9_COMP *cpi, } active_best_quality = get_active_quality( q, rc->gfu_boost, gf_low, gf_high, - gf_low_motion_minq, gf_high_motion_minq); + arfgf_low_motion_minq, arfgf_high_motion_minq); } else { // Use the lower of active_worst_quality and recent/average Q. if (cm->current_video_frame > 1) { @@ -676,17 +672,12 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi, if (oxcf->rc_mode == RC_MODE_CONSTRAINED_QUALITY) { if (q < cq_level) q = cq_level; - if (rc->frames_since_key > 1) { - active_best_quality = get_active_quality(q, rc->gfu_boost, - gf_low, gf_high, - afq_low_motion_minq, - afq_high_motion_minq); - } else { - active_best_quality = get_active_quality(q, rc->gfu_boost, - gf_low, gf_high, - gf_low_motion_minq, - gf_high_motion_minq); - } + + active_best_quality = get_active_quality(q, rc->gfu_boost, + gf_low, gf_high, + arfgf_low_motion_minq, + arfgf_high_motion_minq); + // Constrained quality use slightly lower active best. active_best_quality = active_best_quality * 15 / 16; @@ -694,20 +685,14 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi, if (!cpi->refresh_alt_ref_frame) { active_best_quality = cq_level; } else { - if (rc->frames_since_key > 1) { - active_best_quality = get_active_quality( - q, rc->gfu_boost, gf_low, gf_high, - afq_low_motion_minq, afq_high_motion_minq); - } else { - active_best_quality = get_active_quality( - q, rc->gfu_boost, gf_low, gf_high, - gf_low_motion_minq, gf_high_motion_minq); - } + active_best_quality = get_active_quality( + q, rc->gfu_boost, gf_low, gf_high, + arfgf_low_motion_minq, arfgf_high_motion_minq); } } else { active_best_quality = get_active_quality( q, rc->gfu_boost, gf_low, gf_high, - gf_low_motion_minq, gf_high_motion_minq); + arfgf_low_motion_minq, arfgf_high_motion_minq); } } else { if (oxcf->rc_mode == RC_MODE_CONSTANT_QUALITY) { @@ -867,17 +852,12 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, if (oxcf->rc_mode == RC_MODE_CONSTRAINED_QUALITY) { if (q < cq_level) q = cq_level; - if (rc->frames_since_key > 1) { - active_best_quality = get_active_quality(q, rc->gfu_boost, - gf_low, gf_high, - afq_low_motion_minq, - afq_high_motion_minq); - } else { - active_best_quality = get_active_quality(q, rc->gfu_boost, - gf_low, gf_high, - gf_low_motion_minq, - gf_high_motion_minq); - } + + active_best_quality = get_active_quality(q, rc->gfu_boost, + gf_low, gf_high, + arfgf_low_motion_minq, + arfgf_high_motion_minq); + // Constrained quality use slightly lower active best. active_best_quality = active_best_quality * 15 / 16; @@ -885,20 +865,14 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, if (!cpi->refresh_alt_ref_frame) { active_best_quality = cq_level; } else { - if (rc->frames_since_key > 1) { - active_best_quality = get_active_quality( - q, rc->gfu_boost, gf_low, gf_high, - afq_low_motion_minq, afq_high_motion_minq); - } else { - active_best_quality = get_active_quality( - q, rc->gfu_boost, gf_low, gf_high, - gf_low_motion_minq, gf_high_motion_minq); - } + active_best_quality = get_active_quality( + q, rc->gfu_boost, gf_low, gf_high, + arfgf_low_motion_minq, arfgf_high_motion_minq); } } else { active_best_quality = get_active_quality( q, rc->gfu_boost, gf_low, gf_high, - gf_low_motion_minq, gf_high_motion_minq); + arfgf_low_motion_minq, arfgf_high_motion_minq); } } else { if (oxcf->rc_mode == RC_MODE_CONSTANT_QUALITY) { diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index b9cd7d554..f4def1eef 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -1833,8 +1833,8 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x, // Take wtd average of the step_params based on the last frame's // max mv magnitude and the best ref mvs of the current block for // the given reference. - step_param = (vp9_init_search_range(cpi, max_mv) + - cpi->mv_step_param) >> 1; + step_param = (vp9_init_search_range(&cpi->sf, max_mv) + + cpi->mv_step_param) / 2; } else { step_param = cpi->mv_step_param; } @@ -2352,8 +2352,8 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x, // Take wtd average of the step_params based on the last frame's // max mv magnitude and that based on the best ref mvs of the current // block for the given reference. - step_param = (vp9_init_search_range(cpi, x->max_mv_context[ref]) + - cpi->mv_step_param) >> 1; + step_param = (vp9_init_search_range(&cpi->sf, x->max_mv_context[ref]) + + cpi->mv_step_param) / 2; } else { step_param = cpi->mv_step_param; } diff --git a/vp9/encoder/vp9_speed_features.h b/vp9/encoder/vp9_speed_features.h index cff99a6dc..a384a4360 100644 --- a/vp9/encoder/vp9_speed_features.h +++ b/vp9/encoder/vp9_speed_features.h @@ -129,7 +129,7 @@ typedef enum { ONE_LOOP_REDUCED = 2 } FAST_COEFF_UPDATE; -typedef struct { +typedef struct SPEED_FEATURES { // Frame level coding parameter update int frame_parameter_update; diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index 792e8d21b..2e98fa717 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -221,7 +221,7 @@ void vp9_inc_frame_in_layer(SVC *svc) { ++lc->current_video_frame_in_layer; } -int vp9_is_upper_layer_key_frame(const VP9_COMP *cpi) { +int vp9_is_upper_layer_key_frame(const VP9_COMP *const cpi) { return cpi->use_svc && cpi->svc.number_temporal_layers == 1 && cpi->svc.spatial_layer_id > 0 && diff --git a/vp9/encoder/x86/vp9_dct32x32_sse2.c b/vp9/encoder/x86/vp9_dct32x32_sse2.c index 2d59775ce..42fdbbdc5 100644 --- a/vp9/encoder/x86/vp9_dct32x32_sse2.c +++ b/vp9/encoder/x86/vp9_dct32x32_sse2.c @@ -12,6 +12,9 @@ #include "vp9/common/vp9_idct.h" // for cospi constants #include "vpx_ports/mem.h" +#define pair_set_epi32(a, b) \ + _mm_set_epi32(b, a, b, a) + #if FDCT32x32_HIGH_PRECISION static INLINE __m128i k_madd_epi32(__m128i a, __m128i b) { __m128i buf0, buf1; diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index 06b482305..6dca8399f 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -375,80 +375,68 @@ static void parse_superframe_index(const uint8_t *data, size_t data_sz, } } +static vpx_codec_err_t decode_one_iter(vpx_codec_alg_priv_t *ctx, + const uint8_t **data_start_ptr, + const uint8_t *data_end, + uint32_t frame_size, void *user_priv, + long deadline) { + const vpx_codec_err_t res = decode_one(ctx, data_start_ptr, frame_size, + user_priv, deadline); + if (res != VPX_CODEC_OK) + return res; + + // Account for suboptimal termination by the encoder. + while (*data_start_ptr < data_end) { + const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state, + *data_start_ptr); + if (marker) + break; + (*data_start_ptr)++; + } + + return VPX_CODEC_OK; +} + static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, const uint8_t *data, unsigned int data_sz, void *user_priv, long deadline) { const uint8_t *data_start = data; - const uint8_t *data_end = data + data_sz; - vpx_codec_err_t res = VPX_CODEC_OK; - uint32_t sizes[8]; - int frames_this_pts, frame_count = 0; + const uint8_t *const data_end = data + data_sz; + vpx_codec_err_t res; + uint32_t frame_sizes[8]; + int frame_count; if (data == NULL || data_sz == 0) return VPX_CODEC_INVALID_PARAM; - parse_superframe_index(data, data_sz, sizes, &frames_this_pts, + parse_superframe_index(data, data_sz, frame_sizes, &frame_count, ctx->decrypt_cb, ctx->decrypt_state); - do { - if (data_sz) { - uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state, - data_start); - // Skip over the superframe index, if present - if ((marker & 0xe0) == 0xc0) { - const uint32_t frames = (marker & 0x7) + 1; - const uint32_t mag = ((marker >> 3) & 0x3) + 1; - const uint32_t index_sz = 2 + mag * frames; - - if (data_sz >= index_sz) { - uint8_t marker2 = read_marker(ctx->decrypt_cb, ctx->decrypt_state, - data_start + index_sz - 1); - if (marker2 == marker) { - data_start += index_sz; - data_sz -= index_sz; - if (data_start < data_end) - continue; - else - break; - } - } - } - } - - // Use the correct size for this frame, if an index is present. - if (frames_this_pts) { - uint32_t this_sz = sizes[frame_count]; + if (frame_count > 0) { + int i; - if (data_sz < this_sz) { + for (i = 0; i < frame_count; ++i) { + const uint32_t frame_size = frame_sizes[i]; + if (data_start < data || data_start + frame_size >= data_end) { ctx->base.err_detail = "Invalid frame size in index"; return VPX_CODEC_CORRUPT_FRAME; } - data_sz = this_sz; - frame_count++; + res = decode_one_iter(ctx, &data_start, data_end, frame_size, + user_priv, deadline); + if (res != VPX_CODEC_OK) + return res; } - - res = decode_one(ctx, &data_start, data_sz, user_priv, deadline); - assert(data_start >= data); - assert(data_start <= data_end); - - // Early exit if there was a decode error - if (res) - break; - - // Account for suboptimal termination by the encoder. + } else { while (data_start < data_end) { - uint8_t marker3 = read_marker(ctx->decrypt_cb, ctx->decrypt_state, - data_start); - if (marker3) - break; - data_start++; + res = decode_one_iter(ctx, &data_start, data_end, data_end - data_start, + user_priv, deadline); + if (res != VPX_CODEC_OK) + return res; } + } - data_sz = (unsigned int)(data_end - data_start); - } while (data_start < data_end); - - return res; + return VPX_CODEC_OK; } static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx, |