summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
Diffstat (limited to 'vp9')
-rw-r--r--vp9/common/vp9_idct.h3
-rw-r--r--vp9/encoder/vp9_encodeframe.c67
-rw-r--r--vp9/encoder/vp9_encoder.c4
-rw-r--r--vp9/encoder/vp9_firstpass.c4
-rw-r--r--vp9/encoder/vp9_mcomp.c6
-rw-r--r--vp9/encoder/vp9_mcomp.h4
-rw-r--r--vp9/encoder/vp9_pickmode.c12
-rw-r--r--vp9/encoder/vp9_ratectrl.c80
-rw-r--r--vp9/encoder/vp9_rdopt.c8
-rw-r--r--vp9/encoder/vp9_speed_features.h2
-rw-r--r--vp9/encoder/vp9_svc_layercontext.c2
-rw-r--r--vp9/encoder/x86/vp9_dct32x32_sse2.c3
-rw-r--r--vp9/vp9_dx_iface.c98
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,