2010-05-18 17:58:33 +02:00
|
|
|
/*
|
2010-09-09 14:16:39 +02:00
|
|
|
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
2010-05-18 17:58:33 +02:00
|
|
|
*
|
2010-06-18 18:39:21 +02:00
|
|
|
* Use of this source code is governed by a BSD-style license
|
2010-06-04 22:19:40 +02:00
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
2010-06-18 18:39:21 +02:00
|
|
|
* in the file PATENTS. All contributing project authors may
|
2010-06-04 22:19:40 +02:00
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
2010-05-18 17:58:33 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <assert.h>
|
2012-11-27 22:59:17 +01:00
|
|
|
|
2013-05-02 20:57:16 +02:00
|
|
|
#include "vp9/common/vp9_pragmas.h"
|
2012-11-28 19:41:40 +01:00
|
|
|
#include "vp9/encoder/vp9_tokenize.h"
|
|
|
|
#include "vp9/encoder/vp9_treewriter.h"
|
|
|
|
#include "vp9/encoder/vp9_onyx_int.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_entropymode.h"
|
|
|
|
#include "vp9/common/vp9_reconinter.h"
|
|
|
|
#include "vp9/common/vp9_reconintra.h"
|
|
|
|
#include "vp9/common/vp9_quant_common.h"
|
2012-11-28 19:41:40 +01:00
|
|
|
#include "vp9/encoder/vp9_encodemb.h"
|
|
|
|
#include "vp9/encoder/vp9_quantize.h"
|
|
|
|
#include "vp9/encoder/vp9_variance.h"
|
|
|
|
#include "vp9/encoder/vp9_mcomp.h"
|
|
|
|
#include "vp9/encoder/vp9_rdopt.h"
|
|
|
|
#include "vp9/encoder/vp9_ratectrl.h"
|
2010-05-18 17:58:33 +02:00
|
|
|
#include "vpx_mem/vpx_mem.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_systemdependent.h"
|
|
|
|
#include "vp9/encoder/vp9_encodemv.h"
|
|
|
|
#include "vp9/common/vp9_seg_common.h"
|
|
|
|
#include "vp9/common/vp9_pred_common.h"
|
|
|
|
#include "vp9/common/vp9_entropy.h"
|
2013-10-08 02:03:29 +02:00
|
|
|
#include "./vp9_rtcd.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_mvref_common.h"
|
2013-01-06 03:20:25 +01:00
|
|
|
#include "vp9/common/vp9_common.h"
|
2012-08-24 16:44:01 +02:00
|
|
|
|
2012-04-18 22:51:58 +02:00
|
|
|
#define INVALID_MV 0x80008000
|
|
|
|
|
2012-07-18 22:43:01 +02:00
|
|
|
/* Factor to weigh the rate for switchable interp filters */
|
|
|
|
#define SWITCHABLE_INTERP_RATE_FACTOR 1
|
|
|
|
|
2013-09-28 01:02:49 +02:00
|
|
|
#define LAST_FRAME_MODE_MASK 0xFFEDCD60
|
|
|
|
#define GOLDEN_FRAME_MODE_MASK 0xFFDA3BB0
|
|
|
|
#define ALT_REF_MODE_MASK 0xFFC648D0
|
2013-09-05 02:15:05 +02:00
|
|
|
|
2013-10-01 17:57:18 +02:00
|
|
|
#define MIN_EARLY_TERM_INDEX 3
|
|
|
|
|
2014-01-06 21:23:36 +01:00
|
|
|
typedef struct {
|
|
|
|
MB_PREDICTION_MODE mode;
|
|
|
|
MV_REFERENCE_FRAME ref_frame[2];
|
|
|
|
} MODE_DEFINITION;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
MV_REFERENCE_FRAME ref_frame[2];
|
|
|
|
} REF_DEFINITION;
|
|
|
|
|
2012-10-31 01:12:12 +01:00
|
|
|
const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
|
2014-01-06 21:23:36 +01:00
|
|
|
{NEARESTMV, {LAST_FRAME, NONE}},
|
|
|
|
{NEARESTMV, {ALTREF_FRAME, NONE}},
|
|
|
|
{NEARESTMV, {GOLDEN_FRAME, NONE}},
|
|
|
|
|
|
|
|
{DC_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
|
|
|
|
{NEWMV, {LAST_FRAME, NONE}},
|
|
|
|
{NEWMV, {ALTREF_FRAME, NONE}},
|
|
|
|
{NEWMV, {GOLDEN_FRAME, NONE}},
|
|
|
|
|
|
|
|
{NEARMV, {LAST_FRAME, NONE}},
|
|
|
|
{NEARMV, {ALTREF_FRAME, NONE}},
|
|
|
|
{NEARESTMV, {LAST_FRAME, ALTREF_FRAME}},
|
|
|
|
{NEARESTMV, {GOLDEN_FRAME, ALTREF_FRAME}},
|
|
|
|
|
|
|
|
{TM_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
|
|
|
|
{NEARMV, {LAST_FRAME, ALTREF_FRAME}},
|
|
|
|
{NEWMV, {LAST_FRAME, ALTREF_FRAME}},
|
|
|
|
{NEARMV, {GOLDEN_FRAME, NONE}},
|
|
|
|
{NEARMV, {GOLDEN_FRAME, ALTREF_FRAME}},
|
|
|
|
{NEWMV, {GOLDEN_FRAME, ALTREF_FRAME}},
|
|
|
|
|
|
|
|
{ZEROMV, {LAST_FRAME, NONE}},
|
|
|
|
{ZEROMV, {GOLDEN_FRAME, NONE}},
|
|
|
|
{ZEROMV, {ALTREF_FRAME, NONE}},
|
|
|
|
{ZEROMV, {LAST_FRAME, ALTREF_FRAME}},
|
|
|
|
{ZEROMV, {GOLDEN_FRAME, ALTREF_FRAME}},
|
|
|
|
|
|
|
|
{H_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
{V_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
{D135_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
{D207_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
{D153_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
{D63_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
{D117_PRED, {INTRA_FRAME, NONE}},
|
|
|
|
{D45_PRED, {INTRA_FRAME, NONE}},
|
2013-09-28 01:02:49 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
|
2014-01-06 21:23:36 +01:00
|
|
|
{{LAST_FRAME, NONE}},
|
|
|
|
{{GOLDEN_FRAME, NONE}},
|
|
|
|
{{ALTREF_FRAME, NONE}},
|
|
|
|
{{LAST_FRAME, ALTREF_FRAME}},
|
|
|
|
{{GOLDEN_FRAME, ALTREF_FRAME}},
|
|
|
|
{{INTRA_FRAME, NONE}},
|
2010-05-18 17:58:33 +02:00
|
|
|
};
|
|
|
|
|
2013-06-03 13:51:29 +02:00
|
|
|
// The baseline rd thresholds for breaking out of the rd loop for
|
|
|
|
// certain modes are assumed to be based on 8x8 blocks.
|
|
|
|
// This table is used to correct for blocks size.
|
|
|
|
// The factors here are << 2 (2 = x0.5, 32 = x8 etc).
|
2013-08-10 02:47:32 +02:00
|
|
|
static int rd_thresh_block_size_factor[BLOCK_SIZES] =
|
2013-06-03 13:51:29 +02:00
|
|
|
{2, 3, 3, 4, 6, 6, 8, 12, 12, 16, 24, 24, 32};
|
|
|
|
|
2013-10-09 20:32:03 +02:00
|
|
|
#define RD_THRESH_MAX_FACT 64
|
|
|
|
#define RD_THRESH_INC 1
|
|
|
|
#define RD_THRESH_POW 1.25
|
2013-10-11 02:24:55 +02:00
|
|
|
#define RD_MULT_EPB_RATIO 64
|
2013-10-09 20:32:03 +02:00
|
|
|
|
2013-10-09 23:14:34 +02:00
|
|
|
#define MV_COST_WEIGHT 108
|
|
|
|
#define MV_COST_WEIGHT_SUB 120
|
2013-06-03 13:51:29 +02:00
|
|
|
|
2013-11-27 21:57:21 +01:00
|
|
|
static int raster_block_offset(BLOCK_SIZE plane_bsize,
|
|
|
|
int raster_block, int stride) {
|
|
|
|
const int bw = b_width_log2(plane_bsize);
|
|
|
|
const int y = 4 * (raster_block >> bw);
|
|
|
|
const int x = 4 * (raster_block & ((1 << bw) - 1));
|
|
|
|
return y * stride + x;
|
|
|
|
}
|
|
|
|
static int16_t* raster_block_offset_int16(BLOCK_SIZE plane_bsize,
|
|
|
|
int raster_block, int16_t *base) {
|
2013-12-06 21:04:06 +01:00
|
|
|
const int stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
|
2013-11-27 21:57:21 +01:00
|
|
|
return base + raster_block_offset(plane_bsize, raster_block, stride);
|
|
|
|
}
|
|
|
|
|
2013-11-25 21:44:05 +01:00
|
|
|
static void fill_mode_costs(VP9_COMP *c) {
|
|
|
|
VP9_COMMON *const cm = &c->common;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < INTRA_MODES; i++)
|
|
|
|
for (j = 0; j < INTRA_MODES; j++)
|
|
|
|
vp9_cost_tokens((int *)c->mb.y_mode_costs[i][j], vp9_kf_y_mode_prob[i][j],
|
|
|
|
vp9_intra_mode_tree);
|
|
|
|
|
|
|
|
// TODO(rbultje) separate tables for superblock costing?
|
|
|
|
vp9_cost_tokens(c->mb.mbmode_cost, cm->fc.y_mode_prob[1],
|
|
|
|
vp9_intra_mode_tree);
|
|
|
|
vp9_cost_tokens(c->mb.intra_uv_mode_cost[1],
|
|
|
|
cm->fc.uv_mode_prob[INTRA_MODES - 1], vp9_intra_mode_tree);
|
|
|
|
vp9_cost_tokens(c->mb.intra_uv_mode_cost[0],
|
|
|
|
vp9_kf_uv_mode_prob[INTRA_MODES - 1],
|
|
|
|
vp9_intra_mode_tree);
|
|
|
|
|
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
|
|
|
|
vp9_cost_tokens((int *)c->mb.switchable_interp_costs[i],
|
|
|
|
cm->fc.switchable_interp_prob[i],
|
|
|
|
vp9_switchable_interp_tree);
|
|
|
|
}
|
|
|
|
|
2013-07-25 00:13:58 +02:00
|
|
|
static void fill_token_costs(vp9_coeff_cost *c,
|
2013-12-06 19:54:00 +01:00
|
|
|
vp9_coeff_probs_model (*p)[PLANE_TYPES]) {
|
2013-05-08 19:04:14 +02:00
|
|
|
int i, j, k, l;
|
2013-05-31 18:18:59 +02:00
|
|
|
TX_SIZE t;
|
2013-12-06 02:08:06 +01:00
|
|
|
for (t = TX_4X4; t <= TX_32X32; ++t)
|
2013-12-06 19:54:00 +01:00
|
|
|
for (i = 0; i < PLANE_TYPES; ++i)
|
2013-12-06 02:08:06 +01:00
|
|
|
for (j = 0; j < REF_TYPES; ++j)
|
|
|
|
for (k = 0; k < COEF_BANDS; ++k)
|
|
|
|
for (l = 0; l < BAND_COEFF_CONTEXTS(k); ++l) {
|
2013-05-31 18:18:59 +02:00
|
|
|
vp9_prob probs[ENTROPY_NODES];
|
|
|
|
vp9_model_to_full_probs(p[t][i][j][k][l], probs);
|
2013-07-25 00:13:58 +02:00
|
|
|
vp9_cost_tokens((int *)c[t][i][j][k][0][l], probs,
|
2013-05-31 18:18:59 +02:00
|
|
|
vp9_coef_tree);
|
2013-07-25 00:13:58 +02:00
|
|
|
vp9_cost_tokens_skip((int *)c[t][i][j][k][1][l], probs,
|
2013-05-31 18:18:59 +02:00
|
|
|
vp9_coef_tree);
|
2013-12-04 02:23:03 +01:00
|
|
|
assert(c[t][i][j][k][0][l][EOB_TOKEN] ==
|
|
|
|
c[t][i][j][k][1][l][EOB_TOKEN]);
|
2013-05-31 18:18:59 +02:00
|
|
|
}
|
2013-02-20 19:16:24 +01:00
|
|
|
}
|
|
|
|
|
2013-07-23 04:16:54 +02:00
|
|
|
static const int rd_iifactor[32] = {
|
|
|
|
4, 4, 3, 2, 1, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
};
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2010-12-02 00:50:14 +01:00
|
|
|
// 3* dc_qlookup[Q]*dc_qlookup[Q];
|
2011-11-23 12:32:20 +01:00
|
|
|
|
2010-12-24 04:59:12 +01:00
|
|
|
/* values are now correlated to quantizer */
|
2011-11-21 16:45:10 +01:00
|
|
|
static int sad_per_bit16lut[QINDEX_RANGE];
|
|
|
|
static int sad_per_bit4lut[QINDEX_RANGE];
|
|
|
|
|
2012-10-30 20:58:42 +01:00
|
|
|
void vp9_init_me_luts() {
|
2012-07-14 00:21:29 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
// Initialize the sad lut tables using a formulaic calculation for now
|
|
|
|
// This is to make it easier to resolve the impact of experimental changes
|
|
|
|
// to the quantizer tables.
|
|
|
|
for (i = 0; i < QINDEX_RANGE; i++) {
|
|
|
|
sad_per_bit16lut[i] =
|
2012-10-30 20:58:42 +01:00
|
|
|
(int)((0.0418 * vp9_convert_qindex_to_q(i)) + 2.4107);
|
2013-05-02 20:57:16 +02:00
|
|
|
sad_per_bit4lut[i] = (int)(0.063 * vp9_convert_qindex_to_q(i) + 2.742);
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2011-11-21 16:45:10 +01:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
int vp9_compute_rd_mult(VP9_COMP *cpi, int qindex) {
|
2013-04-26 21:30:20 +02:00
|
|
|
const int q = vp9_dc_quant(qindex, 0);
|
2013-10-11 02:24:55 +02:00
|
|
|
// TODO(debargha): Adjust the function below
|
2013-10-07 20:20:10 +02:00
|
|
|
int rdmult = 88 * q * q / 25;
|
|
|
|
if (cpi->pass == 2 && (cpi->common.frame_type != KEY_FRAME)) {
|
|
|
|
if (cpi->twopass.next_iiratio > 31)
|
|
|
|
rdmult += (rdmult * rd_iifactor[31]) >> 4;
|
|
|
|
else
|
|
|
|
rdmult += (rdmult * rd_iifactor[cpi->twopass.next_iiratio]) >> 4;
|
|
|
|
}
|
|
|
|
return rdmult;
|
2013-10-11 02:24:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int compute_rd_thresh_factor(int qindex) {
|
|
|
|
int q;
|
|
|
|
// TODO(debargha): Adjust the function below
|
|
|
|
q = (int)(pow(vp9_dc_quant(qindex, 0) / 4.0, RD_THRESH_POW) * 5.12);
|
|
|
|
if (q < 8)
|
|
|
|
q = 8;
|
|
|
|
return q;
|
2011-11-23 12:32:20 +01:00
|
|
|
}
|
|
|
|
|
2013-03-02 02:39:31 +01:00
|
|
|
void vp9_initialize_me_consts(VP9_COMP *cpi, int qindex) {
|
|
|
|
cpi->mb.sadperbit16 = sad_per_bit16lut[qindex];
|
|
|
|
cpi->mb.sadperbit4 = sad_per_bit4lut[qindex];
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
static void set_block_thresholds(VP9_COMP *cpi) {
|
|
|
|
int i, bsize, segment_id;
|
|
|
|
VP9_COMMON *cm = &cpi->common;
|
|
|
|
|
|
|
|
for (segment_id = 0; segment_id < MAX_SEGMENTS; ++segment_id) {
|
|
|
|
int q;
|
|
|
|
int segment_qindex = vp9_get_qindex(&cm->seg, segment_id, cm->base_qindex);
|
|
|
|
segment_qindex = clamp(segment_qindex + cm->y_dc_delta_q, 0, MAXQ);
|
|
|
|
q = compute_rd_thresh_factor(segment_qindex);
|
2010-12-02 00:50:14 +01:00
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
for (bsize = 0; bsize < BLOCK_SIZES; ++bsize) {
|
2013-09-26 22:34:33 +02:00
|
|
|
// Threshold here seem unecessarily harsh but fine given actual
|
|
|
|
// range of values used for cpi->sf.thresh_mult[]
|
|
|
|
int thresh_max = INT_MAX / (q * rd_thresh_block_size_factor[bsize]);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
for (i = 0; i < MAX_MODES; ++i) {
|
|
|
|
if (cpi->sf.thresh_mult[i] < thresh_max) {
|
|
|
|
cpi->rd_threshes[segment_id][bsize][i] =
|
|
|
|
cpi->sf.thresh_mult[i] * q *
|
|
|
|
rd_thresh_block_size_factor[bsize] / 4;
|
|
|
|
} else {
|
|
|
|
cpi->rd_threshes[segment_id][bsize][i] = INT_MAX;
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2013-09-28 01:02:49 +02:00
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
for (i = 0; i < MAX_REFS; ++i) {
|
|
|
|
if (cpi->sf.thresh_mult_sub8x8[i] < thresh_max) {
|
|
|
|
cpi->rd_thresh_sub8x8[segment_id][bsize][i] =
|
|
|
|
cpi->sf.thresh_mult_sub8x8[i] * q *
|
|
|
|
rd_thresh_block_size_factor[bsize] / 4;
|
|
|
|
} else {
|
|
|
|
cpi->rd_thresh_sub8x8[segment_id][bsize][i] = INT_MAX;
|
|
|
|
}
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2013-10-09 20:32:03 +02:00
|
|
|
}
|
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
void vp9_initialize_rd_consts(VP9_COMP *cpi) {
|
|
|
|
VP9_COMMON *cm = &cpi->common;
|
|
|
|
int qindex, i;
|
2013-10-09 20:32:03 +02:00
|
|
|
|
|
|
|
vp9_clear_system_state(); // __asm emms;
|
|
|
|
|
|
|
|
// Further tests required to see if optimum is different
|
|
|
|
// for key frames, golden frames and arf frames.
|
|
|
|
// if (cpi->common.refresh_golden_frame ||
|
|
|
|
// cpi->common.refresh_alt_ref_frame)
|
2013-10-07 20:20:10 +02:00
|
|
|
qindex = clamp(cm->base_qindex + cm->y_dc_delta_q, 0, MAXQ);
|
2013-10-09 20:32:03 +02:00
|
|
|
|
2013-10-11 02:24:55 +02:00
|
|
|
cpi->RDDIV = RDDIV_BITS; // in bits (to multiply D by 128)
|
2013-10-07 20:20:10 +02:00
|
|
|
cpi->RDMULT = vp9_compute_rd_mult(cpi, qindex);
|
|
|
|
|
2013-10-11 02:24:55 +02:00
|
|
|
cpi->mb.errorperbit = cpi->RDMULT / RD_MULT_EPB_RATIO;
|
2013-10-09 20:32:03 +02:00
|
|
|
cpi->mb.errorperbit += (cpi->mb.errorperbit == 0);
|
|
|
|
|
|
|
|
vp9_set_speed_features(cpi);
|
|
|
|
|
2013-11-07 23:56:58 +01:00
|
|
|
cpi->mb.select_txfm_size = (cpi->sf.tx_size_search_method == USE_LARGESTALL &&
|
|
|
|
cm->frame_type != KEY_FRAME) ?
|
2013-12-03 00:24:41 +01:00
|
|
|
0 : 1;
|
2013-11-06 06:07:08 +01:00
|
|
|
|
2013-10-07 20:20:10 +02:00
|
|
|
set_block_thresholds(cpi);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-10-21 20:10:11 +02:00
|
|
|
fill_token_costs(cpi->mb.token_costs, cm->fc.coef_probs);
|
32x32 transform for superblocks.
This adds Debargha's DCT/DWT hybrid and a regular 32x32 DCT, and adds
code all over the place to wrap that in the bitstream/encoder/decoder/RD.
Some implementation notes (these probably need careful review):
- token range is extended by 1 bit, since the value range out of this
transform is [-16384,16383].
- the coefficients coming out of the FDCT are manually scaled back by
1 bit, or else they won't fit in int16_t (they are 17 bits). Because
of this, the RD error scoring does not right-shift the MSE score by
two (unlike for 4x4/8x8/16x16).
- to compensate for this loss in precision, the quantizer is halved
also. This is currently a little hacky.
- FDCT and IDCT is double-only right now. Needs a fixed-point impl.
- There are no default probabilities for the 32x32 transform yet; I'm
simply using the 16x16 luma ones. A future commit will add newly
generated probabilities for all transforms.
- No ADST version. I don't think we'll add one for this level; if an
ADST is desired, transform-size selection can scale back to 16x16
or lower, and use an ADST at that level.
Additional notes specific to Debargha's DWT/DCT hybrid:
- coefficient scale is different for the top/left 16x16 (DCT-over-DWT)
block than for the rest (DWT pixel differences) of the block. Therefore,
RD error scoring isn't easily scalable between coefficient and pixel
domain. Thus, unfortunately, we need to compute the RD distortion in
the pixel domain until we figure out how to scale these appropriately.
Change-Id: I00386f20f35d7fabb19aba94c8162f8aee64ef2b
2012-12-07 23:45:05 +01:00
|
|
|
|
2013-10-19 02:44:19 +02:00
|
|
|
for (i = 0; i < PARTITION_CONTEXTS; i++)
|
2013-11-02 02:23:06 +01:00
|
|
|
vp9_cost_tokens(cpi->mb.partition_cost[i], get_partition_probs(cm, i),
|
2013-04-17 18:25:06 +02:00
|
|
|
vp9_partition_tree);
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
/*rough estimate for costing*/
|
2013-11-25 21:44:05 +01:00
|
|
|
fill_mode_costs(cpi);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-10-21 20:10:11 +02:00
|
|
|
if (!frame_is_intra_only(cm)) {
|
2012-10-30 20:58:42 +01:00
|
|
|
vp9_build_nmv_cost_table(
|
2012-07-26 22:42:07 +02:00
|
|
|
cpi->mb.nmvjointcost,
|
2013-10-21 20:10:11 +02:00
|
|
|
cm->allow_high_precision_mv ? cpi->mb.nmvcost_hp : cpi->mb.nmvcost,
|
|
|
|
&cm->fc.nmvc,
|
|
|
|
cm->allow_high_precision_mv, 1, 1);
|
2013-07-03 19:54:36 +02:00
|
|
|
|
2013-11-26 23:53:17 +01:00
|
|
|
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
|
|
|
|
vp9_cost_tokens((int *)cpi->mb.inter_mode_cost[i],
|
|
|
|
cm->fc.inter_mode_probs[i], vp9_inter_mode_tree);
|
2012-07-26 22:42:07 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2013-07-12 20:38:44 +02:00
|
|
|
static INLINE void linear_interpolate2(double x, int ntab, int inv_step,
|
2013-07-11 01:51:07 +02:00
|
|
|
const double *tab1, const double *tab2,
|
|
|
|
double *v1, double *v2) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
double y = x * inv_step;
|
|
|
|
int d = (int) y;
|
|
|
|
if (d >= ntab - 1) {
|
2013-07-11 01:51:07 +02:00
|
|
|
*v1 = tab1[ntab - 1];
|
|
|
|
*v2 = tab2[ntab - 1];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else {
|
|
|
|
double a = y - d;
|
2013-07-11 01:51:07 +02:00
|
|
|
*v1 = tab1[d] * (1 - a) + tab1[d + 1] * a;
|
|
|
|
*v2 = tab2[d] * (1 - a) + tab2[d + 1] * a;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-11 01:51:07 +02:00
|
|
|
static void model_rd_norm(double x, double *R, double *D) {
|
|
|
|
static const int inv_tab_step = 8;
|
|
|
|
static const int tab_size = 120;
|
|
|
|
// NOTE: The tables below must be of the same size
|
|
|
|
//
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
// Normalized rate
|
2013-07-11 01:51:07 +02:00
|
|
|
// This table models the rate for a Laplacian source
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
// source with given variance when quantized with a uniform quantizer
|
|
|
|
// with given stepsize. The closed form expression is:
|
|
|
|
// Rn(x) = H(sqrt(r)) + sqrt(r)*[1 + H(r)/(1 - r)],
|
|
|
|
// where r = exp(-sqrt(2) * x) and x = qpstep / sqrt(variance),
|
|
|
|
// and H(x) is the binary entropy function.
|
|
|
|
static const double rate_tab[] = {
|
|
|
|
64.00, 4.944, 3.949, 3.372, 2.966, 2.655, 2.403, 2.194,
|
|
|
|
2.014, 1.858, 1.720, 1.596, 1.485, 1.384, 1.291, 1.206,
|
|
|
|
1.127, 1.054, 0.986, 0.923, 0.863, 0.808, 0.756, 0.708,
|
|
|
|
0.662, 0.619, 0.579, 0.541, 0.506, 0.473, 0.442, 0.412,
|
|
|
|
0.385, 0.359, 0.335, 0.313, 0.291, 0.272, 0.253, 0.236,
|
|
|
|
0.220, 0.204, 0.190, 0.177, 0.165, 0.153, 0.142, 0.132,
|
|
|
|
0.123, 0.114, 0.106, 0.099, 0.091, 0.085, 0.079, 0.073,
|
|
|
|
0.068, 0.063, 0.058, 0.054, 0.050, 0.047, 0.043, 0.040,
|
|
|
|
0.037, 0.034, 0.032, 0.029, 0.027, 0.025, 0.023, 0.022,
|
|
|
|
0.020, 0.019, 0.017, 0.016, 0.015, 0.014, 0.013, 0.012,
|
|
|
|
0.011, 0.010, 0.009, 0.008, 0.008, 0.007, 0.007, 0.006,
|
|
|
|
0.006, 0.005, 0.005, 0.005, 0.004, 0.004, 0.004, 0.003,
|
|
|
|
0.003, 0.003, 0.003, 0.002, 0.002, 0.002, 0.002, 0.002,
|
|
|
|
0.002, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001,
|
|
|
|
0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.000,
|
|
|
|
};
|
|
|
|
// Normalized distortion
|
2013-07-11 01:51:07 +02:00
|
|
|
// This table models the normalized distortion for a Laplacian source
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
// source with given variance when quantized with a uniform quantizer
|
|
|
|
// with given stepsize. The closed form expression is:
|
|
|
|
// Dn(x) = 1 - 1/sqrt(2) * x / sinh(x/sqrt(2))
|
|
|
|
// where x = qpstep / sqrt(variance)
|
|
|
|
// Note the actual distortion is Dn * variance.
|
|
|
|
static const double dist_tab[] = {
|
|
|
|
0.000, 0.001, 0.005, 0.012, 0.021, 0.032, 0.045, 0.061,
|
|
|
|
0.079, 0.098, 0.119, 0.142, 0.166, 0.190, 0.216, 0.242,
|
|
|
|
0.269, 0.296, 0.324, 0.351, 0.378, 0.405, 0.432, 0.458,
|
|
|
|
0.484, 0.509, 0.534, 0.557, 0.580, 0.603, 0.624, 0.645,
|
|
|
|
0.664, 0.683, 0.702, 0.719, 0.735, 0.751, 0.766, 0.780,
|
|
|
|
0.794, 0.807, 0.819, 0.830, 0.841, 0.851, 0.861, 0.870,
|
|
|
|
0.878, 0.886, 0.894, 0.901, 0.907, 0.913, 0.919, 0.925,
|
|
|
|
0.930, 0.935, 0.939, 0.943, 0.947, 0.951, 0.954, 0.957,
|
|
|
|
0.960, 0.963, 0.966, 0.968, 0.971, 0.973, 0.975, 0.976,
|
|
|
|
0.978, 0.980, 0.981, 0.982, 0.984, 0.985, 0.986, 0.987,
|
|
|
|
0.988, 0.989, 0.990, 0.990, 0.991, 0.992, 0.992, 0.993,
|
|
|
|
0.993, 0.994, 0.994, 0.995, 0.995, 0.996, 0.996, 0.996,
|
|
|
|
0.996, 0.997, 0.997, 0.997, 0.997, 0.998, 0.998, 0.998,
|
|
|
|
0.998, 0.998, 0.998, 0.999, 0.999, 0.999, 0.999, 0.999,
|
|
|
|
0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 1.000,
|
|
|
|
};
|
2013-07-11 01:51:07 +02:00
|
|
|
/*
|
|
|
|
assert(sizeof(rate_tab) == tab_size * sizeof(rate_tab[0]);
|
|
|
|
assert(sizeof(dist_tab) == tab_size * sizeof(dist_tab[0]);
|
|
|
|
assert(sizeof(rate_tab) == sizeof(dist_tab));
|
|
|
|
*/
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
assert(x >= 0.0);
|
2013-07-11 01:51:07 +02:00
|
|
|
linear_interpolate2(x, tab_size, inv_tab_step,
|
|
|
|
rate_tab, dist_tab, R, D);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void model_rd_from_var_lapndz(int var, int n, int qstep,
|
|
|
|
int *rate, int64_t *dist) {
|
|
|
|
// This function models the rate and distortion for a Laplacian
|
|
|
|
// source with given variance when quantized with a uniform quantizer
|
|
|
|
// with given stepsize. The closed form expressions are in:
|
|
|
|
// Hang and Chen, "Source Model for transform video coder and its
|
|
|
|
// application - Part I: Fundamental Theory", IEEE Trans. Circ.
|
|
|
|
// Sys. for Video Tech., April 1997.
|
|
|
|
vp9_clear_system_state();
|
|
|
|
if (var == 0 || n == 0) {
|
|
|
|
*rate = 0;
|
|
|
|
*dist = 0;
|
|
|
|
} else {
|
|
|
|
double D, R;
|
|
|
|
double s2 = (double) var / n;
|
|
|
|
double x = qstep / sqrt(s2);
|
2013-07-11 01:51:07 +02:00
|
|
|
model_rd_norm(x, &R, &D);
|
2013-09-17 18:45:13 +02:00
|
|
|
*rate = (int)((n << 8) * R + 0.5);
|
|
|
|
*dist = (int)(var * D + 0.5);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
vp9_clear_system_state();
|
|
|
|
}
|
|
|
|
|
2013-08-27 20:05:08 +02:00
|
|
|
static void model_rd_for_sb(VP9_COMP *cpi, BLOCK_SIZE bsize,
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
MACROBLOCK *x, MACROBLOCKD *xd,
|
|
|
|
int *out_rate_sum, int64_t *out_dist_sum) {
|
|
|
|
// Note our transform coeffs are 8 times an orthogonal transform.
|
|
|
|
// Hence quantizer step is also 8 times. To get effective quantizer
|
|
|
|
// we need to divide by 8 before sending to modeling function.
|
|
|
|
int i, rate_sum = 0, dist_sum = 0;
|
2013-12-21 00:24:22 +01:00
|
|
|
int ref = xd->mi_8x8[0]->mbmi.ref_frame[0];
|
|
|
|
unsigned int sse;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; ++i) {
|
|
|
|
struct macroblock_plane *const p = &x->plane[i];
|
|
|
|
struct macroblockd_plane *const pd = &xd->plane[i];
|
2013-08-27 20:05:08 +02:00
|
|
|
const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
int rate;
|
|
|
|
int64_t dist;
|
|
|
|
(void) cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride,
|
2013-12-21 00:24:22 +01:00
|
|
|
pd->dst.buf, pd->dst.stride, &sse);
|
|
|
|
if (i == 0)
|
|
|
|
x->pred_sse[ref] = sse;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
// sse works better than var, since there is no dc prediction used
|
2013-12-21 00:24:22 +01:00
|
|
|
model_rd_from_var_lapndz(sse, 1 << num_pels_log2_lookup[bs],
|
2013-07-11 01:51:07 +02:00
|
|
|
pd->dequant[1] >> 3, &rate, &dist);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
|
|
|
rate_sum += rate;
|
2013-09-17 18:45:13 +02:00
|
|
|
dist_sum += (int)dist;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*out_rate_sum = rate_sum;
|
|
|
|
*out_dist_sum = dist_sum << 4;
|
|
|
|
}
|
|
|
|
|
2013-08-27 20:05:08 +02:00
|
|
|
static void model_rd_for_sb_y_tx(VP9_COMP *cpi, BLOCK_SIZE bsize,
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
TX_SIZE tx_size,
|
|
|
|
MACROBLOCK *x, MACROBLOCKD *xd,
|
|
|
|
int *out_rate_sum, int64_t *out_dist_sum,
|
|
|
|
int *out_skip) {
|
2013-08-27 01:18:28 +02:00
|
|
|
int j, k;
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bs;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
struct macroblock_plane *const p = &x->plane[0];
|
|
|
|
struct macroblockd_plane *const pd = &xd->plane[0];
|
2013-08-27 01:18:28 +02:00
|
|
|
const int width = 4 << num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int height = 4 << num_4x4_blocks_high_lookup[bsize];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
int rate_sum = 0;
|
|
|
|
int64_t dist_sum = 0;
|
2013-08-27 01:18:28 +02:00
|
|
|
const int t = 4 << tx_size;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
|
|
|
if (tx_size == TX_4X4) {
|
|
|
|
bs = BLOCK_4X4;
|
|
|
|
} else if (tx_size == TX_8X8) {
|
|
|
|
bs = BLOCK_8X8;
|
|
|
|
} else if (tx_size == TX_16X16) {
|
|
|
|
bs = BLOCK_16X16;
|
|
|
|
} else if (tx_size == TX_32X32) {
|
|
|
|
bs = BLOCK_32X32;
|
|
|
|
} else {
|
|
|
|
assert(0);
|
|
|
|
}
|
2013-08-27 01:18:28 +02:00
|
|
|
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
*out_skip = 1;
|
2013-07-23 15:51:44 +02:00
|
|
|
for (j = 0; j < height; j += t) {
|
|
|
|
for (k = 0; k < width; k += t) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
int rate;
|
|
|
|
int64_t dist;
|
|
|
|
unsigned int sse;
|
2013-08-27 01:18:28 +02:00
|
|
|
cpi->fn_ptr[bs].vf(&p->src.buf[j * p->src.stride + k], p->src.stride,
|
|
|
|
&pd->dst.buf[j * pd->dst.stride + k], pd->dst.stride,
|
|
|
|
&sse);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
// sse works better than var, since there is no dc prediction used
|
2013-08-27 01:18:28 +02:00
|
|
|
model_rd_from_var_lapndz(sse, t * t, pd->dequant[1] >> 3, &rate, &dist);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
rate_sum += rate;
|
|
|
|
dist_sum += dist;
|
|
|
|
*out_skip &= (rate < 1024);
|
|
|
|
}
|
|
|
|
}
|
2013-08-27 01:18:28 +02:00
|
|
|
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
*out_rate_sum = rate_sum;
|
2013-08-27 01:18:28 +02:00
|
|
|
*out_dist_sum = dist_sum << 4;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t vp9_block_error_c(int16_t *coeff, int16_t *dqcoeff,
|
2013-06-28 02:41:54 +02:00
|
|
|
intptr_t block_size, int64_t *ssz) {
|
2013-06-21 21:54:52 +02:00
|
|
|
int i;
|
2013-06-28 02:41:54 +02:00
|
|
|
int64_t error = 0, sqcoeff = 0;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2012-08-07 00:03:04 +02:00
|
|
|
for (i = 0; i < block_size; i++) {
|
2012-07-14 00:21:29 +02:00
|
|
|
int this_diff = coeff[i] - dqcoeff[i];
|
2013-06-21 21:54:52 +02:00
|
|
|
error += (unsigned)this_diff * this_diff;
|
2013-06-28 02:41:54 +02:00
|
|
|
sqcoeff += (unsigned) coeff[i] * coeff[i];
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-06-28 02:41:54 +02:00
|
|
|
*ssz = sqcoeff;
|
2012-07-14 00:21:29 +02:00
|
|
|
return error;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2013-07-25 00:13:58 +02:00
|
|
|
/* The trailing '0' is a terminator which is used inside cost_coeffs() to
|
|
|
|
* decide whether to include cost of a trailing EOB node or not (i.e. we
|
|
|
|
* can skip this if the last coefficient in this transform block, e.g. the
|
|
|
|
* 16th coefficient in a 4x4 block or the 64th coefficient in a 8x8 block,
|
|
|
|
* were non-zero). */
|
2013-07-27 02:15:37 +02:00
|
|
|
static const int16_t band_counts[TX_SIZES][8] = {
|
2013-07-25 00:13:58 +02:00
|
|
|
{ 1, 2, 3, 4, 3, 16 - 13, 0 },
|
|
|
|
{ 1, 2, 3, 4, 11, 64 - 21, 0 },
|
|
|
|
{ 1, 2, 3, 4, 11, 256 - 21, 0 },
|
|
|
|
{ 1, 2, 3, 4, 11, 1024 - 21, 0 },
|
2013-07-23 01:09:09 +02:00
|
|
|
};
|
|
|
|
|
2013-10-11 20:26:32 +02:00
|
|
|
static INLINE int cost_coeffs(MACROBLOCK *x,
|
2013-08-21 22:02:28 +02:00
|
|
|
int plane, int block,
|
2013-07-23 01:09:09 +02:00
|
|
|
ENTROPY_CONTEXT *A, ENTROPY_CONTEXT *L,
|
2013-04-04 21:03:27 +02:00
|
|
|
TX_SIZE tx_size,
|
2013-07-23 01:09:09 +02:00
|
|
|
const int16_t *scan, const int16_t *nb) {
|
2013-10-11 20:26:32 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-11-27 03:52:10 +01:00
|
|
|
struct macroblock_plane *p = &x->plane[plane];
|
2013-08-21 22:02:28 +02:00
|
|
|
struct macroblockd_plane *pd = &xd->plane[plane];
|
|
|
|
const PLANE_TYPE type = pd->plane_type;
|
2013-07-25 00:13:58 +02:00
|
|
|
const int16_t *band_count = &band_counts[tx_size][1];
|
2013-12-04 02:59:32 +01:00
|
|
|
const int eob = p->eobs[block];
|
2013-11-27 03:52:10 +01:00
|
|
|
const int16_t *const qcoeff_ptr = BLOCK_OFFSET(p->qcoeff, block);
|
2013-06-06 22:44:34 +02:00
|
|
|
const int ref = mbmi->ref_frame[0] != INTRA_FRAME;
|
2013-12-06 02:08:06 +01:00
|
|
|
unsigned int (*token_costs)[2][COEFF_CONTEXTS][ENTROPY_TOKENS] =
|
2013-10-11 20:26:32 +02:00
|
|
|
x->token_costs[tx_size][type][ref];
|
2013-08-21 22:02:28 +02:00
|
|
|
const ENTROPY_CONTEXT above_ec = !!*A, left_ec = !!*L;
|
2013-10-11 20:26:32 +02:00
|
|
|
uint8_t *p_tok = x->token_cache;
|
2013-08-21 22:02:28 +02:00
|
|
|
int pt = combine_entropy_contexts(above_ec, left_ec);
|
|
|
|
int c, cost;
|
2013-02-20 19:16:24 +01:00
|
|
|
|
|
|
|
// Check for consistency of tx_size with mode info
|
2013-12-06 19:54:00 +01:00
|
|
|
assert(type == PLANE_TYPE_Y ? mbmi->tx_size == tx_size
|
2013-08-21 22:02:28 +02:00
|
|
|
: get_uv_tx_size(mbmi) == tx_size);
|
2013-04-04 20:07:19 +02:00
|
|
|
|
2013-06-28 05:57:37 +02:00
|
|
|
if (eob == 0) {
|
|
|
|
// single eob token
|
2013-12-04 02:23:03 +01:00
|
|
|
cost = token_costs[0][0][pt][EOB_TOKEN];
|
2013-07-23 01:09:09 +02:00
|
|
|
c = 0;
|
2013-06-28 05:57:37 +02:00
|
|
|
} else {
|
2013-08-21 22:02:28 +02:00
|
|
|
int band_left = *band_count++;
|
2013-06-28 05:57:37 +02:00
|
|
|
|
|
|
|
// dc token
|
2013-08-21 22:02:28 +02:00
|
|
|
int v = qcoeff_ptr[0];
|
|
|
|
int prev_t = vp9_dct_value_tokens_ptr[v].token;
|
2013-07-25 00:13:58 +02:00
|
|
|
cost = (*token_costs)[0][pt][prev_t] + vp9_dct_value_cost_ptr[v];
|
2013-10-11 20:26:32 +02:00
|
|
|
p_tok[0] = vp9_pt_energy_class[prev_t];
|
2013-07-25 00:13:58 +02:00
|
|
|
++token_costs;
|
2013-06-28 05:57:37 +02:00
|
|
|
|
|
|
|
// ac tokens
|
|
|
|
for (c = 1; c < eob; c++) {
|
|
|
|
const int rc = scan[c];
|
2013-06-28 19:21:25 +02:00
|
|
|
int t;
|
2013-06-28 05:57:37 +02:00
|
|
|
|
|
|
|
v = qcoeff_ptr[rc];
|
|
|
|
t = vp9_dct_value_tokens_ptr[v].token;
|
2013-10-11 20:26:32 +02:00
|
|
|
pt = get_coef_context(nb, p_tok, c);
|
2013-07-25 00:13:58 +02:00
|
|
|
cost += (*token_costs)[!prev_t][pt][t] + vp9_dct_value_cost_ptr[v];
|
2013-10-11 20:26:32 +02:00
|
|
|
p_tok[rc] = vp9_pt_energy_class[t];
|
2013-06-28 19:21:25 +02:00
|
|
|
prev_t = t;
|
2013-07-23 01:09:09 +02:00
|
|
|
if (!--band_left) {
|
2013-07-25 00:13:58 +02:00
|
|
|
band_left = *band_count++;
|
|
|
|
++token_costs;
|
2013-07-23 01:09:09 +02:00
|
|
|
}
|
2012-09-10 07:42:35 +02:00
|
|
|
}
|
2013-06-28 05:57:37 +02:00
|
|
|
|
|
|
|
// eob token
|
2013-07-25 00:13:58 +02:00
|
|
|
if (band_left) {
|
2013-10-11 20:26:32 +02:00
|
|
|
pt = get_coef_context(nb, p_tok, c);
|
2013-12-04 02:23:03 +01:00
|
|
|
cost += (*token_costs)[0][pt][EOB_TOKEN];
|
2013-04-22 19:58:49 +02:00
|
|
|
}
|
2012-08-06 20:22:28 +02:00
|
|
|
}
|
|
|
|
|
2013-04-29 19:37:25 +02:00
|
|
|
// is eob first coefficient;
|
2013-08-21 22:02:28 +02:00
|
|
|
*A = *L = (c > 0);
|
2013-04-29 19:37:25 +02:00
|
|
|
|
2012-08-06 20:22:28 +02:00
|
|
|
return cost;
|
|
|
|
}
|
|
|
|
|
2013-08-19 22:20:21 +02:00
|
|
|
static void dist_block(int plane, int block, TX_SIZE tx_size, void *arg) {
|
2013-08-16 02:03:03 +02:00
|
|
|
const int ss_txfrm_size = tx_size << 1;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
struct rdcost_block_args* args = arg;
|
|
|
|
MACROBLOCK* const x = args->x;
|
|
|
|
MACROBLOCKD* const xd = &x->e_mbd;
|
2013-08-14 03:58:21 +02:00
|
|
|
struct macroblock_plane *const p = &x->plane[plane];
|
|
|
|
struct macroblockd_plane *const pd = &xd->plane[plane];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
int64_t this_sse;
|
|
|
|
int shift = args->tx_size == TX_32X32 ? 0 : 2;
|
2013-08-10 01:40:05 +02:00
|
|
|
int16_t *const coeff = BLOCK_OFFSET(p->coeff, block);
|
|
|
|
int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
|
2013-10-10 19:37:40 +02:00
|
|
|
args->dist = vp9_block_error(coeff, dqcoeff, 16 << ss_txfrm_size,
|
|
|
|
&this_sse) >> shift;
|
|
|
|
args->sse = this_sse >> shift;
|
2013-07-09 01:48:47 +02:00
|
|
|
|
2013-11-20 05:25:55 +01:00
|
|
|
if (x->skip_encode && !is_inter_block(&xd->mi_8x8[0]->mbmi)) {
|
2013-07-09 01:48:47 +02:00
|
|
|
// TODO(jingning): tune the model to better capture the distortion.
|
|
|
|
int64_t p = (pd->dequant[1] * pd->dequant[1] *
|
2013-10-09 23:36:48 +02:00
|
|
|
(1 << ss_txfrm_size)) >> (shift + 2);
|
2013-10-10 19:37:40 +02:00
|
|
|
args->dist += (p >> 4);
|
|
|
|
args->sse += p;
|
2013-07-09 01:48:47 +02:00
|
|
|
}
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
2013-08-27 20:05:08 +02:00
|
|
|
static void rate_block(int plane, int block, BLOCK_SIZE plane_bsize,
|
2013-08-16 02:03:03 +02:00
|
|
|
TX_SIZE tx_size, void *arg) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
struct rdcost_block_args* args = arg;
|
2013-08-19 22:20:21 +02:00
|
|
|
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
int x_idx, y_idx;
|
2013-08-19 22:20:21 +02:00
|
|
|
txfrm_block_to_raster_xy(plane_bsize, args->tx_size, block, &x_idx, &y_idx);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
args->rate = cost_coeffs(args->x, plane, block, args->t_above + x_idx,
|
|
|
|
args->t_left + y_idx, args->tx_size,
|
|
|
|
args->scan, args->nb);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
2013-11-25 01:14:54 +01:00
|
|
|
static void block_rd_txfm(int plane, int block, BLOCK_SIZE plane_bsize,
|
|
|
|
TX_SIZE tx_size, void *arg) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
struct rdcost_block_args *args = arg;
|
|
|
|
MACROBLOCK *const x = args->x;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-08-16 21:51:20 +02:00
|
|
|
struct encode_b_args encode_args = {x, NULL};
|
2013-07-17 18:56:46 +02:00
|
|
|
int64_t rd1, rd2, rd;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
2013-07-03 01:48:15 +02:00
|
|
|
if (args->skip)
|
|
|
|
return;
|
|
|
|
|
2013-10-10 21:11:44 +02:00
|
|
|
if (!is_inter_block(&xd->mi_8x8[0]->mbmi))
|
2013-08-20 00:47:24 +02:00
|
|
|
vp9_encode_block_intra(plane, block, plane_bsize, tx_size, &encode_args);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
else
|
2013-08-19 22:20:21 +02:00
|
|
|
vp9_xform_quant(plane, block, plane_bsize, tx_size, &encode_args);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
2013-08-19 22:20:21 +02:00
|
|
|
dist_block(plane, block, tx_size, args);
|
|
|
|
rate_block(plane, block, plane_bsize, tx_size, args);
|
2013-10-10 19:37:40 +02:00
|
|
|
rd1 = RDCOST(x->rdmult, x->rddiv, args->rate, args->dist);
|
|
|
|
rd2 = RDCOST(x->rdmult, x->rddiv, 0, args->sse);
|
2013-09-21 01:29:24 +02:00
|
|
|
|
|
|
|
// TODO(jingning): temporarily enabled only for luma component
|
2013-09-20 20:30:46 +02:00
|
|
|
rd = MIN(rd1, rd2);
|
2013-11-18 23:44:38 +01:00
|
|
|
if (plane == 0)
|
2013-12-04 02:59:32 +01:00
|
|
|
x->zcoeff_blk[tx_size][block] = !x->plane[plane].eobs[block] ||
|
2013-11-18 23:44:38 +01:00
|
|
|
(rd1 > rd2 && !xd->lossless);
|
2013-09-21 01:29:24 +02:00
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
args->this_rate += args->rate;
|
|
|
|
args->this_dist += args->dist;
|
|
|
|
args->this_sse += args->sse;
|
2013-09-20 20:30:46 +02:00
|
|
|
args->this_rd += rd;
|
|
|
|
|
|
|
|
if (args->this_rd > args->best_rd) {
|
|
|
|
args->skip = 1;
|
|
|
|
return;
|
|
|
|
}
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
2013-09-25 02:26:05 +02:00
|
|
|
void vp9_get_entropy_contexts(TX_SIZE tx_size,
|
|
|
|
ENTROPY_CONTEXT t_above[16], ENTROPY_CONTEXT t_left[16],
|
|
|
|
const ENTROPY_CONTEXT *above, const ENTROPY_CONTEXT *left,
|
|
|
|
int num_4x4_w, int num_4x4_h) {
|
|
|
|
int i;
|
|
|
|
switch (tx_size) {
|
|
|
|
case TX_4X4:
|
|
|
|
vpx_memcpy(t_above, above, sizeof(ENTROPY_CONTEXT) * num_4x4_w);
|
|
|
|
vpx_memcpy(t_left, left, sizeof(ENTROPY_CONTEXT) * num_4x4_h);
|
|
|
|
break;
|
|
|
|
case TX_8X8:
|
|
|
|
for (i = 0; i < num_4x4_w; i += 2)
|
|
|
|
t_above[i] = !!*(const uint16_t *)&above[i];
|
|
|
|
for (i = 0; i < num_4x4_h; i += 2)
|
|
|
|
t_left[i] = !!*(const uint16_t *)&left[i];
|
|
|
|
break;
|
|
|
|
case TX_16X16:
|
|
|
|
for (i = 0; i < num_4x4_w; i += 4)
|
|
|
|
t_above[i] = !!*(const uint32_t *)&above[i];
|
|
|
|
for (i = 0; i < num_4x4_h; i += 4)
|
|
|
|
t_left[i] = !!*(const uint32_t *)&left[i];
|
|
|
|
break;
|
|
|
|
case TX_32X32:
|
|
|
|
for (i = 0; i < num_4x4_w; i += 8)
|
|
|
|
t_above[i] = !!*(const uint64_t *)&above[i];
|
|
|
|
for (i = 0; i < num_4x4_h; i += 8)
|
|
|
|
t_left[i] = !!*(const uint64_t *)&left[i];
|
|
|
|
break;
|
|
|
|
default:
|
2013-12-13 04:44:08 +01:00
|
|
|
assert(0 && "Invalid transform size.");
|
2013-09-25 02:26:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
static void init_rdcost_stack(MACROBLOCK *x, TX_SIZE tx_size,
|
|
|
|
const int num_4x4_w, const int num_4x4_h,
|
|
|
|
const int64_t ref_rdcost,
|
|
|
|
struct rdcost_block_args *arg) {
|
|
|
|
vpx_memset(arg, 0, sizeof(struct rdcost_block_args));
|
|
|
|
arg->x = x;
|
|
|
|
arg->tx_size = tx_size;
|
|
|
|
arg->bw = num_4x4_w;
|
|
|
|
arg->bh = num_4x4_h;
|
|
|
|
arg->best_rd = ref_rdcost;
|
|
|
|
}
|
|
|
|
|
2013-08-16 21:51:20 +02:00
|
|
|
static void txfm_rd_in_plane(MACROBLOCK *x,
|
2013-10-10 19:37:40 +02:00
|
|
|
struct rdcost_block_args *rd_stack,
|
2013-08-14 03:58:21 +02:00
|
|
|
int *rate, int64_t *distortion,
|
|
|
|
int *skippable, int64_t *sse,
|
|
|
|
int64_t ref_best_rd, int plane,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize, TX_SIZE tx_size) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-08-14 03:58:21 +02:00
|
|
|
struct macroblockd_plane *const pd = &xd->plane[plane];
|
2013-08-27 20:05:08 +02:00
|
|
|
const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
|
2013-09-25 02:26:05 +02:00
|
|
|
const int num_4x4_w = num_4x4_blocks_wide_lookup[bs];
|
|
|
|
const int num_4x4_h = num_4x4_blocks_high_lookup[bs];
|
2013-11-23 01:20:45 +01:00
|
|
|
const scan_order *so;
|
2013-09-25 02:26:05 +02:00
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
init_rdcost_stack(x, tx_size, num_4x4_w, num_4x4_h,
|
|
|
|
ref_best_rd, rd_stack);
|
2013-08-14 03:58:21 +02:00
|
|
|
if (plane == 0)
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->mbmi.tx_size = tx_size;
|
2013-08-14 03:58:21 +02:00
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
vp9_get_entropy_contexts(tx_size, rd_stack->t_above, rd_stack->t_left,
|
2013-09-25 02:26:05 +02:00
|
|
|
pd->above_context, pd->left_context,
|
|
|
|
num_4x4_w, num_4x4_h);
|
2013-10-04 01:07:26 +02:00
|
|
|
|
2013-11-23 01:20:45 +01:00
|
|
|
so = get_scan(xd, tx_size, pd->plane_type, 0);
|
|
|
|
rd_stack->scan = so->scan;
|
|
|
|
rd_stack->nb = so->neighbors;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
foreach_transformed_block_in_plane(xd, bsize, plane,
|
2013-11-25 01:14:54 +01:00
|
|
|
block_rd_txfm, rd_stack);
|
2013-10-10 19:37:40 +02:00
|
|
|
if (rd_stack->skip) {
|
2013-09-20 20:30:46 +02:00
|
|
|
*rate = INT_MAX;
|
|
|
|
*distortion = INT64_MAX;
|
|
|
|
*sse = INT64_MAX;
|
|
|
|
*skippable = 0;
|
|
|
|
} else {
|
2013-10-10 19:37:40 +02:00
|
|
|
*distortion = rd_stack->this_dist;
|
|
|
|
*rate = rd_stack->this_rate;
|
|
|
|
*sse = rd_stack->this_sse;
|
2013-12-04 02:59:32 +01:00
|
|
|
*skippable = vp9_is_skippable_in_plane(x, bsize, plane);
|
2013-09-20 20:30:46 +02:00
|
|
|
}
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void choose_largest_txfm_size(VP9_COMP *cpi, MACROBLOCK *x,
|
|
|
|
int *rate, int64_t *distortion,
|
|
|
|
int *skip, int64_t *sse,
|
2013-07-11 01:51:07 +02:00
|
|
|
int64_t ref_best_rd,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bs) {
|
2013-09-25 02:24:35 +02:00
|
|
|
const TX_SIZE max_tx_size = max_txsize_lookup[bs];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2013-10-17 20:09:14 +02:00
|
|
|
const TX_SIZE largest_tx_size = tx_mode_to_biggest_tx_size[cm->tx_mode];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-10-17 20:09:14 +02:00
|
|
|
|
|
|
|
mbmi->tx_size = MIN(max_tx_size, largest_tx_size);
|
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
txfm_rd_in_plane(x, &cpi->rdcost_stack, rate, distortion, skip,
|
2013-08-28 04:47:53 +02:00
|
|
|
&sse[mbmi->tx_size], ref_best_rd, 0, bs,
|
|
|
|
mbmi->tx_size);
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[0]++;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
|
2012-11-08 20:03:00 +01:00
|
|
|
static void choose_txfm_size_from_rd(VP9_COMP *cpi, MACROBLOCK *x,
|
32x32 transform for superblocks.
This adds Debargha's DCT/DWT hybrid and a regular 32x32 DCT, and adds
code all over the place to wrap that in the bitstream/encoder/decoder/RD.
Some implementation notes (these probably need careful review):
- token range is extended by 1 bit, since the value range out of this
transform is [-16384,16383].
- the coefficients coming out of the FDCT are manually scaled back by
1 bit, or else they won't fit in int16_t (they are 17 bits). Because
of this, the RD error scoring does not right-shift the MSE score by
two (unlike for 4x4/8x8/16x16).
- to compensate for this loss in precision, the quantizer is halved
also. This is currently a little hacky.
- FDCT and IDCT is double-only right now. Needs a fixed-point impl.
- There are no default probabilities for the 32x32 transform yet; I'm
simply using the 16x16 luma ones. A future commit will add newly
generated probabilities for all transforms.
- No ADST version. I don't think we'll add one for this level; if an
ADST is desired, transform-size selection can scale back to 16x16
or lower, and use an ADST at that level.
Additional notes specific to Debargha's DWT/DCT hybrid:
- coefficient scale is different for the top/left 16x16 (DCT-over-DWT)
block than for the rest (DWT pixel differences) of the block. Therefore,
RD error scoring isn't easily scalable between coefficient and pixel
domain. Thus, unfortunately, we need to compute the RD distortion in
the pixel domain until we figure out how to scale these appropriately.
Change-Id: I00386f20f35d7fabb19aba94c8162f8aee64ef2b
2012-12-07 23:45:05 +01:00
|
|
|
int (*r)[2], int *rate,
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t *d, int64_t *distortion,
|
32x32 transform for superblocks.
This adds Debargha's DCT/DWT hybrid and a regular 32x32 DCT, and adds
code all over the place to wrap that in the bitstream/encoder/decoder/RD.
Some implementation notes (these probably need careful review):
- token range is extended by 1 bit, since the value range out of this
transform is [-16384,16383].
- the coefficients coming out of the FDCT are manually scaled back by
1 bit, or else they won't fit in int16_t (they are 17 bits). Because
of this, the RD error scoring does not right-shift the MSE score by
two (unlike for 4x4/8x8/16x16).
- to compensate for this loss in precision, the quantizer is halved
also. This is currently a little hacky.
- FDCT and IDCT is double-only right now. Needs a fixed-point impl.
- There are no default probabilities for the 32x32 transform yet; I'm
simply using the 16x16 luma ones. A future commit will add newly
generated probabilities for all transforms.
- No ADST version. I don't think we'll add one for this level; if an
ADST is desired, transform-size selection can scale back to 16x16
or lower, and use an ADST at that level.
Additional notes specific to Debargha's DWT/DCT hybrid:
- coefficient scale is different for the top/left 16x16 (DCT-over-DWT)
block than for the rest (DWT pixel differences) of the block. Therefore,
RD error scoring isn't easily scalable between coefficient and pixel
domain. Thus, unfortunately, we need to compute the RD distortion in
the pixel domain until we figure out how to scale these appropriately.
Change-Id: I00386f20f35d7fabb19aba94c8162f8aee64ef2b
2012-12-07 23:45:05 +01:00
|
|
|
int *s, int *skip,
|
2013-08-03 02:28:23 +02:00
|
|
|
int64_t tx_cache[TX_MODES],
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bs) {
|
2013-08-13 01:56:32 +02:00
|
|
|
const TX_SIZE max_tx_size = max_txsize_lookup[bs];
|
2012-11-08 20:03:00 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-12-10 23:11:26 +01:00
|
|
|
vp9_prob skip_prob = vp9_get_skip_prob(cm, xd);
|
2013-07-27 02:15:37 +02:00
|
|
|
int64_t rd[TX_SIZES][2];
|
32x32 transform for superblocks.
This adds Debargha's DCT/DWT hybrid and a regular 32x32 DCT, and adds
code all over the place to wrap that in the bitstream/encoder/decoder/RD.
Some implementation notes (these probably need careful review):
- token range is extended by 1 bit, since the value range out of this
transform is [-16384,16383].
- the coefficients coming out of the FDCT are manually scaled back by
1 bit, or else they won't fit in int16_t (they are 17 bits). Because
of this, the RD error scoring does not right-shift the MSE score by
two (unlike for 4x4/8x8/16x16).
- to compensate for this loss in precision, the quantizer is halved
also. This is currently a little hacky.
- FDCT and IDCT is double-only right now. Needs a fixed-point impl.
- There are no default probabilities for the 32x32 transform yet; I'm
simply using the 16x16 luma ones. A future commit will add newly
generated probabilities for all transforms.
- No ADST version. I don't think we'll add one for this level; if an
ADST is desired, transform-size selection can scale back to 16x16
or lower, and use an ADST at that level.
Additional notes specific to Debargha's DWT/DCT hybrid:
- coefficient scale is different for the top/left 16x16 (DCT-over-DWT)
block than for the rest (DWT pixel differences) of the block. Therefore,
RD error scoring isn't easily scalable between coefficient and pixel
domain. Thus, unfortunately, we need to compute the RD distortion in
the pixel domain until we figure out how to scale these appropriately.
Change-Id: I00386f20f35d7fabb19aba94c8162f8aee64ef2b
2012-12-07 23:45:05 +01:00
|
|
|
int n, m;
|
2013-04-09 19:54:19 +02:00
|
|
|
int s0, s1;
|
2013-11-25 21:45:51 +01:00
|
|
|
const TX_SIZE max_mode_tx_size = tx_mode_to_biggest_tx_size[cm->tx_mode];
|
|
|
|
int64_t best_rd = INT64_MAX;
|
|
|
|
TX_SIZE best_tx = TX_4X4;
|
32x32 transform for superblocks.
This adds Debargha's DCT/DWT hybrid and a regular 32x32 DCT, and adds
code all over the place to wrap that in the bitstream/encoder/decoder/RD.
Some implementation notes (these probably need careful review):
- token range is extended by 1 bit, since the value range out of this
transform is [-16384,16383].
- the coefficients coming out of the FDCT are manually scaled back by
1 bit, or else they won't fit in int16_t (they are 17 bits). Because
of this, the RD error scoring does not right-shift the MSE score by
two (unlike for 4x4/8x8/16x16).
- to compensate for this loss in precision, the quantizer is halved
also. This is currently a little hacky.
- FDCT and IDCT is double-only right now. Needs a fixed-point impl.
- There are no default probabilities for the 32x32 transform yet; I'm
simply using the 16x16 luma ones. A future commit will add newly
generated probabilities for all transforms.
- No ADST version. I don't think we'll add one for this level; if an
ADST is desired, transform-size selection can scale back to 16x16
or lower, and use an ADST at that level.
Additional notes specific to Debargha's DWT/DCT hybrid:
- coefficient scale is different for the top/left 16x16 (DCT-over-DWT)
block than for the rest (DWT pixel differences) of the block. Therefore,
RD error scoring isn't easily scalable between coefficient and pixel
domain. Thus, unfortunately, we need to compute the RD distortion in
the pixel domain until we figure out how to scale these appropriately.
Change-Id: I00386f20f35d7fabb19aba94c8162f8aee64ef2b
2012-12-07 23:45:05 +01:00
|
|
|
|
2013-11-06 02:36:43 +01:00
|
|
|
const vp9_prob *tx_probs = get_tx_probs2(max_tx_size, xd, &cm->fc.tx_probs);
|
2013-04-09 19:54:19 +02:00
|
|
|
assert(skip_prob > 0);
|
|
|
|
s0 = vp9_cost_bit(skip_prob, 0);
|
|
|
|
s1 = vp9_cost_bit(skip_prob, 1);
|
2012-11-08 20:03:00 +01:00
|
|
|
|
2013-08-03 02:28:23 +02:00
|
|
|
for (n = TX_4X4; n <= max_tx_size; n++) {
|
2013-11-25 21:45:51 +01:00
|
|
|
r[n][1] = r[n][0];
|
|
|
|
if (r[n][0] < INT_MAX) {
|
|
|
|
for (m = 0; m <= n - (n == max_tx_size); m++) {
|
|
|
|
if (m == n)
|
|
|
|
r[n][1] += vp9_cost_zero(tx_probs[m]);
|
|
|
|
else
|
|
|
|
r[n][1] += vp9_cost_one(tx_probs[m]);
|
|
|
|
}
|
|
|
|
}
|
2013-07-03 01:48:15 +02:00
|
|
|
if (d[n] == INT64_MAX) {
|
|
|
|
rd[n][0] = rd[n][1] = INT64_MAX;
|
2013-11-25 21:45:51 +01:00
|
|
|
} else if (s[n]) {
|
2013-04-09 19:54:19 +02:00
|
|
|
rd[n][0] = rd[n][1] = RDCOST(x->rdmult, x->rddiv, s1, d[n]);
|
|
|
|
} else {
|
|
|
|
rd[n][0] = RDCOST(x->rdmult, x->rddiv, r[n][0] + s0, d[n]);
|
|
|
|
rd[n][1] = RDCOST(x->rdmult, x->rddiv, r[n][1] + s0, d[n]);
|
2012-10-09 18:18:21 +02:00
|
|
|
}
|
2013-11-25 21:45:51 +01:00
|
|
|
|
|
|
|
if (rd[n][1] < best_rd) {
|
|
|
|
best_tx = n;
|
|
|
|
best_rd = rd[n][1];
|
|
|
|
}
|
2012-10-09 18:18:21 +02:00
|
|
|
}
|
2013-11-25 21:45:51 +01:00
|
|
|
mbmi->tx_size = cm->tx_mode == TX_MODE_SELECT ?
|
|
|
|
best_tx : MIN(max_tx_size, max_mode_tx_size);
|
2012-10-09 18:18:21 +02:00
|
|
|
|
|
|
|
|
2013-08-28 04:47:53 +02:00
|
|
|
*distortion = d[mbmi->tx_size];
|
|
|
|
*rate = r[mbmi->tx_size][cm->tx_mode == TX_MODE_SELECT];
|
|
|
|
*skip = s[mbmi->tx_size];
|
2012-11-08 20:03:00 +01:00
|
|
|
|
2013-08-03 02:28:23 +02:00
|
|
|
tx_cache[ONLY_4X4] = rd[TX_4X4][0];
|
|
|
|
tx_cache[ALLOW_8X8] = rd[TX_8X8][0];
|
|
|
|
tx_cache[ALLOW_16X16] = rd[MIN(max_tx_size, TX_16X16)][0];
|
|
|
|
tx_cache[ALLOW_32X32] = rd[MIN(max_tx_size, TX_32X32)][0];
|
2013-04-02 23:50:40 +02:00
|
|
|
|
2013-11-25 21:45:51 +01:00
|
|
|
if (max_tx_size == TX_32X32 && best_tx == TX_32X32) {
|
|
|
|
tx_cache[TX_MODE_SELECT] = rd[TX_32X32][1];
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[0]++;
|
2013-11-25 21:45:51 +01:00
|
|
|
} else if (max_tx_size >= TX_16X16 && best_tx == TX_16X16) {
|
|
|
|
tx_cache[TX_MODE_SELECT] = rd[TX_16X16][1];
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[max_tx_size - TX_16X16]++;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else if (rd[TX_8X8][1] < rd[TX_4X4][1]) {
|
2013-11-25 21:45:51 +01:00
|
|
|
tx_cache[TX_MODE_SELECT] = rd[TX_8X8][1];
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[max_tx_size - TX_8X8]++;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else {
|
2013-11-25 21:45:51 +01:00
|
|
|
tx_cache[TX_MODE_SELECT] = rd[TX_4X4][1];
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[max_tx_size - TX_4X4]++;
|
2013-04-23 18:51:09 +02:00
|
|
|
}
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
2013-03-06 00:18:06 +01:00
|
|
|
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
static void choose_txfm_size_from_modelrd(VP9_COMP *cpi, MACROBLOCK *x,
|
|
|
|
int (*r)[2], int *rate,
|
|
|
|
int64_t *d, int64_t *distortion,
|
|
|
|
int *s, int *skip, int64_t *sse,
|
2013-07-11 01:51:07 +02:00
|
|
|
int64_t ref_best_rd,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bs) {
|
2013-09-25 02:24:35 +02:00
|
|
|
const TX_SIZE max_tx_size = max_txsize_lookup[bs];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-12-10 23:11:26 +01:00
|
|
|
vp9_prob skip_prob = vp9_get_skip_prob(cm, xd);
|
2013-07-27 02:15:37 +02:00
|
|
|
int64_t rd[TX_SIZES][2];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
int n, m;
|
|
|
|
int s0, s1;
|
2013-07-27 02:15:37 +02:00
|
|
|
double scale_rd[TX_SIZES] = {1.73, 1.44, 1.20, 1.00};
|
2013-11-25 21:45:51 +01:00
|
|
|
const TX_SIZE max_mode_tx_size = tx_mode_to_biggest_tx_size[cm->tx_mode];
|
|
|
|
int64_t best_rd = INT64_MAX;
|
|
|
|
TX_SIZE best_tx = TX_4X4;
|
2013-03-06 00:18:06 +01:00
|
|
|
|
2013-11-06 02:36:43 +01:00
|
|
|
const vp9_prob *tx_probs = get_tx_probs2(max_tx_size, xd, &cm->fc.tx_probs);
|
2013-11-25 21:45:51 +01:00
|
|
|
assert(skip_prob > 0);
|
|
|
|
s0 = vp9_cost_bit(skip_prob, 0);
|
|
|
|
s1 = vp9_cost_bit(skip_prob, 1);
|
2013-04-11 00:55:59 +02:00
|
|
|
|
2013-09-25 02:24:35 +02:00
|
|
|
for (n = TX_4X4; n <= max_tx_size; n++) {
|
2013-11-25 21:45:51 +01:00
|
|
|
double scale = scale_rd[n];
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
r[n][1] = r[n][0];
|
2013-09-25 02:24:35 +02:00
|
|
|
for (m = 0; m <= n - (n == max_tx_size); m++) {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
if (m == n)
|
|
|
|
r[n][1] += vp9_cost_zero(tx_probs[m]);
|
|
|
|
else
|
|
|
|
r[n][1] += vp9_cost_one(tx_probs[m]);
|
|
|
|
}
|
|
|
|
if (s[n]) {
|
2013-11-25 21:45:51 +01:00
|
|
|
rd[n][0] = rd[n][1] = RDCOST(x->rdmult, x->rddiv, s1, d[n]) * scale;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else {
|
2013-11-25 21:45:51 +01:00
|
|
|
rd[n][0] = RDCOST(x->rdmult, x->rddiv, r[n][0] + s0, d[n]) * scale;
|
|
|
|
rd[n][1] = RDCOST(x->rdmult, x->rddiv, r[n][1] + s0, d[n]) * scale;
|
|
|
|
}
|
|
|
|
if (rd[n][1] < best_rd) {
|
|
|
|
best_rd = rd[n][1];
|
|
|
|
best_tx = n;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
|
|
|
}
|
2013-07-02 01:50:58 +02:00
|
|
|
|
2013-11-25 21:45:51 +01:00
|
|
|
mbmi->tx_size = cm->tx_mode == TX_MODE_SELECT ?
|
|
|
|
best_tx : MIN(max_tx_size, max_mode_tx_size);
|
2013-07-02 01:50:58 +02:00
|
|
|
|
2013-08-13 01:34:48 +02:00
|
|
|
// Actually encode using the chosen mode if a model was used, but do not
|
|
|
|
// update the r, d costs
|
2013-10-10 19:37:40 +02:00
|
|
|
txfm_rd_in_plane(x, &cpi->rdcost_stack, rate, distortion, skip,
|
|
|
|
&sse[mbmi->tx_size], ref_best_rd, 0, bs, mbmi->tx_size);
|
2013-06-04 00:33:31 +02:00
|
|
|
|
2013-11-25 21:45:51 +01:00
|
|
|
if (max_tx_size == TX_32X32 && best_tx == TX_32X32) {
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[0]++;
|
2013-11-25 21:45:51 +01:00
|
|
|
} else if (max_tx_size >= TX_16X16 && best_tx == TX_16X16) {
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[max_tx_size - TX_16X16]++;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else if (rd[TX_8X8][1] <= rd[TX_4X4][1]) {
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[max_tx_size - TX_8X8]++;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else {
|
2013-09-25 02:24:35 +02:00
|
|
|
cpi->tx_stepdown_count[max_tx_size - TX_4X4]++;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
32x32 transform for superblocks.
This adds Debargha's DCT/DWT hybrid and a regular 32x32 DCT, and adds
code all over the place to wrap that in the bitstream/encoder/decoder/RD.
Some implementation notes (these probably need careful review):
- token range is extended by 1 bit, since the value range out of this
transform is [-16384,16383].
- the coefficients coming out of the FDCT are manually scaled back by
1 bit, or else they won't fit in int16_t (they are 17 bits). Because
of this, the RD error scoring does not right-shift the MSE score by
two (unlike for 4x4/8x8/16x16).
- to compensate for this loss in precision, the quantizer is halved
also. This is currently a little hacky.
- FDCT and IDCT is double-only right now. Needs a fixed-point impl.
- There are no default probabilities for the 32x32 transform yet; I'm
simply using the 16x16 luma ones. A future commit will add newly
generated probabilities for all transforms.
- No ADST version. I don't think we'll add one for this level; if an
ADST is desired, transform-size selection can scale back to 16x16
or lower, and use an ADST at that level.
Additional notes specific to Debargha's DWT/DCT hybrid:
- coefficient scale is different for the top/left 16x16 (DCT-over-DWT)
block than for the rest (DWT pixel differences) of the block. Therefore,
RD error scoring isn't easily scalable between coefficient and pixel
domain. Thus, unfortunately, we need to compute the RD distortion in
the pixel domain until we figure out how to scale these appropriately.
Change-Id: I00386f20f35d7fabb19aba94c8162f8aee64ef2b
2012-12-07 23:45:05 +01:00
|
|
|
}
|
|
|
|
|
2012-11-08 20:03:00 +01:00
|
|
|
static void super_block_yrd(VP9_COMP *cpi,
|
2013-06-21 21:54:52 +02:00
|
|
|
MACROBLOCK *x, int *rate, int64_t *distortion,
|
2013-08-27 20:05:08 +02:00
|
|
|
int *skip, int64_t *psse, BLOCK_SIZE bs,
|
2013-07-29 22:38:40 +02:00
|
|
|
int64_t txfm_cache[TX_MODES],
|
2013-07-03 01:48:15 +02:00
|
|
|
int64_t ref_best_rd) {
|
2013-07-27 02:15:37 +02:00
|
|
|
int r[TX_SIZES][2], s[TX_SIZES];
|
|
|
|
int64_t d[TX_SIZES], sse[TX_SIZES];
|
2013-05-31 00:13:08 +02:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-10-10 19:37:40 +02:00
|
|
|
struct rdcost_block_args *rdcost_stack = &cpi->rdcost_stack;
|
2013-10-23 19:06:11 +02:00
|
|
|
const int b_inter_mode = is_inter_block(mbmi);
|
2013-11-26 23:55:53 +01:00
|
|
|
const TX_SIZE max_tx_size = max_txsize_lookup[bs];
|
|
|
|
TX_SIZE tx_size;
|
|
|
|
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-06-06 20:14:04 +02:00
|
|
|
assert(bs == mbmi->sb_type);
|
2013-10-23 19:06:11 +02:00
|
|
|
if (b_inter_mode)
|
2013-06-04 00:33:31 +02:00
|
|
|
vp9_subtract_sby(x, bs);
|
2013-01-06 03:20:25 +01:00
|
|
|
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
if (cpi->sf.tx_size_search_method == USE_LARGESTALL ||
|
|
|
|
(cpi->sf.tx_size_search_method != USE_FULL_RD &&
|
2013-10-23 19:06:11 +02:00
|
|
|
!b_inter_mode)) {
|
2013-07-29 22:38:40 +02:00
|
|
|
vpx_memset(txfm_cache, 0, TX_MODES * sizeof(int64_t));
|
2013-07-11 01:51:07 +02:00
|
|
|
choose_largest_txfm_size(cpi, x, rate, distortion, skip, sse,
|
|
|
|
ref_best_rd, bs);
|
2013-06-29 02:10:22 +02:00
|
|
|
if (psse)
|
2013-08-28 04:47:53 +02:00
|
|
|
*psse = sse[mbmi->tx_size];
|
2013-05-31 00:13:08 +02:00
|
|
|
return;
|
|
|
|
}
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
|
|
|
|
if (cpi->sf.tx_size_search_method == USE_LARGESTINTRA_MODELINTER &&
|
2013-10-23 19:06:11 +02:00
|
|
|
b_inter_mode) {
|
2013-11-26 23:55:53 +01:00
|
|
|
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
|
|
|
|
model_rd_for_sb_y_tx(cpi, bs, tx_size, x, xd,
|
|
|
|
&r[tx_size][0], &d[tx_size], &s[tx_size]);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
choose_txfm_size_from_modelrd(cpi, x, r, rate, d, distortion, s,
|
2013-08-13 01:34:48 +02:00
|
|
|
skip, sse, ref_best_rd, bs);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
} else {
|
2013-11-26 23:55:53 +01:00
|
|
|
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
|
|
|
|
txfm_rd_in_plane(x, rdcost_stack, &r[tx_size][0], &d[tx_size],
|
|
|
|
&s[tx_size], &sse[tx_size],
|
|
|
|
ref_best_rd, 0, bs, tx_size);
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
choose_txfm_size_from_rd(cpi, x, r, rate, d, distortion, s,
|
|
|
|
skip, txfm_cache, bs);
|
|
|
|
}
|
2013-06-28 02:41:54 +02:00
|
|
|
if (psse)
|
2013-08-28 04:47:53 +02:00
|
|
|
*psse = sse[mbmi->tx_size];
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-07-03 23:47:54 +02:00
|
|
|
static int conditional_skipintra(MB_PREDICTION_MODE mode,
|
|
|
|
MB_PREDICTION_MODE best_intra_mode) {
|
2013-07-02 20:18:00 +02:00
|
|
|
if (mode == D117_PRED &&
|
|
|
|
best_intra_mode != V_PRED &&
|
|
|
|
best_intra_mode != D135_PRED)
|
|
|
|
return 1;
|
|
|
|
if (mode == D63_PRED &&
|
|
|
|
best_intra_mode != V_PRED &&
|
|
|
|
best_intra_mode != D45_PRED)
|
|
|
|
return 1;
|
2013-08-24 02:33:48 +02:00
|
|
|
if (mode == D207_PRED &&
|
2013-07-02 20:18:00 +02:00
|
|
|
best_intra_mode != H_PRED &&
|
|
|
|
best_intra_mode != D45_PRED)
|
|
|
|
return 1;
|
|
|
|
if (mode == D153_PRED &&
|
|
|
|
best_intra_mode != H_PRED &&
|
|
|
|
best_intra_mode != D135_PRED)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-02 23:50:40 +02:00
|
|
|
static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
|
2013-05-25 01:13:54 +02:00
|
|
|
MB_PREDICTION_MODE *best_mode,
|
2012-08-07 01:21:23 +02:00
|
|
|
int *bmode_costs,
|
|
|
|
ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
|
|
|
|
int *bestrate, int *bestratey,
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t *bestdistortion,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize, int64_t rd_thresh) {
|
2013-05-21 01:04:28 +02:00
|
|
|
MB_PREDICTION_MODE mode;
|
2012-10-16 01:41:41 +02:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-07-19 18:17:00 +02:00
|
|
|
int64_t best_rd = rd_thresh;
|
2012-07-14 00:21:29 +02:00
|
|
|
int rate = 0;
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t distortion;
|
2013-06-26 04:41:56 +02:00
|
|
|
struct macroblock_plane *p = &x->plane[0];
|
|
|
|
struct macroblockd_plane *pd = &xd->plane[0];
|
|
|
|
const int src_stride = p->src.stride;
|
2013-07-09 01:48:47 +02:00
|
|
|
const int dst_stride = pd->dst.stride;
|
2013-11-19 04:00:49 +01:00
|
|
|
const uint8_t *src_init = &p->src.buf[raster_block_offset(BLOCK_8X8, ib,
|
|
|
|
src_stride)];
|
|
|
|
uint8_t *dst_init = &pd->dst.buf[raster_block_offset(BLOCK_8X8, ib,
|
|
|
|
dst_stride)];
|
2013-05-21 01:04:28 +02:00
|
|
|
int16_t *src_diff, *coeff;
|
|
|
|
|
|
|
|
ENTROPY_CONTEXT ta[2], tempa[2];
|
|
|
|
ENTROPY_CONTEXT tl[2], templ[2];
|
2013-10-29 20:18:53 +01:00
|
|
|
|
2013-08-05 21:15:52 +02:00
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
|
2013-10-28 22:28:28 +01:00
|
|
|
int idx, idy;
|
2013-07-23 00:39:43 +02:00
|
|
|
uint8_t best_dst[8 * 8];
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
assert(ib < 4);
|
2013-05-07 14:58:36 +02:00
|
|
|
|
2013-05-21 01:04:28 +02:00
|
|
|
vpx_memcpy(ta, a, sizeof(ta));
|
|
|
|
vpx_memcpy(tl, l, sizeof(tl));
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->mbmi.tx_size = TX_4X4;
|
2013-05-21 01:04:28 +02:00
|
|
|
|
|
|
|
for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
|
2013-01-14 23:37:53 +01:00
|
|
|
int64_t this_rd;
|
2013-05-21 01:04:28 +02:00
|
|
|
int ratey = 0;
|
2013-08-22 18:23:02 +02:00
|
|
|
|
2013-10-11 02:29:46 +02:00
|
|
|
if (!(cpi->sf.intra_y_mode_mask[TX_4X4] & (1 << mode)))
|
2013-08-22 18:23:02 +02:00
|
|
|
continue;
|
|
|
|
|
2013-07-02 20:18:00 +02:00
|
|
|
// Only do the oblique modes if the best so far is
|
|
|
|
// one of the neighboring directional modes
|
2013-07-03 23:47:54 +02:00
|
|
|
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
|
|
|
|
if (conditional_skipintra(mode, *best_mode))
|
2013-07-02 20:18:00 +02:00
|
|
|
continue;
|
|
|
|
}
|
2012-10-09 22:19:15 +02:00
|
|
|
|
2013-05-30 18:58:53 +02:00
|
|
|
rate = bmode_costs[mode];
|
2013-05-21 01:04:28 +02:00
|
|
|
distortion = 0;
|
|
|
|
|
|
|
|
vpx_memcpy(tempa, ta, sizeof(ta));
|
|
|
|
vpx_memcpy(templ, tl, sizeof(tl));
|
|
|
|
|
2013-07-23 15:51:44 +02:00
|
|
|
for (idy = 0; idy < num_4x4_blocks_high; ++idy) {
|
|
|
|
for (idx = 0; idx < num_4x4_blocks_wide; ++idx) {
|
2013-06-28 02:41:54 +02:00
|
|
|
int64_t ssz;
|
2013-11-23 01:20:45 +01:00
|
|
|
const scan_order *so;
|
2013-11-19 04:00:49 +01:00
|
|
|
const uint8_t *src = src_init + idx * 4 + idy * 4 * src_stride;
|
2013-07-23 00:39:43 +02:00
|
|
|
uint8_t *dst = dst_init + idx * 4 + idy * 4 * dst_stride;
|
2013-10-28 22:28:28 +01:00
|
|
|
const int block = ib + idy * 2 + idx;
|
2013-10-29 20:18:53 +01:00
|
|
|
TX_TYPE tx_type;
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->bmi[block].as_mode = mode;
|
2013-08-19 22:20:21 +02:00
|
|
|
src_diff = raster_block_offset_int16(BLOCK_8X8, block, p->src_diff);
|
2013-08-10 01:40:05 +02:00
|
|
|
coeff = BLOCK_OFFSET(x->plane[0].coeff, block);
|
2013-07-23 00:39:43 +02:00
|
|
|
vp9_predict_intra_block(xd, block, 1,
|
2013-06-26 04:41:56 +02:00
|
|
|
TX_4X4, mode,
|
2013-07-09 01:48:47 +02:00
|
|
|
x->skip_encode ? src : dst,
|
|
|
|
x->skip_encode ? src_stride : dst_stride,
|
2013-12-13 05:33:06 +01:00
|
|
|
dst, dst_stride, idx, idy, 0);
|
2013-05-21 01:04:28 +02:00
|
|
|
vp9_subtract_block(4, 4, src_diff, 8,
|
|
|
|
src, src_stride,
|
2013-07-09 01:48:47 +02:00
|
|
|
dst, dst_stride);
|
2013-05-21 01:04:28 +02:00
|
|
|
|
2013-12-06 19:54:00 +01:00
|
|
|
tx_type = get_tx_type_4x4(PLANE_TYPE_Y, xd, block);
|
2013-11-23 01:20:45 +01:00
|
|
|
so = &vp9_scan_orders[TX_4X4][tx_type];
|
2013-10-29 20:18:53 +01:00
|
|
|
|
2013-10-22 22:09:36 +02:00
|
|
|
if (tx_type != DCT_DCT)
|
2013-05-21 01:04:28 +02:00
|
|
|
vp9_short_fht4x4(src_diff, coeff, 8, tx_type);
|
2013-10-22 22:09:36 +02:00
|
|
|
else
|
2013-10-22 00:27:35 +02:00
|
|
|
x->fwd_txm4x4(src_diff, coeff, 8);
|
2013-10-29 20:18:53 +01:00
|
|
|
|
2013-12-03 03:33:50 +01:00
|
|
|
vp9_regular_quantize_b_4x4(x, 0, block, so->scan, so->iscan);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-11-23 01:20:45 +01:00
|
|
|
ratey += cost_coeffs(x, 0, block, tempa + idx, templ + idy, TX_4X4,
|
|
|
|
so->scan, so->neighbors);
|
2013-08-10 01:40:05 +02:00
|
|
|
distortion += vp9_block_error(coeff, BLOCK_OFFSET(pd->dqcoeff, block),
|
2013-06-28 02:41:54 +02:00
|
|
|
16, &ssz) >> 2;
|
2013-07-19 18:17:00 +02:00
|
|
|
if (RDCOST(x->rdmult, x->rddiv, ratey, distortion) >= best_rd)
|
|
|
|
goto next;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-07-11 00:45:34 +02:00
|
|
|
if (tx_type != DCT_DCT)
|
2013-10-11 22:31:32 +02:00
|
|
|
vp9_iht4x4_16_add(BLOCK_OFFSET(pd->dqcoeff, block),
|
2013-07-11 00:45:34 +02:00
|
|
|
dst, pd->dst.stride, tx_type);
|
2013-05-21 01:04:28 +02:00
|
|
|
else
|
2013-10-08 20:27:56 +02:00
|
|
|
xd->itxm_add(BLOCK_OFFSET(pd->dqcoeff, block), dst, pd->dst.stride,
|
|
|
|
16);
|
2013-05-21 01:04:28 +02:00
|
|
|
}
|
|
|
|
}
|
2012-06-25 21:26:09 +02:00
|
|
|
|
2013-01-14 23:37:53 +01:00
|
|
|
rate += ratey;
|
|
|
|
this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
|
2012-06-25 21:26:09 +02:00
|
|
|
|
2013-01-14 23:37:53 +01:00
|
|
|
if (this_rd < best_rd) {
|
|
|
|
*bestrate = rate;
|
|
|
|
*bestratey = ratey;
|
|
|
|
*bestdistortion = distortion;
|
|
|
|
best_rd = this_rd;
|
|
|
|
*best_mode = mode;
|
2013-05-21 01:04:28 +02:00
|
|
|
vpx_memcpy(a, tempa, sizeof(tempa));
|
|
|
|
vpx_memcpy(l, templ, sizeof(templ));
|
2013-07-23 00:39:43 +02:00
|
|
|
for (idy = 0; idy < num_4x4_blocks_high * 4; ++idy)
|
|
|
|
vpx_memcpy(best_dst + idy * 8, dst_init + idy * dst_stride,
|
|
|
|
num_4x4_blocks_wide * 4);
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
2013-07-19 18:17:00 +02:00
|
|
|
next:
|
|
|
|
{}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2013-05-21 01:04:28 +02:00
|
|
|
|
2013-07-19 18:17:00 +02:00
|
|
|
if (best_rd >= rd_thresh || x->skip_encode)
|
2013-07-09 01:48:47 +02:00
|
|
|
return best_rd;
|
|
|
|
|
2013-07-23 00:39:43 +02:00
|
|
|
for (idy = 0; idy < num_4x4_blocks_high * 4; ++idy)
|
|
|
|
vpx_memcpy(dst_init + idy * dst_stride, best_dst + idy * 8,
|
|
|
|
num_4x4_blocks_wide * 4);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
return best_rd;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2013-07-31 21:58:19 +02:00
|
|
|
static int64_t rd_pick_intra_sub_8x8_y_mode(VP9_COMP * const cpi,
|
|
|
|
MACROBLOCK * const mb,
|
|
|
|
int * const rate,
|
|
|
|
int * const rate_y,
|
|
|
|
int64_t * const distortion,
|
|
|
|
int64_t best_rd) {
|
2013-05-21 01:04:28 +02:00
|
|
|
int i, j;
|
2012-07-14 00:21:29 +02:00
|
|
|
MACROBLOCKD *const xd = &mb->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MODE_INFO *const mic = xd->mi_8x8[0];
|
2013-09-11 19:45:44 +02:00
|
|
|
const MODE_INFO *above_mi = xd->mi_8x8[-xd->mode_info_stride];
|
2013-10-22 02:01:57 +02:00
|
|
|
const MODE_INFO *left_mi = xd->left_available ? xd->mi_8x8[-1] : NULL;
|
2013-10-10 21:11:44 +02:00
|
|
|
const BLOCK_SIZE bsize = xd->mi_8x8[0]->mbmi.sb_type;
|
2013-08-05 21:15:52 +02:00
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
|
2013-05-21 01:04:28 +02:00
|
|
|
int idx, idy;
|
2013-05-11 02:06:37 +02:00
|
|
|
int cost = 0;
|
2013-07-31 21:58:19 +02:00
|
|
|
int64_t total_distortion = 0;
|
2012-07-14 00:21:29 +02:00
|
|
|
int tot_rate_y = 0;
|
|
|
|
int64_t total_rd = 0;
|
2013-05-21 01:04:28 +02:00
|
|
|
ENTROPY_CONTEXT t_above[4], t_left[4];
|
2012-07-14 00:21:29 +02:00
|
|
|
int *bmode_costs;
|
|
|
|
|
2013-04-29 19:37:25 +02:00
|
|
|
vpx_memcpy(t_above, xd->plane[0].above_context, sizeof(t_above));
|
|
|
|
vpx_memcpy(t_left, xd->plane[0].left_context, sizeof(t_left));
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-05-30 18:58:53 +02:00
|
|
|
bmode_costs = mb->mbmode_cost;
|
2011-02-14 19:32:58 +01:00
|
|
|
|
2013-07-30 19:16:03 +02:00
|
|
|
// Pick modes for each sub-block (of size 4x4, 4x8, or 8x4) in an 8x8 block.
|
2013-07-23 15:51:44 +02:00
|
|
|
for (idy = 0; idy < 2; idy += num_4x4_blocks_high) {
|
|
|
|
for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
|
2013-08-19 18:28:34 +02:00
|
|
|
MB_PREDICTION_MODE best_mode = DC_PRED;
|
|
|
|
int r = INT_MAX, ry = INT_MAX;
|
|
|
|
int64_t d = INT64_MAX, this_rd = INT64_MAX;
|
2013-05-21 01:04:28 +02:00
|
|
|
i = idy * 2 + idx;
|
2013-07-19 20:55:36 +02:00
|
|
|
if (cpi->common.frame_type == KEY_FRAME) {
|
2013-09-11 19:45:44 +02:00
|
|
|
const MB_PREDICTION_MODE A = above_block_mode(mic, above_mi, i);
|
2013-10-22 02:01:57 +02:00
|
|
|
const MB_PREDICTION_MODE L = left_block_mode(mic, left_mi, i);
|
2013-05-21 01:04:28 +02:00
|
|
|
|
2013-05-30 18:58:53 +02:00
|
|
|
bmode_costs = mb->y_mode_costs[A][L];
|
2013-05-21 01:04:28 +02:00
|
|
|
}
|
2011-02-14 19:32:58 +01:00
|
|
|
|
2013-07-19 18:17:00 +02:00
|
|
|
this_rd = rd_pick_intra4x4block(cpi, mb, i, &best_mode, bmode_costs,
|
2013-08-10 01:25:01 +02:00
|
|
|
t_above + idx, t_left + idy, &r, &ry, &d,
|
|
|
|
bsize, best_rd - total_rd);
|
2013-07-19 18:17:00 +02:00
|
|
|
if (this_rd >= best_rd - total_rd)
|
|
|
|
return INT64_MAX;
|
|
|
|
|
|
|
|
total_rd += this_rd;
|
2013-05-21 01:04:28 +02:00
|
|
|
cost += r;
|
2013-07-31 21:58:19 +02:00
|
|
|
total_distortion += d;
|
2013-05-21 01:04:28 +02:00
|
|
|
tot_rate_y += ry;
|
|
|
|
|
2013-07-03 01:51:57 +02:00
|
|
|
mic->bmi[i].as_mode = best_mode;
|
2013-07-23 15:51:44 +02:00
|
|
|
for (j = 1; j < num_4x4_blocks_high; ++j)
|
2013-07-03 01:51:57 +02:00
|
|
|
mic->bmi[i + j * 2].as_mode = best_mode;
|
2013-07-23 15:51:44 +02:00
|
|
|
for (j = 1; j < num_4x4_blocks_wide; ++j)
|
2013-07-03 01:51:57 +02:00
|
|
|
mic->bmi[i + j].as_mode = best_mode;
|
2013-05-21 01:04:28 +02:00
|
|
|
|
|
|
|
if (total_rd >= best_rd)
|
2013-07-18 02:24:33 +02:00
|
|
|
return INT64_MAX;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-07-31 21:58:19 +02:00
|
|
|
*rate = cost;
|
2012-11-05 21:50:16 +01:00
|
|
|
*rate_y = tot_rate_y;
|
2013-07-31 21:58:19 +02:00
|
|
|
*distortion = total_distortion;
|
2013-09-11 19:45:44 +02:00
|
|
|
mic->mbmi.mode = mic->bmi[3].as_mode;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-07-31 21:58:19 +02:00
|
|
|
return RDCOST(mb->rdmult, mb->rddiv, cost, total_distortion);
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
2011-06-08 18:05:05 +02:00
|
|
|
|
2013-04-11 00:55:59 +02:00
|
|
|
static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
|
|
|
int *rate, int *rate_tokenonly,
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t *distortion, int *skippable,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize,
|
2013-08-03 02:28:23 +02:00
|
|
|
int64_t tx_cache[TX_MODES],
|
2013-07-18 03:21:41 +02:00
|
|
|
int64_t best_rd) {
|
2012-08-20 23:43:34 +02:00
|
|
|
MB_PREDICTION_MODE mode;
|
2013-08-19 18:28:34 +02:00
|
|
|
MB_PREDICTION_MODE mode_selected = DC_PRED;
|
2013-05-31 00:13:08 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MODE_INFO *const mic = xd->mi_8x8[0];
|
2013-06-21 21:54:52 +02:00
|
|
|
int this_rate, this_rate_tokenonly, s;
|
2013-07-18 03:21:41 +02:00
|
|
|
int64_t this_distortion, this_rd;
|
2013-08-19 18:28:34 +02:00
|
|
|
TX_SIZE best_tx = TX_4X4;
|
2013-04-11 00:55:59 +02:00
|
|
|
int i;
|
2013-05-30 18:58:53 +02:00
|
|
|
int *bmode_costs = x->mbmode_cost;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-08-03 02:28:23 +02:00
|
|
|
if (cpi->sf.tx_size_search_method == USE_FULL_RD)
|
2013-07-29 22:38:40 +02:00
|
|
|
for (i = 0; i < TX_MODES; i++)
|
2013-08-03 02:28:23 +02:00
|
|
|
tx_cache[i] = INT64_MAX;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-07-30 19:16:03 +02:00
|
|
|
/* Y Search for intra prediction mode */
|
2013-01-06 03:20:25 +01:00
|
|
|
for (mode = DC_PRED; mode <= TM_PRED; mode++) {
|
2013-08-03 02:28:23 +02:00
|
|
|
int64_t local_tx_cache[TX_MODES];
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO *above_mi = xd->mi_8x8[-xd->mode_info_stride];
|
2013-10-22 02:01:57 +02:00
|
|
|
MODE_INFO *left_mi = xd->left_available ? xd->mi_8x8[-1] : NULL;
|
2013-06-06 15:07:09 +02:00
|
|
|
|
2013-10-11 02:29:46 +02:00
|
|
|
if (!(cpi->sf.intra_y_mode_mask[max_txsize_lookup[bsize]] & (1 << mode)))
|
2013-08-22 18:23:02 +02:00
|
|
|
continue;
|
|
|
|
|
2013-05-30 18:58:53 +02:00
|
|
|
if (cpi->common.frame_type == KEY_FRAME) {
|
2013-09-11 19:45:44 +02:00
|
|
|
const MB_PREDICTION_MODE A = above_block_mode(mic, above_mi, 0);
|
2013-10-22 02:01:57 +02:00
|
|
|
const MB_PREDICTION_MODE L = left_block_mode(mic, left_mi, 0);
|
2013-05-30 18:58:53 +02:00
|
|
|
|
|
|
|
bmode_costs = x->y_mode_costs[A][L];
|
|
|
|
}
|
2013-08-20 21:55:41 +02:00
|
|
|
mic->mbmi.mode = mode;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-06-28 02:41:54 +02:00
|
|
|
super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, &s, NULL,
|
2013-08-03 02:28:23 +02:00
|
|
|
bsize, local_tx_cache, best_rd);
|
2013-07-03 01:48:15 +02:00
|
|
|
|
|
|
|
if (this_rate_tokenonly == INT_MAX)
|
|
|
|
continue;
|
2013-05-31 00:13:08 +02:00
|
|
|
|
2013-05-21 01:04:28 +02:00
|
|
|
this_rate = this_rate_tokenonly + bmode_costs[mode];
|
2013-01-06 03:20:25 +01:00
|
|
|
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
|
|
|
|
|
|
|
|
if (this_rd < best_rd) {
|
|
|
|
mode_selected = mode;
|
|
|
|
best_rd = this_rd;
|
2013-08-28 04:47:53 +02:00
|
|
|
best_tx = mic->mbmi.tx_size;
|
2013-01-06 03:20:25 +01:00
|
|
|
*rate = this_rate;
|
|
|
|
*rate_tokenonly = this_rate_tokenonly;
|
|
|
|
*distortion = this_distortion;
|
|
|
|
*skippable = s;
|
|
|
|
}
|
2012-10-09 18:18:21 +02:00
|
|
|
|
2013-07-03 01:48:15 +02:00
|
|
|
if (cpi->sf.tx_size_search_method == USE_FULL_RD && this_rd < INT64_MAX) {
|
2013-08-29 19:26:52 +02:00
|
|
|
for (i = 0; i < TX_MODES && local_tx_cache[i] < INT64_MAX; i++) {
|
2013-08-03 02:28:23 +02:00
|
|
|
const int64_t adj_rd = this_rd + local_tx_cache[i] -
|
|
|
|
local_tx_cache[cpi->common.tx_mode];
|
|
|
|
if (adj_rd < tx_cache[i]) {
|
|
|
|
tx_cache[i] = adj_rd;
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-08-20 21:55:41 +02:00
|
|
|
mic->mbmi.mode = mode_selected;
|
2013-08-28 04:47:53 +02:00
|
|
|
mic->mbmi.tx_size = best_tx;
|
2012-08-29 20:25:38 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
return best_rd;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
2012-06-25 21:26:09 +02:00
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
static void super_block_uvrd(VP9_COMP *const cpi, MACROBLOCK *x,
|
2013-06-21 21:54:52 +02:00
|
|
|
int *rate, int64_t *distortion, int *skippable,
|
2013-08-27 20:05:08 +02:00
|
|
|
int64_t *sse, BLOCK_SIZE bsize,
|
2013-08-15 01:50:45 +02:00
|
|
|
int64_t ref_best_rd) {
|
2013-05-01 01:13:20 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-06-28 18:19:50 +02:00
|
|
|
TX_SIZE uv_txfm_size = get_uv_tx_size(mbmi);
|
2013-08-14 03:58:21 +02:00
|
|
|
int plane;
|
|
|
|
int pnrate = 0, pnskip = 1;
|
|
|
|
int64_t pndist = 0, pnsse = 0;
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-08-15 01:50:45 +02:00
|
|
|
if (ref_best_rd < 0)
|
|
|
|
goto term;
|
|
|
|
|
2013-08-14 03:58:21 +02:00
|
|
|
if (is_inter_block(mbmi))
|
2013-06-06 06:14:14 +02:00
|
|
|
vp9_subtract_sbuv(x, bsize);
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-08-14 03:58:21 +02:00
|
|
|
*rate = 0;
|
|
|
|
*distortion = 0;
|
|
|
|
*sse = 0;
|
|
|
|
*skippable = 1;
|
|
|
|
|
|
|
|
for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
|
2013-10-10 19:37:40 +02:00
|
|
|
txfm_rd_in_plane(x, &cpi->rdcost_stack, &pnrate, &pndist, &pnskip, &pnsse,
|
2013-08-15 01:50:45 +02:00
|
|
|
ref_best_rd, plane, bsize, uv_txfm_size);
|
|
|
|
if (pnrate == INT_MAX)
|
|
|
|
goto term;
|
2013-08-14 03:58:21 +02:00
|
|
|
*rate += pnrate;
|
|
|
|
*distortion += pndist;
|
|
|
|
*sse += pnsse;
|
|
|
|
*skippable &= pnskip;
|
|
|
|
}
|
2013-08-15 01:50:45 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
term:
|
|
|
|
*rate = INT_MAX;
|
|
|
|
*distortion = INT64_MAX;
|
|
|
|
*sse = INT64_MAX;
|
|
|
|
*skippable = 0;
|
|
|
|
return;
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-11-07 23:56:58 +01:00
|
|
|
PICK_MODE_CONTEXT *ctx,
|
2013-05-01 01:13:20 +02:00
|
|
|
int *rate, int *rate_tokenonly,
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t *distortion, int *skippable,
|
2013-12-09 20:03:02 +01:00
|
|
|
BLOCK_SIZE bsize, TX_SIZE max_tx_size) {
|
2013-05-01 01:13:20 +02:00
|
|
|
MB_PREDICTION_MODE mode;
|
2013-08-19 18:28:34 +02:00
|
|
|
MB_PREDICTION_MODE mode_selected = DC_PRED;
|
2013-05-01 01:13:20 +02:00
|
|
|
int64_t best_rd = INT64_MAX, this_rd;
|
2013-06-21 21:54:52 +02:00
|
|
|
int this_rate_tokenonly, this_rate, s;
|
2013-08-14 03:58:21 +02:00
|
|
|
int64_t this_distortion, this_sse;
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-12-03 00:24:41 +01:00
|
|
|
for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
|
2013-12-09 20:03:02 +01:00
|
|
|
if (!(cpi->sf.intra_uv_mode_mask[max_tx_size] & (1 << mode)))
|
2013-08-22 18:23:02 +02:00
|
|
|
continue;
|
2013-07-10 17:59:18 +02:00
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
x->e_mbd.mi_8x8[0]->mbmi.uv_mode = mode;
|
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
super_block_uvrd(cpi, x, &this_rate_tokenonly,
|
2013-08-15 01:50:45 +02:00
|
|
|
&this_distortion, &s, &this_sse, bsize, best_rd);
|
|
|
|
if (this_rate_tokenonly == INT_MAX)
|
|
|
|
continue;
|
2013-05-01 01:13:20 +02:00
|
|
|
this_rate = this_rate_tokenonly +
|
2013-07-19 20:55:36 +02:00
|
|
|
x->intra_uv_mode_cost[cpi->common.frame_type][mode];
|
2013-05-01 01:13:20 +02:00
|
|
|
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
|
|
|
|
|
|
|
|
if (this_rd < best_rd) {
|
|
|
|
mode_selected = mode;
|
|
|
|
best_rd = this_rd;
|
|
|
|
*rate = this_rate;
|
|
|
|
*rate_tokenonly = this_rate_tokenonly;
|
|
|
|
*distortion = this_distortion;
|
|
|
|
*skippable = s;
|
2013-11-07 23:56:58 +01:00
|
|
|
if (!x->select_txfm_size) {
|
|
|
|
int i;
|
|
|
|
struct macroblock_plane *const p = x->plane;
|
|
|
|
struct macroblockd_plane *const pd = x->e_mbd.plane;
|
|
|
|
for (i = 1; i < MAX_MB_PLANE; ++i) {
|
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][2];
|
2013-12-03 00:24:41 +01:00
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][2];
|
2013-11-07 23:56:58 +01:00
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][2];
|
2013-12-04 02:59:32 +01:00
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][2];
|
2013-11-07 23:56:58 +01:00
|
|
|
|
|
|
|
ctx->coeff_pbuf[i][2] = ctx->coeff_pbuf[i][0];
|
|
|
|
ctx->qcoeff_pbuf[i][2] = ctx->qcoeff_pbuf[i][0];
|
|
|
|
ctx->dqcoeff_pbuf[i][2] = ctx->dqcoeff_pbuf[i][0];
|
|
|
|
ctx->eobs_pbuf[i][2] = ctx->eobs_pbuf[i][0];
|
|
|
|
|
|
|
|
ctx->coeff_pbuf[i][0] = p[i].coeff;
|
2013-11-27 03:52:10 +01:00
|
|
|
ctx->qcoeff_pbuf[i][0] = p[i].qcoeff;
|
2013-11-07 23:56:58 +01:00
|
|
|
ctx->dqcoeff_pbuf[i][0] = pd[i].dqcoeff;
|
2013-12-04 02:59:32 +01:00
|
|
|
ctx->eobs_pbuf[i][0] = p[i].eobs;
|
2013-11-07 23:56:58 +01:00
|
|
|
}
|
|
|
|
}
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
x->e_mbd.mi_8x8[0]->mbmi.uv_mode = mode_selected;
|
2013-05-01 01:13:20 +02:00
|
|
|
return best_rd;
|
|
|
|
}
|
|
|
|
|
2013-07-16 19:12:34 +02:00
|
|
|
static int64_t rd_sbuv_dcpred(VP9_COMP *cpi, MACROBLOCK *x,
|
|
|
|
int *rate, int *rate_tokenonly,
|
|
|
|
int64_t *distortion, int *skippable,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize) {
|
2013-07-16 19:12:34 +02:00
|
|
|
int64_t this_rd;
|
2013-08-14 03:58:21 +02:00
|
|
|
int64_t this_sse;
|
2013-07-16 19:12:34 +02:00
|
|
|
|
2013-09-11 19:45:44 +02:00
|
|
|
x->e_mbd.mi_8x8[0]->mbmi.uv_mode = DC_PRED;
|
2013-10-10 19:37:40 +02:00
|
|
|
super_block_uvrd(cpi, x, rate_tokenonly, distortion,
|
|
|
|
skippable, &this_sse, bsize, INT64_MAX);
|
2013-07-16 19:12:34 +02:00
|
|
|
*rate = *rate_tokenonly +
|
2013-07-19 20:55:36 +02:00
|
|
|
x->intra_uv_mode_cost[cpi->common.frame_type][DC_PRED];
|
2013-07-16 19:12:34 +02:00
|
|
|
this_rd = RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
|
|
|
|
|
|
|
|
return this_rd;
|
|
|
|
}
|
|
|
|
|
2013-11-07 23:56:58 +01:00
|
|
|
static void choose_intra_uv_mode(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
|
2013-12-09 20:03:02 +01:00
|
|
|
BLOCK_SIZE bsize, TX_SIZE max_tx_size,
|
|
|
|
int *rate_uv, int *rate_uv_tokenonly,
|
2013-07-18 22:09:38 +02:00
|
|
|
int64_t *dist_uv, int *skip_uv,
|
|
|
|
MB_PREDICTION_MODE *mode_uv) {
|
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
|
|
|
|
// Use an estimated rd for uv_intra based on DC_PRED if the
|
|
|
|
// appropriate speed flag is set.
|
|
|
|
if (cpi->sf.use_uv_intra_rd_estimate) {
|
|
|
|
rd_sbuv_dcpred(cpi, x, rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
|
2013-08-06 00:23:49 +02:00
|
|
|
bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize);
|
2013-07-18 22:09:38 +02:00
|
|
|
// Else do a proper rd search for each possible transform size that may
|
|
|
|
// be considered in the main rd loop.
|
|
|
|
} else {
|
2013-11-07 23:56:58 +01:00
|
|
|
rd_pick_intra_sbuv_mode(cpi, x, ctx,
|
2013-07-18 22:09:38 +02:00
|
|
|
rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
|
2013-12-09 20:03:02 +01:00
|
|
|
bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize, max_tx_size);
|
2013-07-18 22:09:38 +02:00
|
|
|
}
|
2013-09-11 19:45:44 +02:00
|
|
|
*mode_uv = x->e_mbd.mi_8x8[0]->mbmi.uv_mode;
|
2013-07-18 22:09:38 +02:00
|
|
|
}
|
|
|
|
|
2013-07-11 23:14:47 +02:00
|
|
|
static int cost_mv_ref(VP9_COMP *cpi, MB_PREDICTION_MODE mode,
|
|
|
|
int mode_context) {
|
2013-07-03 19:54:36 +02:00
|
|
|
MACROBLOCK *const x = &cpi->mb;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
const int segment_id = xd->mi_8x8[0]->mbmi.segment_id;
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-07-11 23:14:47 +02:00
|
|
|
// Don't account for mode here if segment skip is enabled.
|
2013-08-14 20:20:33 +02:00
|
|
|
if (!vp9_segfeature_active(&cpi->common.seg, segment_id, SEG_LVL_SKIP)) {
|
2013-07-11 23:14:47 +02:00
|
|
|
assert(is_inter_mode(mode));
|
2013-11-05 20:58:57 +01:00
|
|
|
return x->inter_mode_cost[mode_context][INTER_OFFSET(mode)];
|
2013-07-11 23:14:47 +02:00
|
|
|
} else {
|
2013-05-01 01:13:20 +02:00
|
|
|
return 0;
|
2013-07-11 23:14:47 +02:00
|
|
|
}
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void vp9_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv) {
|
2013-09-11 19:45:44 +02:00
|
|
|
x->e_mbd.mi_8x8[0]->mbmi.mode = mb;
|
|
|
|
x->e_mbd.mi_8x8[0]->mbmi.mv[0].as_int = mv->as_int;
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
|
|
|
|
2013-06-14 00:10:42 +02:00
|
|
|
static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize,
|
2013-06-14 00:10:42 +02:00
|
|
|
int_mv *frame_mv,
|
|
|
|
int mi_row, int mi_col,
|
|
|
|
int_mv single_newmv[MAX_REF_FRAMES],
|
|
|
|
int *rate_mv);
|
|
|
|
|
2013-05-29 21:52:57 +02:00
|
|
|
static int labels2mode(MACROBLOCK *x, int i,
|
2013-05-25 01:13:54 +02:00
|
|
|
MB_PREDICTION_MODE this_mode,
|
2013-05-01 01:13:20 +02:00
|
|
|
int_mv *this_mv, int_mv *this_second_mv,
|
2013-05-26 23:40:49 +02:00
|
|
|
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES],
|
2013-05-30 06:59:41 +02:00
|
|
|
int_mv seg_mvs[MAX_REF_FRAMES],
|
2013-05-01 01:13:20 +02:00
|
|
|
int_mv *best_ref_mv,
|
|
|
|
int_mv *second_best_ref_mv,
|
|
|
|
int *mvjcost, int *mvcost[2], VP9_COMP *cpi) {
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MODE_INFO *const mic = xd->mi_8x8[0];
|
2013-08-20 21:55:41 +02:00
|
|
|
MB_MODE_INFO *mbmi = &mic->mbmi;
|
2013-05-28 23:02:29 +02:00
|
|
|
int cost = 0, thismvcost = 0;
|
2013-05-16 07:28:36 +02:00
|
|
|
int idx, idy;
|
2013-08-05 21:15:52 +02:00
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type];
|
2013-09-17 23:06:00 +02:00
|
|
|
const int has_second_rf = has_second_ref(mbmi);
|
2013-05-01 01:13:20 +02:00
|
|
|
|
|
|
|
/* We have to be careful retrieving previously-encoded motion vectors.
|
|
|
|
Ones from this macroblock have to be pulled from the BLOCKD array
|
|
|
|
as they have not yet made it to the bmi array in our MB_MODE_INFO. */
|
2013-05-28 23:02:29 +02:00
|
|
|
MB_PREDICTION_MODE m;
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-05-28 23:02:29 +02:00
|
|
|
// the only time we should do costing for new motion vector or mode
|
|
|
|
// is when we are on a new label (jbb May 08, 2007)
|
|
|
|
switch (m = this_mode) {
|
|
|
|
case NEWMV:
|
2013-06-06 22:44:34 +02:00
|
|
|
this_mv->as_int = seg_mvs[mbmi->ref_frame[0]].as_int;
|
2013-09-20 11:52:43 +02:00
|
|
|
thismvcost = vp9_mv_bit_cost(&this_mv->as_mv, &best_ref_mv->as_mv,
|
2013-10-09 20:32:03 +02:00
|
|
|
mvjcost, mvcost, MV_COST_WEIGHT_SUB);
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf) {
|
2013-06-06 22:44:34 +02:00
|
|
|
this_second_mv->as_int = seg_mvs[mbmi->ref_frame[1]].as_int;
|
2013-09-20 11:52:43 +02:00
|
|
|
thismvcost += vp9_mv_bit_cost(&this_second_mv->as_mv,
|
|
|
|
&second_best_ref_mv->as_mv,
|
2013-10-09 20:32:03 +02:00
|
|
|
mvjcost, mvcost, MV_COST_WEIGHT_SUB);
|
2013-05-28 23:02:29 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NEARESTMV:
|
2013-06-06 22:44:34 +02:00
|
|
|
this_mv->as_int = frame_mv[NEARESTMV][mbmi->ref_frame[0]].as_int;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf)
|
2013-05-28 23:02:29 +02:00
|
|
|
this_second_mv->as_int =
|
2013-06-06 22:44:34 +02:00
|
|
|
frame_mv[NEARESTMV][mbmi->ref_frame[1]].as_int;
|
2013-05-28 23:02:29 +02:00
|
|
|
break;
|
|
|
|
case NEARMV:
|
2013-06-06 22:44:34 +02:00
|
|
|
this_mv->as_int = frame_mv[NEARMV][mbmi->ref_frame[0]].as_int;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf)
|
2013-05-28 23:02:29 +02:00
|
|
|
this_second_mv->as_int =
|
2013-06-06 22:44:34 +02:00
|
|
|
frame_mv[NEARMV][mbmi->ref_frame[1]].as_int;
|
2013-05-28 23:02:29 +02:00
|
|
|
break;
|
|
|
|
case ZEROMV:
|
|
|
|
this_mv->as_int = 0;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf)
|
2013-05-28 23:02:29 +02:00
|
|
|
this_second_mv->as_int = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-07-03 19:54:36 +02:00
|
|
|
cost = cost_mv_ref(cpi, this_mode,
|
2013-08-13 18:47:40 +02:00
|
|
|
mbmi->mode_context[mbmi->ref_frame[0]]);
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-05-28 23:02:29 +02:00
|
|
|
mic->bmi[i].as_mv[0].as_int = this_mv->as_int;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf)
|
2013-05-28 23:02:29 +02:00
|
|
|
mic->bmi[i].as_mv[1].as_int = this_second_mv->as_int;
|
|
|
|
|
2013-10-07 20:20:50 +02:00
|
|
|
mic->bmi[i].as_mode = m;
|
|
|
|
|
2013-07-23 15:51:44 +02:00
|
|
|
for (idy = 0; idy < num_4x4_blocks_high; ++idy)
|
|
|
|
for (idx = 0; idx < num_4x4_blocks_wide; ++idx)
|
2013-05-28 23:02:29 +02:00
|
|
|
vpx_memcpy(&mic->bmi[i + idy * 2 + idx],
|
|
|
|
&mic->bmi[i], sizeof(mic->bmi[i]));
|
2013-05-01 01:13:20 +02:00
|
|
|
|
|
|
|
cost += thismvcost;
|
|
|
|
return cost;
|
|
|
|
}
|
|
|
|
|
2013-07-09 01:01:01 +02:00
|
|
|
static int64_t encode_inter_mb_segment(VP9_COMP *cpi,
|
2013-05-01 01:13:20 +02:00
|
|
|
MACROBLOCK *x,
|
2013-07-09 01:01:01 +02:00
|
|
|
int64_t best_yrd,
|
2013-05-29 21:52:57 +02:00
|
|
|
int i,
|
2013-05-01 01:13:20 +02:00
|
|
|
int *labelyrate,
|
2013-07-11 00:18:52 +02:00
|
|
|
int64_t *distortion, int64_t *sse,
|
2013-05-01 01:13:20 +02:00
|
|
|
ENTROPY_CONTEXT *ta,
|
2013-12-19 20:16:05 +01:00
|
|
|
ENTROPY_CONTEXT *tl,
|
|
|
|
int mi_row, int mi_col) {
|
2013-05-29 21:52:57 +02:00
|
|
|
int k;
|
2013-05-01 01:13:20 +02:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-08-03 00:26:32 +02:00
|
|
|
struct macroblockd_plane *const pd = &xd->plane[0];
|
2013-09-18 14:20:10 +02:00
|
|
|
struct macroblock_plane *const p = &x->plane[0];
|
2013-10-10 21:11:44 +02:00
|
|
|
MODE_INFO *const mi = xd->mi_8x8[0];
|
2013-11-20 21:39:29 +01:00
|
|
|
const BLOCK_SIZE plane_bsize = get_plane_block_size(mi->mbmi.sb_type, pd);
|
|
|
|
const int width = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
|
|
|
|
const int height = 4 * num_4x4_blocks_high_lookup[plane_bsize];
|
2013-05-16 07:28:36 +02:00
|
|
|
int idx, idy;
|
2013-09-18 14:20:10 +02:00
|
|
|
|
2013-11-19 04:00:49 +01:00
|
|
|
const uint8_t *const src = &p->src.buf[raster_block_offset(BLOCK_8X8, i,
|
|
|
|
p->src.stride)];
|
|
|
|
uint8_t *const dst = &pd->dst.buf[raster_block_offset(BLOCK_8X8, i,
|
|
|
|
pd->dst.stride)];
|
2013-07-11 00:18:52 +02:00
|
|
|
int64_t thisdistortion = 0, thissse = 0;
|
2013-09-18 14:20:10 +02:00
|
|
|
int thisrate = 0, ref;
|
2013-11-23 01:20:45 +01:00
|
|
|
const scan_order *so = &vp9_default_scan_orders[TX_4X4];
|
2013-09-18 14:20:10 +02:00
|
|
|
const int is_compound = has_second_ref(&mi->mbmi);
|
|
|
|
for (ref = 0; ref < 1 + is_compound; ++ref) {
|
2013-11-19 04:00:49 +01:00
|
|
|
const uint8_t *pre = &pd->pre[ref].buf[raster_block_offset(BLOCK_8X8, i,
|
|
|
|
pd->pre[ref].stride)];
|
2013-08-27 01:52:13 +02:00
|
|
|
vp9_build_inter_predictor(pre, pd->pre[ref].stride,
|
2013-08-03 00:26:32 +02:00
|
|
|
dst, pd->dst.stride,
|
2013-08-27 01:52:13 +02:00
|
|
|
&mi->bmi[i].as_mv[ref].as_mv,
|
2013-12-28 03:44:19 +01:00
|
|
|
&xd->block_refs[ref]->sf,
|
2013-12-19 20:16:05 +01:00
|
|
|
width, height, ref, &xd->subpix, MV_PRECISION_Q3,
|
|
|
|
mi_col * MI_SIZE + 4 * (i % 2),
|
|
|
|
mi_row * MI_SIZE + 4 * (i / 2));
|
2013-05-29 21:52:57 +02:00
|
|
|
}
|
2013-05-16 07:28:36 +02:00
|
|
|
|
2013-09-18 14:20:10 +02:00
|
|
|
vp9_subtract_block(height, width,
|
|
|
|
raster_block_offset_int16(BLOCK_8X8, i, p->src_diff), 8,
|
|
|
|
src, p->src.stride,
|
2013-08-03 00:26:32 +02:00
|
|
|
dst, pd->dst.stride);
|
2013-05-29 21:52:57 +02:00
|
|
|
|
|
|
|
k = i;
|
2013-07-23 15:51:44 +02:00
|
|
|
for (idy = 0; idy < height / 4; ++idy) {
|
|
|
|
for (idx = 0; idx < width / 4; ++idx) {
|
2013-07-17 23:21:44 +02:00
|
|
|
int64_t ssz, rd, rd1, rd2;
|
2013-09-18 14:20:10 +02:00
|
|
|
int16_t* coeff;
|
2013-06-28 02:41:54 +02:00
|
|
|
|
2013-05-29 21:52:57 +02:00
|
|
|
k += (idy * 2 + idx);
|
2013-09-18 14:20:10 +02:00
|
|
|
coeff = BLOCK_OFFSET(p->coeff, k);
|
|
|
|
x->fwd_txm4x4(raster_block_offset_int16(BLOCK_8X8, k, p->src_diff),
|
2013-10-22 00:27:35 +02:00
|
|
|
coeff, 8);
|
2013-12-03 03:33:50 +01:00
|
|
|
vp9_regular_quantize_b_4x4(x, 0, k, so->scan, so->iscan);
|
2013-08-10 01:40:05 +02:00
|
|
|
thisdistortion += vp9_block_error(coeff, BLOCK_OFFSET(pd->dqcoeff, k),
|
2013-08-03 00:26:32 +02:00
|
|
|
16, &ssz);
|
2013-07-11 00:18:52 +02:00
|
|
|
thissse += ssz;
|
2013-11-23 01:20:45 +01:00
|
|
|
thisrate += cost_coeffs(x, 0, k, ta + (k & 1), tl + (k >> 1), TX_4X4,
|
|
|
|
so->scan, so->neighbors);
|
2013-07-17 23:21:44 +02:00
|
|
|
rd1 = RDCOST(x->rdmult, x->rddiv, thisrate, thisdistortion >> 2);
|
|
|
|
rd2 = RDCOST(x->rdmult, x->rddiv, 0, thissse >> 2);
|
|
|
|
rd = MIN(rd1, rd2);
|
|
|
|
if (rd >= best_yrd)
|
|
|
|
return INT64_MAX;
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
|
|
|
}
|
2013-09-18 14:20:10 +02:00
|
|
|
|
2013-07-17 23:21:44 +02:00
|
|
|
*distortion = thisdistortion >> 2;
|
|
|
|
*labelyrate = thisrate;
|
2013-07-11 00:18:52 +02:00
|
|
|
*sse = thissse >> 2;
|
2013-05-29 21:52:57 +02:00
|
|
|
|
2013-05-01 01:13:20 +02:00
|
|
|
return RDCOST(x->rdmult, x->rddiv, *labelyrate, *distortion);
|
|
|
|
}
|
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
typedef struct {
|
|
|
|
int eobs;
|
|
|
|
int brate;
|
|
|
|
int byrate;
|
|
|
|
int64_t bdist;
|
|
|
|
int64_t bsse;
|
|
|
|
int64_t brdcost;
|
|
|
|
int_mv mvs[2];
|
|
|
|
ENTROPY_CONTEXT ta[2];
|
|
|
|
ENTROPY_CONTEXT tl[2];
|
|
|
|
} SEG_RDSTAT;
|
|
|
|
|
2013-05-01 01:13:20 +02:00
|
|
|
typedef struct {
|
|
|
|
int_mv *ref_mv, *second_ref_mv;
|
|
|
|
int_mv mvp;
|
|
|
|
|
|
|
|
int64_t segment_rd;
|
|
|
|
int r;
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t d;
|
2013-07-11 00:18:52 +02:00
|
|
|
int64_t sse;
|
2013-05-01 01:13:20 +02:00
|
|
|
int segment_yrate;
|
2013-05-25 01:13:54 +02:00
|
|
|
MB_PREDICTION_MODE modes[4];
|
2013-08-23 03:40:34 +02:00
|
|
|
SEG_RDSTAT rdstat[4][INTER_MODES];
|
2013-05-01 01:13:20 +02:00
|
|
|
int mvthresh;
|
|
|
|
} BEST_SEG_INFO;
|
|
|
|
|
|
|
|
static INLINE int mv_check_bounds(MACROBLOCK *x, int_mv *mv) {
|
|
|
|
int r = 0;
|
|
|
|
r |= (mv->as_mv.row >> 3) < x->mv_row_min;
|
|
|
|
r |= (mv->as_mv.row >> 3) > x->mv_row_max;
|
|
|
|
r |= (mv->as_mv.col >> 3) < x->mv_col_min;
|
|
|
|
r |= (mv->as_mv.col >> 3) > x->mv_col_max;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2013-05-30 06:59:41 +02:00
|
|
|
static INLINE void mi_buf_shift(MACROBLOCK *x, int i) {
|
2013-09-11 19:45:44 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &x->e_mbd.mi_8x8[0]->mbmi;
|
2013-08-19 22:20:21 +02:00
|
|
|
struct macroblock_plane *const p = &x->plane[0];
|
|
|
|
struct macroblockd_plane *const pd = &x->e_mbd.plane[0];
|
|
|
|
|
2013-11-19 04:00:49 +01:00
|
|
|
p->src.buf = &p->src.buf[raster_block_offset(BLOCK_8X8, i, p->src.stride)];
|
2013-08-19 22:20:21 +02:00
|
|
|
assert(((intptr_t)pd->pre[0].buf & 0x7) == 0);
|
2013-11-19 04:00:49 +01:00
|
|
|
pd->pre[0].buf = &pd->pre[0].buf[raster_block_offset(BLOCK_8X8, i,
|
|
|
|
pd->pre[0].stride)];
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_ref(mbmi))
|
2013-11-19 04:00:49 +01:00
|
|
|
pd->pre[1].buf = &pd->pre[1].buf[raster_block_offset(BLOCK_8X8, i,
|
|
|
|
pd->pre[1].stride)];
|
2013-05-30 06:59:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE void mi_buf_restore(MACROBLOCK *x, struct buf_2d orig_src,
|
|
|
|
struct buf_2d orig_pre[2]) {
|
2013-09-11 19:45:44 +02:00
|
|
|
MB_MODE_INFO *mbmi = &x->e_mbd.mi_8x8[0]->mbmi;
|
2013-05-30 06:59:41 +02:00
|
|
|
x->plane[0].src = orig_src;
|
|
|
|
x->e_mbd.plane[0].pre[0] = orig_pre[0];
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_ref(mbmi))
|
2013-05-30 06:59:41 +02:00
|
|
|
x->e_mbd.plane[0].pre[1] = orig_pre[1];
|
|
|
|
}
|
|
|
|
|
2013-05-01 01:13:20 +02:00
|
|
|
static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-10-25 17:18:04 +02:00
|
|
|
const TileInfo *const tile,
|
2013-07-18 02:07:32 +02:00
|
|
|
BEST_SEG_INFO *bsi_buf, int filter_idx,
|
2013-05-30 06:59:41 +02:00
|
|
|
int_mv seg_mvs[4][MAX_REF_FRAMES],
|
|
|
|
int mi_row, int mi_col) {
|
2013-10-07 20:20:50 +02:00
|
|
|
int i, br = 0, idx, idy;
|
2013-07-18 02:07:32 +02:00
|
|
|
int64_t bd = 0, block_sse = 0;
|
2013-05-26 23:40:49 +02:00
|
|
|
MB_PREDICTION_MODE this_mode;
|
2014-01-07 02:29:16 +01:00
|
|
|
VP9_COMMON *cm = &cpi->common;
|
2013-09-11 19:45:44 +02:00
|
|
|
MODE_INFO *mi = x->e_mbd.mi_8x8[0];
|
2013-07-18 01:46:53 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &mi->mbmi;
|
2013-12-04 02:59:32 +01:00
|
|
|
struct macroblock_plane *const p = &x->plane[0];
|
2013-10-30 21:52:55 +01:00
|
|
|
struct macroblockd_plane *const pd = &x->e_mbd.plane[0];
|
2013-05-01 01:13:20 +02:00
|
|
|
const int label_count = 4;
|
2013-07-09 01:01:01 +02:00
|
|
|
int64_t this_segment_rd = 0;
|
2013-05-01 01:13:20 +02:00
|
|
|
int label_mv_thresh;
|
|
|
|
int segmentyrate = 0;
|
2013-08-27 20:05:08 +02:00
|
|
|
const BLOCK_SIZE bsize = mbmi->sb_type;
|
2013-08-05 21:15:52 +02:00
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
|
2013-05-01 01:13:20 +02:00
|
|
|
vp9_variance_fn_ptr_t *v_fn_ptr;
|
2013-07-18 02:07:32 +02:00
|
|
|
ENTROPY_CONTEXT t_above[2], t_left[2];
|
|
|
|
BEST_SEG_INFO *bsi = bsi_buf + filter_idx;
|
|
|
|
int mode_idx;
|
|
|
|
int subpelmv = 1, have_ref = 0;
|
2013-09-17 23:06:00 +02:00
|
|
|
const int has_second_rf = has_second_ref(mbmi);
|
2013-05-16 07:28:36 +02:00
|
|
|
|
2013-10-30 21:52:55 +01:00
|
|
|
vpx_memcpy(t_above, pd->above_context, sizeof(t_above));
|
|
|
|
vpx_memcpy(t_left, pd->left_context, sizeof(t_left));
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-07-23 15:51:44 +02:00
|
|
|
v_fn_ptr = &cpi->fn_ptr[bsize];
|
2013-05-01 01:13:20 +02:00
|
|
|
|
|
|
|
// 64 makes this threshold really big effectively
|
|
|
|
// making it so that we very rarely check mvs on
|
|
|
|
// segments. setting this to 1 would make mv thresh
|
|
|
|
// roughly equal to what it is for macroblocks
|
|
|
|
label_mv_thresh = 1 * bsi->mvthresh / label_count;
|
|
|
|
|
|
|
|
// Segmentation method overheads
|
2013-07-23 15:51:44 +02:00
|
|
|
for (idy = 0; idy < 2; idy += num_4x4_blocks_high) {
|
|
|
|
for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
|
2013-05-16 07:28:36 +02:00
|
|
|
// TODO(jingning,rbultje): rewrite the rate-distortion optimization
|
2013-05-22 06:28:42 +02:00
|
|
|
// loop for 4x4/4x8/8x4 block coding. to be replaced with new rd loop
|
2013-05-26 23:40:49 +02:00
|
|
|
int_mv mode_mv[MB_MODE_COUNT], second_mode_mv[MB_MODE_COUNT];
|
|
|
|
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
|
|
|
|
MB_PREDICTION_MODE mode_selected = ZEROMV;
|
2013-07-18 02:07:32 +02:00
|
|
|
int64_t best_rd = INT64_MAX;
|
2013-05-16 07:28:36 +02:00
|
|
|
i = idy * 2 + idx;
|
|
|
|
|
2013-06-06 22:44:34 +02:00
|
|
|
frame_mv[ZEROMV][mbmi->ref_frame[0]].as_int = 0;
|
2014-01-07 02:29:16 +01:00
|
|
|
vp9_append_sub8x8_mvs_for_idx(cm, &x->e_mbd, tile,
|
2013-12-11 02:56:53 +01:00
|
|
|
i, 0, mi_row, mi_col,
|
2013-06-06 22:44:34 +02:00
|
|
|
&frame_mv[NEARESTMV][mbmi->ref_frame[0]],
|
2013-12-11 02:56:53 +01:00
|
|
|
&frame_mv[NEARMV][mbmi->ref_frame[0]]);
|
2013-09-18 01:31:46 +02:00
|
|
|
if (has_second_rf) {
|
|
|
|
frame_mv[ZEROMV][mbmi->ref_frame[1]].as_int = 0;
|
2014-01-07 02:29:16 +01:00
|
|
|
vp9_append_sub8x8_mvs_for_idx(cm, &x->e_mbd, tile,
|
2013-12-11 02:56:53 +01:00
|
|
|
i, 1, mi_row, mi_col,
|
2013-09-18 01:31:46 +02:00
|
|
|
&frame_mv[NEARESTMV][mbmi->ref_frame[1]],
|
2013-12-11 02:56:53 +01:00
|
|
|
&frame_mv[NEARMV][mbmi->ref_frame[1]]);
|
2013-09-18 01:31:46 +02:00
|
|
|
}
|
2013-05-16 07:28:36 +02:00
|
|
|
// search for the best motion vector on this segment
|
2013-05-26 23:40:49 +02:00
|
|
|
for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
|
2013-05-30 06:59:41 +02:00
|
|
|
const struct buf_2d orig_src = x->plane[0].src;
|
|
|
|
struct buf_2d orig_pre[2];
|
|
|
|
|
2013-11-05 20:58:57 +01:00
|
|
|
mode_idx = INTER_OFFSET(this_mode);
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i][mode_idx].brdcost = INT64_MAX;
|
|
|
|
|
2013-07-17 22:53:35 +02:00
|
|
|
// if we're near/nearest and mv == 0,0, compare to zeromv
|
|
|
|
if ((this_mode == NEARMV || this_mode == NEARESTMV ||
|
|
|
|
this_mode == ZEROMV) &&
|
|
|
|
frame_mv[this_mode][mbmi->ref_frame[0]].as_int == 0 &&
|
2013-09-17 23:06:00 +02:00
|
|
|
(!has_second_rf ||
|
2013-07-17 22:53:35 +02:00
|
|
|
frame_mv[this_mode][mbmi->ref_frame[1]].as_int == 0)) {
|
2013-08-13 18:47:40 +02:00
|
|
|
int rfc = mbmi->mode_context[mbmi->ref_frame[0]];
|
2013-07-17 22:53:35 +02:00
|
|
|
int c1 = cost_mv_ref(cpi, NEARMV, rfc);
|
|
|
|
int c2 = cost_mv_ref(cpi, NEARESTMV, rfc);
|
|
|
|
int c3 = cost_mv_ref(cpi, ZEROMV, rfc);
|
|
|
|
|
|
|
|
if (this_mode == NEARMV) {
|
2013-07-18 18:34:59 +02:00
|
|
|
if (c1 > c3)
|
2013-07-17 22:53:35 +02:00
|
|
|
continue;
|
|
|
|
} else if (this_mode == NEARESTMV) {
|
2013-07-18 18:34:59 +02:00
|
|
|
if (c2 > c3)
|
2013-07-17 22:53:35 +02:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
assert(this_mode == ZEROMV);
|
2013-09-17 23:06:00 +02:00
|
|
|
if (!has_second_rf) {
|
2013-07-18 18:34:59 +02:00
|
|
|
if ((c3 >= c2 &&
|
|
|
|
frame_mv[NEARESTMV][mbmi->ref_frame[0]].as_int == 0) ||
|
|
|
|
(c3 >= c1 &&
|
|
|
|
frame_mv[NEARMV][mbmi->ref_frame[0]].as_int == 0))
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if ((c3 >= c2 &&
|
|
|
|
frame_mv[NEARESTMV][mbmi->ref_frame[0]].as_int == 0 &&
|
|
|
|
frame_mv[NEARESTMV][mbmi->ref_frame[1]].as_int == 0) ||
|
|
|
|
(c3 >= c1 &&
|
|
|
|
frame_mv[NEARMV][mbmi->ref_frame[0]].as_int == 0 &&
|
|
|
|
frame_mv[NEARMV][mbmi->ref_frame[1]].as_int == 0))
|
|
|
|
continue;
|
|
|
|
}
|
2013-07-17 22:53:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-30 21:52:55 +01:00
|
|
|
vpx_memcpy(orig_pre, pd->pre, sizeof(orig_pre));
|
2013-07-18 02:07:32 +02:00
|
|
|
vpx_memcpy(bsi->rdstat[i][mode_idx].ta, t_above,
|
|
|
|
sizeof(bsi->rdstat[i][mode_idx].ta));
|
|
|
|
vpx_memcpy(bsi->rdstat[i][mode_idx].tl, t_left,
|
|
|
|
sizeof(bsi->rdstat[i][mode_idx].tl));
|
2013-05-16 07:28:36 +02:00
|
|
|
|
|
|
|
// motion search for newmv (single predictor case only)
|
2013-09-17 23:06:00 +02:00
|
|
|
if (!has_second_rf && this_mode == NEWMV &&
|
2013-07-16 21:04:07 +02:00
|
|
|
seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV) {
|
2014-01-07 02:58:01 +01:00
|
|
|
int_mv *const new_mv = &mode_mv[NEWMV];
|
2013-05-16 07:28:36 +02:00
|
|
|
int step_param = 0;
|
|
|
|
int further_steps;
|
|
|
|
int thissme, bestsme = INT_MAX;
|
2013-05-29 21:52:57 +02:00
|
|
|
int sadpb = x->sadperbit4;
|
2014-01-03 20:48:07 +01:00
|
|
|
MV mvp_full;
|
2013-07-22 23:47:57 +02:00
|
|
|
int max_mv;
|
2013-05-16 07:28:36 +02:00
|
|
|
|
|
|
|
/* Is the best so far sufficiently good that we cant justify doing
|
|
|
|
* and new motion search. */
|
2013-07-18 02:07:32 +02:00
|
|
|
if (best_rd < label_mv_thresh)
|
2013-05-16 07:28:36 +02:00
|
|
|
break;
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-05-16 07:28:36 +02:00
|
|
|
if (cpi->compressor_speed) {
|
|
|
|
// use previous block's result as next block's MV predictor.
|
|
|
|
if (i > 0) {
|
2013-09-11 19:45:44 +02:00
|
|
|
bsi->mvp.as_int = mi->bmi[i - 1].as_mv[0].as_int;
|
2013-05-16 07:28:36 +02:00
|
|
|
if (i == 2)
|
2013-09-11 19:45:44 +02:00
|
|
|
bsi->mvp.as_int = mi->bmi[i - 2].as_mv[0].as_int;
|
2013-05-16 07:28:36 +02:00
|
|
|
}
|
|
|
|
}
|
2013-07-22 23:47:57 +02:00
|
|
|
if (i == 0)
|
|
|
|
max_mv = x->max_mv_context[mbmi->ref_frame[0]];
|
|
|
|
else
|
|
|
|
max_mv = MAX(abs(bsi->mvp.as_mv.row), abs(bsi->mvp.as_mv.col)) >> 3;
|
2013-09-12 19:06:47 +02:00
|
|
|
|
2014-01-07 02:29:16 +01:00
|
|
|
if (cpi->sf.auto_mv_step_size && cm->show_frame) {
|
2013-07-12 18:52:24 +02:00
|
|
|
// 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.
|
2013-07-22 23:47:57 +02:00
|
|
|
step_param = (vp9_init_search_range(cpi, max_mv) +
|
|
|
|
cpi->mv_step_param) >> 1;
|
2013-07-12 18:52:24 +02:00
|
|
|
} else {
|
|
|
|
step_param = cpi->mv_step_param;
|
|
|
|
}
|
2013-05-16 07:28:36 +02:00
|
|
|
|
2014-01-03 20:48:07 +01:00
|
|
|
mvp_full.row = bsi->mvp.as_mv.row >> 3;
|
|
|
|
mvp_full.col = bsi->mvp.as_mv.col >> 3;
|
2013-05-29 21:52:57 +02:00
|
|
|
|
2014-01-07 02:29:16 +01:00
|
|
|
if (cpi->sf.adaptive_motion_search && cm->show_frame) {
|
2014-01-03 20:48:07 +01:00
|
|
|
mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].as_mv.row >> 3;
|
|
|
|
mvp_full.col = x->pred_mv[mbmi->ref_frame[0]].as_mv.col >> 3;
|
2013-09-12 19:06:47 +02:00
|
|
|
step_param = MAX(step_param, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
|
2013-05-30 06:59:41 +02:00
|
|
|
// adjust src pointer for this block
|
|
|
|
mi_buf_shift(x, i);
|
2013-12-11 19:57:15 +01:00
|
|
|
|
2013-12-11 22:59:10 +01:00
|
|
|
vp9_set_mv_search_range(x, &bsi->ref_mv->as_mv);
|
2013-12-11 19:57:15 +01:00
|
|
|
|
2013-07-22 23:47:57 +02:00
|
|
|
if (cpi->sf.search_method == HEX) {
|
2014-01-03 20:48:07 +01:00
|
|
|
bestsme = vp9_hex_search(x, &mvp_full,
|
2013-07-22 23:47:57 +02:00
|
|
|
step_param,
|
|
|
|
sadpb, 1, v_fn_ptr, 1,
|
2013-09-26 01:44:19 +02:00
|
|
|
&bsi->ref_mv->as_mv,
|
2014-01-07 02:58:01 +01:00
|
|
|
&new_mv->as_mv);
|
2013-07-22 23:47:57 +02:00
|
|
|
} else if (cpi->sf.search_method == SQUARE) {
|
2014-01-03 20:48:07 +01:00
|
|
|
bestsme = vp9_square_search(x, &mvp_full,
|
2013-07-22 23:47:57 +02:00
|
|
|
step_param,
|
|
|
|
sadpb, 1, v_fn_ptr, 1,
|
2013-09-26 01:44:19 +02:00
|
|
|
&bsi->ref_mv->as_mv,
|
2014-01-07 02:58:01 +01:00
|
|
|
&new_mv->as_mv);
|
2013-07-22 23:47:57 +02:00
|
|
|
} else if (cpi->sf.search_method == BIGDIA) {
|
2014-01-03 20:48:07 +01:00
|
|
|
bestsme = vp9_bigdia_search(x, &mvp_full,
|
2013-07-22 23:47:57 +02:00
|
|
|
step_param,
|
|
|
|
sadpb, 1, v_fn_ptr, 1,
|
2013-09-26 01:44:19 +02:00
|
|
|
&bsi->ref_mv->as_mv,
|
2014-01-07 02:58:01 +01:00
|
|
|
&new_mv->as_mv);
|
2013-07-22 23:47:57 +02:00
|
|
|
} else {
|
|
|
|
bestsme = vp9_full_pixel_diamond(cpi, x, &mvp_full, step_param,
|
|
|
|
sadpb, further_steps, 0, v_fn_ptr,
|
2014-01-03 20:48:07 +01:00
|
|
|
&bsi->ref_mv->as_mv,
|
2014-01-07 02:58:01 +01:00
|
|
|
new_mv);
|
2013-07-22 23:47:57 +02:00
|
|
|
}
|
2013-05-29 21:52:57 +02:00
|
|
|
|
|
|
|
// Should we do a full search (best quality only)
|
|
|
|
if (cpi->compressor_speed == 0) {
|
|
|
|
/* Check if mvp_full is within the range. */
|
2014-01-03 20:48:07 +01:00
|
|
|
clamp_mv(&mvp_full, x->mv_col_min, x->mv_col_max,
|
2013-05-29 21:52:57 +02:00
|
|
|
x->mv_row_min, x->mv_row_max);
|
|
|
|
|
2014-01-03 20:48:07 +01:00
|
|
|
thissme = cpi->full_search_sad(x, &mvp_full,
|
2013-05-29 21:52:57 +02:00
|
|
|
sadpb, 16, v_fn_ptr,
|
|
|
|
x->nmvjointcost, x->mvcost,
|
2013-12-14 00:24:48 +01:00
|
|
|
&bsi->ref_mv->as_mv, i);
|
2013-05-29 21:52:57 +02:00
|
|
|
|
|
|
|
if (thissme < bestsme) {
|
|
|
|
bestsme = thissme;
|
2014-01-07 02:58:01 +01:00
|
|
|
new_mv->as_int = mi->bmi[i].as_mv[0].as_int;
|
2013-05-29 21:52:57 +02:00
|
|
|
} else {
|
|
|
|
/* The full search result is actually worse so re-instate the
|
|
|
|
* previous best vector */
|
2014-01-07 02:58:01 +01:00
|
|
|
mi->bmi[i].as_mv[0].as_int = new_mv->as_int;
|
2013-05-16 07:28:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bestsme < INT_MAX) {
|
|
|
|
int distortion;
|
2013-09-24 21:48:12 +02:00
|
|
|
cpi->find_fractional_mv_step(x,
|
2014-01-07 02:58:01 +01:00
|
|
|
&new_mv->as_mv,
|
2013-09-24 21:48:12 +02:00
|
|
|
&bsi->ref_mv->as_mv,
|
2014-01-07 02:29:16 +01:00
|
|
|
cm->allow_high_precision_mv,
|
2013-09-24 21:48:12 +02:00
|
|
|
x->errorperbit, v_fn_ptr,
|
2013-08-07 00:53:35 +02:00
|
|
|
0, cpi->sf.subpel_iters_per_step,
|
2013-05-16 07:28:36 +02:00
|
|
|
x->nmvjointcost, x->mvcost,
|
2013-12-21 00:24:22 +01:00
|
|
|
&distortion,
|
|
|
|
&x->pred_sse[mbmi->ref_frame[0]]);
|
2013-05-16 07:28:36 +02:00
|
|
|
|
2013-09-12 19:06:47 +02:00
|
|
|
// save motion search result for use in compound prediction
|
2014-01-07 02:58:01 +01:00
|
|
|
seg_mvs[i][mbmi->ref_frame[0]].as_int = new_mv->as_int;
|
2013-05-16 07:28:36 +02:00
|
|
|
}
|
|
|
|
|
2013-09-12 19:06:47 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search)
|
2014-01-07 02:58:01 +01:00
|
|
|
x->pred_mv[mbmi->ref_frame[0]].as_int = new_mv->as_int;
|
2013-09-12 19:06:47 +02:00
|
|
|
|
2013-05-16 07:28:36 +02:00
|
|
|
// restore src pointers
|
2013-05-30 06:59:41 +02:00
|
|
|
mi_buf_restore(x, orig_src, orig_pre);
|
2013-07-16 21:04:07 +02:00
|
|
|
}
|
|
|
|
|
2013-11-05 03:45:45 +01:00
|
|
|
if (has_second_rf) {
|
2013-06-06 22:44:34 +02:00
|
|
|
if (seg_mvs[i][mbmi->ref_frame[1]].as_int == INVALID_MV ||
|
|
|
|
seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV)
|
2013-05-16 07:28:36 +02:00
|
|
|
continue;
|
2013-11-05 03:45:45 +01:00
|
|
|
}
|
2013-05-30 06:59:41 +02:00
|
|
|
|
2013-11-05 03:45:45 +01:00
|
|
|
if (has_second_rf && this_mode == NEWMV &&
|
|
|
|
mbmi->interp_filter == EIGHTTAP) {
|
2013-05-30 06:59:41 +02:00
|
|
|
// adjust src pointers
|
|
|
|
mi_buf_shift(x, i);
|
2013-07-03 13:53:36 +02:00
|
|
|
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
|
2013-06-14 00:10:42 +02:00
|
|
|
int rate_mv;
|
|
|
|
joint_motion_search(cpi, x, bsize, frame_mv[this_mode],
|
|
|
|
mi_row, mi_col, seg_mvs[i],
|
|
|
|
&rate_mv);
|
2013-06-06 22:44:34 +02:00
|
|
|
seg_mvs[i][mbmi->ref_frame[0]].as_int =
|
|
|
|
frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
|
|
|
|
seg_mvs[i][mbmi->ref_frame[1]].as_int =
|
|
|
|
frame_mv[this_mode][mbmi->ref_frame[1]].as_int;
|
2013-05-30 06:59:41 +02:00
|
|
|
}
|
|
|
|
// restore src pointers
|
|
|
|
mi_buf_restore(x, orig_src, orig_pre);
|
2013-05-16 07:28:36 +02:00
|
|
|
}
|
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i][mode_idx].brate =
|
|
|
|
labels2mode(x, i, this_mode, &mode_mv[this_mode],
|
|
|
|
&second_mode_mv[this_mode], frame_mv, seg_mvs[i],
|
|
|
|
bsi->ref_mv, bsi->second_ref_mv, x->nmvjointcost,
|
|
|
|
x->mvcost, cpi);
|
|
|
|
|
2013-11-01 20:53:37 +01:00
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i][mode_idx].mvs[0].as_int = mode_mv[this_mode].as_int;
|
2013-07-23 15:51:44 +02:00
|
|
|
if (num_4x4_blocks_wide > 1)
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i + 1][mode_idx].mvs[0].as_int =
|
|
|
|
mode_mv[this_mode].as_int;
|
2013-07-23 15:51:44 +02:00
|
|
|
if (num_4x4_blocks_high > 1)
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i + 2][mode_idx].mvs[0].as_int =
|
|
|
|
mode_mv[this_mode].as_int;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf) {
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i][mode_idx].mvs[1].as_int =
|
|
|
|
second_mode_mv[this_mode].as_int;
|
2013-07-23 15:51:44 +02:00
|
|
|
if (num_4x4_blocks_wide > 1)
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i + 1][mode_idx].mvs[1].as_int =
|
|
|
|
second_mode_mv[this_mode].as_int;
|
2013-07-23 15:51:44 +02:00
|
|
|
if (num_4x4_blocks_high > 1)
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i + 2][mode_idx].mvs[1].as_int =
|
|
|
|
second_mode_mv[this_mode].as_int;
|
|
|
|
}
|
2013-05-16 07:28:36 +02:00
|
|
|
|
|
|
|
// Trap vectors that reach beyond the UMV borders
|
2013-07-18 02:12:02 +02:00
|
|
|
if (mv_check_bounds(x, &mode_mv[this_mode]))
|
2013-05-16 07:28:36 +02:00
|
|
|
continue;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf &&
|
2013-05-16 07:28:36 +02:00
|
|
|
mv_check_bounds(x, &second_mode_mv[this_mode]))
|
|
|
|
continue;
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
if (filter_idx > 0) {
|
|
|
|
BEST_SEG_INFO *ref_bsi = bsi_buf;
|
|
|
|
subpelmv = (mode_mv[this_mode].as_mv.row & 0x0f) ||
|
|
|
|
(mode_mv[this_mode].as_mv.col & 0x0f);
|
|
|
|
have_ref = mode_mv[this_mode].as_int ==
|
|
|
|
ref_bsi->rdstat[i][mode_idx].mvs[0].as_int;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf) {
|
2013-07-18 02:07:32 +02:00
|
|
|
subpelmv |= (second_mode_mv[this_mode].as_mv.row & 0x0f) ||
|
|
|
|
(second_mode_mv[this_mode].as_mv.col & 0x0f);
|
|
|
|
have_ref &= second_mode_mv[this_mode].as_int ==
|
|
|
|
ref_bsi->rdstat[i][mode_idx].mvs[1].as_int;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (filter_idx > 1 && !subpelmv && !have_ref) {
|
|
|
|
ref_bsi = bsi_buf + 1;
|
|
|
|
have_ref = mode_mv[this_mode].as_int ==
|
|
|
|
ref_bsi->rdstat[i][mode_idx].mvs[0].as_int;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_rf) {
|
2013-07-18 02:07:32 +02:00
|
|
|
have_ref &= second_mode_mv[this_mode].as_int ==
|
|
|
|
ref_bsi->rdstat[i][mode_idx].mvs[1].as_int;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!subpelmv && have_ref &&
|
|
|
|
ref_bsi->rdstat[i][mode_idx].brdcost < INT64_MAX) {
|
|
|
|
vpx_memcpy(&bsi->rdstat[i][mode_idx], &ref_bsi->rdstat[i][mode_idx],
|
|
|
|
sizeof(SEG_RDSTAT));
|
2013-10-30 21:52:55 +01:00
|
|
|
if (num_4x4_blocks_wide > 1)
|
|
|
|
bsi->rdstat[i + 1][mode_idx].eobs =
|
|
|
|
ref_bsi->rdstat[i + 1][mode_idx].eobs;
|
|
|
|
if (num_4x4_blocks_high > 1)
|
|
|
|
bsi->rdstat[i + 2][mode_idx].eobs =
|
|
|
|
ref_bsi->rdstat[i + 2][mode_idx].eobs;
|
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
if (bsi->rdstat[i][mode_idx].brdcost < best_rd) {
|
|
|
|
mode_selected = this_mode;
|
|
|
|
best_rd = bsi->rdstat[i][mode_idx].brdcost;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2013-07-17 23:21:44 +02:00
|
|
|
}
|
2013-05-16 07:28:36 +02:00
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[i][mode_idx].brdcost =
|
|
|
|
encode_inter_mb_segment(cpi, x,
|
|
|
|
bsi->segment_rd - this_segment_rd, i,
|
|
|
|
&bsi->rdstat[i][mode_idx].byrate,
|
|
|
|
&bsi->rdstat[i][mode_idx].bdist,
|
|
|
|
&bsi->rdstat[i][mode_idx].bsse,
|
|
|
|
bsi->rdstat[i][mode_idx].ta,
|
2013-12-19 20:16:05 +01:00
|
|
|
bsi->rdstat[i][mode_idx].tl,
|
|
|
|
mi_row, mi_col);
|
2013-07-18 02:07:32 +02:00
|
|
|
if (bsi->rdstat[i][mode_idx].brdcost < INT64_MAX) {
|
|
|
|
bsi->rdstat[i][mode_idx].brdcost += RDCOST(x->rdmult, x->rddiv,
|
|
|
|
bsi->rdstat[i][mode_idx].brate, 0);
|
|
|
|
bsi->rdstat[i][mode_idx].brate += bsi->rdstat[i][mode_idx].byrate;
|
2013-12-04 02:59:32 +01:00
|
|
|
bsi->rdstat[i][mode_idx].eobs = p->eobs[i];
|
2013-10-30 21:52:55 +01:00
|
|
|
if (num_4x4_blocks_wide > 1)
|
2013-12-04 02:59:32 +01:00
|
|
|
bsi->rdstat[i + 1][mode_idx].eobs = p->eobs[i + 1];
|
2013-10-30 21:52:55 +01:00
|
|
|
if (num_4x4_blocks_high > 1)
|
2013-12-04 02:59:32 +01:00
|
|
|
bsi->rdstat[i + 2][mode_idx].eobs = p->eobs[i + 2];
|
2013-07-18 02:07:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bsi->rdstat[i][mode_idx].brdcost < best_rd) {
|
2013-05-16 07:28:36 +02:00
|
|
|
mode_selected = this_mode;
|
2013-07-18 02:07:32 +02:00
|
|
|
best_rd = bsi->rdstat[i][mode_idx].brdcost;
|
2013-05-16 07:28:36 +02:00
|
|
|
}
|
|
|
|
} /*for each 4x4 mode*/
|
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
if (best_rd == INT64_MAX) {
|
|
|
|
int iy, midx;
|
|
|
|
for (iy = i + 1; iy < 4; ++iy)
|
2013-08-23 03:40:34 +02:00
|
|
|
for (midx = 0; midx < INTER_MODES; ++midx)
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[iy][midx].brdcost = INT64_MAX;
|
2013-07-17 23:21:44 +02:00
|
|
|
bsi->segment_rd = INT64_MAX;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-11-05 20:58:57 +01:00
|
|
|
mode_idx = INTER_OFFSET(mode_selected);
|
2013-07-18 02:07:32 +02:00
|
|
|
vpx_memcpy(t_above, bsi->rdstat[i][mode_idx].ta, sizeof(t_above));
|
|
|
|
vpx_memcpy(t_left, bsi->rdstat[i][mode_idx].tl, sizeof(t_left));
|
2013-05-16 07:28:36 +02:00
|
|
|
|
2013-05-29 21:52:57 +02:00
|
|
|
labels2mode(x, i, mode_selected, &mode_mv[mode_selected],
|
2013-05-26 23:40:49 +02:00
|
|
|
&second_mode_mv[mode_selected], frame_mv, seg_mvs[i],
|
2013-05-16 07:28:36 +02:00
|
|
|
bsi->ref_mv, bsi->second_ref_mv, x->nmvjointcost,
|
|
|
|
x->mvcost, cpi);
|
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
br += bsi->rdstat[i][mode_idx].brate;
|
|
|
|
bd += bsi->rdstat[i][mode_idx].bdist;
|
|
|
|
block_sse += bsi->rdstat[i][mode_idx].bsse;
|
|
|
|
segmentyrate += bsi->rdstat[i][mode_idx].byrate;
|
|
|
|
this_segment_rd += bsi->rdstat[i][mode_idx].brdcost;
|
2013-07-09 01:01:01 +02:00
|
|
|
|
|
|
|
if (this_segment_rd > bsi->segment_rd) {
|
2013-07-18 02:07:32 +02:00
|
|
|
int iy, midx;
|
|
|
|
for (iy = i + 1; iy < 4; ++iy)
|
2013-08-23 03:40:34 +02:00
|
|
|
for (midx = 0; midx < INTER_MODES; ++midx)
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->rdstat[iy][midx].brdcost = INT64_MAX;
|
2013-07-09 01:01:01 +02:00
|
|
|
bsi->segment_rd = INT64_MAX;
|
|
|
|
return;
|
|
|
|
}
|
2013-05-16 07:28:36 +02:00
|
|
|
}
|
2013-05-01 01:13:20 +02:00
|
|
|
} /* for each label */
|
|
|
|
|
2013-07-09 01:01:01 +02:00
|
|
|
bsi->r = br;
|
|
|
|
bsi->d = bd;
|
|
|
|
bsi->segment_yrate = segmentyrate;
|
|
|
|
bsi->segment_rd = this_segment_rd;
|
2013-07-11 00:18:52 +02:00
|
|
|
bsi->sse = block_sse;
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
// update the coding decisions
|
|
|
|
for (i = 0; i < 4; ++i)
|
2013-10-07 20:20:50 +02:00
|
|
|
bsi->modes[i] = mi->bmi[i].as_mode;
|
2013-03-04 23:12:17 +01:00
|
|
|
}
|
|
|
|
|
2013-07-09 01:01:01 +02:00
|
|
|
static int64_t rd_pick_best_mbsegmentation(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-10-25 17:18:04 +02:00
|
|
|
const TileInfo *const tile,
|
2013-07-09 01:01:01 +02:00
|
|
|
int_mv *best_ref_mv,
|
|
|
|
int_mv *second_best_ref_mv,
|
|
|
|
int64_t best_rd,
|
|
|
|
int *returntotrate,
|
|
|
|
int *returnyrate,
|
|
|
|
int64_t *returndistortion,
|
2013-07-11 00:18:52 +02:00
|
|
|
int *skippable, int64_t *psse,
|
|
|
|
int mvthresh,
|
2013-07-09 01:01:01 +02:00
|
|
|
int_mv seg_mvs[4][MAX_REF_FRAMES],
|
2013-07-18 02:07:32 +02:00
|
|
|
BEST_SEG_INFO *bsi_buf,
|
|
|
|
int filter_idx,
|
2013-07-09 01:01:01 +02:00
|
|
|
int mi_row, int mi_col) {
|
2013-05-01 01:13:20 +02:00
|
|
|
int i;
|
2013-07-18 02:07:32 +02:00
|
|
|
BEST_SEG_INFO *bsi = bsi_buf + filter_idx;
|
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MODE_INFO *mi = xd->mi_8x8[0];
|
2013-07-18 02:07:32 +02:00
|
|
|
MB_MODE_INFO *mbmi = &mi->mbmi;
|
|
|
|
int mode_idx;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-07-25 23:13:44 +02:00
|
|
|
vp9_zero(*bsi);
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->segment_rd = best_rd;
|
|
|
|
bsi->ref_mv = best_ref_mv;
|
|
|
|
bsi->second_ref_mv = second_best_ref_mv;
|
|
|
|
bsi->mvp.as_int = best_ref_mv->as_int;
|
|
|
|
bsi->mvthresh = mvthresh;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-05-01 01:13:20 +02:00
|
|
|
for (i = 0; i < 4; i++)
|
2013-07-18 02:07:32 +02:00
|
|
|
bsi->modes[i] = ZEROMV;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
rd_check_segment_txsize(cpi, x, tile, bsi_buf, filter_idx, seg_mvs,
|
|
|
|
mi_row, mi_col);
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-07-22 21:37:30 +02:00
|
|
|
if (bsi->segment_rd > best_rd)
|
2013-07-20 00:18:05 +02:00
|
|
|
return INT64_MAX;
|
2013-05-01 01:13:20 +02:00
|
|
|
/* set it to the best */
|
|
|
|
for (i = 0; i < 4; i++) {
|
2013-11-05 20:58:57 +01:00
|
|
|
mode_idx = INTER_OFFSET(bsi->modes[i]);
|
2013-07-18 02:07:32 +02:00
|
|
|
mi->bmi[i].as_mv[0].as_int = bsi->rdstat[i][mode_idx].mvs[0].as_int;
|
2013-09-17 23:06:00 +02:00
|
|
|
if (has_second_ref(mbmi))
|
2013-07-18 02:07:32 +02:00
|
|
|
mi->bmi[i].as_mv[1].as_int = bsi->rdstat[i][mode_idx].mvs[1].as_int;
|
2013-12-04 02:59:32 +01:00
|
|
|
x->plane[0].eobs[i] = bsi->rdstat[i][mode_idx].eobs;
|
2013-10-07 20:20:50 +02:00
|
|
|
mi->bmi[i].as_mode = bsi->modes[i];
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
2013-07-18 01:46:53 +02:00
|
|
|
|
2013-05-01 01:13:20 +02:00
|
|
|
/*
|
|
|
|
* used to set mbmi->mv.as_int
|
|
|
|
*/
|
2013-07-18 02:07:32 +02:00
|
|
|
*returntotrate = bsi->r;
|
|
|
|
*returndistortion = bsi->d;
|
|
|
|
*returnyrate = bsi->segment_yrate;
|
2013-12-04 02:59:32 +01:00
|
|
|
*skippable = vp9_is_skippable_in_plane(x, BLOCK_8X8, 0);
|
2013-07-18 02:07:32 +02:00
|
|
|
*psse = bsi->sse;
|
|
|
|
mbmi->mode = bsi->modes[3];
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-07-18 02:07:32 +02:00
|
|
|
return bsi->segment_rd;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
static void mv_pred(VP9_COMP *cpi, MACROBLOCK *x,
|
|
|
|
uint8_t *ref_y_buffer, int ref_y_stride,
|
2013-08-27 20:05:08 +02:00
|
|
|
int ref_frame, BLOCK_SIZE block_size ) {
|
2013-05-05 07:09:43 +02:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-05-05 07:09:43 +02:00
|
|
|
int_mv this_mv;
|
|
|
|
int i;
|
|
|
|
int zero_seen = 0;
|
|
|
|
int best_index = 0;
|
|
|
|
int best_sad = INT_MAX;
|
|
|
|
int this_sad = INT_MAX;
|
2013-11-25 21:45:51 +01:00
|
|
|
int max_mv = 0;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
uint8_t *src_y_ptr = x->plane[0].src.buf;
|
|
|
|
uint8_t *ref_y_ptr;
|
|
|
|
int row_offset, col_offset;
|
2013-09-12 19:06:47 +02:00
|
|
|
int num_mv_refs = MAX_MV_REF_CANDIDATES +
|
|
|
|
(cpi->sf.adaptive_motion_search &&
|
2013-09-16 21:44:50 +02:00
|
|
|
cpi->common.show_frame &&
|
|
|
|
block_size < cpi->sf.max_partition_size);
|
2012-04-18 22:51:58 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Get the sad for each candidate reference mv
|
2013-09-12 19:06:47 +02:00
|
|
|
for (i = 0; i < num_mv_refs; i++) {
|
|
|
|
this_mv.as_int = (i < MAX_MV_REF_CANDIDATES) ?
|
|
|
|
mbmi->ref_mvs[ref_frame][i].as_int : x->pred_mv[ref_frame].as_int;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-07-12 18:52:24 +02:00
|
|
|
max_mv = MAX(max_mv,
|
|
|
|
MAX(abs(this_mv.as_mv.row), abs(this_mv.as_mv.col)) >> 3);
|
2013-05-05 07:09:43 +02:00
|
|
|
// The list is at an end if we see 0 for a second time.
|
|
|
|
if (!this_mv.as_int && zero_seen)
|
|
|
|
break;
|
|
|
|
zero_seen = zero_seen || !this_mv.as_int;
|
2011-05-24 19:24:52 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
row_offset = this_mv.as_mv.row >> 3;
|
|
|
|
col_offset = this_mv.as_mv.col >> 3;
|
|
|
|
ref_y_ptr = ref_y_buffer + (ref_y_stride * row_offset) + col_offset;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Find sad for current vector.
|
|
|
|
this_sad = cpi->fn_ptr[block_size].sdf(src_y_ptr, x->plane[0].src.stride,
|
|
|
|
ref_y_ptr, ref_y_stride,
|
|
|
|
0x7fffffff);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Note if it is the best so far.
|
|
|
|
if (this_sad < best_sad) {
|
|
|
|
best_sad = this_sad;
|
|
|
|
best_index = i;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2012-08-07 01:21:23 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Note the index of the mv that worked best in the reference list.
|
|
|
|
x->mv_best_ref_index[ref_frame] = best_index;
|
2013-07-12 18:52:24 +02:00
|
|
|
x->max_mv_context[ref_frame] = max_mv;
|
2013-12-21 00:24:22 +01:00
|
|
|
x->pred_mv_sad[ref_frame] = best_sad;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
static void estimate_ref_frame_costs(VP9_COMP *cpi, int segment_id,
|
2013-06-06 22:44:34 +02:00
|
|
|
unsigned int *ref_costs_single,
|
|
|
|
unsigned int *ref_costs_comp,
|
|
|
|
vp9_prob *comp_mode_p) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
|
2013-08-14 20:20:33 +02:00
|
|
|
int seg_ref_active = vp9_segfeature_active(&cm->seg, segment_id,
|
2013-06-06 22:44:34 +02:00
|
|
|
SEG_LVL_REF_FRAME);
|
2013-05-05 07:09:43 +02:00
|
|
|
if (seg_ref_active) {
|
2013-06-06 22:44:34 +02:00
|
|
|
vpx_memset(ref_costs_single, 0, MAX_REF_FRAMES * sizeof(*ref_costs_single));
|
|
|
|
vpx_memset(ref_costs_comp, 0, MAX_REF_FRAMES * sizeof(*ref_costs_comp));
|
|
|
|
*comp_mode_p = 128;
|
|
|
|
} else {
|
2013-12-06 02:01:03 +01:00
|
|
|
vp9_prob intra_inter_p = vp9_get_intra_inter_prob(cm, xd);
|
2013-06-06 22:44:34 +02:00
|
|
|
vp9_prob comp_inter_p = 128;
|
2013-05-05 07:09:43 +02:00
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT) {
|
2013-12-06 20:23:01 +01:00
|
|
|
comp_inter_p = vp9_get_reference_mode_prob(cm, xd);
|
2013-06-06 22:44:34 +02:00
|
|
|
*comp_mode_p = comp_inter_p;
|
2013-05-05 07:09:43 +02:00
|
|
|
} else {
|
2013-06-06 22:44:34 +02:00
|
|
|
*comp_mode_p = 128;
|
|
|
|
}
|
2013-05-05 07:09:43 +02:00
|
|
|
|
2013-06-06 22:44:34 +02:00
|
|
|
ref_costs_single[INTRA_FRAME] = vp9_cost_bit(intra_inter_p, 0);
|
2013-05-05 07:09:43 +02:00
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
if (cm->reference_mode != COMPOUND_REFERENCE) {
|
2013-07-10 04:55:07 +02:00
|
|
|
vp9_prob ref_single_p1 = vp9_get_pred_prob_single_ref_p1(cm, xd);
|
|
|
|
vp9_prob ref_single_p2 = vp9_get_pred_prob_single_ref_p2(cm, xd);
|
2013-06-06 22:44:34 +02:00
|
|
|
unsigned int base_cost = vp9_cost_bit(intra_inter_p, 1);
|
2013-05-05 07:09:43 +02:00
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT)
|
2013-06-06 22:44:34 +02:00
|
|
|
base_cost += vp9_cost_bit(comp_inter_p, 0);
|
2013-05-05 07:09:43 +02:00
|
|
|
|
2013-06-06 22:44:34 +02:00
|
|
|
ref_costs_single[LAST_FRAME] = ref_costs_single[GOLDEN_FRAME] =
|
|
|
|
ref_costs_single[ALTREF_FRAME] = base_cost;
|
|
|
|
ref_costs_single[LAST_FRAME] += vp9_cost_bit(ref_single_p1, 0);
|
|
|
|
ref_costs_single[GOLDEN_FRAME] += vp9_cost_bit(ref_single_p1, 1);
|
|
|
|
ref_costs_single[ALTREF_FRAME] += vp9_cost_bit(ref_single_p1, 1);
|
|
|
|
ref_costs_single[GOLDEN_FRAME] += vp9_cost_bit(ref_single_p2, 0);
|
|
|
|
ref_costs_single[ALTREF_FRAME] += vp9_cost_bit(ref_single_p2, 1);
|
|
|
|
} else {
|
|
|
|
ref_costs_single[LAST_FRAME] = 512;
|
|
|
|
ref_costs_single[GOLDEN_FRAME] = 512;
|
|
|
|
ref_costs_single[ALTREF_FRAME] = 512;
|
2012-10-17 20:40:00 +02:00
|
|
|
}
|
2013-12-10 00:13:34 +01:00
|
|
|
if (cm->reference_mode != SINGLE_REFERENCE) {
|
2013-07-10 04:55:07 +02:00
|
|
|
vp9_prob ref_comp_p = vp9_get_pred_prob_comp_ref_p(cm, xd);
|
2013-06-06 22:44:34 +02:00
|
|
|
unsigned int base_cost = vp9_cost_bit(intra_inter_p, 1);
|
2013-05-05 07:09:43 +02:00
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT)
|
2013-06-06 22:44:34 +02:00
|
|
|
base_cost += vp9_cost_bit(comp_inter_p, 1);
|
|
|
|
|
|
|
|
ref_costs_comp[LAST_FRAME] = base_cost + vp9_cost_bit(ref_comp_p, 0);
|
|
|
|
ref_costs_comp[GOLDEN_FRAME] = base_cost + vp9_cost_bit(ref_comp_p, 1);
|
|
|
|
} else {
|
|
|
|
ref_costs_comp[LAST_FRAME] = 512;
|
|
|
|
ref_costs_comp[GOLDEN_FRAME] = 512;
|
|
|
|
}
|
2012-10-17 20:40:00 +02:00
|
|
|
}
|
|
|
|
}
|
2011-06-23 00:07:04 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
static void store_coding_context(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
|
2013-07-08 23:49:33 +02:00
|
|
|
int mode_index,
|
|
|
|
int_mv *ref_mv,
|
|
|
|
int_mv *second_ref_mv,
|
2013-11-23 01:35:37 +01:00
|
|
|
int64_t comp_pred_diff[REFERENCE_MODES],
|
2013-08-03 02:28:23 +02:00
|
|
|
int64_t tx_size_diff[TX_MODES],
|
2013-10-30 22:40:34 +01:00
|
|
|
int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS]) {
|
2013-05-05 07:09:43 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2010-12-06 22:42:52 +01:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Take a snapshot of the coding context so it can be
|
|
|
|
// restored if we decide to encode this way
|
|
|
|
ctx->skip = x->skip;
|
|
|
|
ctx->best_mode_index = mode_index;
|
2013-10-10 21:11:44 +02:00
|
|
|
ctx->mic = *xd->mi_8x8[0];
|
2013-06-01 01:00:32 +02:00
|
|
|
|
2014-01-03 20:31:00 +01:00
|
|
|
ctx->best_ref_mv[0].as_int = ref_mv->as_int;
|
|
|
|
ctx->best_ref_mv[1].as_int = second_ref_mv->as_int;
|
2010-12-06 22:42:52 +01:00
|
|
|
|
2013-11-23 01:35:37 +01:00
|
|
|
ctx->single_pred_diff = (int)comp_pred_diff[SINGLE_REFERENCE];
|
|
|
|
ctx->comp_pred_diff = (int)comp_pred_diff[COMPOUND_REFERENCE];
|
|
|
|
ctx->hybrid_pred_diff = (int)comp_pred_diff[REFERENCE_MODE_SELECT];
|
2010-12-06 22:42:52 +01:00
|
|
|
|
2013-09-24 18:07:08 +02:00
|
|
|
vpx_memcpy(ctx->tx_rd_diff, tx_size_diff, sizeof(ctx->tx_rd_diff));
|
|
|
|
vpx_memcpy(ctx->best_filter_diff, best_filter_diff,
|
2013-10-30 22:40:34 +01:00
|
|
|
sizeof(*best_filter_diff) * SWITCHABLE_FILTER_CONTEXTS);
|
2013-05-05 07:09:43 +02:00
|
|
|
}
|
2010-12-06 22:42:52 +01:00
|
|
|
|
2013-05-07 20:31:12 +02:00
|
|
|
static void setup_pred_block(const MACROBLOCKD *xd,
|
|
|
|
struct buf_2d dst[MAX_MB_PLANE],
|
|
|
|
const YV12_BUFFER_CONFIG *src,
|
|
|
|
int mi_row, int mi_col,
|
|
|
|
const struct scale_factors *scale,
|
|
|
|
const struct scale_factors *scale_uv) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
dst[0].buf = src->y_buffer;
|
|
|
|
dst[0].stride = src->y_stride;
|
|
|
|
dst[1].buf = src->u_buffer;
|
|
|
|
dst[2].buf = src->v_buffer;
|
|
|
|
dst[1].stride = dst[2].stride = src->uv_stride;
|
2013-05-16 02:55:08 +02:00
|
|
|
#if CONFIG_ALPHA
|
|
|
|
dst[3].buf = src->alpha_buffer;
|
|
|
|
dst[3].stride = src->alpha_stride;
|
|
|
|
#endif
|
2013-05-07 20:31:12 +02:00
|
|
|
|
|
|
|
// TODO(jkoleszar): Make scale factors per-plane data
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++) {
|
|
|
|
setup_pred_plane(dst + i, dst[i].buf, dst[i].stride, mi_row, mi_col,
|
|
|
|
i ? scale_uv : scale,
|
|
|
|
xd->plane[i].subsampling_x, xd->plane[i].subsampling_y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
static void setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-10-25 17:18:04 +02:00
|
|
|
const TileInfo *const tile,
|
2013-05-05 07:09:43 +02:00
|
|
|
int idx, MV_REFERENCE_FRAME frame_type,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE block_size,
|
2013-05-05 07:09:43 +02:00
|
|
|
int mi_row, int mi_col,
|
|
|
|
int_mv frame_nearest_mv[MAX_REF_FRAMES],
|
|
|
|
int_mv frame_near_mv[MAX_REF_FRAMES],
|
2013-12-20 01:06:33 +01:00
|
|
|
struct buf_2d yv12_mb[4][MAX_MB_PLANE]) {
|
2013-05-05 07:09:43 +02:00
|
|
|
VP9_COMMON *cm = &cpi->common;
|
|
|
|
YV12_BUFFER_CONFIG *yv12 = &cm->yv12_fb[cpi->common.ref_frame_map[idx]];
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-12-28 03:44:19 +01:00
|
|
|
const struct scale_factors *const sf = &cm->frame_refs[frame_type - 1].sf;
|
2010-12-23 17:23:03 +01:00
|
|
|
|
2010-12-06 22:42:52 +01:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// TODO(jkoleszar): Is the UV buffer ever used here? If so, need to make this
|
|
|
|
// use the UV scaling factors.
|
2013-12-20 01:06:33 +01:00
|
|
|
setup_pred_block(xd, yv12_mb[frame_type], yv12, mi_row, mi_col, sf, sf);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Gets an initial list of candidate vectors from neighbours and orders them
|
2013-10-25 17:18:04 +02:00
|
|
|
vp9_find_mv_refs(cm, xd, tile, xd->mi_8x8[0],
|
2013-09-11 19:45:44 +02:00
|
|
|
xd->last_mi,
|
2013-05-05 07:09:43 +02:00
|
|
|
frame_type,
|
2013-08-23 21:00:14 +02:00
|
|
|
mbmi->ref_mvs[frame_type], mi_row, mi_col);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Candidate refinement carried out at encoder and decoder
|
2013-10-21 19:12:14 +02:00
|
|
|
vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv,
|
2013-05-05 07:09:43 +02:00
|
|
|
mbmi->ref_mvs[frame_type],
|
|
|
|
&frame_nearest_mv[frame_type],
|
|
|
|
&frame_near_mv[frame_type]);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Further refinement that is encode side only to test the top few candidates
|
|
|
|
// in full and choose the best as the centre point for subsequent searches.
|
|
|
|
// The current implementation doesn't support scaling.
|
2013-12-20 01:06:33 +01:00
|
|
|
if (!vp9_is_scaled(sf) && block_size >= BLOCK_8X8)
|
2013-05-07 20:31:12 +02:00
|
|
|
mv_pred(cpi, x, yv12_mb[frame_type][0].buf, yv12->y_stride,
|
2013-05-05 07:09:43 +02:00
|
|
|
frame_type, block_size);
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-06-14 00:10:42 +02:00
|
|
|
static YV12_BUFFER_CONFIG *get_scaled_ref_frame(VP9_COMP *cpi, int ref_frame) {
|
|
|
|
YV12_BUFFER_CONFIG *scaled_ref_frame = NULL;
|
|
|
|
int fb = get_ref_frame_idx(cpi, ref_frame);
|
2013-09-05 17:55:47 +02:00
|
|
|
int fb_scale = get_scale_ref_frame_idx(cpi, ref_frame);
|
|
|
|
if (cpi->scaled_ref_idx[fb_scale] != cpi->common.ref_frame_map[fb])
|
|
|
|
scaled_ref_frame = &cpi->common.yv12_fb[cpi->scaled_ref_idx[fb_scale]];
|
2013-06-14 00:10:42 +02:00
|
|
|
return scaled_ref_frame;
|
|
|
|
}
|
|
|
|
|
2013-08-06 20:04:31 +02:00
|
|
|
static INLINE int get_switchable_rate(const MACROBLOCK *x) {
|
|
|
|
const MACROBLOCKD *const xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
const MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-08-06 20:04:31 +02:00
|
|
|
const int ctx = vp9_get_pred_context_switchable_interp(xd);
|
|
|
|
return SWITCHABLE_INTERP_RATE_FACTOR *
|
|
|
|
x->switchable_interp_costs[ctx][mbmi->interp_filter];
|
2013-05-07 21:23:14 +02:00
|
|
|
}
|
|
|
|
|
2013-06-14 00:10:42 +02:00
|
|
|
static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-10-25 17:18:04 +02:00
|
|
|
const TileInfo *const tile,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize,
|
2013-06-14 00:10:42 +02:00
|
|
|
int mi_row, int mi_col,
|
|
|
|
int_mv *tmp_mv, int *rate_mv) {
|
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-07-03 23:43:23 +02:00
|
|
|
VP9_COMMON *cm = &cpi->common;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-06-14 00:10:42 +02:00
|
|
|
struct buf_2d backup_yv12[MAX_MB_PLANE] = {{0}};
|
|
|
|
int bestsme = INT_MAX;
|
2013-06-24 16:19:16 +02:00
|
|
|
int further_steps, step_param;
|
2013-06-14 00:10:42 +02:00
|
|
|
int sadpb = x->sadperbit16;
|
2014-01-07 03:07:12 +01:00
|
|
|
MV mvp_full;
|
2013-06-14 00:10:42 +02:00
|
|
|
int ref = mbmi->ref_frame[0];
|
|
|
|
int_mv ref_mv = mbmi->ref_mvs[ref][0];
|
|
|
|
|
|
|
|
int tmp_col_min = x->mv_col_min;
|
|
|
|
int tmp_col_max = x->mv_col_max;
|
|
|
|
int tmp_row_min = x->mv_row_min;
|
|
|
|
int tmp_row_max = x->mv_row_max;
|
|
|
|
|
|
|
|
YV12_BUFFER_CONFIG *scaled_ref_frame = get_scaled_ref_frame(cpi, ref);
|
|
|
|
|
|
|
|
if (scaled_ref_frame) {
|
|
|
|
int i;
|
|
|
|
// Swap out the reference frame for a version that's been scaled to
|
|
|
|
// match the resolution of the current frame, allowing the existing
|
|
|
|
// motion search code to be used without additional modifications.
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++)
|
|
|
|
backup_yv12[i] = xd->plane[i].pre[0];
|
|
|
|
|
2013-07-18 00:27:12 +02:00
|
|
|
setup_pre_planes(xd, 0, scaled_ref_frame, mi_row, mi_col, NULL);
|
2013-06-14 00:10:42 +02:00
|
|
|
}
|
|
|
|
|
2013-12-11 22:59:10 +01:00
|
|
|
vp9_set_mv_search_range(x, &ref_mv.as_mv);
|
2013-06-14 00:10:42 +02:00
|
|
|
|
2013-07-03 23:43:23 +02:00
|
|
|
// Adjust search parameters based on small partitions' result.
|
|
|
|
if (x->fast_ms) {
|
|
|
|
// adjust search range
|
|
|
|
step_param = 6;
|
|
|
|
if (x->fast_ms > 1)
|
|
|
|
step_param = 8;
|
2013-06-26 18:06:25 +02:00
|
|
|
} else {
|
2013-07-03 23:43:23 +02:00
|
|
|
// Work out the size of the first step in the mv step search.
|
|
|
|
// 0 here is maximum length first step. 1 is MAX >> 1 etc.
|
|
|
|
if (cpi->sf.auto_mv_step_size && cpi->common.show_frame) {
|
2013-07-12 18:52:24 +02:00
|
|
|
// 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;
|
2013-07-03 23:43:23 +02:00
|
|
|
} else {
|
2013-07-12 18:52:24 +02:00
|
|
|
step_param = cpi->mv_step_param;
|
2013-07-03 23:43:23 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-14 00:10:42 +02:00
|
|
|
|
2013-09-12 19:06:47 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search && bsize < BLOCK_64X64 &&
|
|
|
|
cpi->common.show_frame) {
|
|
|
|
int boffset = 2 * (b_width_log2(BLOCK_64X64) - MIN(b_height_log2(bsize),
|
|
|
|
b_width_log2(bsize)));
|
|
|
|
step_param = MAX(step_param, boffset);
|
|
|
|
}
|
|
|
|
|
2013-12-21 00:24:22 +01:00
|
|
|
if (cpi->sf.adaptive_motion_search) {
|
|
|
|
int bwl = b_width_log2_lookup[bsize];
|
|
|
|
int bhl = b_height_log2_lookup[bsize];
|
|
|
|
int i;
|
|
|
|
int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
|
|
|
|
|
|
|
|
if (tlevel < 5)
|
|
|
|
step_param += 2;
|
|
|
|
|
|
|
|
for (i = LAST_FRAME; i <= ALTREF_FRAME && cpi->common.show_frame; ++i) {
|
|
|
|
if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
|
|
|
|
x->pred_mv[ref].as_int = 0;
|
|
|
|
tmp_mv->as_int = INVALID_MV;
|
|
|
|
|
|
|
|
if (scaled_ref_frame) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++)
|
|
|
|
xd->plane[i].pre[0] = backup_yv12[i];
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-07 03:07:12 +01:00
|
|
|
mvp_full = x->mv_best_ref_index[ref] < MAX_MV_REF_CANDIDATES
|
|
|
|
? mbmi->ref_mvs[ref][x->mv_best_ref_index[ref]].as_mv
|
|
|
|
: x->pred_mv[ref].as_mv;
|
2013-09-12 19:06:47 +02:00
|
|
|
|
2014-01-07 03:07:12 +01:00
|
|
|
mvp_full.col >>= 3;
|
|
|
|
mvp_full.row >>= 3;
|
2013-06-14 00:10:42 +02:00
|
|
|
|
|
|
|
// Further step/diamond searches as necessary
|
|
|
|
further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
|
|
|
|
|
2013-07-22 23:47:57 +02:00
|
|
|
if (cpi->sf.search_method == HEX) {
|
2014-01-07 03:07:12 +01:00
|
|
|
bestsme = vp9_hex_search(x, &mvp_full, step_param, sadpb, 1,
|
2013-12-05 02:22:32 +01:00
|
|
|
&cpi->fn_ptr[bsize], 1,
|
2013-09-26 01:44:19 +02:00
|
|
|
&ref_mv.as_mv, &tmp_mv->as_mv);
|
2013-07-22 23:47:57 +02:00
|
|
|
} else if (cpi->sf.search_method == SQUARE) {
|
2014-01-07 03:07:12 +01:00
|
|
|
bestsme = vp9_square_search(x, &mvp_full, step_param, sadpb, 1,
|
2013-12-05 02:22:32 +01:00
|
|
|
&cpi->fn_ptr[bsize], 1,
|
2013-09-26 01:44:19 +02:00
|
|
|
&ref_mv.as_mv, &tmp_mv->as_mv);
|
2013-07-22 23:47:57 +02:00
|
|
|
} else if (cpi->sf.search_method == BIGDIA) {
|
2014-01-07 03:07:12 +01:00
|
|
|
bestsme = vp9_bigdia_search(x, &mvp_full, step_param, sadpb, 1,
|
2013-12-05 02:22:32 +01:00
|
|
|
&cpi->fn_ptr[bsize], 1,
|
2013-09-26 01:44:19 +02:00
|
|
|
&ref_mv.as_mv, &tmp_mv->as_mv);
|
2013-07-22 23:47:57 +02:00
|
|
|
} else {
|
2014-01-07 03:07:12 +01:00
|
|
|
bestsme = vp9_full_pixel_diamond(cpi, x, &mvp_full, step_param,
|
2013-07-22 23:47:57 +02:00
|
|
|
sadpb, further_steps, 1,
|
2013-12-05 02:22:32 +01:00
|
|
|
&cpi->fn_ptr[bsize],
|
2014-01-03 20:48:07 +01:00
|
|
|
&ref_mv.as_mv, tmp_mv);
|
2013-07-22 23:47:57 +02:00
|
|
|
}
|
2013-06-14 00:10:42 +02:00
|
|
|
|
|
|
|
x->mv_col_min = tmp_col_min;
|
|
|
|
x->mv_col_max = tmp_col_max;
|
|
|
|
x->mv_row_min = tmp_row_min;
|
|
|
|
x->mv_row_max = tmp_row_max;
|
|
|
|
|
|
|
|
if (bestsme < INT_MAX) {
|
2013-07-22 23:47:57 +02:00
|
|
|
int dis; /* TODO: use dis in distortion calculation later. */
|
2013-09-24 21:48:12 +02:00
|
|
|
cpi->find_fractional_mv_step(x, &tmp_mv->as_mv, &ref_mv.as_mv,
|
2013-10-21 19:12:14 +02:00
|
|
|
cm->allow_high_precision_mv,
|
2013-06-14 00:10:42 +02:00
|
|
|
x->errorperbit,
|
2013-12-05 02:22:32 +01:00
|
|
|
&cpi->fn_ptr[bsize],
|
2013-08-07 00:53:35 +02:00
|
|
|
0, cpi->sf.subpel_iters_per_step,
|
2013-06-14 00:10:42 +02:00
|
|
|
x->nmvjointcost, x->mvcost,
|
2013-12-21 00:24:22 +01:00
|
|
|
&dis, &x->pred_sse[ref]);
|
2013-06-14 00:10:42 +02:00
|
|
|
}
|
2013-09-20 11:52:43 +02:00
|
|
|
*rate_mv = vp9_mv_bit_cost(&tmp_mv->as_mv, &ref_mv.as_mv,
|
2013-10-09 20:32:03 +02:00
|
|
|
x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
|
2013-09-12 19:06:47 +02:00
|
|
|
|
|
|
|
if (cpi->sf.adaptive_motion_search && cpi->common.show_frame)
|
|
|
|
x->pred_mv[ref].as_int = tmp_mv->as_int;
|
|
|
|
|
2013-06-14 00:10:42 +02:00
|
|
|
if (scaled_ref_frame) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++)
|
|
|
|
xd->plane[i].pre[0] = backup_yv12[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize,
|
2013-06-14 00:10:42 +02:00
|
|
|
int_mv *frame_mv,
|
|
|
|
int mi_row, int mi_col,
|
|
|
|
int_mv single_newmv[MAX_REF_FRAMES],
|
|
|
|
int *rate_mv) {
|
2013-12-06 21:04:06 +01:00
|
|
|
const int pw = 4 * num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int ph = 4 * num_4x4_blocks_high_lookup[bsize];
|
2013-05-28 23:02:29 +02:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-11-12 01:04:02 +01:00
|
|
|
const int refs[2] = { mbmi->ref_frame[0],
|
|
|
|
mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1] };
|
2013-05-28 23:02:29 +02:00
|
|
|
int_mv ref_mv[2];
|
2013-11-12 01:04:02 +01:00
|
|
|
int ite, ref;
|
2013-05-28 23:02:29 +02:00
|
|
|
// Prediction buffer from second frame.
|
|
|
|
uint8_t *second_pred = vpx_memalign(16, pw * ph * sizeof(uint8_t));
|
|
|
|
|
|
|
|
// Do joint motion search in compound mode to get more accurate mv.
|
2013-11-12 01:04:02 +01:00
|
|
|
struct buf_2d backup_yv12[2][MAX_MB_PLANE];
|
|
|
|
struct buf_2d scaled_first_yv12 = xd->plane[0].pre[0];
|
2013-05-28 23:02:29 +02:00
|
|
|
int last_besterr[2] = {INT_MAX, INT_MAX};
|
2013-11-12 01:04:02 +01:00
|
|
|
YV12_BUFFER_CONFIG *const scaled_ref_frame[2] = {
|
|
|
|
get_scaled_ref_frame(cpi, mbmi->ref_frame[0]),
|
|
|
|
get_scaled_ref_frame(cpi, mbmi->ref_frame[1])
|
|
|
|
};
|
2013-05-28 23:02:29 +02:00
|
|
|
|
2013-11-12 01:04:02 +01:00
|
|
|
for (ref = 0; ref < 2; ++ref) {
|
|
|
|
ref_mv[ref] = mbmi->ref_mvs[refs[ref]][0];
|
|
|
|
|
|
|
|
if (scaled_ref_frame[ref]) {
|
|
|
|
int i;
|
|
|
|
// Swap out the reference frame for a version that's been scaled to
|
|
|
|
// match the resolution of the current frame, allowing the existing
|
|
|
|
// motion search code to be used without additional modifications.
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++)
|
|
|
|
backup_yv12[ref][i] = xd->plane[i].pre[ref];
|
|
|
|
setup_pre_planes(xd, ref, scaled_ref_frame[ref], mi_row, mi_col, NULL);
|
|
|
|
}
|
2013-05-28 23:02:29 +02:00
|
|
|
|
2013-11-12 01:04:02 +01:00
|
|
|
frame_mv[refs[ref]].as_int = single_newmv[refs[ref]].as_int;
|
2013-05-28 23:02:29 +02:00
|
|
|
}
|
2013-05-29 21:52:57 +02:00
|
|
|
|
2013-05-28 23:02:29 +02:00
|
|
|
// Allow joint search multiple times iteratively for each ref frame
|
|
|
|
// and break out the search loop if it couldn't find better mv.
|
|
|
|
for (ite = 0; ite < 4; ite++) {
|
|
|
|
struct buf_2d ref_yv12[2];
|
|
|
|
int bestsme = INT_MAX;
|
|
|
|
int sadpb = x->sadperbit16;
|
|
|
|
int_mv tmp_mv;
|
|
|
|
int search_range = 3;
|
|
|
|
|
|
|
|
int tmp_col_min = x->mv_col_min;
|
|
|
|
int tmp_col_max = x->mv_col_max;
|
|
|
|
int tmp_row_min = x->mv_row_min;
|
|
|
|
int tmp_row_max = x->mv_row_max;
|
|
|
|
int id = ite % 2;
|
|
|
|
|
|
|
|
// Initialized here because of compiler problem in Visual Studio.
|
|
|
|
ref_yv12[0] = xd->plane[0].pre[0];
|
|
|
|
ref_yv12[1] = xd->plane[0].pre[1];
|
|
|
|
|
|
|
|
// Get pred block from second frame.
|
|
|
|
vp9_build_inter_predictor(ref_yv12[!id].buf,
|
|
|
|
ref_yv12[!id].stride,
|
|
|
|
second_pred, pw,
|
2013-08-03 00:26:32 +02:00
|
|
|
&frame_mv[refs[!id]].as_mv,
|
2013-12-28 03:44:19 +01:00
|
|
|
&xd->block_refs[!id]->sf,
|
2013-05-28 23:02:29 +02:00
|
|
|
pw, ph, 0,
|
2013-12-19 20:16:05 +01:00
|
|
|
&xd->subpix, MV_PRECISION_Q3,
|
|
|
|
mi_col * MI_SIZE, mi_row * MI_SIZE);
|
2013-05-28 23:02:29 +02:00
|
|
|
|
|
|
|
// Compound motion search on first ref frame.
|
|
|
|
if (id)
|
|
|
|
xd->plane[0].pre[0] = ref_yv12[id];
|
2013-12-11 22:59:10 +01:00
|
|
|
vp9_set_mv_search_range(x, &ref_mv[id].as_mv);
|
2013-05-28 23:02:29 +02:00
|
|
|
|
|
|
|
// Use mv result from single mode as mvp.
|
|
|
|
tmp_mv.as_int = frame_mv[refs[id]].as_int;
|
|
|
|
|
|
|
|
tmp_mv.as_mv.col >>= 3;
|
|
|
|
tmp_mv.as_mv.row >>= 3;
|
|
|
|
|
|
|
|
// Small-range full-pixel motion search
|
2013-12-14 02:20:40 +01:00
|
|
|
bestsme = vp9_refining_search_8p_c(x, &tmp_mv.as_mv, sadpb,
|
2013-05-28 23:02:29 +02:00
|
|
|
search_range,
|
2013-12-05 02:22:32 +01:00
|
|
|
&cpi->fn_ptr[bsize],
|
2013-05-28 23:02:29 +02:00
|
|
|
x->nmvjointcost, x->mvcost,
|
2013-12-14 02:20:40 +01:00
|
|
|
&ref_mv[id].as_mv, second_pred,
|
2013-05-28 23:02:29 +02:00
|
|
|
pw, ph);
|
|
|
|
|
|
|
|
x->mv_col_min = tmp_col_min;
|
|
|
|
x->mv_col_max = tmp_col_max;
|
|
|
|
x->mv_row_min = tmp_row_min;
|
|
|
|
x->mv_row_max = tmp_row_max;
|
|
|
|
|
|
|
|
if (bestsme < INT_MAX) {
|
|
|
|
int dis; /* TODO: use dis in distortion calculation later. */
|
2013-12-21 00:24:22 +01:00
|
|
|
unsigned int sse;
|
2013-08-08 02:01:43 +02:00
|
|
|
bestsme = cpi->find_fractional_mv_step_comp(
|
2013-09-24 21:48:12 +02:00
|
|
|
x, &tmp_mv.as_mv,
|
|
|
|
&ref_mv[id].as_mv,
|
2013-10-21 19:12:14 +02:00
|
|
|
cpi->common.allow_high_precision_mv,
|
2013-08-07 00:53:35 +02:00
|
|
|
x->errorperbit,
|
2013-12-05 02:22:32 +01:00
|
|
|
&cpi->fn_ptr[bsize],
|
2013-08-07 00:53:35 +02:00
|
|
|
0, cpi->sf.subpel_iters_per_step,
|
|
|
|
x->nmvjointcost, x->mvcost,
|
2013-12-21 00:24:22 +01:00
|
|
|
&dis, &sse, second_pred,
|
2013-08-07 00:53:35 +02:00
|
|
|
pw, ph);
|
2013-05-28 23:02:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (id)
|
|
|
|
xd->plane[0].pre[0] = scaled_first_yv12;
|
|
|
|
|
|
|
|
if (bestsme < last_besterr[id]) {
|
2013-05-29 21:52:57 +02:00
|
|
|
frame_mv[refs[id]].as_int = tmp_mv.as_int;
|
2013-05-28 23:02:29 +02:00
|
|
|
last_besterr[id] = bestsme;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-12 01:04:02 +01:00
|
|
|
*rate_mv = 0;
|
2013-05-28 23:02:29 +02:00
|
|
|
|
2013-11-12 01:04:02 +01:00
|
|
|
for (ref = 0; ref < 2; ++ref) {
|
|
|
|
if (scaled_ref_frame[ref]) {
|
|
|
|
// restore the predictor
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++)
|
|
|
|
xd->plane[i].pre[ref] = backup_yv12[ref][i];
|
|
|
|
}
|
|
|
|
|
|
|
|
*rate_mv += vp9_mv_bit_cost(&frame_mv[refs[ref]].as_mv,
|
|
|
|
&mbmi->ref_mvs[refs[ref]][0].as_mv,
|
|
|
|
x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
|
2013-05-28 23:02:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
vpx_free(second_pred);
|
|
|
|
}
|
|
|
|
|
2013-11-20 00:29:22 +01:00
|
|
|
static INLINE void restore_dst_buf(MACROBLOCKD *xd,
|
|
|
|
uint8_t *orig_dst[MAX_MB_PLANE],
|
|
|
|
int orig_dst_stride[MAX_MB_PLANE]) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++) {
|
|
|
|
xd->plane[i].dst.buf = orig_dst[i];
|
|
|
|
xd->plane[i].dst.stride = orig_dst_stride[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-10-25 17:18:04 +02:00
|
|
|
const TileInfo *const tile,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize,
|
2013-05-09 01:27:35 +02:00
|
|
|
int64_t txfm_cache[],
|
2013-06-21 21:54:52 +02:00
|
|
|
int *rate2, int64_t *distortion,
|
|
|
|
int *skippable,
|
|
|
|
int *rate_y, int64_t *distortion_y,
|
|
|
|
int *rate_uv, int64_t *distortion_uv,
|
2013-05-05 07:09:43 +02:00
|
|
|
int *mode_excluded, int *disable_skip,
|
2013-10-24 02:45:52 +02:00
|
|
|
INTERPOLATION_TYPE *best_filter,
|
2013-07-17 20:33:15 +02:00
|
|
|
int_mv (*mode_mv)[MAX_REF_FRAMES],
|
2013-05-07 18:45:28 +02:00
|
|
|
int mi_row, int mi_col,
|
2013-06-28 02:41:54 +02:00
|
|
|
int_mv single_newmv[MAX_REF_FRAMES],
|
2013-08-15 01:50:45 +02:00
|
|
|
int64_t *psse,
|
|
|
|
const int64_t ref_best_rd) {
|
2013-05-05 07:09:43 +02:00
|
|
|
VP9_COMMON *cm = &cpi->common;
|
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-09-26 04:03:04 +02:00
|
|
|
const int is_comp_pred = has_second_ref(mbmi);
|
2013-05-05 07:09:43 +02:00
|
|
|
const int num_refs = is_comp_pred ? 2 : 1;
|
|
|
|
const int this_mode = mbmi->mode;
|
2013-07-17 20:33:15 +02:00
|
|
|
int_mv *frame_mv = mode_mv[this_mode];
|
2013-05-05 07:09:43 +02:00
|
|
|
int i;
|
2013-06-06 22:44:34 +02:00
|
|
|
int refs[2] = { mbmi->ref_frame[0],
|
2013-06-14 00:10:42 +02:00
|
|
|
(mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
|
2013-05-05 07:09:43 +02:00
|
|
|
int_mv cur_mv[2];
|
|
|
|
int64_t this_rd = 0;
|
2013-07-10 18:26:32 +02:00
|
|
|
DECLARE_ALIGNED_ARRAY(16, uint8_t, tmp_buf, MAX_MB_PLANE * 64 * 64);
|
2013-05-05 07:09:43 +02:00
|
|
|
int pred_exists = 0;
|
|
|
|
int intpel_mv;
|
|
|
|
int64_t rd, best_rd = INT64_MAX;
|
2013-07-10 18:26:32 +02:00
|
|
|
int best_needs_copy = 0;
|
|
|
|
uint8_t *orig_dst[MAX_MB_PLANE];
|
|
|
|
int orig_dst_stride[MAX_MB_PLANE];
|
2013-07-09 01:01:01 +02:00
|
|
|
int rs = 0;
|
2010-12-06 22:42:52 +01:00
|
|
|
|
2013-11-05 03:45:45 +01:00
|
|
|
if (is_comp_pred) {
|
|
|
|
if (frame_mv[refs[0]].as_int == INVALID_MV ||
|
|
|
|
frame_mv[refs[1]].as_int == INVALID_MV)
|
|
|
|
return INT64_MAX;
|
|
|
|
}
|
|
|
|
|
2013-07-30 19:16:03 +02:00
|
|
|
if (this_mode == NEWMV) {
|
2013-06-14 00:10:42 +02:00
|
|
|
int rate_mv;
|
2013-07-30 19:16:03 +02:00
|
|
|
if (is_comp_pred) {
|
|
|
|
// Initialize mv using single prediction mode result.
|
|
|
|
frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
|
|
|
|
frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int;
|
|
|
|
|
|
|
|
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
|
|
|
|
joint_motion_search(cpi, x, bsize, frame_mv,
|
|
|
|
mi_row, mi_col, single_newmv, &rate_mv);
|
2013-06-14 00:10:42 +02:00
|
|
|
} else {
|
2013-09-20 11:52:43 +02:00
|
|
|
rate_mv = vp9_mv_bit_cost(&frame_mv[refs[0]].as_mv,
|
|
|
|
&mbmi->ref_mvs[refs[0]][0].as_mv,
|
2013-10-09 20:32:03 +02:00
|
|
|
x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
|
2013-09-20 11:52:43 +02:00
|
|
|
rate_mv += vp9_mv_bit_cost(&frame_mv[refs[1]].as_mv,
|
|
|
|
&mbmi->ref_mvs[refs[1]][0].as_mv,
|
2013-10-09 20:32:03 +02:00
|
|
|
x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2013-07-30 19:16:03 +02:00
|
|
|
*rate2 += rate_mv;
|
|
|
|
} else {
|
|
|
|
int_mv tmp_mv;
|
2013-10-25 17:18:04 +02:00
|
|
|
single_motion_search(cpi, x, tile, bsize, mi_row, mi_col,
|
|
|
|
&tmp_mv, &rate_mv);
|
2013-07-30 19:16:03 +02:00
|
|
|
*rate2 += rate_mv;
|
|
|
|
frame_mv[refs[0]].as_int =
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->bmi[0].as_mv[0].as_int = tmp_mv.as_int;
|
2013-07-30 19:16:03 +02:00
|
|
|
single_newmv[refs[0]].as_int = tmp_mv.as_int;
|
|
|
|
}
|
2013-05-05 07:09:43 +02:00
|
|
|
}
|
2013-07-17 20:33:15 +02:00
|
|
|
|
|
|
|
// if we're near/nearest and mv == 0,0, compare to zeromv
|
|
|
|
if ((this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
|
|
|
|
frame_mv[refs[0]].as_int == 0 &&
|
2013-08-14 20:20:33 +02:00
|
|
|
!vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP) &&
|
2013-07-17 20:33:15 +02:00
|
|
|
(num_refs == 1 || frame_mv[refs[1]].as_int == 0)) {
|
2013-08-13 18:47:40 +02:00
|
|
|
int rfc = mbmi->mode_context[mbmi->ref_frame[0]];
|
2013-07-17 20:33:15 +02:00
|
|
|
int c1 = cost_mv_ref(cpi, NEARMV, rfc);
|
|
|
|
int c2 = cost_mv_ref(cpi, NEARESTMV, rfc);
|
|
|
|
int c3 = cost_mv_ref(cpi, ZEROMV, rfc);
|
|
|
|
|
|
|
|
if (this_mode == NEARMV) {
|
2013-07-18 18:34:59 +02:00
|
|
|
if (c1 > c3)
|
2013-07-17 20:33:15 +02:00
|
|
|
return INT64_MAX;
|
|
|
|
} else if (this_mode == NEARESTMV) {
|
2013-07-18 18:34:59 +02:00
|
|
|
if (c2 > c3)
|
2013-07-17 20:33:15 +02:00
|
|
|
return INT64_MAX;
|
|
|
|
} else {
|
|
|
|
assert(this_mode == ZEROMV);
|
2013-07-18 18:34:59 +02:00
|
|
|
if (num_refs == 1) {
|
|
|
|
if ((c3 >= c2 &&
|
|
|
|
mode_mv[NEARESTMV][mbmi->ref_frame[0]].as_int == 0) ||
|
|
|
|
(c3 >= c1 &&
|
|
|
|
mode_mv[NEARMV][mbmi->ref_frame[0]].as_int == 0))
|
|
|
|
return INT64_MAX;
|
|
|
|
} else {
|
|
|
|
if ((c3 >= c2 &&
|
|
|
|
mode_mv[NEARESTMV][mbmi->ref_frame[0]].as_int == 0 &&
|
|
|
|
mode_mv[NEARESTMV][mbmi->ref_frame[1]].as_int == 0) ||
|
|
|
|
(c3 >= c1 &&
|
|
|
|
mode_mv[NEARMV][mbmi->ref_frame[0]].as_int == 0 &&
|
|
|
|
mode_mv[NEARMV][mbmi->ref_frame[1]].as_int == 0))
|
|
|
|
return INT64_MAX;
|
|
|
|
}
|
2013-07-17 20:33:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
for (i = 0; i < num_refs; ++i) {
|
2013-05-27 23:16:45 +02:00
|
|
|
cur_mv[i] = frame_mv[refs[i]];
|
2013-05-05 07:09:43 +02:00
|
|
|
// Clip "next_nearest" so that it does not extend to far out of image
|
2013-08-01 01:11:03 +02:00
|
|
|
if (this_mode != NEWMV)
|
|
|
|
clamp_mv2(&cur_mv[i].as_mv, xd);
|
2012-12-20 23:56:19 +01:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
if (mv_check_bounds(x, &cur_mv[i]))
|
|
|
|
return INT64_MAX;
|
|
|
|
mbmi->mv[i].as_int = cur_mv[i].as_int;
|
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-07-10 18:26:32 +02:00
|
|
|
// do first prediction into the destination buffer. Do the next
|
|
|
|
// prediction into a temporary buffer. Then keep track of which one
|
|
|
|
// of these currently holds the best predictor, and use the other
|
|
|
|
// one for future predictions. In the end, copy from tmp_buf to
|
|
|
|
// dst if necessary.
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++) {
|
|
|
|
orig_dst[i] = xd->plane[i].dst.buf;
|
|
|
|
orig_dst_stride[i] = xd->plane[i].dst.stride;
|
|
|
|
}
|
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
/* We don't include the cost of the second reference here, because there
|
|
|
|
* are only three options: Last/Golden, ARF/Last or Golden/ARF, or in other
|
|
|
|
* words if you present them in that order, the second one is always known
|
|
|
|
* if the first is known */
|
2013-07-03 19:54:36 +02:00
|
|
|
*rate2 += cost_mv_ref(cpi, this_mode,
|
2013-08-13 18:47:40 +02:00
|
|
|
mbmi->mode_context[mbmi->ref_frame[0]]);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
if (!(*mode_excluded))
|
2014-01-07 02:29:16 +01:00
|
|
|
*mode_excluded = is_comp_pred ? cm->reference_mode == SINGLE_REFERENCE
|
|
|
|
: cm->reference_mode == COMPOUND_REFERENCE;
|
2013-07-09 01:01:01 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
pred_exists = 0;
|
|
|
|
// Are all MVs integer pel for Y and UV
|
|
|
|
intpel_mv = (mbmi->mv[0].as_mv.row & 15) == 0 &&
|
2013-06-14 00:10:42 +02:00
|
|
|
(mbmi->mv[0].as_mv.col & 15) == 0;
|
2013-05-05 07:09:43 +02:00
|
|
|
if (is_comp_pred)
|
|
|
|
intpel_mv &= (mbmi->mv[1].as_mv.row & 15) == 0 &&
|
2013-06-14 00:10:42 +02:00
|
|
|
(mbmi->mv[1].as_mv.col & 15) == 0;
|
2013-11-20 00:29:22 +01:00
|
|
|
|
2013-12-13 21:58:49 +01:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Search for best switchable filter by checking the variance of
|
|
|
|
// pred error irrespective of whether the filter will be used
|
2013-12-17 02:52:59 +01:00
|
|
|
cpi->mask_filter_rd = 0;
|
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
|
|
|
|
cpi->rd_filter_cache[i] = INT64_MAX;
|
|
|
|
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
if (cm->mcomp_filter_type != BILINEAR) {
|
2013-05-31 00:13:08 +02:00
|
|
|
*best_filter = EIGHTTAP;
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
if (x->source_variance <
|
|
|
|
cpi->sf.disable_filter_search_var_thresh) {
|
|
|
|
*best_filter = EIGHTTAP;
|
|
|
|
} else {
|
2013-12-13 21:58:49 +01:00
|
|
|
int newbest;
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
int tmp_rate_sum = 0;
|
|
|
|
int64_t tmp_dist_sum = 0;
|
|
|
|
|
2013-08-23 03:40:34 +02:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
int j;
|
|
|
|
int64_t rs_rd;
|
|
|
|
mbmi->interp_filter = i;
|
|
|
|
vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
|
|
|
|
rs = get_switchable_rate(x);
|
|
|
|
rs_rd = RDCOST(x->rdmult, x->rddiv, rs, 0);
|
|
|
|
|
|
|
|
if (i > 0 && intpel_mv) {
|
2013-12-17 02:52:59 +01:00
|
|
|
rd = RDCOST(x->rdmult, x->rddiv, tmp_rate_sum, tmp_dist_sum);
|
|
|
|
cpi->rd_filter_cache[i] = rd;
|
2013-08-23 03:40:34 +02:00
|
|
|
cpi->rd_filter_cache[SWITCHABLE_FILTERS] =
|
2013-12-17 02:52:59 +01:00
|
|
|
MIN(cpi->rd_filter_cache[SWITCHABLE_FILTERS], rd + rs_rd);
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE)
|
|
|
|
rd += rs_rd;
|
2013-12-17 02:52:59 +01:00
|
|
|
cpi->mask_filter_rd = MAX(cpi->mask_filter_rd, rd);
|
2013-07-10 18:26:32 +02:00
|
|
|
} else {
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
int rate_sum = 0;
|
|
|
|
int64_t dist_sum = 0;
|
|
|
|
if ((cm->mcomp_filter_type == SWITCHABLE &&
|
|
|
|
(!i || best_needs_copy)) ||
|
|
|
|
(cm->mcomp_filter_type != SWITCHABLE &&
|
|
|
|
(cm->mcomp_filter_type == mbmi->interp_filter ||
|
|
|
|
(i == 0 && intpel_mv)))) {
|
2013-11-20 00:29:22 +01:00
|
|
|
restore_dst_buf(xd, orig_dst, orig_dst_stride);
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
} else {
|
|
|
|
for (j = 0; j < MAX_MB_PLANE; j++) {
|
|
|
|
xd->plane[j].dst.buf = tmp_buf + j * 64 * 64;
|
|
|
|
xd->plane[j].dst.stride = 64;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
|
|
|
|
model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
|
2013-12-17 02:52:59 +01:00
|
|
|
|
|
|
|
rd = RDCOST(x->rdmult, x->rddiv, rate_sum, dist_sum);
|
|
|
|
cpi->rd_filter_cache[i] = rd;
|
2013-08-23 03:40:34 +02:00
|
|
|
cpi->rd_filter_cache[SWITCHABLE_FILTERS] =
|
2013-12-17 02:52:59 +01:00
|
|
|
MIN(cpi->rd_filter_cache[SWITCHABLE_FILTERS], rd + rs_rd);
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE)
|
|
|
|
rd += rs_rd;
|
2013-12-17 02:52:59 +01:00
|
|
|
cpi->mask_filter_rd = MAX(cpi->mask_filter_rd, rd);
|
|
|
|
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
if (i == 0 && intpel_mv) {
|
|
|
|
tmp_rate_sum = rate_sum;
|
|
|
|
tmp_dist_sum = dist_sum;
|
2013-07-10 18:26:32 +02:00
|
|
|
}
|
|
|
|
}
|
2013-12-17 02:52:59 +01:00
|
|
|
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
if (i == 0 && cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) {
|
|
|
|
if (rd / 2 > ref_best_rd) {
|
2013-11-20 00:29:22 +01:00
|
|
|
restore_dst_buf(xd, orig_dst, orig_dst_stride);
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
return INT64_MAX;
|
2013-07-09 01:01:01 +02:00
|
|
|
}
|
|
|
|
}
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
newbest = i == 0 || rd < best_rd;
|
|
|
|
|
|
|
|
if (newbest) {
|
|
|
|
best_rd = rd;
|
|
|
|
*best_filter = mbmi->interp_filter;
|
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE && i && !intpel_mv)
|
|
|
|
best_needs_copy = !best_needs_copy;
|
|
|
|
}
|
2012-10-09 18:18:21 +02:00
|
|
|
|
Cleanup/enhancements of switchable filter search
Cleans up the switchable filter search logic. Also adds a
speed feature - a variance threshold - to disable filter search
if source variance is lower than this value.
Results: derfraw300
threshold = 16, psnr -0.238%, 4-5% speedup (tested on football)
threshold = 32, psnr -0.381%, 8-9% speedup (tested on football)
threshold = 64, psnr -0.611%, 12-13% speedup (tested on football)
threshold = 96, psnr -0.804%, 16-17% speedup (tested on football)
Based on these results, the threshold is chosen as 16 for speed 1,
32 for speed 2, 64 for speed 3 and 96 for speed 4.
Change-Id: Ib630d39192773b1983d3d349b97973768e170c04
2013-08-16 22:51:00 +02:00
|
|
|
if ((cm->mcomp_filter_type == SWITCHABLE && newbest) ||
|
|
|
|
(cm->mcomp_filter_type != SWITCHABLE &&
|
|
|
|
cm->mcomp_filter_type == mbmi->interp_filter)) {
|
|
|
|
pred_exists = 1;
|
|
|
|
}
|
2012-10-09 18:18:21 +02:00
|
|
|
}
|
2013-11-20 00:29:22 +01:00
|
|
|
restore_dst_buf(xd, orig_dst, orig_dst_stride);
|
2013-07-10 18:26:32 +02:00
|
|
|
}
|
2013-02-12 02:08:52 +01:00
|
|
|
}
|
2013-07-30 19:16:03 +02:00
|
|
|
// Set the appropriate filter
|
2013-05-05 07:09:43 +02:00
|
|
|
mbmi->interp_filter = cm->mcomp_filter_type != SWITCHABLE ?
|
2013-06-14 00:10:42 +02:00
|
|
|
cm->mcomp_filter_type : *best_filter;
|
2013-05-05 07:09:43 +02:00
|
|
|
vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
|
2013-08-01 01:59:15 +02:00
|
|
|
rs = cm->mcomp_filter_type == SWITCHABLE ? get_switchable_rate(x) : 0;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
if (pred_exists) {
|
2013-07-10 18:26:32 +02:00
|
|
|
if (best_needs_copy) {
|
|
|
|
// again temporarily set the buffers to local memory to prevent a memcpy
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++) {
|
|
|
|
xd->plane[i].dst.buf = tmp_buf + i * 64 * 64;
|
|
|
|
xd->plane[i].dst.stride = 64;
|
|
|
|
}
|
2013-05-07 20:49:21 +02:00
|
|
|
}
|
2013-05-05 07:09:43 +02:00
|
|
|
} else {
|
|
|
|
// Handles the special case when a filter that is not in the
|
|
|
|
// switchable list (ex. bilinear, 6-tap) is indicated at the frame level
|
|
|
|
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-07-09 01:01:01 +02:00
|
|
|
if (cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) {
|
|
|
|
int tmp_rate;
|
|
|
|
int64_t tmp_dist;
|
|
|
|
model_rd_for_sb(cpi, bsize, x, xd, &tmp_rate, &tmp_dist);
|
|
|
|
rd = RDCOST(x->rdmult, x->rddiv, rs + tmp_rate, tmp_dist);
|
|
|
|
// if current pred_error modeled rd is substantially more than the best
|
|
|
|
// so far, do not bother doing full rd
|
|
|
|
if (rd / 2 > ref_best_rd) {
|
2013-11-20 00:29:22 +01:00
|
|
|
restore_dst_buf(xd, orig_dst, orig_dst_stride);
|
2013-07-09 01:01:01 +02:00
|
|
|
return INT64_MAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-07 02:29:16 +01:00
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE)
|
2013-08-01 01:59:15 +02:00
|
|
|
*rate2 += get_switchable_rate(x);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-09-06 02:10:58 +02:00
|
|
|
if (!is_comp_pred && cpi->enable_encode_breakout) {
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
if (cpi->active_map_enabled && x->active_ptr[0] == 0)
|
|
|
|
x->skip = 1;
|
|
|
|
else if (x->encode_breakout) {
|
2013-08-27 20:05:08 +02:00
|
|
|
const BLOCK_SIZE y_size = get_plane_block_size(bsize, &xd->plane[0]);
|
|
|
|
const BLOCK_SIZE uv_size = get_plane_block_size(bsize, &xd->plane[1]);
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
unsigned int var, sse;
|
|
|
|
// Skipping threshold for ac.
|
|
|
|
unsigned int thresh_ac;
|
|
|
|
// The encode_breakout input
|
|
|
|
unsigned int encode_breakout = x->encode_breakout << 4;
|
2013-09-17 18:45:13 +02:00
|
|
|
unsigned int max_thresh = 36000;
|
2013-09-06 02:10:58 +02:00
|
|
|
|
|
|
|
// Use extreme low threshold for static frames to limit skipping.
|
|
|
|
if (cpi->enable_encode_breakout == 2)
|
|
|
|
max_thresh = 128;
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
|
2013-07-26 04:17:46 +02:00
|
|
|
// Calculate threshold according to dequant value.
|
|
|
|
thresh_ac = (xd->plane[0].dequant[1] * xd->plane[0].dequant[1]) / 9;
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
|
|
|
|
// Use encode_breakout input if it is bigger than internal threshold.
|
|
|
|
if (thresh_ac < encode_breakout)
|
|
|
|
thresh_ac = encode_breakout;
|
|
|
|
|
2013-09-06 02:10:58 +02:00
|
|
|
// Set a maximum for threshold to avoid big PSNR loss in low bitrate case.
|
|
|
|
if (thresh_ac > max_thresh)
|
|
|
|
thresh_ac = max_thresh;
|
|
|
|
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
var = cpi->fn_ptr[y_size].vf(x->plane[0].src.buf, x->plane[0].src.stride,
|
|
|
|
xd->plane[0].dst.buf,
|
|
|
|
xd->plane[0].dst.stride, &sse);
|
|
|
|
|
|
|
|
// Adjust threshold according to partition size.
|
|
|
|
thresh_ac >>= 8 - (b_width_log2_lookup[bsize] +
|
|
|
|
b_height_log2_lookup[bsize]);
|
|
|
|
|
|
|
|
// Y skipping condition checking
|
|
|
|
if (sse < thresh_ac || sse == 0) {
|
|
|
|
// Skipping threshold for dc
|
|
|
|
unsigned int thresh_dc;
|
|
|
|
|
|
|
|
thresh_dc = (xd->plane[0].dequant[0] * xd->plane[0].dequant[0] >> 6);
|
|
|
|
|
|
|
|
// dc skipping checking
|
|
|
|
if ((sse - var) < thresh_dc || sse == var) {
|
|
|
|
unsigned int sse_u, sse_v;
|
|
|
|
unsigned int var_u, var_v;
|
|
|
|
|
|
|
|
var_u = cpi->fn_ptr[uv_size].vf(x->plane[1].src.buf,
|
|
|
|
x->plane[1].src.stride,
|
|
|
|
xd->plane[1].dst.buf,
|
|
|
|
xd->plane[1].dst.stride, &sse_u);
|
|
|
|
|
|
|
|
// U skipping condition checking
|
|
|
|
if ((sse_u * 4 < thresh_ac || sse_u == 0) &&
|
|
|
|
(sse_u - var_u < thresh_dc || sse_u == var_u)) {
|
|
|
|
var_v = cpi->fn_ptr[uv_size].vf(x->plane[2].src.buf,
|
|
|
|
x->plane[2].src.stride,
|
|
|
|
xd->plane[2].dst.buf,
|
|
|
|
xd->plane[2].dst.stride, &sse_v);
|
|
|
|
|
|
|
|
// V skipping condition checking
|
|
|
|
if ((sse_v * 4 < thresh_ac || sse_v == 0) &&
|
|
|
|
(sse_v - var_v < thresh_dc || sse_v == var_v)) {
|
|
|
|
x->skip = 1;
|
|
|
|
|
2013-08-31 00:19:49 +02:00
|
|
|
// The cost of skip bit needs to be added.
|
2013-12-10 23:11:26 +01:00
|
|
|
*rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
|
|
|
|
// Scaling factor for SSE from spatial domain to frequency domain
|
|
|
|
// is 16. Adjust distortion accordingly.
|
|
|
|
*distortion_uv = (sse_u + sse_v) << 4;
|
|
|
|
*distortion = (sse << 4) + *distortion_uv;
|
|
|
|
|
|
|
|
*disable_skip = 1;
|
|
|
|
this_rd = RDCOST(x->rdmult, x->rddiv, *rate2, *distortion);
|
|
|
|
}
|
|
|
|
}
|
2013-05-05 07:09:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-08-10 03:25:29 +02:00
|
|
|
}
|
|
|
|
|
2012-10-09 18:18:21 +02:00
|
|
|
if (!x->skip) {
|
2013-05-05 07:09:43 +02:00
|
|
|
int skippable_y, skippable_uv;
|
2013-08-15 01:50:45 +02:00
|
|
|
int64_t sseuv = INT64_MAX;
|
|
|
|
int64_t rdcosty = INT64_MAX;
|
2012-10-09 18:18:21 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
// Y cost and distortion
|
2013-06-28 02:41:54 +02:00
|
|
|
super_block_yrd(cpi, x, rate_y, distortion_y, &skippable_y, psse,
|
2013-07-03 01:48:15 +02:00
|
|
|
bsize, txfm_cache, ref_best_rd);
|
|
|
|
|
|
|
|
if (*rate_y == INT_MAX) {
|
|
|
|
*rate2 = INT_MAX;
|
|
|
|
*distortion = INT64_MAX;
|
2013-11-20 00:29:22 +01:00
|
|
|
restore_dst_buf(xd, orig_dst, orig_dst_stride);
|
2013-07-03 01:48:15 +02:00
|
|
|
return INT64_MAX;
|
|
|
|
}
|
2013-05-31 00:13:08 +02:00
|
|
|
|
2013-05-05 07:09:43 +02:00
|
|
|
*rate2 += *rate_y;
|
|
|
|
*distortion += *distortion_y;
|
2013-04-23 00:42:41 +02:00
|
|
|
|
2013-08-15 01:50:45 +02:00
|
|
|
rdcosty = RDCOST(x->rdmult, x->rddiv, *rate2, *distortion);
|
|
|
|
rdcosty = MIN(rdcosty, RDCOST(x->rdmult, x->rddiv, 0, *psse));
|
|
|
|
|
2013-10-10 19:37:40 +02:00
|
|
|
super_block_uvrd(cpi, x, rate_uv, distortion_uv, &skippable_uv, &sseuv,
|
2013-08-15 01:50:45 +02:00
|
|
|
bsize, ref_best_rd - rdcosty);
|
|
|
|
if (*rate_uv == INT_MAX) {
|
|
|
|
*rate2 = INT_MAX;
|
|
|
|
*distortion = INT64_MAX;
|
2013-11-20 00:29:22 +01:00
|
|
|
restore_dst_buf(xd, orig_dst, orig_dst_stride);
|
2013-08-15 01:50:45 +02:00
|
|
|
return INT64_MAX;
|
|
|
|
}
|
2013-04-23 00:42:41 +02:00
|
|
|
|
2013-06-28 02:41:54 +02:00
|
|
|
*psse += sseuv;
|
2013-05-05 07:09:43 +02:00
|
|
|
*rate2 += *rate_uv;
|
|
|
|
*distortion += *distortion_uv;
|
|
|
|
*skippable = skippable_y && skippable_uv;
|
2013-04-23 00:42:41 +02:00
|
|
|
}
|
|
|
|
|
2013-11-20 00:29:22 +01:00
|
|
|
restore_dst_buf(xd, orig_dst, orig_dst_stride);
|
2013-05-05 07:09:43 +02:00
|
|
|
return this_rd; // if 0, this will be re-calculated by caller
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2013-11-07 23:56:58 +01:00
|
|
|
static void swap_block_ptr(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
|
|
|
|
int max_plane) {
|
2013-11-06 06:07:08 +01:00
|
|
|
struct macroblock_plane *const p = x->plane;
|
|
|
|
struct macroblockd_plane *const pd = x->e_mbd.plane;
|
2013-11-07 23:56:58 +01:00
|
|
|
int i;
|
2013-11-06 06:07:08 +01:00
|
|
|
|
2013-11-07 23:56:58 +01:00
|
|
|
for (i = 0; i < max_plane; ++i) {
|
2013-11-06 06:07:08 +01:00
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][1];
|
2013-11-27 03:52:10 +01:00
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][1];
|
2013-11-06 06:07:08 +01:00
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][1];
|
2013-12-04 02:59:32 +01:00
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][1];
|
2013-11-06 06:07:08 +01:00
|
|
|
|
|
|
|
ctx->coeff_pbuf[i][1] = ctx->coeff_pbuf[i][0];
|
|
|
|
ctx->qcoeff_pbuf[i][1] = ctx->qcoeff_pbuf[i][0];
|
|
|
|
ctx->dqcoeff_pbuf[i][1] = ctx->dqcoeff_pbuf[i][0];
|
|
|
|
ctx->eobs_pbuf[i][1] = ctx->eobs_pbuf[i][0];
|
|
|
|
|
|
|
|
ctx->coeff_pbuf[i][0] = p[i].coeff;
|
2013-11-27 03:52:10 +01:00
|
|
|
ctx->qcoeff_pbuf[i][0] = p[i].qcoeff;
|
2013-11-06 06:07:08 +01:00
|
|
|
ctx->dqcoeff_pbuf[i][0] = pd[i].dqcoeff;
|
2013-12-04 02:59:32 +01:00
|
|
|
ctx->eobs_pbuf[i][0] = p[i].eobs;
|
2013-11-06 06:07:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-11 00:55:59 +02:00
|
|
|
void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-06-21 21:54:52 +02:00
|
|
|
int *returnrate, int64_t *returndist,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize,
|
2013-07-17 18:56:46 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx, int64_t best_rd) {
|
2013-07-18 03:21:41 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
|
|
|
int rate_y = 0, rate_uv = 0, rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
|
2013-09-11 19:45:44 +02:00
|
|
|
int y_skip = 0, uv_skip = 0;
|
2013-08-03 02:28:23 +02:00
|
|
|
int64_t dist_y = 0, dist_uv = 0, tx_cache[TX_MODES] = { 0 };
|
2013-12-09 20:03:02 +01:00
|
|
|
TX_SIZE max_uv_tx_size;
|
2013-07-09 01:48:47 +02:00
|
|
|
x->skip_encode = 0;
|
2013-04-15 21:50:32 +02:00
|
|
|
ctx->skip = 0;
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->mbmi.ref_frame[0] = INTRA_FRAME;
|
2013-12-09 20:03:02 +01:00
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize >= BLOCK_8X8) {
|
2013-07-18 03:21:41 +02:00
|
|
|
if (rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly,
|
2013-08-03 02:28:23 +02:00
|
|
|
&dist_y, &y_skip, bsize, tx_cache,
|
2013-07-18 03:21:41 +02:00
|
|
|
best_rd) >= best_rd) {
|
|
|
|
*returnrate = INT_MAX;
|
|
|
|
return;
|
|
|
|
}
|
2013-12-09 20:03:02 +01:00
|
|
|
max_uv_tx_size = get_uv_tx_size_impl(xd->mi_8x8[0]->mbmi.tx_size, bsize);
|
2013-11-07 23:56:58 +01:00
|
|
|
rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv, &rate_uv_tokenonly,
|
2013-12-09 20:03:02 +01:00
|
|
|
&dist_uv, &uv_skip, bsize, max_uv_tx_size);
|
2013-07-18 03:21:41 +02:00
|
|
|
} else {
|
|
|
|
y_skip = 0;
|
2013-07-31 21:58:19 +02:00
|
|
|
if (rd_pick_intra_sub_8x8_y_mode(cpi, x, &rate_y, &rate_y_tokenonly,
|
|
|
|
&dist_y, best_rd) >= best_rd) {
|
2013-07-18 03:21:41 +02:00
|
|
|
*returnrate = INT_MAX;
|
|
|
|
return;
|
|
|
|
}
|
2013-12-09 20:03:02 +01:00
|
|
|
max_uv_tx_size = get_uv_tx_size_impl(xd->mi_8x8[0]->mbmi.tx_size, bsize);
|
2013-11-07 23:56:58 +01:00
|
|
|
rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv, &rate_uv_tokenonly,
|
2013-12-09 20:03:02 +01:00
|
|
|
&dist_uv, &uv_skip, BLOCK_8X8, max_uv_tx_size);
|
2013-07-18 03:21:41 +02:00
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-04-09 19:54:19 +02:00
|
|
|
if (y_skip && uv_skip) {
|
2012-08-29 19:43:20 +02:00
|
|
|
*returnrate = rate_y + rate_uv - rate_y_tokenonly - rate_uv_tokenonly +
|
2013-12-10 23:11:26 +01:00
|
|
|
vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
|
2013-08-16 02:03:14 +02:00
|
|
|
*returndist = dist_y + dist_uv;
|
2013-08-03 02:28:23 +02:00
|
|
|
vp9_zero(ctx->tx_rd_diff);
|
2013-01-06 03:20:25 +01:00
|
|
|
} else {
|
Tx size selection enhancements
(1) Refines the modeling function and uses that to add some speed
features. Specifically, intead of using a flag use_largest_txfm as
a speed feature, an enum tx_size_search_method is used, of which
two of the types are USE_FULL_RD and USE_LARGESTALL. Two other
new types are added:
USE_LARGESTINTRA (use largest only for intra)
USE_LARGESTINTRA_MODELINTER (use largest for intra, and model for
inter)
(2) Another change is that the framework for deciding transform type
is simplified to use a heuristic count based method rather than
an rd based method using txfm_cache. In practice the new method
is found to work just as well - with derf only -0.01 down.
The new method is more compatible with the new framework where
certain rd costs are based on full rd and certain others are
based on modeled rd or are not computed. In this patch the existing
rd based method is still kept for use in the USE_FULL_RD mode.
In the other modes, the count based method is used.
However the recommendation is to remove it eventually since the
benefit is limited, and will remove a lot of complications in
the code
(3) Finally a bug is fixed with the existing use_largest_txfm speed feature
that causes mismatches when the lossless mode and 4x4 WH transform is
forced.
Results on derf:
USE_FULL_RD: +0.03% (due to change in the tables), 0% encode time reduction
USE_LARGESTINTRA: -0.21%, 15% encode time reduction (this one is a
pretty good compromise)
USE_LARGESTINTRA_MODELINTER: -0.98%, 22% encode time reduction
(currently the benefit of modeling is limited for txfm size selection,
but keeping this enum as a placeholder) .
USE_LARGESTALL: -1.05%, 27% encode-time reduction (same as existing
use_largest_txfm speed feature).
Change-Id: I4d60a5f9ce78fbc90cddf2f97ed91d8bc0d4f936
2013-06-22 01:31:12 +02:00
|
|
|
int i;
|
2013-12-10 23:11:26 +01:00
|
|
|
*returnrate = rate_y + rate_uv + vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0);
|
2013-08-16 02:03:14 +02:00
|
|
|
*returndist = dist_y + dist_uv;
|
2013-08-03 02:28:23 +02:00
|
|
|
if (cpi->sf.tx_size_search_method == USE_FULL_RD)
|
2013-09-24 18:37:55 +02:00
|
|
|
for (i = 0; i < TX_MODES; i++) {
|
|
|
|
if (tx_cache[i] < INT64_MAX && tx_cache[cm->tx_mode] < INT64_MAX)
|
|
|
|
ctx->tx_rd_diff[i] = tx_cache[i] - tx_cache[cm->tx_mode];
|
|
|
|
else
|
|
|
|
ctx->tx_rd_diff[i] = 0;
|
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
2013-04-11 18:33:49 +02:00
|
|
|
|
2013-10-10 21:11:44 +02:00
|
|
|
ctx->mic = *xd->mi_8x8[0];
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
2011-06-08 18:05:05 +02:00
|
|
|
|
2013-04-11 00:55:59 +02:00
|
|
|
int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-10-25 17:18:04 +02:00
|
|
|
const TileInfo *const tile,
|
2013-04-26 20:57:17 +02:00
|
|
|
int mi_row, int mi_col,
|
2013-04-11 00:55:59 +02:00
|
|
|
int *returnrate,
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t *returndistortion,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize,
|
2013-07-17 18:56:46 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx,
|
|
|
|
int64_t best_rd_so_far) {
|
2012-10-31 01:53:32 +01:00
|
|
|
VP9_COMMON *cm = &cpi->common;
|
2012-08-20 23:43:34 +02:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-08-14 20:20:33 +02:00
|
|
|
const struct segmentation *seg = &cm->seg;
|
2013-08-27 20:05:08 +02:00
|
|
|
const BLOCK_SIZE block_size = get_plane_block_size(bsize, &xd->plane[0]);
|
2013-09-28 01:02:49 +02:00
|
|
|
MB_PREDICTION_MODE this_mode;
|
2013-07-24 18:59:36 +02:00
|
|
|
MV_REFERENCE_FRAME ref_frame, second_ref_frame;
|
2013-09-11 19:45:44 +02:00
|
|
|
unsigned char segment_id = mbmi->segment_id;
|
2012-11-08 20:03:00 +01:00
|
|
|
int comp_pred, i;
|
2012-10-30 01:58:18 +01:00
|
|
|
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
|
2013-05-07 20:31:12 +02:00
|
|
|
struct buf_2d yv12_mb[4][MAX_MB_PLANE];
|
2013-08-15 20:37:56 +02:00
|
|
|
int_mv single_newmv[MAX_REF_FRAMES] = { { 0 } };
|
2012-10-31 22:40:53 +01:00
|
|
|
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
|
|
|
|
VP9_ALT_FLAG };
|
2013-07-17 18:56:46 +02:00
|
|
|
int64_t best_rd = best_rd_so_far;
|
2013-08-03 02:28:23 +02:00
|
|
|
int64_t best_tx_rd[TX_MODES];
|
|
|
|
int64_t best_tx_diff[TX_MODES];
|
2013-11-23 01:35:37 +01:00
|
|
|
int64_t best_pred_diff[REFERENCE_MODES];
|
|
|
|
int64_t best_pred_rd[REFERENCE_MODES];
|
2013-10-30 22:40:34 +01:00
|
|
|
int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
|
|
|
|
int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
|
2013-08-15 20:37:56 +02:00
|
|
|
MB_MODE_INFO best_mbmode = { 0 };
|
2012-11-30 16:29:43 +01:00
|
|
|
int mode_index, best_mode_index = 0;
|
2013-06-06 22:44:34 +02:00
|
|
|
unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
|
|
|
|
vp9_prob comp_mode_p;
|
2013-07-02 20:18:00 +02:00
|
|
|
int64_t best_intra_rd = INT64_MAX;
|
2013-07-03 23:47:54 +02:00
|
|
|
int64_t best_inter_rd = INT64_MAX;
|
2013-07-02 20:18:00 +02:00
|
|
|
MB_PREDICTION_MODE best_intra_mode = DC_PRED;
|
2013-07-03 23:47:54 +02:00
|
|
|
MV_REFERENCE_FRAME best_inter_ref_frame = LAST_FRAME;
|
2013-10-24 02:45:52 +02:00
|
|
|
INTERPOLATION_TYPE tmp_best_filter = SWITCHABLE;
|
2013-07-27 02:15:37 +02:00
|
|
|
int rate_uv_intra[TX_SIZES], rate_uv_tokenonly[TX_SIZES];
|
|
|
|
int64_t dist_uv[TX_SIZES];
|
|
|
|
int skip_uv[TX_SIZES];
|
|
|
|
MB_PREDICTION_MODE mode_uv[TX_SIZES];
|
2013-04-23 00:42:41 +02:00
|
|
|
int64_t mode_distortions[MB_MODE_COUNT] = {-1};
|
2013-10-21 20:10:11 +02:00
|
|
|
int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
|
2013-08-28 21:22:37 +02:00
|
|
|
const int bws = num_8x8_blocks_wide_lookup[bsize] / 2;
|
|
|
|
const int bhs = num_8x8_blocks_high_lookup[bsize] / 2;
|
2013-06-28 02:41:54 +02:00
|
|
|
int best_skip2 = 0;
|
2013-04-23 00:42:41 +02:00
|
|
|
|
2013-11-13 02:28:27 +01:00
|
|
|
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
|
2013-07-09 01:48:47 +02:00
|
|
|
|
2013-04-23 00:42:41 +02:00
|
|
|
// Everywhere the flag is set the error is much higher than its neighbors.
|
|
|
|
ctx->modes_with_high_error = 0;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-06-06 22:44:34 +02:00
|
|
|
estimate_ref_frame_costs(cpi, segment_id, ref_costs_single, ref_costs_comp,
|
|
|
|
&comp_mode_p);
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-11-23 01:35:37 +01:00
|
|
|
for (i = 0; i < REFERENCE_MODES; ++i)
|
2013-01-14 20:49:30 +01:00
|
|
|
best_pred_rd[i] = INT64_MAX;
|
2013-07-29 22:38:40 +02:00
|
|
|
for (i = 0; i < TX_MODES; i++)
|
2013-08-03 02:28:23 +02:00
|
|
|
best_tx_rd[i] = INT64_MAX;
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
|
2013-07-08 23:49:33 +02:00
|
|
|
best_filter_rd[i] = INT64_MAX;
|
2013-07-27 02:15:37 +02:00
|
|
|
for (i = 0; i < TX_SIZES; i++)
|
2013-07-18 22:09:38 +02:00
|
|
|
rate_uv_intra[i] = INT_MAX;
|
2013-12-21 00:24:22 +01:00
|
|
|
for (i = 0; i < MAX_REF_FRAMES; ++i)
|
|
|
|
x->pred_sse[i] = INT_MAX;
|
2012-11-08 20:03:00 +01:00
|
|
|
|
2013-07-17 18:56:46 +02:00
|
|
|
*returnrate = INT_MAX;
|
|
|
|
|
2012-08-20 23:43:34 +02:00
|
|
|
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
|
2013-12-21 00:24:22 +01:00
|
|
|
x->pred_mv_sad[ref_frame] = INT_MAX;
|
2012-08-20 23:43:34 +02:00
|
|
|
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
|
2014-01-06 23:50:54 +01:00
|
|
|
setup_buffer_inter(cpi, x, tile, get_ref_frame_idx(cpi, ref_frame),
|
|
|
|
ref_frame, block_size, mi_row, mi_col,
|
2013-12-20 01:06:33 +01:00
|
|
|
frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
2012-10-30 01:58:18 +01:00
|
|
|
frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
|
|
|
|
frame_mv[ZEROMV][ref_frame].as_int = 0;
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
2013-07-16 16:56:42 +02:00
|
|
|
|
2013-02-12 02:08:52 +01:00
|
|
|
for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
|
2012-11-16 00:50:07 +01:00
|
|
|
int mode_excluded = 0;
|
2013-01-14 20:49:30 +01:00
|
|
|
int64_t this_rd = INT64_MAX;
|
2012-08-20 23:43:34 +02:00
|
|
|
int disable_skip = 0;
|
|
|
|
int compmode_cost = 0;
|
2012-10-30 01:58:18 +01:00
|
|
|
int rate2 = 0, rate_y = 0, rate_uv = 0;
|
2013-06-21 21:54:52 +02:00
|
|
|
int64_t distortion2 = 0, distortion_y = 0, distortion_uv = 0;
|
2013-08-10 01:15:08 +02:00
|
|
|
int skippable = 0;
|
2013-08-03 02:28:23 +02:00
|
|
|
int64_t tx_cache[TX_MODES];
|
2013-05-16 07:28:36 +02:00
|
|
|
int i;
|
2013-06-28 02:41:54 +02:00
|
|
|
int this_skip2 = 0;
|
|
|
|
int64_t total_sse = INT_MAX;
|
2013-07-03 23:47:54 +02:00
|
|
|
int early_term = 0;
|
2013-05-16 07:28:36 +02:00
|
|
|
|
2013-07-29 22:38:40 +02:00
|
|
|
for (i = 0; i < TX_MODES; ++i)
|
2013-08-03 02:28:23 +02:00
|
|
|
tx_cache[i] = INT64_MAX;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
x->skip = 0;
|
2013-07-01 17:27:12 +02:00
|
|
|
this_mode = vp9_mode_order[mode_index].mode;
|
2014-01-06 21:23:36 +01:00
|
|
|
ref_frame = vp9_mode_order[mode_index].ref_frame[0];
|
|
|
|
second_ref_frame = vp9_mode_order[mode_index].ref_frame[1];
|
2013-07-01 17:27:12 +02:00
|
|
|
|
2013-09-05 02:15:05 +02:00
|
|
|
// Look at the reference frame of the best mode so far and set the
|
|
|
|
// skip mask to look at a subset of the remaining modes.
|
|
|
|
if (mode_index > cpi->sf.mode_skip_start) {
|
|
|
|
if (mode_index == (cpi->sf.mode_skip_start + 1)) {
|
2014-01-06 21:23:36 +01:00
|
|
|
switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
|
2013-09-05 02:15:05 +02:00
|
|
|
case INTRA_FRAME:
|
|
|
|
cpi->mode_skip_mask = 0;
|
|
|
|
break;
|
|
|
|
case LAST_FRAME:
|
|
|
|
cpi->mode_skip_mask = LAST_FRAME_MODE_MASK;
|
|
|
|
break;
|
|
|
|
case GOLDEN_FRAME:
|
|
|
|
cpi->mode_skip_mask = GOLDEN_FRAME_MODE_MASK;
|
|
|
|
break;
|
|
|
|
case ALTREF_FRAME:
|
|
|
|
cpi->mode_skip_mask = ALT_REF_MODE_MASK;
|
|
|
|
break;
|
|
|
|
case NONE:
|
|
|
|
case MAX_REF_FRAMES:
|
2013-12-13 04:44:08 +01:00
|
|
|
assert(0 && "Invalid Reference frame");
|
2013-09-05 02:15:05 +02:00
|
|
|
}
|
|
|
|
}
|
2013-09-17 18:45:13 +02:00
|
|
|
if (cpi->mode_skip_mask & ((int64_t)1 << mode_index))
|
2013-09-05 02:15:05 +02:00
|
|
|
continue;
|
|
|
|
}
|
2013-07-01 17:27:12 +02:00
|
|
|
|
2013-07-25 20:19:37 +02:00
|
|
|
// Skip if the current reference frame has been masked off
|
2013-07-01 17:27:12 +02:00
|
|
|
if (cpi->sf.reference_masking && !cpi->set_ref_frame_mask &&
|
|
|
|
(cpi->ref_frame_mask & (1 << ref_frame)))
|
|
|
|
continue;
|
|
|
|
|
2012-08-20 23:43:34 +02:00
|
|
|
// Test best rd so far against threshold for trying this mode.
|
2013-10-07 20:20:10 +02:00
|
|
|
if ((best_rd < ((int64_t)cpi->rd_threshes[segment_id][bsize][mode_index] *
|
2013-09-18 01:31:46 +02:00
|
|
|
cpi->rd_thresh_freq_fact[bsize][mode_index] >> 5)) ||
|
2013-10-07 20:20:10 +02:00
|
|
|
cpi->rd_threshes[segment_id][bsize][mode_index] == INT_MAX)
|
2013-05-16 07:28:36 +02:00
|
|
|
continue;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-06-10 19:19:25 +02:00
|
|
|
// Do not allow compound prediction if the segment level reference
|
|
|
|
// frame feature is in use as in this case there can only be one reference.
|
2013-07-24 18:59:36 +02:00
|
|
|
if ((second_ref_frame > INTRA_FRAME) &&
|
2013-08-01 23:53:14 +02:00
|
|
|
vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
|
2013-06-10 19:19:25 +02:00
|
|
|
continue;
|
|
|
|
|
2013-07-03 23:43:23 +02:00
|
|
|
// Skip some checking based on small partitions' result.
|
|
|
|
if (x->fast_ms > 1 && !ref_frame)
|
|
|
|
continue;
|
|
|
|
if (x->fast_ms > 2 && ref_frame != x->subblock_ref)
|
|
|
|
continue;
|
|
|
|
|
2013-06-06 22:44:34 +02:00
|
|
|
mbmi->ref_frame[0] = ref_frame;
|
2013-07-24 18:59:36 +02:00
|
|
|
mbmi->ref_frame[1] = second_ref_frame;
|
2013-05-06 19:25:38 +02:00
|
|
|
|
2013-05-29 21:34:10 +02:00
|
|
|
if (!(ref_frame == INTRA_FRAME
|
|
|
|
|| (cpi->ref_frame_flags & flag_list[ref_frame]))) {
|
|
|
|
continue;
|
|
|
|
}
|
2013-07-24 18:59:36 +02:00
|
|
|
if (!(second_ref_frame == NONE
|
|
|
|
|| (cpi->ref_frame_flags & flag_list[second_ref_frame]))) {
|
2013-05-29 21:34:10 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-07-24 18:59:36 +02:00
|
|
|
comp_pred = second_ref_frame > INTRA_FRAME;
|
2013-07-03 23:47:54 +02:00
|
|
|
if (comp_pred) {
|
|
|
|
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA)
|
2014-01-06 21:23:36 +01:00
|
|
|
if (vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
|
2013-07-03 23:47:54 +02:00
|
|
|
continue;
|
|
|
|
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
|
2013-07-24 18:59:36 +02:00
|
|
|
if (ref_frame != best_inter_ref_frame &&
|
|
|
|
second_ref_frame != best_inter_ref_frame)
|
2013-07-03 23:47:54 +02:00
|
|
|
continue;
|
|
|
|
}
|
2013-05-06 19:25:38 +02:00
|
|
|
|
2013-12-20 01:06:33 +01:00
|
|
|
set_scale_factors(cm, xd, ref_frame - 1, second_ref_frame - 1);
|
2012-10-30 01:58:18 +01:00
|
|
|
mbmi->uv_mode = DC_PRED;
|
Spatial resamping of ZEROMV predictors
This patch allows coding frames using references of different
resolution, in ZEROMV mode. For compound prediction, either
reference may be scaled.
To test, I use the resize_test and enable WRITE_RECON_BUFFER
in vp9_onyxd_if.c. It's also useful to apply this patch to
test/i420_video_source.h:
--- a/test/i420_video_source.h
+++ b/test/i420_video_source.h
@@ -93,6 +93,7 @@ class I420VideoSource : public VideoSource {
virtual void FillFrame() {
// Read a frame from input_file.
+ if (frame_ != 3)
if (fread(img_->img_data, raw_sz_, 1, input_file_) == 0) {
limit_ = frame_;
}
This forces the frame that the resolution changes on to be coded
with no motion, only scaling, and improves the quality of the
result.
Change-Id: I1ee75d19a437ff801192f767fd02a36bcbd1d496
2013-02-25 05:55:14 +01:00
|
|
|
|
2012-12-20 23:56:19 +01:00
|
|
|
// Evaluate all sub-pel filters irrespective of whether we can use
|
|
|
|
// them for this frame.
|
2013-02-12 02:08:52 +01:00
|
|
|
mbmi->interp_filter = cm->mcomp_filter_type;
|
2013-10-21 20:10:11 +02:00
|
|
|
vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
|
2012-08-20 23:43:34 +02:00
|
|
|
|
|
|
|
if (comp_pred) {
|
2013-07-24 18:59:36 +02:00
|
|
|
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
|
2012-08-20 23:43:34 +02:00
|
|
|
continue;
|
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
mode_excluded = mode_excluded ? mode_excluded
|
|
|
|
: cm->reference_mode == SINGLE_REFERENCE;
|
2012-08-20 23:43:34 +02:00
|
|
|
} else {
|
2013-12-10 00:13:34 +01:00
|
|
|
if (ref_frame != INTRA_FRAME && second_ref_frame != INTRA_FRAME)
|
|
|
|
mode_excluded = mode_excluded ?
|
|
|
|
mode_excluded : cm->reference_mode == COMPOUND_REFERENCE;
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
|
|
|
|
2013-08-01 18:04:15 +02:00
|
|
|
// Select prediction reference frames.
|
2013-05-07 20:31:12 +02:00
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++) {
|
|
|
|
xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
|
|
|
|
if (comp_pred)
|
2013-07-24 18:59:36 +02:00
|
|
|
xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
|
2013-05-07 20:31:12 +02:00
|
|
|
}
|
2013-04-20 04:16:14 +02:00
|
|
|
|
2012-08-20 23:43:34 +02:00
|
|
|
// If the segment reference frame feature is enabled....
|
|
|
|
// then do nothing if the current ref frame is not allowed..
|
2013-08-01 23:53:14 +02:00
|
|
|
if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
|
|
|
|
vp9_get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) !=
|
2013-07-10 21:29:43 +02:00
|
|
|
(int)ref_frame) {
|
2012-08-20 23:43:34 +02:00
|
|
|
continue;
|
2013-01-28 16:22:53 +01:00
|
|
|
// If the segment skip feature is enabled....
|
2012-08-20 23:43:34 +02:00
|
|
|
// then do nothing if the current mode is not allowed..
|
2013-08-01 23:53:14 +02:00
|
|
|
} else if (vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) &&
|
2013-09-28 01:02:49 +02:00
|
|
|
(this_mode != ZEROMV && ref_frame != INTRA_FRAME)) {
|
2012-08-20 23:43:34 +02:00
|
|
|
continue;
|
2013-01-28 16:22:53 +01:00
|
|
|
// Disable this drop out case if the ref frame
|
2012-08-20 23:43:34 +02:00
|
|
|
// segment level feature is enabled for this segment. This is to
|
|
|
|
// prevent the possibility that we end up unable to pick any mode.
|
2013-08-01 23:53:14 +02:00
|
|
|
} else if (!vp9_segfeature_active(seg, segment_id,
|
2013-07-10 21:29:43 +02:00
|
|
|
SEG_LVL_REF_FRAME)) {
|
2012-08-20 23:43:34 +02:00
|
|
|
// Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
|
|
|
|
// unless ARNR filtering is enabled in which case we want
|
2013-07-18 21:12:48 +02:00
|
|
|
// an unfiltered alternative. We allow near/nearest as well
|
|
|
|
// because they may result in zero-zero MVs but be cheaper.
|
2013-12-13 18:32:05 +01:00
|
|
|
if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
|
2013-09-28 01:02:49 +02:00
|
|
|
if ((this_mode != ZEROMV &&
|
|
|
|
!(this_mode == NEARMV &&
|
|
|
|
frame_mv[NEARMV][ALTREF_FRAME].as_int == 0) &&
|
|
|
|
!(this_mode == NEARESTMV &&
|
|
|
|
frame_mv[NEARESTMV][ALTREF_FRAME].as_int == 0)) ||
|
2013-07-18 21:12:48 +02:00
|
|
|
ref_frame != ALTREF_FRAME) {
|
2012-08-20 23:43:34 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-06-06 15:07:09 +02:00
|
|
|
// TODO(JBB): This is to make up for the fact that we don't have sad
|
|
|
|
// functions that work when the block size reads outside the umv. We
|
|
|
|
// should fix this either by making the motion search just work on
|
|
|
|
// a representative block in the boundary ( first ) and then implement a
|
|
|
|
// function that does sads when inside the border..
|
2013-06-06 17:59:22 +02:00
|
|
|
if (((mi_row + bhs) > cm->mi_rows || (mi_col + bws) > cm->mi_cols) &&
|
2013-09-28 01:02:49 +02:00
|
|
|
this_mode == NEWMV) {
|
2013-06-06 15:07:09 +02:00
|
|
|
continue;
|
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-08-21 13:34:14 +02:00
|
|
|
#ifdef MODE_TEST_HIT_STATS
|
|
|
|
// TEST/DEBUG CODE
|
|
|
|
// Keep a rcord of the number of test hits at each size
|
|
|
|
cpi->mode_test_hits[bsize]++;
|
|
|
|
#endif
|
|
|
|
|
2013-05-01 01:13:20 +02:00
|
|
|
|
2013-09-28 01:02:49 +02:00
|
|
|
if (ref_frame == INTRA_FRAME) {
|
2013-04-11 00:55:59 +02:00
|
|
|
TX_SIZE uv_tx;
|
2013-07-31 18:33:58 +02:00
|
|
|
// Disable intra modes other than DC_PRED for blocks with low variance
|
|
|
|
// Threshold for intra skipping based on source variance
|
|
|
|
// TODO(debargha): Specialize the threshold for super block sizes
|
2013-09-17 18:45:13 +02:00
|
|
|
static const unsigned int skip_intra_var_thresh[BLOCK_SIZES] = {
|
2013-07-31 18:33:58 +02:00
|
|
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
|
|
};
|
|
|
|
if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) &&
|
2013-09-28 01:02:49 +02:00
|
|
|
this_mode != DC_PRED &&
|
2013-07-31 18:33:58 +02:00
|
|
|
x->source_variance < skip_intra_var_thresh[mbmi->sb_type])
|
|
|
|
continue;
|
2013-07-02 20:18:00 +02:00
|
|
|
// Only search the oblique modes if the best so far is
|
|
|
|
// one of the neighboring directional modes
|
2013-07-03 23:47:54 +02:00
|
|
|
if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
|
2013-09-28 01:02:49 +02:00
|
|
|
(this_mode >= D45_PRED && this_mode <= TM_PRED)) {
|
2014-01-06 21:23:36 +01:00
|
|
|
if (vp9_mode_order[best_mode_index].ref_frame[0] > INTRA_FRAME)
|
2013-07-03 23:47:54 +02:00
|
|
|
continue;
|
|
|
|
}
|
2013-09-28 01:02:49 +02:00
|
|
|
mbmi->mode = this_mode;
|
2013-07-03 23:47:54 +02:00
|
|
|
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
|
2013-09-12 15:39:42 +02:00
|
|
|
if (conditional_skipintra(mbmi->mode, best_intra_mode))
|
2013-07-02 20:18:00 +02:00
|
|
|
continue;
|
|
|
|
}
|
2013-09-12 01:34:55 +02:00
|
|
|
|
2013-06-28 02:41:54 +02:00
|
|
|
super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, NULL,
|
2013-08-03 02:28:23 +02:00
|
|
|
bsize, tx_cache, best_rd);
|
2013-07-03 01:48:15 +02:00
|
|
|
|
|
|
|
if (rate_y == INT_MAX)
|
|
|
|
continue;
|
2013-04-11 00:55:59 +02:00
|
|
|
|
2013-12-09 20:03:02 +01:00
|
|
|
uv_tx = get_uv_tx_size_impl(mbmi->tx_size, bsize);
|
2013-07-18 22:09:38 +02:00
|
|
|
if (rate_uv_intra[uv_tx] == INT_MAX) {
|
2013-12-09 20:03:02 +01:00
|
|
|
choose_intra_uv_mode(cpi, ctx, bsize, uv_tx,
|
|
|
|
&rate_uv_intra[uv_tx], &rate_uv_tokenonly[uv_tx],
|
|
|
|
&dist_uv[uv_tx], &skip_uv[uv_tx], &mode_uv[uv_tx]);
|
2013-07-18 22:09:38 +02:00
|
|
|
}
|
2013-04-11 00:55:59 +02:00
|
|
|
|
2013-07-18 22:09:38 +02:00
|
|
|
rate_uv = rate_uv_tokenonly[uv_tx];
|
2013-04-11 00:55:59 +02:00
|
|
|
distortion_uv = dist_uv[uv_tx];
|
|
|
|
skippable = skippable && skip_uv[uv_tx];
|
|
|
|
mbmi->uv_mode = mode_uv[uv_tx];
|
2012-11-16 00:50:07 +01:00
|
|
|
|
2013-07-18 22:09:38 +02:00
|
|
|
rate2 = rate_y + x->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
|
2013-09-28 01:02:49 +02:00
|
|
|
if (this_mode != DC_PRED && this_mode != TM_PRED)
|
2013-05-01 01:13:20 +02:00
|
|
|
rate2 += intra_cost_penalty;
|
2012-11-16 00:50:07 +01:00
|
|
|
distortion2 = distortion_y + distortion_uv;
|
|
|
|
} else {
|
2013-09-28 01:02:49 +02:00
|
|
|
mbmi->mode = this_mode;
|
2013-07-24 18:59:36 +02:00
|
|
|
compmode_cost = vp9_cost_bit(comp_mode_p, second_ref_frame > INTRA_FRAME);
|
2013-10-25 17:18:04 +02:00
|
|
|
this_rd = handle_inter_mode(cpi, x, tile, bsize,
|
2013-08-03 02:28:23 +02:00
|
|
|
tx_cache,
|
2012-11-16 00:50:07 +01:00
|
|
|
&rate2, &distortion2, &skippable,
|
|
|
|
&rate_y, &distortion_y,
|
|
|
|
&rate_uv, &distortion_uv,
|
2013-02-07 19:09:05 +01:00
|
|
|
&mode_excluded, &disable_skip,
|
2013-07-17 20:33:15 +02:00
|
|
|
&tmp_best_filter, frame_mv,
|
2013-06-14 00:10:42 +02:00
|
|
|
mi_row, mi_col,
|
2013-07-03 01:48:15 +02:00
|
|
|
single_newmv, &total_sse, best_rd);
|
2013-01-14 20:49:30 +01:00
|
|
|
if (this_rd == INT64_MAX)
|
2012-11-16 00:50:07 +01:00
|
|
|
continue;
|
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT)
|
2012-08-20 23:43:34 +02:00
|
|
|
rate2 += compmode_cost;
|
|
|
|
|
|
|
|
// Estimate the reference frame signaling cost and add it
|
|
|
|
// to the rolling cost variable.
|
2013-07-24 18:59:36 +02:00
|
|
|
if (second_ref_frame > INTRA_FRAME) {
|
|
|
|
rate2 += ref_costs_comp[ref_frame];
|
2013-06-06 22:44:34 +02:00
|
|
|
} else {
|
2013-07-24 18:59:36 +02:00
|
|
|
rate2 += ref_costs_single[ref_frame];
|
2013-06-06 22:44:34 +02:00
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
|
|
|
|
if (!disable_skip) {
|
|
|
|
// Test for the condition where skip block will be activated
|
|
|
|
// because there are no non zero coefficients and make any
|
|
|
|
// necessary adjustment for rate. Ignore if skip is coded at
|
|
|
|
// segment level as the cost wont have been added in.
|
2013-04-09 19:54:19 +02:00
|
|
|
// Is Mb level skip allowed (i.e. not coded at segment level).
|
2013-08-01 23:53:14 +02:00
|
|
|
const int mb_skip_allowed = !vp9_segfeature_active(seg, segment_id,
|
2013-07-10 21:29:43 +02:00
|
|
|
SEG_LVL_SKIP);
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-09-28 01:02:49 +02:00
|
|
|
if (skippable) {
|
2013-04-09 19:54:19 +02:00
|
|
|
// Back out the coefficient coding costs
|
|
|
|
rate2 -= (rate_y + rate_uv);
|
2013-07-09 01:01:01 +02:00
|
|
|
// for best yrd calculation
|
2013-04-09 19:54:19 +02:00
|
|
|
rate_uv = 0;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-04-09 19:54:19 +02:00
|
|
|
if (mb_skip_allowed) {
|
|
|
|
int prob_skip_cost;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-04-09 19:54:19 +02:00
|
|
|
// Cost the skip mb case
|
2013-12-10 23:11:26 +01:00
|
|
|
vp9_prob skip_prob = vp9_get_skip_prob(cm, xd);
|
2013-04-09 19:54:19 +02:00
|
|
|
if (skip_prob) {
|
|
|
|
prob_skip_cost = vp9_cost_bit(skip_prob, 1);
|
|
|
|
rate2 += prob_skip_cost;
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
|
|
|
}
|
2013-07-24 18:59:36 +02:00
|
|
|
} else if (mb_skip_allowed && ref_frame != INTRA_FRAME && !xd->lossless) {
|
2013-06-28 02:41:54 +02:00
|
|
|
if (RDCOST(x->rdmult, x->rddiv, rate_y + rate_uv, distortion2) <
|
|
|
|
RDCOST(x->rdmult, x->rddiv, 0, total_sse)) {
|
|
|
|
// Add in the cost of the no skip flag.
|
2013-12-10 23:11:26 +01:00
|
|
|
rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0);
|
2013-06-28 02:41:54 +02:00
|
|
|
} else {
|
2013-07-08 23:49:33 +02:00
|
|
|
// FIXME(rbultje) make this work for splitmv also
|
2013-12-10 23:11:26 +01:00
|
|
|
rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
|
2013-06-28 02:41:54 +02:00
|
|
|
distortion2 = total_sse;
|
|
|
|
assert(total_sse >= 0);
|
|
|
|
rate2 -= (rate_y + rate_uv);
|
|
|
|
rate_y = 0;
|
|
|
|
rate_uv = 0;
|
|
|
|
this_skip2 = 1;
|
|
|
|
}
|
2013-04-09 19:54:19 +02:00
|
|
|
} else if (mb_skip_allowed) {
|
2012-08-20 23:43:34 +02:00
|
|
|
// Add in the cost of the no skip flag.
|
2013-12-10 23:11:26 +01:00
|
|
|
rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0);
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the final RD estimate for this mode.
|
|
|
|
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
|
|
|
|
}
|
|
|
|
|
2013-07-03 23:47:54 +02:00
|
|
|
// Keep record of best intra rd
|
2013-10-29 04:00:55 +01:00
|
|
|
if (!is_inter_block(&xd->mi_8x8[0]->mbmi) &&
|
2013-07-02 20:18:00 +02:00
|
|
|
this_rd < best_intra_rd) {
|
2012-08-20 23:43:34 +02:00
|
|
|
best_intra_rd = this_rd;
|
2013-10-10 21:11:44 +02:00
|
|
|
best_intra_mode = xd->mi_8x8[0]->mbmi.mode;
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
2013-10-29 04:00:55 +01:00
|
|
|
|
2013-07-03 23:47:54 +02:00
|
|
|
// Keep record of best inter rd with single reference
|
2013-11-03 18:14:46 +01:00
|
|
|
if (is_inter_block(&xd->mi_8x8[0]->mbmi) &&
|
|
|
|
!has_second_ref(&xd->mi_8x8[0]->mbmi) &&
|
|
|
|
!mode_excluded && this_rd < best_inter_rd) {
|
2013-07-03 23:47:54 +02:00
|
|
|
best_inter_rd = this_rd;
|
|
|
|
best_inter_ref_frame = ref_frame;
|
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-07-24 18:59:36 +02:00
|
|
|
if (!disable_skip && ref_frame == INTRA_FRAME) {
|
2013-11-23 01:35:37 +01:00
|
|
|
for (i = 0; i < REFERENCE_MODES; ++i)
|
2012-11-08 20:03:00 +01:00
|
|
|
best_pred_rd[i] = MIN(best_pred_rd[i], this_rd);
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
|
2013-07-08 23:49:33 +02:00
|
|
|
best_filter_rd[i] = MIN(best_filter_rd[i], this_rd);
|
2012-11-30 20:46:20 +01:00
|
|
|
}
|
|
|
|
|
2013-09-28 01:02:49 +02:00
|
|
|
// Store the respective mode distortions for later use.
|
|
|
|
if (mode_distortions[this_mode] == -1
|
|
|
|
|| distortion2 < mode_distortions[this_mode]) {
|
|
|
|
mode_distortions[this_mode] = distortion2;
|
|
|
|
}
|
2013-04-23 00:42:41 +02:00
|
|
|
|
2012-08-20 23:43:34 +02:00
|
|
|
// Did this mode help.. i.e. is it the new best mode
|
|
|
|
if (this_rd < best_rd || x->skip) {
|
2013-11-07 23:56:58 +01:00
|
|
|
int max_plane = MAX_MB_PLANE;
|
2012-08-20 23:43:34 +02:00
|
|
|
if (!mode_excluded) {
|
|
|
|
// Note index of best mode so far
|
|
|
|
best_mode_index = mode_index;
|
|
|
|
|
2013-05-30 20:27:40 +02:00
|
|
|
if (ref_frame == INTRA_FRAME) {
|
2012-08-20 23:43:34 +02:00
|
|
|
/* required for left and above block mv */
|
2012-11-16 00:50:07 +01:00
|
|
|
mbmi->mv[0].as_int = 0;
|
2013-11-07 23:56:58 +01:00
|
|
|
max_plane = 1;
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*returnrate = rate2;
|
|
|
|
*returndistortion = distortion2;
|
|
|
|
best_rd = this_rd;
|
2013-06-01 01:00:32 +02:00
|
|
|
best_mbmode = *mbmi;
|
2013-06-28 02:41:54 +02:00
|
|
|
best_skip2 = this_skip2;
|
2013-11-06 06:07:08 +01:00
|
|
|
if (!x->select_txfm_size)
|
2013-11-07 23:56:58 +01:00
|
|
|
swap_block_ptr(x, ctx, max_plane);
|
2013-10-15 01:03:23 +02:00
|
|
|
vpx_memcpy(ctx->zcoeff_blk, x->zcoeff_blk[mbmi->tx_size],
|
2013-10-16 21:43:03 +02:00
|
|
|
sizeof(uint8_t) * ctx->num_4x4_blk);
|
2013-05-01 23:43:33 +02:00
|
|
|
|
2013-07-03 23:47:54 +02:00
|
|
|
// TODO(debargha): enhance this test with a better distortion prediction
|
|
|
|
// based on qp, activity mask and history
|
2013-10-01 17:57:18 +02:00
|
|
|
if ((cpi->sf.mode_search_skip_flags & FLAG_EARLY_TERMINATE) &&
|
|
|
|
(mode_index > MIN_EARLY_TERM_INDEX)) {
|
2013-07-31 18:33:58 +02:00
|
|
|
const int qstep = xd->plane[0].dequant[1];
|
|
|
|
// TODO(debargha): Enhance this by specializing for each mode_index
|
|
|
|
int scale = 4;
|
|
|
|
if (x->source_variance < UINT_MAX) {
|
|
|
|
const int var_adjust = (x->source_variance < 16);
|
|
|
|
scale -= var_adjust;
|
|
|
|
}
|
|
|
|
if (ref_frame > INTRA_FRAME &&
|
|
|
|
distortion2 * scale < qstep * qstep) {
|
2013-07-03 23:47:54 +02:00
|
|
|
early_term = 1;
|
2013-07-31 18:33:58 +02:00
|
|
|
}
|
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* keep record of best compound/single-only prediction */
|
2013-07-24 18:59:36 +02:00
|
|
|
if (!disable_skip && ref_frame != INTRA_FRAME) {
|
2013-11-25 21:45:51 +01:00
|
|
|
int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT) {
|
2012-08-20 23:43:34 +02:00
|
|
|
single_rate = rate2 - compmode_cost;
|
|
|
|
hybrid_rate = rate2;
|
|
|
|
} else {
|
|
|
|
single_rate = rate2;
|
|
|
|
hybrid_rate = rate2 + compmode_cost;
|
|
|
|
}
|
|
|
|
|
|
|
|
single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
|
|
|
|
hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
|
|
|
|
|
2013-07-24 18:59:36 +02:00
|
|
|
if (second_ref_frame <= INTRA_FRAME &&
|
2013-11-23 01:35:37 +01:00
|
|
|
single_rd < best_pred_rd[SINGLE_REFERENCE]) {
|
|
|
|
best_pred_rd[SINGLE_REFERENCE] = single_rd;
|
2013-07-24 18:59:36 +02:00
|
|
|
} else if (second_ref_frame > INTRA_FRAME &&
|
2013-11-23 01:35:37 +01:00
|
|
|
single_rd < best_pred_rd[COMPOUND_REFERENCE]) {
|
|
|
|
best_pred_rd[COMPOUND_REFERENCE] = single_rd;
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
2013-11-23 01:35:37 +01:00
|
|
|
if (hybrid_rd < best_pred_rd[REFERENCE_MODE_SELECT])
|
|
|
|
best_pred_rd[REFERENCE_MODE_SELECT] = hybrid_rd;
|
2012-11-08 20:03:00 +01:00
|
|
|
}
|
|
|
|
|
2013-07-08 23:49:33 +02:00
|
|
|
/* keep record of best filter type */
|
2013-07-24 18:59:36 +02:00
|
|
|
if (!mode_excluded && !disable_skip && ref_frame != INTRA_FRAME &&
|
2013-07-08 23:49:33 +02:00
|
|
|
cm->mcomp_filter_type != BILINEAR) {
|
|
|
|
int64_t ref = cpi->rd_filter_cache[cm->mcomp_filter_type == SWITCHABLE ?
|
2013-08-23 03:40:34 +02:00
|
|
|
SWITCHABLE_FILTERS : cm->mcomp_filter_type];
|
2013-12-17 02:52:59 +01:00
|
|
|
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
|
2013-07-08 23:49:33 +02:00
|
|
|
int64_t adj_rd;
|
2013-12-17 02:52:59 +01:00
|
|
|
if (ref == INT64_MAX)
|
|
|
|
adj_rd = 0;
|
|
|
|
else if (cpi->rd_filter_cache[i] == INT64_MAX)
|
|
|
|
// when early termination is triggered, the encoder does not have
|
|
|
|
// access to the rate-distortion cost. it only knows that the cost
|
|
|
|
// should be above the maximum valid value. hence it takes the known
|
|
|
|
// maximum plus an arbitrary constant as the rate-distortion cost.
|
|
|
|
adj_rd = cpi->mask_filter_rd - ref + 10;
|
|
|
|
else
|
|
|
|
adj_rd = cpi->rd_filter_cache[i] - ref;
|
|
|
|
|
|
|
|
adj_rd += this_rd;
|
2013-07-08 23:49:33 +02:00
|
|
|
best_filter_rd[i] = MIN(best_filter_rd[i], adj_rd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-08 20:03:00 +01:00
|
|
|
/* keep record of best txfm size */
|
2013-08-02 20:45:21 +02:00
|
|
|
if (bsize < BLOCK_32X32) {
|
2013-09-28 01:02:49 +02:00
|
|
|
if (bsize < BLOCK_16X16)
|
2013-08-03 02:28:23 +02:00
|
|
|
tx_cache[ALLOW_16X16] = tx_cache[ALLOW_8X8];
|
2013-09-28 01:02:49 +02:00
|
|
|
|
2013-08-03 02:28:23 +02:00
|
|
|
tx_cache[ALLOW_32X32] = tx_cache[ALLOW_16X16];
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
2013-01-14 20:49:30 +01:00
|
|
|
if (!mode_excluded && this_rd != INT64_MAX) {
|
2013-08-29 19:26:52 +02:00
|
|
|
for (i = 0; i < TX_MODES && tx_cache[i] < INT64_MAX; i++) {
|
2013-05-16 07:28:36 +02:00
|
|
|
int64_t adj_rd = INT64_MAX;
|
2013-09-28 01:02:49 +02:00
|
|
|
adj_rd = this_rd + tx_cache[i] - tx_cache[cm->tx_mode];
|
2013-05-16 07:28:36 +02:00
|
|
|
|
2013-08-03 02:28:23 +02:00
|
|
|
if (adj_rd < best_tx_rd[i])
|
|
|
|
best_tx_rd[i] = adj_rd;
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-03 23:47:54 +02:00
|
|
|
if (early_term)
|
|
|
|
break;
|
|
|
|
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
if (x->skip && !comp_pred)
|
2012-08-20 23:43:34 +02:00
|
|
|
break;
|
|
|
|
}
|
Add encoding option --static-thresh
This option exists in VP8, and it was rewritten in VP9 to support
skipping on different partition levels. After prediction is done,
we can check if the residuals in the partition block will be all
quantized to 0. If this is true, the skip flag is set, and only
prediction data are needed in reconstruction. Based on DCT's energy
conservation property, the skipping check can be estimated in
spatial domain.
The prediction error is calculated and compared to a threshold.
The threshold is determined by the dequant values, and also
adjusted by partition sizes. To be precise, the DC and AC parts
for Y, U, and V planes are checked to decide skipping or not.
Test showed that
1. derf set:
when static-thresh = 1, psnr loss is 0.666%;
when static-thresh = 500, psnr loss is 1.162%;
2. stdhd set:
when static-thresh = 1, psnr loss is 1.249%;
when static-thresh = 500, psnr loss is 1.668%;
For different clips, encoding speedup range is between several
percentage and 20+% when static-thresh <= 500. For example,
clip bitrate static-thresh psnr time
akiyo(cif) 500 0 48.923 5.635s(50f)
akiyo 500 500 48.863 4.402s(50f)
parkjoy(1080p) 4000 0 30.380 77.54s(30f)
parkjoy 4000 500 30.384 69.59s(30f)
sunflower(1080p) 4000 0 44.461 85.2s(30f)
sunflower 4000 500 44.418 78.1s(30f)
Higher static-thresh values give larger speedup with larger
quality loss.
Change-Id: I857031ceb466ff314ab580ac5ec5d18542203c53
2013-07-11 20:15:00 +02:00
|
|
|
|
2013-07-17 18:56:46 +02:00
|
|
|
if (best_rd >= best_rd_so_far)
|
|
|
|
return INT64_MAX;
|
2013-07-01 17:27:12 +02:00
|
|
|
|
2013-07-16 19:12:34 +02:00
|
|
|
// If we used an estimate for the uv intra rd in the loop above...
|
|
|
|
if (cpi->sf.use_uv_intra_rd_estimate) {
|
|
|
|
// Do Intra UV best rd mode selection if best mode choice above was intra.
|
2014-01-06 21:23:36 +01:00
|
|
|
if (vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME) {
|
2013-12-03 00:24:41 +01:00
|
|
|
TX_SIZE uv_tx_size;
|
|
|
|
*mbmi = best_mbmode;
|
|
|
|
uv_tx_size = get_uv_tx_size(mbmi);
|
2013-11-07 23:56:58 +01:00
|
|
|
rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv_intra[uv_tx_size],
|
2013-07-16 19:12:34 +02:00
|
|
|
&rate_uv_tokenonly[uv_tx_size],
|
|
|
|
&dist_uv[uv_tx_size],
|
|
|
|
&skip_uv[uv_tx_size],
|
2013-12-09 20:03:02 +01:00
|
|
|
bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize,
|
|
|
|
uv_tx_size);
|
2013-07-16 19:12:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-01 17:27:12 +02:00
|
|
|
// If we are using reference masking and the set mask flag is set then
|
|
|
|
// create the reference frame mask.
|
|
|
|
if (cpi->sf.reference_masking && cpi->set_ref_frame_mask)
|
2014-01-06 21:23:36 +01:00
|
|
|
cpi->ref_frame_mask = ~(1 << vp9_mode_order[best_mode_index].ref_frame[0]);
|
2013-07-01 17:27:12 +02:00
|
|
|
|
2013-04-23 00:42:41 +02:00
|
|
|
// Flag all modes that have a distortion thats > 2x the best we found at
|
|
|
|
// this level.
|
|
|
|
for (mode_index = 0; mode_index < MB_MODE_COUNT; ++mode_index) {
|
2013-05-30 21:49:38 +02:00
|
|
|
if (mode_index == NEARESTMV || mode_index == NEARMV || mode_index == NEWMV)
|
2013-04-23 00:42:41 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (mode_distortions[mode_index] > 2 * *returndistortion) {
|
|
|
|
ctx->modes_with_high_error |= (1 << mode_index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-20 23:56:19 +01:00
|
|
|
assert((cm->mcomp_filter_type == SWITCHABLE) ||
|
|
|
|
(cm->mcomp_filter_type == best_mbmode.interp_filter) ||
|
2013-11-20 05:25:55 +01:00
|
|
|
!is_inter_block(&best_mbmode));
|
2012-12-20 23:56:19 +01:00
|
|
|
|
2013-08-01 18:04:15 +02:00
|
|
|
// Updating rd_thresh_freq_fact[] here means that the different
|
2013-06-03 13:51:29 +02:00
|
|
|
// partition/block sizes are handled independently based on the best
|
|
|
|
// choice for the current partition. It may well be better to keep a scaled
|
|
|
|
// best rd so far value and update rd_thresh_freq_fact based on the mode/size
|
|
|
|
// combination that wins out.
|
2013-07-02 13:34:41 +02:00
|
|
|
if (cpi->sf.adaptive_rd_thresh) {
|
2013-06-03 13:51:29 +02:00
|
|
|
for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
|
|
|
|
if (mode_index == best_mode_index) {
|
2013-08-23 15:00:54 +02:00
|
|
|
cpi->rd_thresh_freq_fact[bsize][mode_index] -=
|
|
|
|
(cpi->rd_thresh_freq_fact[bsize][mode_index] >> 3);
|
2013-06-03 13:51:29 +02:00
|
|
|
} else {
|
2013-08-23 15:00:54 +02:00
|
|
|
cpi->rd_thresh_freq_fact[bsize][mode_index] += RD_THRESH_INC;
|
2013-06-03 13:51:29 +02:00
|
|
|
if (cpi->rd_thresh_freq_fact[bsize][mode_index] >
|
2013-10-09 20:32:03 +02:00
|
|
|
(cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT)) {
|
2013-06-03 13:51:29 +02:00
|
|
|
cpi->rd_thresh_freq_fact[bsize][mode_index] =
|
2013-10-09 20:32:03 +02:00
|
|
|
cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT;
|
2013-06-03 13:51:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-20 23:43:34 +02:00
|
|
|
// macroblock modes
|
2013-06-01 01:00:32 +02:00
|
|
|
*mbmi = best_mbmode;
|
2013-06-28 02:41:54 +02:00
|
|
|
x->skip |= best_skip2;
|
2012-11-08 20:03:00 +01:00
|
|
|
|
2013-11-23 01:35:37 +01:00
|
|
|
for (i = 0; i < REFERENCE_MODES; ++i) {
|
2013-09-28 01:02:49 +02:00
|
|
|
if (best_pred_rd[i] == INT64_MAX)
|
|
|
|
best_pred_diff[i] = INT_MIN;
|
|
|
|
else
|
|
|
|
best_pred_diff[i] = best_rd - best_pred_rd[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!x->skip) {
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
|
2013-09-28 01:02:49 +02:00
|
|
|
if (best_filter_rd[i] == INT64_MAX)
|
|
|
|
best_filter_diff[i] = 0;
|
|
|
|
else
|
|
|
|
best_filter_diff[i] = best_rd - best_filter_rd[i];
|
|
|
|
}
|
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE)
|
|
|
|
assert(best_filter_diff[SWITCHABLE_FILTERS] == 0);
|
|
|
|
} else {
|
2013-10-03 21:32:31 +02:00
|
|
|
vp9_zero(best_filter_diff);
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!x->skip) {
|
|
|
|
for (i = 0; i < TX_MODES; i++) {
|
|
|
|
if (best_tx_rd[i] == INT64_MAX)
|
|
|
|
best_tx_diff[i] = 0;
|
|
|
|
else
|
|
|
|
best_tx_diff[i] = best_rd - best_tx_rd[i];
|
|
|
|
}
|
|
|
|
} else {
|
2013-10-03 21:32:31 +02:00
|
|
|
vp9_zero(best_tx_diff);
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
|
2013-12-20 01:06:33 +01:00
|
|
|
set_scale_factors(cm, xd, mbmi->ref_frame[0] - 1, mbmi->ref_frame[1] - 1);
|
2013-09-28 01:02:49 +02:00
|
|
|
store_coding_context(x, ctx, best_mode_index,
|
|
|
|
&mbmi->ref_mvs[mbmi->ref_frame[0]][0],
|
|
|
|
&mbmi->ref_mvs[mbmi->ref_frame[1] < 0 ? 0 :
|
|
|
|
mbmi->ref_frame[1]][0],
|
|
|
|
best_pred_diff, best_tx_diff, best_filter_diff);
|
|
|
|
|
|
|
|
return best_rd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int64_t vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x,
|
2013-10-25 17:18:04 +02:00
|
|
|
const TileInfo *const tile,
|
2013-09-28 01:02:49 +02:00
|
|
|
int mi_row, int mi_col,
|
|
|
|
int *returnrate,
|
|
|
|
int64_t *returndistortion,
|
|
|
|
BLOCK_SIZE bsize,
|
|
|
|
PICK_MODE_CONTEXT *ctx,
|
|
|
|
int64_t best_rd_so_far) {
|
|
|
|
VP9_COMMON *cm = &cpi->common;
|
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2013-10-10 21:11:44 +02:00
|
|
|
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
|
2013-09-28 01:02:49 +02:00
|
|
|
const struct segmentation *seg = &cm->seg;
|
|
|
|
const BLOCK_SIZE block_size = get_plane_block_size(bsize, &xd->plane[0]);
|
|
|
|
MV_REFERENCE_FRAME ref_frame, second_ref_frame;
|
|
|
|
unsigned char segment_id = mbmi->segment_id;
|
|
|
|
int comp_pred, i;
|
|
|
|
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
|
|
|
|
struct buf_2d yv12_mb[4][MAX_MB_PLANE];
|
|
|
|
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
|
|
|
|
VP9_ALT_FLAG };
|
|
|
|
int64_t best_rd = best_rd_so_far;
|
|
|
|
int64_t best_yrd = best_rd_so_far; // FIXME(rbultje) more precise
|
|
|
|
int64_t best_tx_rd[TX_MODES];
|
|
|
|
int64_t best_tx_diff[TX_MODES];
|
2013-11-23 01:35:37 +01:00
|
|
|
int64_t best_pred_diff[REFERENCE_MODES];
|
|
|
|
int64_t best_pred_rd[REFERENCE_MODES];
|
2013-10-30 22:40:34 +01:00
|
|
|
int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
|
|
|
|
int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
|
2013-09-28 01:02:49 +02:00
|
|
|
MB_MODE_INFO best_mbmode = { 0 };
|
|
|
|
int mode_index, best_mode_index = 0;
|
|
|
|
unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
|
|
|
|
vp9_prob comp_mode_p;
|
|
|
|
int64_t best_inter_rd = INT64_MAX;
|
|
|
|
MV_REFERENCE_FRAME best_inter_ref_frame = LAST_FRAME;
|
2013-10-24 02:45:52 +02:00
|
|
|
INTERPOLATION_TYPE tmp_best_filter = SWITCHABLE;
|
2013-09-28 01:02:49 +02:00
|
|
|
int rate_uv_intra[TX_SIZES], rate_uv_tokenonly[TX_SIZES];
|
|
|
|
int64_t dist_uv[TX_SIZES];
|
|
|
|
int skip_uv[TX_SIZES];
|
|
|
|
MB_PREDICTION_MODE mode_uv[TX_SIZES] = { 0 };
|
2014-01-07 02:29:16 +01:00
|
|
|
int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
|
2013-09-28 01:02:49 +02:00
|
|
|
int_mv seg_mvs[4][MAX_REF_FRAMES];
|
2013-10-03 02:05:31 +02:00
|
|
|
b_mode_info best_bmodes[4];
|
2013-09-28 01:02:49 +02:00
|
|
|
int best_skip2 = 0;
|
|
|
|
|
2013-11-13 02:28:27 +01:00
|
|
|
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
|
2013-10-30 21:52:55 +01:00
|
|
|
vpx_memset(x->zcoeff_blk[TX_4X4], 0, 4);
|
2013-09-28 01:02:49 +02:00
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
int j;
|
|
|
|
for (j = 0; j < MAX_REF_FRAMES; j++)
|
|
|
|
seg_mvs[i][j].as_int = INVALID_MV;
|
|
|
|
}
|
|
|
|
|
|
|
|
estimate_ref_frame_costs(cpi, segment_id, ref_costs_single, ref_costs_comp,
|
|
|
|
&comp_mode_p);
|
|
|
|
|
2013-11-23 01:35:37 +01:00
|
|
|
for (i = 0; i < REFERENCE_MODES; ++i)
|
2013-09-28 01:02:49 +02:00
|
|
|
best_pred_rd[i] = INT64_MAX;
|
|
|
|
for (i = 0; i < TX_MODES; i++)
|
|
|
|
best_tx_rd[i] = INT64_MAX;
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
|
2013-09-28 01:02:49 +02:00
|
|
|
best_filter_rd[i] = INT64_MAX;
|
|
|
|
for (i = 0; i < TX_SIZES; i++)
|
|
|
|
rate_uv_intra[i] = INT_MAX;
|
|
|
|
|
|
|
|
*returnrate = INT_MAX;
|
|
|
|
|
|
|
|
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
|
|
|
|
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
|
2014-01-06 23:50:54 +01:00
|
|
|
setup_buffer_inter(cpi, x, tile, get_ref_frame_idx(cpi, ref_frame),
|
|
|
|
ref_frame, block_size, mi_row, mi_col,
|
2013-10-25 17:18:04 +02:00
|
|
|
frame_mv[NEARESTMV], frame_mv[NEARMV],
|
2013-12-20 01:06:33 +01:00
|
|
|
yv12_mb);
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
|
|
|
|
frame_mv[ZEROMV][ref_frame].as_int = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (mode_index = 0; mode_index < MAX_REFS; ++mode_index) {
|
|
|
|
int mode_excluded = 0;
|
|
|
|
int64_t this_rd = INT64_MAX;
|
|
|
|
int disable_skip = 0;
|
|
|
|
int compmode_cost = 0;
|
|
|
|
int rate2 = 0, rate_y = 0, rate_uv = 0;
|
|
|
|
int64_t distortion2 = 0, distortion_y = 0, distortion_uv = 0;
|
|
|
|
int skippable = 0;
|
|
|
|
int64_t tx_cache[TX_MODES];
|
|
|
|
int i;
|
|
|
|
int this_skip2 = 0;
|
|
|
|
int64_t total_sse = INT_MAX;
|
|
|
|
int early_term = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < TX_MODES; ++i)
|
|
|
|
tx_cache[i] = INT64_MAX;
|
|
|
|
|
|
|
|
x->skip = 0;
|
2014-01-06 21:23:36 +01:00
|
|
|
ref_frame = vp9_ref_order[mode_index].ref_frame[0];
|
|
|
|
second_ref_frame = vp9_ref_order[mode_index].ref_frame[1];
|
2013-09-28 01:02:49 +02:00
|
|
|
|
2013-10-04 17:51:22 +02:00
|
|
|
// Look at the reference frame of the best mode so far and set the
|
|
|
|
// skip mask to look at a subset of the remaining modes.
|
|
|
|
if (mode_index > 2 && cpi->sf.mode_skip_start < MAX_MODES) {
|
|
|
|
if (mode_index == 3) {
|
2014-01-06 21:23:36 +01:00
|
|
|
switch (vp9_ref_order[best_mode_index].ref_frame[0]) {
|
2013-10-04 17:51:22 +02:00
|
|
|
case INTRA_FRAME:
|
|
|
|
cpi->mode_skip_mask = 0;
|
|
|
|
break;
|
|
|
|
case LAST_FRAME:
|
|
|
|
cpi->mode_skip_mask = 0x0010;
|
|
|
|
break;
|
|
|
|
case GOLDEN_FRAME:
|
|
|
|
cpi->mode_skip_mask = 0x0008;
|
|
|
|
break;
|
|
|
|
case ALTREF_FRAME:
|
|
|
|
cpi->mode_skip_mask = 0x0000;
|
|
|
|
break;
|
|
|
|
case NONE:
|
|
|
|
case MAX_REF_FRAMES:
|
2013-12-13 04:44:08 +01:00
|
|
|
assert(0 && "Invalid Reference frame");
|
2013-10-04 17:51:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cpi->mode_skip_mask & ((int64_t)1 << mode_index))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-09-28 01:02:49 +02:00
|
|
|
// Skip if the current reference frame has been masked off
|
|
|
|
if (cpi->sf.reference_masking && !cpi->set_ref_frame_mask &&
|
|
|
|
(cpi->ref_frame_mask & (1 << ref_frame)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Test best rd so far against threshold for trying this mode.
|
2013-10-07 20:20:10 +02:00
|
|
|
if ((best_rd <
|
|
|
|
((int64_t)cpi->rd_thresh_sub8x8[segment_id][bsize][mode_index] *
|
|
|
|
cpi->rd_thresh_freq_sub8x8[bsize][mode_index] >> 5)) ||
|
|
|
|
cpi->rd_thresh_sub8x8[segment_id][bsize][mode_index] == INT_MAX)
|
2013-09-28 01:02:49 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Do not allow compound prediction if the segment level reference
|
|
|
|
// frame feature is in use as in this case there can only be one reference.
|
|
|
|
if ((second_ref_frame > INTRA_FRAME) &&
|
|
|
|
vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
mbmi->ref_frame[0] = ref_frame;
|
|
|
|
mbmi->ref_frame[1] = second_ref_frame;
|
|
|
|
|
|
|
|
if (!(ref_frame == INTRA_FRAME
|
|
|
|
|| (cpi->ref_frame_flags & flag_list[ref_frame]))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!(second_ref_frame == NONE
|
|
|
|
|| (cpi->ref_frame_flags & flag_list[second_ref_frame]))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
comp_pred = second_ref_frame > INTRA_FRAME;
|
|
|
|
if (comp_pred) {
|
|
|
|
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA)
|
2014-01-06 21:23:36 +01:00
|
|
|
if (vp9_ref_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
|
2013-09-28 01:02:49 +02:00
|
|
|
continue;
|
|
|
|
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
|
|
|
|
if (ref_frame != best_inter_ref_frame &&
|
|
|
|
second_ref_frame != best_inter_ref_frame)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(jingning, jkoleszar): scaling reference frame not supported for
|
|
|
|
// sub8x8 blocks.
|
2014-01-07 02:29:16 +01:00
|
|
|
if (ref_frame > 0 && vp9_is_scaled(&cm->frame_refs[ref_frame - 1].sf))
|
2013-09-28 01:02:49 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (second_ref_frame > 0 &&
|
2014-01-07 02:29:16 +01:00
|
|
|
vp9_is_scaled(&cm->frame_refs[second_ref_frame - 1].sf))
|
2013-09-28 01:02:49 +02:00
|
|
|
continue;
|
|
|
|
|
2013-12-20 01:06:33 +01:00
|
|
|
set_scale_factors(cm, xd, ref_frame - 1, second_ref_frame - 1);
|
2013-09-28 01:02:49 +02:00
|
|
|
mbmi->uv_mode = DC_PRED;
|
|
|
|
|
|
|
|
// Evaluate all sub-pel filters irrespective of whether we can use
|
|
|
|
// them for this frame.
|
|
|
|
mbmi->interp_filter = cm->mcomp_filter_type;
|
2014-01-07 02:29:16 +01:00
|
|
|
vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
|
2013-09-28 01:02:49 +02:00
|
|
|
|
|
|
|
if (comp_pred) {
|
|
|
|
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
|
|
|
|
continue;
|
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
mode_excluded = mode_excluded ? mode_excluded
|
|
|
|
: cm->reference_mode == SINGLE_REFERENCE;
|
2013-09-28 01:02:49 +02:00
|
|
|
} else {
|
|
|
|
if (ref_frame != INTRA_FRAME && second_ref_frame != INTRA_FRAME) {
|
2013-12-10 00:13:34 +01:00
|
|
|
mode_excluded = mode_excluded ?
|
|
|
|
mode_excluded : cm->reference_mode == COMPOUND_REFERENCE;
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select prediction reference frames.
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++) {
|
|
|
|
xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
|
|
|
|
if (comp_pred)
|
|
|
|
xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the segment reference frame feature is enabled....
|
|
|
|
// then do nothing if the current ref frame is not allowed..
|
|
|
|
if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
|
|
|
|
vp9_get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) !=
|
|
|
|
(int)ref_frame) {
|
|
|
|
continue;
|
|
|
|
// If the segment skip feature is enabled....
|
|
|
|
// then do nothing if the current mode is not allowed..
|
|
|
|
} else if (vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) &&
|
|
|
|
ref_frame != INTRA_FRAME) {
|
|
|
|
continue;
|
|
|
|
// Disable this drop out case if the ref frame
|
|
|
|
// segment level feature is enabled for this segment. This is to
|
|
|
|
// prevent the possibility that we end up unable to pick any mode.
|
|
|
|
} else if (!vp9_segfeature_active(seg, segment_id,
|
|
|
|
SEG_LVL_REF_FRAME)) {
|
|
|
|
// Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
|
|
|
|
// unless ARNR filtering is enabled in which case we want
|
|
|
|
// an unfiltered alternative. We allow near/nearest as well
|
|
|
|
// because they may result in zero-zero MVs but be cheaper.
|
2013-12-13 18:32:05 +01:00
|
|
|
if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
|
2013-09-28 01:02:49 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MODE_TEST_HIT_STATS
|
|
|
|
// TEST/DEBUG CODE
|
|
|
|
// Keep a rcord of the number of test hits at each size
|
|
|
|
cpi->mode_test_hits[bsize]++;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (ref_frame == INTRA_FRAME) {
|
|
|
|
int rate;
|
|
|
|
mbmi->tx_size = TX_4X4;
|
|
|
|
if (rd_pick_intra_sub_8x8_y_mode(cpi, x, &rate, &rate_y,
|
|
|
|
&distortion_y, best_rd) >= best_rd)
|
|
|
|
continue;
|
|
|
|
rate2 += rate;
|
|
|
|
rate2 += intra_cost_penalty;
|
|
|
|
distortion2 += distortion_y;
|
|
|
|
|
|
|
|
if (rate_uv_intra[TX_4X4] == INT_MAX) {
|
2013-12-09 20:03:02 +01:00
|
|
|
choose_intra_uv_mode(cpi, ctx, bsize, TX_4X4,
|
|
|
|
&rate_uv_intra[TX_4X4],
|
2013-09-28 01:02:49 +02:00
|
|
|
&rate_uv_tokenonly[TX_4X4],
|
|
|
|
&dist_uv[TX_4X4], &skip_uv[TX_4X4],
|
|
|
|
&mode_uv[TX_4X4]);
|
|
|
|
}
|
|
|
|
rate2 += rate_uv_intra[TX_4X4];
|
|
|
|
rate_uv = rate_uv_tokenonly[TX_4X4];
|
|
|
|
distortion2 += dist_uv[TX_4X4];
|
|
|
|
distortion_uv = dist_uv[TX_4X4];
|
|
|
|
mbmi->uv_mode = mode_uv[TX_4X4];
|
|
|
|
tx_cache[ONLY_4X4] = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
|
|
|
|
for (i = 0; i < TX_MODES; ++i)
|
|
|
|
tx_cache[i] = tx_cache[ONLY_4X4];
|
|
|
|
} else {
|
|
|
|
int rate;
|
|
|
|
int64_t distortion;
|
|
|
|
int64_t this_rd_thresh;
|
|
|
|
int64_t tmp_rd, tmp_best_rd = INT64_MAX, tmp_best_rdu = INT64_MAX;
|
|
|
|
int tmp_best_rate = INT_MAX, tmp_best_ratey = INT_MAX;
|
|
|
|
int64_t tmp_best_distortion = INT_MAX, tmp_best_sse, uv_sse;
|
|
|
|
int tmp_best_skippable = 0;
|
|
|
|
int switchable_filter_index;
|
2013-10-03 23:00:42 +02:00
|
|
|
int_mv *second_ref = comp_pred ?
|
|
|
|
&mbmi->ref_mvs[second_ref_frame][0] : NULL;
|
2013-10-03 02:05:31 +02:00
|
|
|
b_mode_info tmp_best_bmodes[16];
|
2013-09-28 01:02:49 +02:00
|
|
|
MB_MODE_INFO tmp_best_mbmode;
|
|
|
|
BEST_SEG_INFO bsi[SWITCHABLE_FILTERS];
|
|
|
|
int pred_exists = 0;
|
|
|
|
int uv_skippable;
|
|
|
|
|
|
|
|
this_rd_thresh = (ref_frame == LAST_FRAME) ?
|
2013-10-07 20:20:10 +02:00
|
|
|
cpi->rd_thresh_sub8x8[segment_id][bsize][THR_LAST] :
|
|
|
|
cpi->rd_thresh_sub8x8[segment_id][bsize][THR_ALTR];
|
2013-09-28 01:02:49 +02:00
|
|
|
this_rd_thresh = (ref_frame == GOLDEN_FRAME) ?
|
2013-10-07 20:20:10 +02:00
|
|
|
cpi->rd_thresh_sub8x8[segment_id][bsize][THR_GOLD] : this_rd_thresh;
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->mbmi.tx_size = TX_4X4;
|
2013-09-28 01:02:49 +02:00
|
|
|
|
2013-12-17 02:52:59 +01:00
|
|
|
cpi->mask_filter_rd = 0;
|
2013-12-16 23:38:45 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
|
|
|
|
cpi->rd_filter_cache[i] = INT64_MAX;
|
|
|
|
|
2013-09-28 01:02:49 +02:00
|
|
|
if (cm->mcomp_filter_type != BILINEAR) {
|
|
|
|
tmp_best_filter = EIGHTTAP;
|
|
|
|
if (x->source_variance <
|
|
|
|
cpi->sf.disable_filter_search_var_thresh) {
|
|
|
|
tmp_best_filter = EIGHTTAP;
|
2013-12-13 02:31:04 +01:00
|
|
|
} else if (cpi->sf.adaptive_pred_filter_type == 1 &&
|
|
|
|
ctx->pred_filter_type < SWITCHABLE) {
|
|
|
|
tmp_best_filter = ctx->pred_filter_type;
|
|
|
|
} else if (cpi->sf.adaptive_pred_filter_type == 2) {
|
|
|
|
tmp_best_filter = ctx->pred_filter_type < SWITCHABLE ?
|
|
|
|
ctx->pred_filter_type : 0;
|
2013-09-28 01:02:49 +02:00
|
|
|
} else {
|
|
|
|
for (switchable_filter_index = 0;
|
|
|
|
switchable_filter_index < SWITCHABLE_FILTERS;
|
|
|
|
++switchable_filter_index) {
|
|
|
|
int newbest, rs;
|
|
|
|
int64_t rs_rd;
|
|
|
|
mbmi->interp_filter = switchable_filter_index;
|
2014-01-07 02:29:16 +01:00
|
|
|
vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
|
2013-09-28 01:02:49 +02:00
|
|
|
|
2013-10-25 17:18:04 +02:00
|
|
|
tmp_rd = rd_pick_best_mbsegmentation(cpi, x, tile,
|
2013-09-28 01:02:49 +02:00
|
|
|
&mbmi->ref_mvs[ref_frame][0],
|
|
|
|
second_ref,
|
|
|
|
best_yrd,
|
|
|
|
&rate, &rate_y, &distortion,
|
|
|
|
&skippable, &total_sse,
|
|
|
|
(int)this_rd_thresh, seg_mvs,
|
|
|
|
bsi, switchable_filter_index,
|
|
|
|
mi_row, mi_col);
|
|
|
|
|
|
|
|
if (tmp_rd == INT64_MAX)
|
|
|
|
continue;
|
|
|
|
rs = get_switchable_rate(x);
|
|
|
|
rs_rd = RDCOST(x->rdmult, x->rddiv, rs, 0);
|
2013-12-17 02:52:59 +01:00
|
|
|
cpi->rd_filter_cache[switchable_filter_index] = tmp_rd;
|
2013-09-28 01:02:49 +02:00
|
|
|
cpi->rd_filter_cache[SWITCHABLE_FILTERS] =
|
|
|
|
MIN(cpi->rd_filter_cache[SWITCHABLE_FILTERS],
|
|
|
|
tmp_rd + rs_rd);
|
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE)
|
|
|
|
tmp_rd += rs_rd;
|
|
|
|
|
2013-12-17 02:52:59 +01:00
|
|
|
cpi->mask_filter_rd = MAX(cpi->mask_filter_rd, tmp_rd);
|
2013-12-16 23:38:45 +01:00
|
|
|
|
2013-09-28 01:02:49 +02:00
|
|
|
newbest = (tmp_rd < tmp_best_rd);
|
|
|
|
if (newbest) {
|
|
|
|
tmp_best_filter = mbmi->interp_filter;
|
|
|
|
tmp_best_rd = tmp_rd;
|
|
|
|
}
|
|
|
|
if ((newbest && cm->mcomp_filter_type == SWITCHABLE) ||
|
|
|
|
(mbmi->interp_filter == cm->mcomp_filter_type &&
|
|
|
|
cm->mcomp_filter_type != SWITCHABLE)) {
|
|
|
|
tmp_best_rdu = tmp_rd;
|
|
|
|
tmp_best_rate = rate;
|
|
|
|
tmp_best_ratey = rate_y;
|
|
|
|
tmp_best_distortion = distortion;
|
|
|
|
tmp_best_sse = total_sse;
|
|
|
|
tmp_best_skippable = skippable;
|
|
|
|
tmp_best_mbmode = *mbmi;
|
2013-10-30 21:52:55 +01:00
|
|
|
for (i = 0; i < 4; i++) {
|
2013-10-10 21:11:44 +02:00
|
|
|
tmp_best_bmodes[i] = xd->mi_8x8[0]->bmi[i];
|
2013-12-04 02:59:32 +01:00
|
|
|
x->zcoeff_blk[TX_4X4][i] = !x->plane[0].eobs[i];
|
2013-10-30 21:52:55 +01:00
|
|
|
}
|
2013-09-28 01:02:49 +02:00
|
|
|
pred_exists = 1;
|
|
|
|
if (switchable_filter_index == 0 &&
|
|
|
|
cpi->sf.use_rd_breakout &&
|
|
|
|
best_rd < INT64_MAX) {
|
|
|
|
if (tmp_best_rdu / 2 > best_rd) {
|
|
|
|
// skip searching the other filters if the first is
|
|
|
|
// already substantially larger than the best so far
|
|
|
|
tmp_best_filter = mbmi->interp_filter;
|
|
|
|
tmp_best_rdu = INT64_MAX;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // switchable_filter_index loop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-13 02:31:04 +01:00
|
|
|
if (tmp_best_rdu == INT64_MAX && pred_exists)
|
2013-09-28 01:02:49 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
mbmi->interp_filter = (cm->mcomp_filter_type == SWITCHABLE ?
|
|
|
|
tmp_best_filter : cm->mcomp_filter_type);
|
2014-01-07 02:29:16 +01:00
|
|
|
vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
|
2013-09-28 01:02:49 +02:00
|
|
|
if (!pred_exists) {
|
|
|
|
// Handles the special case when a filter that is not in the
|
|
|
|
// switchable list (bilinear, 6-tap) is indicated at the frame level
|
2013-10-25 17:18:04 +02:00
|
|
|
tmp_rd = rd_pick_best_mbsegmentation(cpi, x, tile,
|
2013-09-28 01:02:49 +02:00
|
|
|
&mbmi->ref_mvs[ref_frame][0],
|
|
|
|
second_ref,
|
|
|
|
best_yrd,
|
|
|
|
&rate, &rate_y, &distortion,
|
|
|
|
&skippable, &total_sse,
|
|
|
|
(int)this_rd_thresh, seg_mvs,
|
|
|
|
bsi, 0,
|
|
|
|
mi_row, mi_col);
|
|
|
|
if (tmp_rd == INT64_MAX)
|
|
|
|
continue;
|
|
|
|
} else {
|
2014-01-07 02:29:16 +01:00
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE) {
|
2013-09-28 01:02:49 +02:00
|
|
|
int rs = get_switchable_rate(x);
|
|
|
|
tmp_best_rdu -= RDCOST(x->rdmult, x->rddiv, rs, 0);
|
|
|
|
}
|
|
|
|
tmp_rd = tmp_best_rdu;
|
|
|
|
total_sse = tmp_best_sse;
|
|
|
|
rate = tmp_best_rate;
|
|
|
|
rate_y = tmp_best_ratey;
|
|
|
|
distortion = tmp_best_distortion;
|
|
|
|
skippable = tmp_best_skippable;
|
|
|
|
*mbmi = tmp_best_mbmode;
|
|
|
|
for (i = 0; i < 4; i++)
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->bmi[i] = tmp_best_bmodes[i];
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
rate2 += rate;
|
|
|
|
distortion2 += distortion;
|
|
|
|
|
2014-01-07 02:29:16 +01:00
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE)
|
2013-09-28 01:02:49 +02:00
|
|
|
rate2 += get_switchable_rate(x);
|
|
|
|
|
2013-12-10 00:13:34 +01:00
|
|
|
if (!mode_excluded)
|
2014-01-07 02:29:16 +01:00
|
|
|
mode_excluded = comp_pred ? cm->reference_mode == SINGLE_REFERENCE
|
|
|
|
: cm->reference_mode == COMPOUND_REFERENCE;
|
2013-12-10 00:13:34 +01:00
|
|
|
|
2013-10-03 23:00:42 +02:00
|
|
|
compmode_cost = vp9_cost_bit(comp_mode_p, comp_pred);
|
2013-06-01 01:00:32 +02:00
|
|
|
|
2013-09-28 01:02:49 +02:00
|
|
|
tmp_best_rdu = best_rd -
|
|
|
|
MIN(RDCOST(x->rdmult, x->rddiv, rate2, distortion2),
|
|
|
|
RDCOST(x->rdmult, x->rddiv, 0, total_sse));
|
|
|
|
|
|
|
|
if (tmp_best_rdu > 0) {
|
|
|
|
// If even the 'Y' rd value of split is higher than best so far
|
|
|
|
// then dont bother looking at UV
|
|
|
|
vp9_build_inter_predictors_sbuv(&x->e_mbd, mi_row, mi_col,
|
|
|
|
BLOCK_8X8);
|
2013-10-10 19:37:40 +02:00
|
|
|
super_block_uvrd(cpi, x, &rate_uv, &distortion_uv, &uv_skippable,
|
2013-09-28 01:02:49 +02:00
|
|
|
&uv_sse, BLOCK_8X8, tmp_best_rdu);
|
|
|
|
if (rate_uv == INT_MAX)
|
|
|
|
continue;
|
|
|
|
rate2 += rate_uv;
|
|
|
|
distortion2 += distortion_uv;
|
|
|
|
skippable = skippable && uv_skippable;
|
|
|
|
total_sse += uv_sse;
|
|
|
|
|
|
|
|
tx_cache[ONLY_4X4] = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
|
|
|
|
for (i = 0; i < TX_MODES; ++i)
|
|
|
|
tx_cache[i] = tx_cache[ONLY_4X4];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-07 02:29:16 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT)
|
2013-09-28 01:02:49 +02:00
|
|
|
rate2 += compmode_cost;
|
|
|
|
|
|
|
|
// Estimate the reference frame signaling cost and add it
|
|
|
|
// to the rolling cost variable.
|
|
|
|
if (second_ref_frame > INTRA_FRAME) {
|
|
|
|
rate2 += ref_costs_comp[ref_frame];
|
|
|
|
} else {
|
|
|
|
rate2 += ref_costs_single[ref_frame];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!disable_skip) {
|
|
|
|
// Test for the condition where skip block will be activated
|
|
|
|
// because there are no non zero coefficients and make any
|
|
|
|
// necessary adjustment for rate. Ignore if skip is coded at
|
|
|
|
// segment level as the cost wont have been added in.
|
|
|
|
// Is Mb level skip allowed (i.e. not coded at segment level).
|
|
|
|
const int mb_skip_allowed = !vp9_segfeature_active(seg, segment_id,
|
|
|
|
SEG_LVL_SKIP);
|
|
|
|
|
|
|
|
if (mb_skip_allowed && ref_frame != INTRA_FRAME && !xd->lossless) {
|
|
|
|
if (RDCOST(x->rdmult, x->rddiv, rate_y + rate_uv, distortion2) <
|
|
|
|
RDCOST(x->rdmult, x->rddiv, 0, total_sse)) {
|
|
|
|
// Add in the cost of the no skip flag.
|
2013-12-10 23:11:26 +01:00
|
|
|
rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0);
|
2013-09-28 01:02:49 +02:00
|
|
|
} else {
|
|
|
|
// FIXME(rbultje) make this work for splitmv also
|
2013-12-10 23:11:26 +01:00
|
|
|
rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
|
2013-09-28 01:02:49 +02:00
|
|
|
distortion2 = total_sse;
|
|
|
|
assert(total_sse >= 0);
|
|
|
|
rate2 -= (rate_y + rate_uv);
|
|
|
|
rate_y = 0;
|
|
|
|
rate_uv = 0;
|
|
|
|
this_skip2 = 1;
|
|
|
|
}
|
|
|
|
} else if (mb_skip_allowed) {
|
|
|
|
// Add in the cost of the no skip flag.
|
2013-12-10 23:11:26 +01:00
|
|
|
rate2 += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0);
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the final RD estimate for this mode.
|
|
|
|
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keep record of best inter rd with single reference
|
2013-11-20 05:25:55 +01:00
|
|
|
if (is_inter_block(&xd->mi_8x8[0]->mbmi) &&
|
|
|
|
!has_second_ref(&xd->mi_8x8[0]->mbmi) &&
|
2013-09-28 01:02:49 +02:00
|
|
|
!mode_excluded &&
|
|
|
|
this_rd < best_inter_rd) {
|
|
|
|
best_inter_rd = this_rd;
|
|
|
|
best_inter_ref_frame = ref_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!disable_skip && ref_frame == INTRA_FRAME) {
|
2013-11-23 01:35:37 +01:00
|
|
|
for (i = 0; i < REFERENCE_MODES; ++i)
|
2013-09-28 01:02:49 +02:00
|
|
|
best_pred_rd[i] = MIN(best_pred_rd[i], this_rd);
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
|
2013-09-28 01:02:49 +02:00
|
|
|
best_filter_rd[i] = MIN(best_filter_rd[i], this_rd);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Did this mode help.. i.e. is it the new best mode
|
|
|
|
if (this_rd < best_rd || x->skip) {
|
|
|
|
if (!mode_excluded) {
|
2013-11-07 23:56:58 +01:00
|
|
|
int max_plane = MAX_MB_PLANE;
|
2013-09-28 01:02:49 +02:00
|
|
|
// Note index of best mode so far
|
|
|
|
best_mode_index = mode_index;
|
|
|
|
|
|
|
|
if (ref_frame == INTRA_FRAME) {
|
|
|
|
/* required for left and above block mv */
|
|
|
|
mbmi->mv[0].as_int = 0;
|
2013-11-07 23:56:58 +01:00
|
|
|
max_plane = 1;
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*returnrate = rate2;
|
|
|
|
*returndistortion = distortion2;
|
|
|
|
best_rd = this_rd;
|
|
|
|
best_yrd = best_rd -
|
|
|
|
RDCOST(x->rdmult, x->rddiv, rate_uv, distortion_uv);
|
|
|
|
best_mbmode = *mbmi;
|
|
|
|
best_skip2 = this_skip2;
|
2013-11-06 06:07:08 +01:00
|
|
|
if (!x->select_txfm_size)
|
2013-11-07 23:56:58 +01:00
|
|
|
swap_block_ptr(x, ctx, max_plane);
|
2013-10-15 01:03:23 +02:00
|
|
|
vpx_memcpy(ctx->zcoeff_blk, x->zcoeff_blk[mbmi->tx_size],
|
2013-10-16 21:43:03 +02:00
|
|
|
sizeof(uint8_t) * ctx->num_4x4_blk);
|
2013-09-28 01:02:49 +02:00
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
2013-10-10 21:11:44 +02:00
|
|
|
best_bmodes[i] = xd->mi_8x8[0]->bmi[i];
|
2013-09-28 01:02:49 +02:00
|
|
|
|
|
|
|
// TODO(debargha): enhance this test with a better distortion prediction
|
|
|
|
// based on qp, activity mask and history
|
2013-10-03 02:05:31 +02:00
|
|
|
if ((cpi->sf.mode_search_skip_flags & FLAG_EARLY_TERMINATE) &&
|
|
|
|
(mode_index > MIN_EARLY_TERM_INDEX)) {
|
2013-09-28 01:02:49 +02:00
|
|
|
const int qstep = xd->plane[0].dequant[1];
|
|
|
|
// TODO(debargha): Enhance this by specializing for each mode_index
|
|
|
|
int scale = 4;
|
|
|
|
if (x->source_variance < UINT_MAX) {
|
|
|
|
const int var_adjust = (x->source_variance < 16);
|
|
|
|
scale -= var_adjust;
|
|
|
|
}
|
|
|
|
if (ref_frame > INTRA_FRAME &&
|
|
|
|
distortion2 * scale < qstep * qstep) {
|
|
|
|
early_term = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* keep record of best compound/single-only prediction */
|
|
|
|
if (!disable_skip && ref_frame != INTRA_FRAME) {
|
2013-11-25 21:45:51 +01:00
|
|
|
int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
|
2013-09-28 01:02:49 +02:00
|
|
|
|
2014-01-07 02:29:16 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT) {
|
2013-09-28 01:02:49 +02:00
|
|
|
single_rate = rate2 - compmode_cost;
|
|
|
|
hybrid_rate = rate2;
|
|
|
|
} else {
|
|
|
|
single_rate = rate2;
|
|
|
|
hybrid_rate = rate2 + compmode_cost;
|
|
|
|
}
|
|
|
|
|
|
|
|
single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
|
|
|
|
hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
|
|
|
|
|
|
|
|
if (second_ref_frame <= INTRA_FRAME &&
|
2013-11-23 01:35:37 +01:00
|
|
|
single_rd < best_pred_rd[SINGLE_REFERENCE]) {
|
|
|
|
best_pred_rd[SINGLE_REFERENCE] = single_rd;
|
2013-09-28 01:02:49 +02:00
|
|
|
} else if (second_ref_frame > INTRA_FRAME &&
|
2013-11-23 01:35:37 +01:00
|
|
|
single_rd < best_pred_rd[COMPOUND_REFERENCE]) {
|
|
|
|
best_pred_rd[COMPOUND_REFERENCE] = single_rd;
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
2013-11-23 01:35:37 +01:00
|
|
|
if (hybrid_rd < best_pred_rd[REFERENCE_MODE_SELECT])
|
|
|
|
best_pred_rd[REFERENCE_MODE_SELECT] = hybrid_rd;
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* keep record of best filter type */
|
|
|
|
if (!mode_excluded && !disable_skip && ref_frame != INTRA_FRAME &&
|
|
|
|
cm->mcomp_filter_type != BILINEAR) {
|
|
|
|
int64_t ref = cpi->rd_filter_cache[cm->mcomp_filter_type == SWITCHABLE ?
|
|
|
|
SWITCHABLE_FILTERS : cm->mcomp_filter_type];
|
2013-12-16 23:38:45 +01:00
|
|
|
int64_t adj_rd;
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
|
2013-12-16 23:38:45 +01:00
|
|
|
if (ref == INT64_MAX)
|
|
|
|
adj_rd = 0;
|
|
|
|
else if (cpi->rd_filter_cache[i] == INT64_MAX)
|
2013-12-17 02:52:59 +01:00
|
|
|
// when early termination is triggered, the encoder does not have
|
|
|
|
// access to the rate-distortion cost. it only knows that the cost
|
|
|
|
// should be above the maximum valid value. hence it takes the known
|
|
|
|
// maximum plus an arbitrary constant as the rate-distortion cost.
|
|
|
|
adj_rd = cpi->mask_filter_rd - ref + 10;
|
2013-12-16 23:38:45 +01:00
|
|
|
else
|
|
|
|
adj_rd = cpi->rd_filter_cache[i] - ref;
|
|
|
|
|
|
|
|
adj_rd += this_rd;
|
2013-09-28 01:02:49 +02:00
|
|
|
best_filter_rd[i] = MIN(best_filter_rd[i], adj_rd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* keep record of best txfm size */
|
|
|
|
if (bsize < BLOCK_32X32) {
|
|
|
|
if (bsize < BLOCK_16X16) {
|
|
|
|
tx_cache[ALLOW_8X8] = tx_cache[ONLY_4X4];
|
|
|
|
tx_cache[ALLOW_16X16] = tx_cache[ALLOW_8X8];
|
|
|
|
}
|
|
|
|
tx_cache[ALLOW_32X32] = tx_cache[ALLOW_16X16];
|
|
|
|
}
|
|
|
|
if (!mode_excluded && this_rd != INT64_MAX) {
|
|
|
|
for (i = 0; i < TX_MODES && tx_cache[i] < INT64_MAX; i++) {
|
|
|
|
int64_t adj_rd = INT64_MAX;
|
|
|
|
if (ref_frame > INTRA_FRAME)
|
|
|
|
adj_rd = this_rd + tx_cache[i] - tx_cache[cm->tx_mode];
|
|
|
|
else
|
|
|
|
adj_rd = this_rd;
|
|
|
|
|
|
|
|
if (adj_rd < best_tx_rd[i])
|
|
|
|
best_tx_rd[i] = adj_rd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (early_term)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (x->skip && !comp_pred)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (best_rd >= best_rd_so_far)
|
|
|
|
return INT64_MAX;
|
|
|
|
|
|
|
|
// If we used an estimate for the uv intra rd in the loop above...
|
|
|
|
if (cpi->sf.use_uv_intra_rd_estimate) {
|
|
|
|
// Do Intra UV best rd mode selection if best mode choice above was intra.
|
2014-01-06 21:23:36 +01:00
|
|
|
if (vp9_ref_order[best_mode_index].ref_frame[0] == INTRA_FRAME) {
|
2013-12-03 00:24:41 +01:00
|
|
|
TX_SIZE uv_tx_size;
|
|
|
|
*mbmi = best_mbmode;
|
|
|
|
uv_tx_size = get_uv_tx_size(mbmi);
|
2013-11-07 23:56:58 +01:00
|
|
|
rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv_intra[uv_tx_size],
|
2013-09-28 01:02:49 +02:00
|
|
|
&rate_uv_tokenonly[uv_tx_size],
|
|
|
|
&dist_uv[uv_tx_size],
|
|
|
|
&skip_uv[uv_tx_size],
|
2013-12-09 20:03:02 +01:00
|
|
|
BLOCK_8X8, uv_tx_size);
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we are using reference masking and the set mask flag is set then
|
|
|
|
// create the reference frame mask.
|
|
|
|
if (cpi->sf.reference_masking && cpi->set_ref_frame_mask)
|
2014-01-06 21:23:36 +01:00
|
|
|
cpi->ref_frame_mask = ~(1 << vp9_ref_order[best_mode_index].ref_frame[0]);
|
2013-09-28 01:02:49 +02:00
|
|
|
|
|
|
|
if (best_rd == INT64_MAX && bsize < BLOCK_8X8) {
|
|
|
|
*returnrate = INT_MAX;
|
|
|
|
*returndistortion = INT_MAX;
|
|
|
|
return best_rd;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert((cm->mcomp_filter_type == SWITCHABLE) ||
|
|
|
|
(cm->mcomp_filter_type == best_mbmode.interp_filter) ||
|
2013-11-20 05:25:55 +01:00
|
|
|
!is_inter_block(&best_mbmode));
|
2013-09-28 01:02:49 +02:00
|
|
|
|
|
|
|
// Updating rd_thresh_freq_fact[] here means that the different
|
|
|
|
// partition/block sizes are handled independently based on the best
|
|
|
|
// choice for the current partition. It may well be better to keep a scaled
|
|
|
|
// best rd so far value and update rd_thresh_freq_fact based on the mode/size
|
|
|
|
// combination that wins out.
|
|
|
|
if (cpi->sf.adaptive_rd_thresh) {
|
|
|
|
for (mode_index = 0; mode_index < MAX_REFS; ++mode_index) {
|
|
|
|
if (mode_index == best_mode_index) {
|
|
|
|
cpi->rd_thresh_freq_sub8x8[bsize][mode_index] -=
|
|
|
|
(cpi->rd_thresh_freq_sub8x8[bsize][mode_index] >> 3);
|
|
|
|
} else {
|
|
|
|
cpi->rd_thresh_freq_sub8x8[bsize][mode_index] += RD_THRESH_INC;
|
|
|
|
if (cpi->rd_thresh_freq_sub8x8[bsize][mode_index] >
|
2013-10-09 20:32:03 +02:00
|
|
|
(cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT)) {
|
2013-09-28 01:02:49 +02:00
|
|
|
cpi->rd_thresh_freq_sub8x8[bsize][mode_index] =
|
2013-10-09 20:32:03 +02:00
|
|
|
cpi->sf.adaptive_rd_thresh * RD_THRESH_MAX_FACT;
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// macroblock modes
|
|
|
|
*mbmi = best_mbmode;
|
|
|
|
x->skip |= best_skip2;
|
2013-11-20 05:25:55 +01:00
|
|
|
if (!is_inter_block(&best_mbmode)) {
|
2013-09-28 01:02:49 +02:00
|
|
|
for (i = 0; i < 4; i++)
|
2013-10-10 21:11:44 +02:00
|
|
|
xd->mi_8x8[0]->bmi[i].as_mode = best_bmodes[i].as_mode;
|
2013-09-28 01:02:49 +02:00
|
|
|
} else {
|
2013-10-07 20:20:50 +02:00
|
|
|
for (i = 0; i < 4; ++i)
|
2013-10-10 21:11:44 +02:00
|
|
|
vpx_memcpy(&xd->mi_8x8[0]->bmi[i], &best_bmodes[i], sizeof(b_mode_info));
|
2013-05-01 23:43:33 +02:00
|
|
|
|
2013-10-10 21:11:44 +02:00
|
|
|
mbmi->mv[0].as_int = xd->mi_8x8[0]->bmi[3].as_mv[0].as_int;
|
|
|
|
mbmi->mv[1].as_int = xd->mi_8x8[0]->bmi[3].as_mv[1].as_int;
|
2013-05-01 23:43:33 +02:00
|
|
|
}
|
2013-05-05 07:09:43 +02:00
|
|
|
|
2013-11-23 01:35:37 +01:00
|
|
|
for (i = 0; i < REFERENCE_MODES; ++i) {
|
2013-01-14 20:49:30 +01:00
|
|
|
if (best_pred_rd[i] == INT64_MAX)
|
2012-11-08 20:03:00 +01:00
|
|
|
best_pred_diff[i] = INT_MIN;
|
|
|
|
else
|
|
|
|
best_pred_diff[i] = best_rd - best_pred_rd[i];
|
|
|
|
}
|
|
|
|
|
2013-07-08 23:49:33 +02:00
|
|
|
if (!x->skip) {
|
2013-10-30 22:40:34 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) {
|
2013-07-08 23:49:33 +02:00
|
|
|
if (best_filter_rd[i] == INT64_MAX)
|
|
|
|
best_filter_diff[i] = 0;
|
|
|
|
else
|
|
|
|
best_filter_diff[i] = best_rd - best_filter_rd[i];
|
|
|
|
}
|
|
|
|
if (cm->mcomp_filter_type == SWITCHABLE)
|
2013-08-23 03:40:34 +02:00
|
|
|
assert(best_filter_diff[SWITCHABLE_FILTERS] == 0);
|
2013-07-08 23:49:33 +02:00
|
|
|
} else {
|
2013-09-27 02:43:55 +02:00
|
|
|
vp9_zero(best_filter_diff);
|
2013-07-08 23:49:33 +02:00
|
|
|
}
|
|
|
|
|
2012-11-08 20:03:00 +01:00
|
|
|
if (!x->skip) {
|
2013-07-29 22:38:40 +02:00
|
|
|
for (i = 0; i < TX_MODES; i++) {
|
2013-08-03 02:28:23 +02:00
|
|
|
if (best_tx_rd[i] == INT64_MAX)
|
|
|
|
best_tx_diff[i] = 0;
|
2012-11-08 20:03:00 +01:00
|
|
|
else
|
2013-08-03 02:28:23 +02:00
|
|
|
best_tx_diff[i] = best_rd - best_tx_rd[i];
|
2012-11-08 20:03:00 +01:00
|
|
|
}
|
|
|
|
} else {
|
2013-09-27 02:43:55 +02:00
|
|
|
vp9_zero(best_tx_diff);
|
2012-11-08 20:03:00 +01:00
|
|
|
}
|
|
|
|
|
2013-12-20 01:06:33 +01:00
|
|
|
set_scale_factors(cm, xd, mbmi->ref_frame[0] - 1, mbmi->ref_frame[1] - 1);
|
2013-05-01 23:43:33 +02:00
|
|
|
store_coding_context(x, ctx, best_mode_index,
|
2013-06-06 22:44:34 +02:00
|
|
|
&mbmi->ref_mvs[mbmi->ref_frame[0]][0],
|
|
|
|
&mbmi->ref_mvs[mbmi->ref_frame[1] < 0 ? 0 :
|
|
|
|
mbmi->ref_frame[1]][0],
|
2013-08-03 02:28:23 +02:00
|
|
|
best_pred_diff, best_tx_diff, best_filter_diff);
|
2012-08-20 23:43:34 +02:00
|
|
|
|
|
|
|
return best_rd;
|
|
|
|
}
|