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
|
|
|
*/
|
|
|
|
|
2013-08-23 00:50:51 +02:00
|
|
|
#include <limits.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2013-05-31 00:13:08 +02:00
|
|
|
#include "./vp9_rtcd.h"
|
2015-05-15 20:52:03 +02:00
|
|
|
#include "./vpx_dsp_rtcd.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "./vpx_config.h"
|
|
|
|
|
2015-08-31 23:36:35 +02:00
|
|
|
#include "vpx_dsp/vpx_dsp_common.h"
|
2015-05-12 04:09:22 +02:00
|
|
|
#include "vpx_ports/mem.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vpx_ports/vpx_timer.h"
|
2015-08-10 20:28:04 +02:00
|
|
|
#include "vpx_ports/system_state.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_common.h"
|
2012-11-29 00:15:51 +01:00
|
|
|
#include "vp9/common/vp9_entropy.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_entropymode.h"
|
2013-10-08 20:27:56 +02:00
|
|
|
#include "vp9/common/vp9_idct.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/common/vp9_mvref_common.h"
|
|
|
|
#include "vp9/common/vp9_pred_common.h"
|
|
|
|
#include "vp9/common/vp9_quant_common.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_reconintra.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/common/vp9_reconinter.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/common/vp9_seg_common.h"
|
2013-02-07 00:30:21 +01:00
|
|
|
#include "vp9/common/vp9_tile_common.h"
|
2014-03-07 19:56:20 +01:00
|
|
|
|
2015-12-17 00:34:07 +01:00
|
|
|
#include "vp9/encoder/vp9_aq_360.h"
|
2014-03-27 00:05:45 +01:00
|
|
|
#include "vp9/encoder/vp9_aq_complexity.h"
|
2014-03-21 22:31:53 +01:00
|
|
|
#include "vp9/encoder/vp9_aq_cyclicrefresh.h"
|
|
|
|
#include "vp9/encoder/vp9_aq_variance.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/encoder/vp9_encodeframe.h"
|
|
|
|
#include "vp9/encoder/vp9_encodemb.h"
|
|
|
|
#include "vp9/encoder/vp9_encodemv.h"
|
2014-12-03 00:47:41 +01:00
|
|
|
#include "vp9/encoder/vp9_ethread.h"
|
2013-11-18 21:36:55 +01:00
|
|
|
#include "vp9/encoder/vp9_extend.h"
|
2014-01-10 20:51:20 +01:00
|
|
|
#include "vp9/encoder/vp9_pickmode.h"
|
2014-07-02 21:36:48 +02:00
|
|
|
#include "vp9/encoder/vp9_rd.h"
|
2013-08-23 00:50:51 +02:00
|
|
|
#include "vp9/encoder/vp9_rdopt.h"
|
|
|
|
#include "vp9/encoder/vp9_segmentation.h"
|
2012-11-27 22:59:17 +01:00
|
|
|
#include "vp9/encoder/vp9_tokenize.h"
|
2013-10-07 20:20:10 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void encode_superblock(VP9_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
|
|
|
|
int output_enabled, int mi_row, int mi_col,
|
|
|
|
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx);
|
2012-10-30 22:25:33 +01:00
|
|
|
|
2017-02-27 23:26:15 +01:00
|
|
|
// Machine learning-based early termination parameters.
|
|
|
|
static const double train_mean[24] = {
|
|
|
|
303501.697372, 3042630.372158, 24.694696, 1.392182,
|
|
|
|
689.413511, 162.027012, 1.478213, 0.0,
|
|
|
|
135382.260230, 912738.513263, 28.845217, 1.515230,
|
|
|
|
544.158492, 131.807995, 1.436863, 0.0,
|
|
|
|
43682.377587, 208131.711766, 28.084737, 1.356677,
|
|
|
|
138.254122, 119.522553, 1.252322, 0.0
|
|
|
|
};
|
|
|
|
|
|
|
|
static const double train_stdm[24] = {
|
|
|
|
673689.212982, 5996652.516628, 0.024449, 1.989792,
|
|
|
|
985.880847, 0.014638, 2.001898, 0.0,
|
|
|
|
208798.775332, 1812548.443284, 0.018693, 1.838009,
|
|
|
|
396.986910, 0.015657, 1.332541, 0.0,
|
|
|
|
55888.847031, 448587.962714, 0.017900, 1.904776,
|
|
|
|
98.652832, 0.016598, 1.320992, 0.0
|
|
|
|
};
|
|
|
|
|
|
|
|
// Error tolerance: 0.01%-0.0.05%-0.1%
|
|
|
|
static const double classifiers[24] = {
|
|
|
|
0.111736, 0.289977, 0.042219, 0.204765, 0.120410, -0.143863,
|
|
|
|
0.282376, 0.847811, 0.637161, 0.131570, 0.018636, 0.202134,
|
|
|
|
0.112797, 0.028162, 0.182450, 1.124367, 0.386133, 0.083700,
|
|
|
|
0.050028, 0.150873, 0.061119, 0.109318, 0.127255, 0.625211
|
|
|
|
};
|
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
// This is used as a reference when computing the source variance for the
|
2016-06-15 03:57:29 +02:00
|
|
|
// purpose of activity masking.
|
2014-01-10 22:48:44 +01:00
|
|
|
// Eventually this should be replaced by custom no-reference routines,
|
|
|
|
// which will be faster.
|
2013-08-01 21:56:12 +02:00
|
|
|
static const uint8_t VP9_VAR_OFFS[64] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
|
2013-08-01 21:56:12 +02:00
|
|
|
};
|
|
|
|
|
2014-09-24 15:36:34 +02:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
static const uint16_t VP9_HIGH_VAR_OFFS_8[64] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
|
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
|
2014-09-24 15:36:34 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const uint16_t VP9_HIGH_VAR_OFFS_10[64] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
|
|
|
|
128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
|
|
|
|
128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
|
|
|
|
128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
|
|
|
|
128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
|
|
|
|
128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
|
|
|
|
128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4,
|
|
|
|
128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4, 128 * 4
|
2014-09-24 15:36:34 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const uint16_t VP9_HIGH_VAR_OFFS_12[64] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16, 128 * 16,
|
|
|
|
128 * 16
|
2014-09-24 15:36:34 +02:00
|
|
|
};
|
|
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
|
2017-09-27 19:17:18 +02:00
|
|
|
unsigned int vp9_get_sby_variance(VP9_COMP *cpi, const struct buf_2d *ref,
|
|
|
|
BLOCK_SIZE bs) {
|
2014-04-09 00:43:51 +02:00
|
|
|
unsigned int sse;
|
2016-07-27 05:43:23 +02:00
|
|
|
const unsigned int var =
|
|
|
|
cpi->fn_ptr[bs].vf(ref->buf, ref->stride, VP9_VAR_OFFS, 0, &sse);
|
2017-09-27 19:17:18 +02:00
|
|
|
return var;
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
}
|
|
|
|
|
2014-09-24 15:36:34 +02:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
2017-09-27 19:17:18 +02:00
|
|
|
unsigned int vp9_high_get_sby_variance(VP9_COMP *cpi, const struct buf_2d *ref,
|
|
|
|
BLOCK_SIZE bs, int bd) {
|
2014-09-24 15:36:34 +02:00
|
|
|
unsigned int var, sse;
|
|
|
|
switch (bd) {
|
|
|
|
case 10:
|
2016-07-27 05:43:23 +02:00
|
|
|
var =
|
|
|
|
cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
|
|
|
|
CONVERT_TO_BYTEPTR(VP9_HIGH_VAR_OFFS_10), 0, &sse);
|
2014-09-24 15:36:34 +02:00
|
|
|
break;
|
|
|
|
case 12:
|
2016-07-27 05:43:23 +02:00
|
|
|
var =
|
|
|
|
cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
|
|
|
|
CONVERT_TO_BYTEPTR(VP9_HIGH_VAR_OFFS_12), 0, &sse);
|
2014-09-24 15:36:34 +02:00
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
default:
|
2016-07-27 05:43:23 +02:00
|
|
|
var =
|
|
|
|
cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
|
|
|
|
CONVERT_TO_BYTEPTR(VP9_HIGH_VAR_OFFS_8), 0, &sse);
|
2014-09-24 15:36:34 +02:00
|
|
|
break;
|
|
|
|
}
|
2017-09-27 19:17:18 +02:00
|
|
|
return var;
|
|
|
|
}
|
|
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
|
|
|
|
unsigned int vp9_get_sby_perpixel_variance(VP9_COMP *cpi,
|
|
|
|
const struct buf_2d *ref,
|
|
|
|
BLOCK_SIZE bs) {
|
|
|
|
return ROUND_POWER_OF_TWO(vp9_get_sby_variance(cpi, ref, bs),
|
|
|
|
num_pels_log2_lookup[bs]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
unsigned int vp9_high_get_sby_perpixel_variance(VP9_COMP *cpi,
|
|
|
|
const struct buf_2d *ref,
|
|
|
|
BLOCK_SIZE bs, int bd) {
|
|
|
|
return (unsigned int)ROUND64_POWER_OF_TWO(
|
|
|
|
(int64_t)vp9_high_get_sby_variance(cpi, ref, bs, bd),
|
|
|
|
num_pels_log2_lookup[bs]);
|
2014-09-24 15:36:34 +02:00
|
|
|
}
|
|
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
|
2014-02-26 02:22:34 +01:00
|
|
|
static unsigned int get_sby_perpixel_diff_variance(VP9_COMP *cpi,
|
2014-04-09 00:43:51 +02:00
|
|
|
const struct buf_2d *ref,
|
|
|
|
int mi_row, int mi_col,
|
2014-02-26 02:22:34 +01:00
|
|
|
BLOCK_SIZE bs) {
|
2015-02-18 18:40:34 +01:00
|
|
|
unsigned int sse, var;
|
|
|
|
uint8_t *last_y;
|
2014-04-09 00:43:51 +02:00
|
|
|
const YV12_BUFFER_CONFIG *last = get_ref_frame_buffer(cpi, LAST_FRAME);
|
2015-02-18 18:40:34 +01:00
|
|
|
|
|
|
|
assert(last != NULL);
|
|
|
|
last_y =
|
|
|
|
&last->y_buffer[mi_row * MI_SIZE * last->y_stride + mi_col * MI_SIZE];
|
|
|
|
var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride, last_y, last->y_stride, &sse);
|
2014-02-26 02:22:34 +01:00
|
|
|
return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
|
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static BLOCK_SIZE get_rd_var_based_fixed_partition(VP9_COMP *cpi, MACROBLOCK *x,
|
2016-07-27 05:43:23 +02:00
|
|
|
int mi_row, int mi_col) {
|
|
|
|
unsigned int var = get_sby_perpixel_diff_variance(
|
|
|
|
cpi, &x->plane[0].src, mi_row, mi_col, BLOCK_64X64);
|
2014-02-26 02:22:34 +01:00
|
|
|
if (var < 8)
|
2014-02-25 00:21:13 +01:00
|
|
|
return BLOCK_64X64;
|
2014-02-26 02:22:34 +01:00
|
|
|
else if (var < 128)
|
2014-02-25 00:21:13 +01:00
|
|
|
return BLOCK_32X32;
|
2014-02-26 02:22:34 +01:00
|
|
|
else if (var < 2048)
|
|
|
|
return BLOCK_16X16;
|
|
|
|
else
|
|
|
|
return BLOCK_8X8;
|
2014-02-25 00:21:13 +01:00
|
|
|
}
|
|
|
|
|
2014-03-04 20:15:35 +01:00
|
|
|
// Lighter version of set_offsets that only sets the mode info
|
|
|
|
// pointers.
|
2014-12-09 19:30:39 +01:00
|
|
|
static INLINE void set_mode_info_offsets(VP9_COMMON *const cm,
|
2015-06-29 18:27:11 +02:00
|
|
|
MACROBLOCK *const x,
|
2016-07-27 05:43:23 +02:00
|
|
|
MACROBLOCKD *const xd, int mi_row,
|
2014-12-09 19:30:39 +01:00
|
|
|
int mi_col) {
|
2014-04-02 01:18:47 +02:00
|
|
|
const int idx_str = xd->mi_stride * mi_row + mi_col;
|
2015-04-21 14:36:58 +02:00
|
|
|
xd->mi = cm->mi_grid_visible + idx_str;
|
|
|
|
xd->mi[0] = cm->mi + idx_str;
|
2015-06-29 18:27:11 +02:00
|
|
|
x->mbmi_ext = x->mbmi_ext_base + (mi_row * cm->mi_cols + mi_col);
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void set_offsets(VP9_COMP *cpi, const TileInfo *const tile,
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x, int mi_row, int mi_col,
|
|
|
|
BLOCK_SIZE bsize) {
|
2014-03-04 20:15:35 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2016-01-20 01:40:20 +01:00
|
|
|
MODE_INFO *mi;
|
2014-03-04 20:15:35 +01:00
|
|
|
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
const int mi_height = num_8x8_blocks_high_lookup[bsize];
|
|
|
|
const struct segmentation *const seg = &cm->seg;
|
2016-08-08 20:42:27 +02:00
|
|
|
MvLimits *const mv_limits = &x->mv_limits;
|
2014-03-04 20:15:35 +01:00
|
|
|
|
2014-04-01 19:57:59 +02:00
|
|
|
set_skip_context(xd, mi_row, mi_col);
|
2014-03-04 20:15:35 +01:00
|
|
|
|
2015-06-29 18:27:11 +02:00
|
|
|
set_mode_info_offsets(cm, x, xd, mi_row, mi_col);
|
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
mi = xd->mi[0];
|
2014-03-04 20:15:35 +01:00
|
|
|
|
|
|
|
// Set up destination pointers.
|
2014-05-16 18:48:26 +02:00
|
|
|
vp9_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
|
2014-03-04 20:15:35 +01:00
|
|
|
|
|
|
|
// Set up limit values for MV components.
|
|
|
|
// Mv beyond the range do not produce new/different prediction block.
|
2016-08-08 20:42:27 +02:00
|
|
|
mv_limits->row_min = -(((mi_row + mi_height) * MI_SIZE) + VP9_INTERP_EXTEND);
|
|
|
|
mv_limits->col_min = -(((mi_col + mi_width) * MI_SIZE) + VP9_INTERP_EXTEND);
|
|
|
|
mv_limits->row_max = (cm->mi_rows - mi_row) * MI_SIZE + VP9_INTERP_EXTEND;
|
|
|
|
mv_limits->col_max = (cm->mi_cols - mi_col) * MI_SIZE + VP9_INTERP_EXTEND;
|
2014-03-04 20:15:35 +01:00
|
|
|
|
|
|
|
// Set up distance of MB to edge of frame in 1/8th pel units.
|
|
|
|
assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
|
2016-07-27 05:43:23 +02:00
|
|
|
set_mi_row_col(xd, tile, mi_row, mi_height, mi_col, mi_width, cm->mi_rows,
|
|
|
|
cm->mi_cols);
|
2014-03-04 20:15:35 +01:00
|
|
|
|
|
|
|
// Set up source buffers.
|
|
|
|
vp9_setup_src_planes(x, cpi->Source, mi_row, mi_col);
|
|
|
|
|
|
|
|
// R/D setup.
|
2014-04-10 00:00:14 +02:00
|
|
|
x->rddiv = cpi->rd.RDDIV;
|
|
|
|
x->rdmult = cpi->rd.RDMULT;
|
2014-03-04 20:15:35 +01:00
|
|
|
|
|
|
|
// Setup segment ID.
|
|
|
|
if (seg->enabled) {
|
2016-07-19 00:44:40 +02:00
|
|
|
if (cpi->oxcf.aq_mode != VARIANCE_AQ && cpi->oxcf.aq_mode != LOOKAHEAD_AQ &&
|
2015-12-17 00:34:07 +01:00
|
|
|
cpi->oxcf.aq_mode != EQUATOR360_AQ) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const uint8_t *const map =
|
|
|
|
seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
vp9_init_plane_quantizers(cpi, x);
|
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
x->encode_breakout = cpi->segment_encode_breakout[mi->segment_id];
|
2014-03-04 20:15:35 +01:00
|
|
|
} else {
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->segment_id = 0;
|
2014-03-04 20:15:35 +01:00
|
|
|
x->encode_breakout = cpi->encode_breakout;
|
|
|
|
}
|
2015-06-16 15:38:34 +02:00
|
|
|
|
|
|
|
// required by vp9_append_sub8x8_mvs_for_idx() and vp9_find_best_ref_mvs()
|
|
|
|
xd->tile = *tile;
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
2014-08-07 23:55:54 +02:00
|
|
|
static void duplicate_mode_info_in_sb(VP9_COMMON *cm, MACROBLOCKD *xd,
|
|
|
|
int mi_row, int mi_col,
|
|
|
|
BLOCK_SIZE bsize) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const int block_width =
|
|
|
|
VPXMIN(num_8x8_blocks_wide_lookup[bsize], cm->mi_cols - mi_col);
|
|
|
|
const int block_height =
|
|
|
|
VPXMIN(num_8x8_blocks_high_lookup[bsize], cm->mi_rows - mi_row);
|
2016-03-02 02:43:02 +01:00
|
|
|
const int mi_stride = xd->mi_stride;
|
|
|
|
MODE_INFO *const src_mi = xd->mi[0];
|
2014-03-04 20:15:35 +01:00
|
|
|
int i, j;
|
2016-07-21 20:47:51 +02:00
|
|
|
|
2014-03-04 20:15:35 +01:00
|
|
|
for (j = 0; j < block_height; ++j)
|
2016-07-27 05:43:23 +02:00
|
|
|
for (i = 0; i < block_width; ++i) xd->mi[j * mi_stride + i] = src_mi;
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void set_block_size(VP9_COMP *const cpi, MACROBLOCK *const x,
|
|
|
|
MACROBLOCKD *const xd, int mi_row, int mi_col,
|
2014-03-04 20:15:35 +01:00
|
|
|
BLOCK_SIZE bsize) {
|
|
|
|
if (cpi->common.mi_cols > mi_col && cpi->common.mi_rows > mi_row) {
|
2015-06-29 18:27:11 +02:00
|
|
|
set_mode_info_offsets(&cpi->common, x, xd, mi_row, mi_col);
|
2016-01-20 01:40:20 +01:00
|
|
|
xd->mi[0]->sb_type = bsize;
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
2017-10-30 21:24:29 +01:00
|
|
|
// This struct is used for computing variance in choose_partitioning(), where
|
|
|
|
// the max number of samples within a superblock is 16x16 (with 4x4 avg). Even
|
|
|
|
// in high bitdepth, uint32_t is enough for sum_square_error (2^12 * 2^12 * 16
|
|
|
|
// * 16 = 2^32).
|
|
|
|
uint32_t sum_square_error;
|
|
|
|
int32_t sum_error;
|
2014-12-11 20:04:49 +01:00
|
|
|
int log2_count;
|
2014-03-04 20:15:35 +01:00
|
|
|
int variance;
|
|
|
|
} var;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
var none;
|
|
|
|
var horz[2];
|
|
|
|
var vert[2];
|
|
|
|
} partition_variance;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
partition_variance part_variances;
|
|
|
|
var split[4];
|
2014-11-12 23:51:49 +01:00
|
|
|
} v4x4;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
partition_variance part_variances;
|
|
|
|
v4x4 split[4];
|
2014-03-04 20:15:35 +01:00
|
|
|
} v8x8;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
partition_variance part_variances;
|
|
|
|
v8x8 split[4];
|
|
|
|
} v16x16;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
partition_variance part_variances;
|
|
|
|
v16x16 split[4];
|
|
|
|
} v32x32;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
partition_variance part_variances;
|
|
|
|
v32x32 split[4];
|
|
|
|
} v64x64;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
partition_variance *part_variances;
|
|
|
|
var *split[4];
|
|
|
|
} variance_node;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
V16X16,
|
|
|
|
V32X32,
|
|
|
|
V64X64,
|
|
|
|
} TREE_LEVEL;
|
|
|
|
|
|
|
|
static void tree_to_node(void *data, BLOCK_SIZE bsize, variance_node *node) {
|
|
|
|
int i;
|
2014-07-16 01:18:34 +02:00
|
|
|
node->part_variances = NULL;
|
2014-03-04 20:15:35 +01:00
|
|
|
switch (bsize) {
|
|
|
|
case BLOCK_64X64: {
|
2016-07-27 05:43:23 +02:00
|
|
|
v64x64 *vt = (v64x64 *)data;
|
2014-03-04 20:15:35 +01:00
|
|
|
node->part_variances = &vt->part_variances;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
node->split[i] = &vt->split[i].part_variances.none;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BLOCK_32X32: {
|
2016-07-27 05:43:23 +02:00
|
|
|
v32x32 *vt = (v32x32 *)data;
|
2014-03-04 20:15:35 +01:00
|
|
|
node->part_variances = &vt->part_variances;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
node->split[i] = &vt->split[i].part_variances.none;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BLOCK_16X16: {
|
2016-07-27 05:43:23 +02:00
|
|
|
v16x16 *vt = (v16x16 *)data;
|
2014-03-04 20:15:35 +01:00
|
|
|
node->part_variances = &vt->part_variances;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
node->split[i] = &vt->split[i].part_variances.none;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BLOCK_8X8: {
|
2016-07-27 05:43:23 +02:00
|
|
|
v8x8 *vt = (v8x8 *)data;
|
2014-03-04 20:15:35 +01:00
|
|
|
node->part_variances = &vt->part_variances;
|
2014-11-12 23:51:49 +01:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
node->split[i] = &vt->split[i].part_variances.none;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BLOCK_4X4: {
|
2016-07-27 05:43:23 +02:00
|
|
|
v4x4 *vt = (v4x4 *)data;
|
2014-11-12 23:51:49 +01:00
|
|
|
node->part_variances = &vt->part_variances;
|
2016-07-27 05:43:23 +02:00
|
|
|
for (i = 0; i < 4; i++) node->split[i] = &vt->split[i];
|
2014-03-04 20:15:35 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
assert(0);
|
2014-08-04 17:52:53 +02:00
|
|
|
break;
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set variance values given sum square error, sum error, count.
|
2017-10-30 21:24:29 +01:00
|
|
|
static void fill_variance(uint32_t s2, int32_t s, int c, var *v) {
|
2014-03-04 20:15:35 +01:00
|
|
|
v->sum_square_error = s2;
|
|
|
|
v->sum_error = s;
|
2014-12-11 20:04:49 +01:00
|
|
|
v->log2_count = c;
|
2014-12-11 18:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void get_variance(var *v) {
|
2016-07-27 05:43:23 +02:00
|
|
|
v->variance =
|
|
|
|
(int)(256 * (v->sum_square_error -
|
|
|
|
((v->sum_error * v->sum_error) >> v->log2_count)) >>
|
|
|
|
v->log2_count);
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
2015-05-15 05:22:50 +02:00
|
|
|
static void sum_2_variances(const var *a, const var *b, var *r) {
|
2014-12-11 20:04:49 +01:00
|
|
|
assert(a->log2_count == b->log2_count);
|
2014-03-04 20:15:35 +01:00
|
|
|
fill_variance(a->sum_square_error + b->sum_square_error,
|
2014-12-11 20:04:49 +01:00
|
|
|
a->sum_error + b->sum_error, a->log2_count + 1, r);
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void fill_variance_tree(void *data, BLOCK_SIZE bsize) {
|
|
|
|
variance_node node;
|
2015-06-02 14:18:21 +02:00
|
|
|
memset(&node, 0, sizeof(node));
|
2014-03-04 20:15:35 +01:00
|
|
|
tree_to_node(data, bsize, &node);
|
|
|
|
sum_2_variances(node.split[0], node.split[1], &node.part_variances->horz[0]);
|
|
|
|
sum_2_variances(node.split[2], node.split[3], &node.part_variances->horz[1]);
|
|
|
|
sum_2_variances(node.split[0], node.split[2], &node.part_variances->vert[0]);
|
|
|
|
sum_2_variances(node.split[1], node.split[3], &node.part_variances->vert[1]);
|
|
|
|
sum_2_variances(&node.part_variances->vert[0], &node.part_variances->vert[1],
|
|
|
|
&node.part_variances->none);
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static int set_vt_partitioning(VP9_COMP *cpi, MACROBLOCK *const x,
|
|
|
|
MACROBLOCKD *const xd, void *data,
|
|
|
|
BLOCK_SIZE bsize, int mi_row, int mi_col,
|
|
|
|
int64_t threshold, BLOCK_SIZE bsize_min,
|
2015-03-16 03:19:29 +01:00
|
|
|
int force_split) {
|
2016-07-27 05:43:23 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-03-04 20:15:35 +01:00
|
|
|
variance_node vt;
|
|
|
|
const int block_width = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
const int block_height = num_8x8_blocks_high_lookup[bsize];
|
2014-11-12 23:51:49 +01:00
|
|
|
|
2014-03-04 20:15:35 +01:00
|
|
|
assert(block_height == block_width);
|
|
|
|
tree_to_node(data, bsize, &vt);
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (force_split == 1) return 0;
|
2015-01-28 20:34:24 +01:00
|
|
|
|
2015-01-06 02:13:13 +01:00
|
|
|
// For bsize=bsize_min (16x16/8x8 for 8x8/4x4 downsampling), select if
|
2014-11-12 23:51:49 +01:00
|
|
|
// variance is below threshold, otherwise split will be selected.
|
|
|
|
// No check for vert/horiz split as too few samples for variance.
|
2015-01-06 02:13:13 +01:00
|
|
|
if (bsize == bsize_min) {
|
2015-04-16 02:48:20 +02:00
|
|
|
// Variance already computed to set the force_split.
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cm->frame_type == KEY_FRAME) get_variance(&vt.part_variances->none);
|
2014-11-12 23:51:49 +01:00
|
|
|
if (mi_col + block_width / 2 < cm->mi_cols &&
|
|
|
|
mi_row + block_height / 2 < cm->mi_rows &&
|
2015-01-06 02:13:13 +01:00
|
|
|
vt.part_variances->none.variance < threshold) {
|
2015-06-29 18:27:11 +02:00
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, bsize);
|
2014-11-12 23:51:49 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
2015-01-06 02:13:13 +01:00
|
|
|
} else if (bsize > bsize_min) {
|
2015-04-16 02:48:20 +02:00
|
|
|
// Variance already computed to set the force_split.
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cm->frame_type == KEY_FRAME) get_variance(&vt.part_variances->none);
|
2015-04-16 02:48:20 +02:00
|
|
|
// For key frame: take split for bsize above 32X32 or very high variance.
|
2014-11-12 23:51:49 +01:00
|
|
|
if (cm->frame_type == KEY_FRAME &&
|
|
|
|
(bsize > BLOCK_32X32 ||
|
2016-07-27 05:43:23 +02:00
|
|
|
vt.part_variances->none.variance > (threshold << 4))) {
|
2014-11-12 23:51:49 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// If variance is low, take the bsize (no split).
|
|
|
|
if (mi_col + block_width / 2 < cm->mi_cols &&
|
|
|
|
mi_row + block_height / 2 < cm->mi_rows &&
|
2015-01-06 02:13:13 +01:00
|
|
|
vt.part_variances->none.variance < threshold) {
|
2015-06-29 18:27:11 +02:00
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, bsize);
|
2014-11-12 23:51:49 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2014-12-11 18:29:36 +01:00
|
|
|
|
2014-11-12 23:51:49 +01:00
|
|
|
// Check vertical split.
|
2014-12-11 18:29:36 +01:00
|
|
|
if (mi_row + block_height / 2 < cm->mi_rows) {
|
2015-04-24 17:22:13 +02:00
|
|
|
BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_VERT);
|
2014-12-11 18:29:36 +01:00
|
|
|
get_variance(&vt.part_variances->vert[0]);
|
|
|
|
get_variance(&vt.part_variances->vert[1]);
|
2015-01-06 02:13:13 +01:00
|
|
|
if (vt.part_variances->vert[0].variance < threshold &&
|
2015-04-24 17:22:13 +02:00
|
|
|
vt.part_variances->vert[1].variance < threshold &&
|
|
|
|
get_plane_block_size(subsize, &xd->plane[1]) < BLOCK_INVALID) {
|
2015-06-29 18:27:11 +02:00
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
|
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col + block_width / 2, subsize);
|
2014-12-11 18:29:36 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2014-10-10 01:01:52 +02:00
|
|
|
}
|
2014-11-12 23:51:49 +01:00
|
|
|
// Check horizontal split.
|
2014-12-11 18:29:36 +01:00
|
|
|
if (mi_col + block_width / 2 < cm->mi_cols) {
|
2015-04-24 17:22:13 +02:00
|
|
|
BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_HORZ);
|
2014-12-11 18:29:36 +01:00
|
|
|
get_variance(&vt.part_variances->horz[0]);
|
|
|
|
get_variance(&vt.part_variances->horz[1]);
|
2015-01-06 02:13:13 +01:00
|
|
|
if (vt.part_variances->horz[0].variance < threshold &&
|
2015-04-24 17:22:13 +02:00
|
|
|
vt.part_variances->horz[1].variance < threshold &&
|
|
|
|
get_plane_block_size(subsize, &xd->plane[1]) < BLOCK_INVALID) {
|
2015-06-29 18:27:11 +02:00
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
|
|
|
|
set_block_size(cpi, x, xd, mi_row + block_height / 2, mi_col, subsize);
|
2014-12-11 18:29:36 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2014-10-10 01:01:52 +02:00
|
|
|
}
|
2014-12-11 18:29:36 +01:00
|
|
|
|
2014-11-12 23:51:49 +01:00
|
|
|
return 0;
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-16 09:51:42 +02:00
|
|
|
static int64_t scale_part_thresh_sumdiff(int64_t threshold_base, int speed,
|
|
|
|
int width, int height,
|
|
|
|
int content_state) {
|
2017-02-13 19:16:42 +01:00
|
|
|
if (speed >= 8) {
|
|
|
|
if (width <= 640 && height <= 480)
|
|
|
|
return (5 * threshold_base) >> 2;
|
|
|
|
else if ((content_state == kLowSadLowSumdiff) ||
|
2017-04-14 20:32:19 +02:00
|
|
|
(content_state == kHighSadLowSumdiff) ||
|
|
|
|
(content_state == kLowVarHighSumdiff))
|
2017-02-13 19:16:42 +01:00
|
|
|
return (5 * threshold_base) >> 2;
|
|
|
|
} else if (speed == 7) {
|
|
|
|
if ((content_state == kLowSadLowSumdiff) ||
|
2017-04-14 20:32:19 +02:00
|
|
|
(content_state == kHighSadLowSumdiff) ||
|
|
|
|
(content_state == kLowVarHighSumdiff)) {
|
2017-02-13 19:16:42 +01:00
|
|
|
return (5 * threshold_base) >> 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return threshold_base;
|
|
|
|
}
|
|
|
|
|
2015-05-21 17:35:11 +02:00
|
|
|
// Set the variance split thresholds for following the block sizes:
|
|
|
|
// 0 - threshold_64x64, 1 - threshold_32x32, 2 - threshold_16x16,
|
|
|
|
// 3 - vbp_threshold_8x8. vbp_threshold_8x8 (to split to 4x4 partition) is
|
|
|
|
// currently only used on key frame.
|
2017-02-13 19:16:42 +01:00
|
|
|
static void set_vbp_thresholds(VP9_COMP *cpi, int64_t thresholds[], int q,
|
|
|
|
int content_state) {
|
2015-05-21 17:35:11 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
const int is_key_frame = (cm->frame_type == KEY_FRAME);
|
|
|
|
const int threshold_multiplier = is_key_frame ? 20 : 1;
|
2016-07-27 05:43:23 +02:00
|
|
|
int64_t threshold_base =
|
|
|
|
(int64_t)(threshold_multiplier * cpi->y_dequant[q][1]);
|
2017-02-13 19:16:42 +01:00
|
|
|
|
2015-05-21 17:35:11 +02:00
|
|
|
if (is_key_frame) {
|
|
|
|
thresholds[0] = threshold_base;
|
|
|
|
thresholds[1] = threshold_base >> 2;
|
|
|
|
thresholds[2] = threshold_base >> 2;
|
|
|
|
thresholds[3] = threshold_base << 2;
|
|
|
|
} else {
|
2017-01-04 01:01:05 +01:00
|
|
|
// Increase base variance threshold based on estimated noise level.
|
|
|
|
if (cpi->noise_estimate.enabled && cm->width >= 640 && cm->height >= 480) {
|
2016-07-27 05:43:23 +02:00
|
|
|
NOISE_LEVEL noise_level =
|
|
|
|
vp9_noise_estimate_extract_level(&cpi->noise_estimate);
|
2015-12-04 20:57:04 +01:00
|
|
|
if (noise_level == kHigh)
|
2015-11-12 03:05:11 +01:00
|
|
|
threshold_base = 3 * threshold_base;
|
2015-12-04 20:57:04 +01:00
|
|
|
else if (noise_level == kMedium)
|
|
|
|
threshold_base = threshold_base << 1;
|
2015-12-15 17:44:40 +01:00
|
|
|
else if (noise_level < kLow)
|
2015-12-09 21:26:48 +01:00
|
|
|
threshold_base = (7 * threshold_base) >> 3;
|
2015-11-01 23:40:05 +01:00
|
|
|
}
|
2017-02-07 02:02:28 +01:00
|
|
|
#if CONFIG_VP9_TEMPORAL_DENOISING
|
2017-04-21 01:32:46 +02:00
|
|
|
if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi) &&
|
|
|
|
cpi->oxcf.speed > 5 && cpi->denoiser.denoising_level >= kDenLow)
|
2017-05-11 21:10:35 +02:00
|
|
|
threshold_base =
|
|
|
|
vp9_scale_part_thresh(threshold_base, cpi->denoiser.denoising_level,
|
|
|
|
content_state, cpi->svc.temporal_layer_id);
|
2017-02-13 19:16:42 +01:00
|
|
|
else
|
2017-02-07 02:02:28 +01:00
|
|
|
threshold_base =
|
2017-02-13 19:16:42 +01:00
|
|
|
scale_part_thresh_sumdiff(threshold_base, cpi->oxcf.speed, cm->width,
|
|
|
|
cm->height, content_state);
|
2017-02-07 02:02:28 +01:00
|
|
|
#else
|
2017-02-13 19:16:42 +01:00
|
|
|
// Increase base variance threshold based on content_state/sum_diff level.
|
|
|
|
threshold_base = scale_part_thresh_sumdiff(
|
|
|
|
threshold_base, cpi->oxcf.speed, cm->width, cm->height, content_state);
|
2017-02-07 02:02:28 +01:00
|
|
|
#endif
|
2016-06-23 18:40:49 +02:00
|
|
|
thresholds[0] = threshold_base;
|
|
|
|
thresholds[2] = threshold_base << cpi->oxcf.speed;
|
2017-08-24 19:36:27 +02:00
|
|
|
if (cm->width >= 1280 && cm->height >= 720 && cpi->oxcf.speed < 7)
|
|
|
|
thresholds[2] = thresholds[2] << 1;
|
2015-05-21 17:35:11 +02:00
|
|
|
if (cm->width <= 352 && cm->height <= 288) {
|
2015-11-11 00:41:39 +01:00
|
|
|
thresholds[0] = threshold_base >> 3;
|
|
|
|
thresholds[1] = threshold_base >> 1;
|
2015-11-13 01:52:45 +01:00
|
|
|
thresholds[2] = threshold_base << 3;
|
2016-06-23 18:40:49 +02:00
|
|
|
} else if (cm->width < 1280 && cm->height < 720) {
|
2015-05-21 17:35:11 +02:00
|
|
|
thresholds[1] = (5 * threshold_base) >> 2;
|
2016-06-23 18:40:49 +02:00
|
|
|
} else if (cm->width < 1920 && cm->height < 1080) {
|
|
|
|
thresholds[1] = threshold_base << 1;
|
|
|
|
} else {
|
|
|
|
thresholds[1] = (5 * threshold_base) >> 1;
|
2015-05-21 17:35:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 19:16:42 +01:00
|
|
|
void vp9_set_variance_partition_thresholds(VP9_COMP *cpi, int q,
|
|
|
|
int content_state) {
|
2015-05-21 17:35:11 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2015-02-09 19:21:17 +01:00
|
|
|
SPEED_FEATURES *const sf = &cpi->sf;
|
2015-05-21 17:35:11 +02:00
|
|
|
const int is_key_frame = (cm->frame_type == KEY_FRAME);
|
2015-03-14 00:51:29 +01:00
|
|
|
if (sf->partition_search_type != VAR_BASED_PARTITION &&
|
|
|
|
sf->partition_search_type != REFERENCE_PARTITION) {
|
2015-02-09 19:21:17 +01:00
|
|
|
return;
|
|
|
|
} else {
|
2017-02-13 19:16:42 +01:00
|
|
|
set_vbp_thresholds(cpi, cpi->vbp_thresholds, q, content_state);
|
2015-05-21 17:35:11 +02:00
|
|
|
// The thresholds below are not changed locally.
|
2015-03-17 20:19:15 +01:00
|
|
|
if (is_key_frame) {
|
2015-04-16 02:48:20 +02:00
|
|
|
cpi->vbp_threshold_sad = 0;
|
2017-01-10 21:43:22 +01:00
|
|
|
cpi->vbp_threshold_copy = 0;
|
2015-03-17 20:19:15 +01:00
|
|
|
cpi->vbp_bsize_min = BLOCK_8X8;
|
|
|
|
} else {
|
2015-05-21 17:35:11 +02:00
|
|
|
if (cm->width <= 352 && cm->height <= 288)
|
2015-11-11 00:41:39 +01:00
|
|
|
cpi->vbp_threshold_sad = 10;
|
2015-05-21 17:35:11 +02:00
|
|
|
else
|
2016-07-27 05:43:23 +02:00
|
|
|
cpi->vbp_threshold_sad = (cpi->y_dequant[q][1] << 1) > 1000
|
|
|
|
? (cpi->y_dequant[q][1] << 1)
|
|
|
|
: 1000;
|
2015-03-17 20:19:15 +01:00
|
|
|
cpi->vbp_bsize_min = BLOCK_16X16;
|
2017-01-10 21:43:22 +01:00
|
|
|
if (cm->width <= 352 && cm->height <= 288)
|
2017-01-13 02:59:22 +01:00
|
|
|
cpi->vbp_threshold_copy = 4000;
|
|
|
|
else if (cm->width <= 640 && cm->height <= 360)
|
2017-01-13 19:27:51 +01:00
|
|
|
cpi->vbp_threshold_copy = 8000;
|
2017-01-10 21:43:22 +01:00
|
|
|
else
|
2017-01-25 02:20:05 +01:00
|
|
|
cpi->vbp_threshold_copy = (cpi->y_dequant[q][1] << 3) > 8000
|
|
|
|
? (cpi->y_dequant[q][1] << 3)
|
|
|
|
: 8000;
|
2015-03-17 20:19:15 +01:00
|
|
|
}
|
2015-04-16 02:48:20 +02:00
|
|
|
cpi->vbp_threshold_minmax = 15 + (q >> 3);
|
2015-02-09 19:21:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-16 02:48:20 +02:00
|
|
|
// Compute the minmax over the 8x8 subblocks.
|
|
|
|
static int compute_minmax_8x8(const uint8_t *s, int sp, const uint8_t *d,
|
|
|
|
int dp, int x16_idx, int y16_idx,
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
int highbd_flag,
|
|
|
|
#endif
|
2016-07-27 05:43:23 +02:00
|
|
|
int pixels_wide, int pixels_high) {
|
2015-04-16 02:48:20 +02:00
|
|
|
int k;
|
|
|
|
int minmax_max = 0;
|
|
|
|
int minmax_min = 255;
|
|
|
|
// Loop over the 4 8x8 subblocks.
|
|
|
|
for (k = 0; k < 4; k++) {
|
|
|
|
int x8_idx = x16_idx + ((k & 1) << 3);
|
|
|
|
int y8_idx = y16_idx + ((k >> 1) << 3);
|
|
|
|
int min = 0;
|
|
|
|
int max = 0;
|
|
|
|
if (x8_idx < pixels_wide && y8_idx < pixels_high) {
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if (highbd_flag & YV12_FLAG_HIGHBITDEPTH) {
|
2015-12-11 21:40:53 +01:00
|
|
|
vpx_highbd_minmax_8x8(s + y8_idx * sp + x8_idx, sp,
|
2016-07-27 05:43:23 +02:00
|
|
|
d + y8_idx * dp + x8_idx, dp, &min, &max);
|
2015-04-16 02:48:20 +02:00
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
vpx_minmax_8x8(s + y8_idx * sp + x8_idx, sp, d + y8_idx * dp + x8_idx,
|
|
|
|
dp, &min, &max);
|
2015-04-16 02:48:20 +02:00
|
|
|
}
|
|
|
|
#else
|
2016-07-27 05:43:23 +02:00
|
|
|
vpx_minmax_8x8(s + y8_idx * sp + x8_idx, sp, d + y8_idx * dp + x8_idx, dp,
|
2015-04-16 02:48:20 +02:00
|
|
|
&min, &max);
|
|
|
|
#endif
|
2016-07-27 05:43:23 +02:00
|
|
|
if ((max - min) > minmax_max) minmax_max = (max - min);
|
|
|
|
if ((max - min) < minmax_min) minmax_min = (max - min);
|
2015-04-16 02:48:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (minmax_max - minmax_min);
|
|
|
|
}
|
|
|
|
|
2015-04-02 21:17:51 +02:00
|
|
|
static void fill_variance_4x4avg(const uint8_t *s, int sp, const uint8_t *d,
|
|
|
|
int dp, int x8_idx, int y8_idx, v8x8 *vst,
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
int highbd_flag,
|
|
|
|
#endif
|
2016-07-27 05:43:23 +02:00
|
|
|
int pixels_wide, int pixels_high,
|
2015-04-02 21:17:51 +02:00
|
|
|
int is_key_frame) {
|
|
|
|
int k;
|
|
|
|
for (k = 0; k < 4; k++) {
|
|
|
|
int x4_idx = x8_idx + ((k & 1) << 2);
|
|
|
|
int y4_idx = y8_idx + ((k >> 1) << 2);
|
|
|
|
unsigned int sse = 0;
|
|
|
|
int sum = 0;
|
|
|
|
if (x4_idx < pixels_wide && y4_idx < pixels_high) {
|
|
|
|
int s_avg;
|
|
|
|
int d_avg = 128;
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if (highbd_flag & YV12_FLAG_HIGHBITDEPTH) {
|
2015-12-11 21:40:53 +01:00
|
|
|
s_avg = vpx_highbd_avg_4x4(s + y4_idx * sp + x4_idx, sp);
|
2015-04-02 21:17:51 +02:00
|
|
|
if (!is_key_frame)
|
2015-12-11 21:40:53 +01:00
|
|
|
d_avg = vpx_highbd_avg_4x4(d + y4_idx * dp + x4_idx, dp);
|
2015-04-02 21:17:51 +02:00
|
|
|
} else {
|
2015-12-11 21:40:53 +01:00
|
|
|
s_avg = vpx_avg_4x4(s + y4_idx * sp + x4_idx, sp);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (!is_key_frame) d_avg = vpx_avg_4x4(d + y4_idx * dp + x4_idx, dp);
|
2015-04-02 21:17:51 +02:00
|
|
|
}
|
|
|
|
#else
|
2015-12-11 21:40:53 +01:00
|
|
|
s_avg = vpx_avg_4x4(s + y4_idx * sp + x4_idx, sp);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (!is_key_frame) d_avg = vpx_avg_4x4(d + y4_idx * dp + x4_idx, dp);
|
2015-04-02 21:17:51 +02:00
|
|
|
#endif
|
|
|
|
sum = s_avg - d_avg;
|
|
|
|
sse = sum * sum;
|
|
|
|
}
|
|
|
|
fill_variance(sse, sum, 0, &vst->split[k].part_variances.none);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fill_variance_8x8avg(const uint8_t *s, int sp, const uint8_t *d,
|
|
|
|
int dp, int x16_idx, int y16_idx, v16x16 *vst,
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
int highbd_flag,
|
|
|
|
#endif
|
2016-07-27 05:43:23 +02:00
|
|
|
int pixels_wide, int pixels_high,
|
2015-04-02 21:17:51 +02:00
|
|
|
int is_key_frame) {
|
|
|
|
int k;
|
|
|
|
for (k = 0; k < 4; k++) {
|
|
|
|
int x8_idx = x16_idx + ((k & 1) << 3);
|
|
|
|
int y8_idx = y16_idx + ((k >> 1) << 3);
|
|
|
|
unsigned int sse = 0;
|
|
|
|
int sum = 0;
|
|
|
|
if (x8_idx < pixels_wide && y8_idx < pixels_high) {
|
|
|
|
int s_avg;
|
|
|
|
int d_avg = 128;
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if (highbd_flag & YV12_FLAG_HIGHBITDEPTH) {
|
2015-12-11 21:40:53 +01:00
|
|
|
s_avg = vpx_highbd_avg_8x8(s + y8_idx * sp + x8_idx, sp);
|
2015-04-02 21:17:51 +02:00
|
|
|
if (!is_key_frame)
|
2015-12-11 21:40:53 +01:00
|
|
|
d_avg = vpx_highbd_avg_8x8(d + y8_idx * dp + x8_idx, dp);
|
2015-04-02 21:17:51 +02:00
|
|
|
} else {
|
2015-12-11 21:40:53 +01:00
|
|
|
s_avg = vpx_avg_8x8(s + y8_idx * sp + x8_idx, sp);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (!is_key_frame) d_avg = vpx_avg_8x8(d + y8_idx * dp + x8_idx, dp);
|
2015-04-02 21:17:51 +02:00
|
|
|
}
|
|
|
|
#else
|
2015-12-11 21:40:53 +01:00
|
|
|
s_avg = vpx_avg_8x8(s + y8_idx * sp + x8_idx, sp);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (!is_key_frame) d_avg = vpx_avg_8x8(d + y8_idx * dp + x8_idx, dp);
|
2015-04-02 21:17:51 +02:00
|
|
|
#endif
|
|
|
|
sum = s_avg - d_avg;
|
|
|
|
sse = sum * sum;
|
|
|
|
}
|
|
|
|
fill_variance(sse, sum, 0, &vst->split[k].part_variances.none);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-30 00:19:28 +02:00
|
|
|
// Check if most of the superblock is skin content, and if so, force split to
|
|
|
|
// 32x32, and set x->sb_is_skin for use in mode selection.
|
|
|
|
static int skin_sb_split(VP9_COMP *cpi, MACROBLOCK *x, const int low_res,
|
|
|
|
int mi_row, int mi_col, int *force_split) {
|
2016-07-27 05:43:23 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2017-01-26 23:09:57 +01:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if (cm->use_highbitdepth) return 0;
|
|
|
|
#endif
|
2016-04-30 00:19:28 +02:00
|
|
|
// Avoid checking superblocks on/near boundary and avoid low resolutions.
|
|
|
|
// Note superblock may still pick 64X64 if y_sad is very small
|
|
|
|
// (i.e., y_sad < cpi->vbp_threshold_sad) below. For now leave this as is.
|
|
|
|
if (!low_res && (mi_col >= 8 && mi_col + 8 < cm->mi_cols && mi_row >= 8 &&
|
2016-07-27 05:43:23 +02:00
|
|
|
mi_row + 8 < cm->mi_rows)) {
|
2016-04-30 00:19:28 +02:00
|
|
|
int num_16x16_skin = 0;
|
|
|
|
int num_16x16_nonskin = 0;
|
|
|
|
uint8_t *ysignal = x->plane[0].src.buf;
|
|
|
|
uint8_t *usignal = x->plane[1].src.buf;
|
|
|
|
uint8_t *vsignal = x->plane[2].src.buf;
|
|
|
|
int sp = x->plane[0].src.stride;
|
|
|
|
int spuv = x->plane[1].src.stride;
|
|
|
|
const int block_index = mi_row * cm->mi_cols + mi_col;
|
|
|
|
const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
|
|
|
|
const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
|
|
|
|
const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
|
|
|
|
const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
|
|
|
|
// Loop through the 16x16 sub-blocks.
|
|
|
|
int i, j;
|
2016-07-27 05:43:23 +02:00
|
|
|
for (i = 0; i < ymis; i += 2) {
|
|
|
|
for (j = 0; j < xmis; j += 2) {
|
2016-04-30 00:19:28 +02:00
|
|
|
int bl_index = block_index + i * cm->mi_cols + j;
|
2017-06-27 22:17:59 +02:00
|
|
|
int is_skin = cpi->skin_map[bl_index];
|
2016-04-30 00:19:28 +02:00
|
|
|
num_16x16_skin += is_skin;
|
|
|
|
num_16x16_nonskin += (1 - is_skin);
|
|
|
|
if (num_16x16_nonskin > 3) {
|
|
|
|
// Exit loop if at least 4 of the 16x16 blocks are not skin.
|
|
|
|
i = ymis;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ysignal += 16;
|
|
|
|
usignal += 8;
|
|
|
|
vsignal += 8;
|
|
|
|
}
|
|
|
|
ysignal += (sp << 4) - 64;
|
|
|
|
usignal += (spuv << 3) - 32;
|
|
|
|
vsignal += (spuv << 3) - 32;
|
|
|
|
}
|
|
|
|
if (num_16x16_skin > 12) {
|
|
|
|
*force_split = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void set_low_temp_var_flag(VP9_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
|
2016-08-23 23:17:28 +02:00
|
|
|
v64x64 *vt, int64_t thresholds[],
|
2016-06-24 19:42:00 +02:00
|
|
|
MV_REFERENCE_FRAME ref_frame_partition,
|
|
|
|
int mi_col, int mi_row) {
|
|
|
|
int i, j;
|
2016-07-27 05:43:23 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2016-06-24 19:42:00 +02:00
|
|
|
const int mv_thr = cm->width > 640 ? 8 : 4;
|
|
|
|
// Check temporal variance for bsize >= 16x16, if LAST_FRAME was selected and
|
|
|
|
// int_pro mv is small. If the temporal variance is small set the flag
|
|
|
|
// variance_low for the block. The variance threshold can be adjusted, the
|
|
|
|
// higher the more aggressive.
|
|
|
|
if (ref_frame_partition == LAST_FRAME &&
|
|
|
|
(cpi->sf.short_circuit_low_temp_var == 1 ||
|
|
|
|
(xd->mi[0]->mv[0].as_mv.col < mv_thr &&
|
|
|
|
xd->mi[0]->mv[0].as_mv.col > -mv_thr &&
|
|
|
|
xd->mi[0]->mv[0].as_mv.row < mv_thr &&
|
|
|
|
xd->mi[0]->mv[0].as_mv.row > -mv_thr))) {
|
2016-08-23 23:17:28 +02:00
|
|
|
if (xd->mi[0]->sb_type == BLOCK_64X64) {
|
|
|
|
if ((vt->part_variances).none.variance < (thresholds[0] >> 1))
|
|
|
|
x->variance_low[0] = 1;
|
2016-06-24 19:42:00 +02:00
|
|
|
} else if (xd->mi[0]->sb_type == BLOCK_64X32) {
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
if (vt->part_variances.horz[i].variance < (thresholds[0] >> 2))
|
|
|
|
x->variance_low[i + 1] = 1;
|
|
|
|
}
|
|
|
|
} else if (xd->mi[0]->sb_type == BLOCK_32X64) {
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
if (vt->part_variances.vert[i].variance < (thresholds[0] >> 2))
|
|
|
|
x->variance_low[i + 3] = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < 4; i++) {
|
2016-08-23 23:17:28 +02:00
|
|
|
const int idx[4][2] = { { 0, 0 }, { 0, 4 }, { 4, 0 }, { 4, 4 } };
|
|
|
|
const int idx_str =
|
|
|
|
cm->mi_stride * (mi_row + idx[i][0]) + mi_col + idx[i][1];
|
|
|
|
MODE_INFO **this_mi = cm->mi_grid_visible + idx_str;
|
|
|
|
|
|
|
|
if (cm->mi_cols <= mi_col + idx[i][1] ||
|
|
|
|
cm->mi_rows <= mi_row + idx[i][0])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((*this_mi)->sb_type == BLOCK_32X32) {
|
2016-11-22 19:10:06 +01:00
|
|
|
int64_t threshold_32x32 = (cpi->sf.short_circuit_low_temp_var == 1 ||
|
|
|
|
cpi->sf.short_circuit_low_temp_var == 3)
|
2017-01-04 20:22:51 +01:00
|
|
|
? ((5 * thresholds[1]) >> 3)
|
2016-11-15 19:37:12 +01:00
|
|
|
: (thresholds[1] >> 1);
|
|
|
|
if (vt->split[i].part_variances.none.variance < threshold_32x32)
|
2016-06-24 19:42:00 +02:00
|
|
|
x->variance_low[i + 5] = 1;
|
2016-11-15 19:37:12 +01:00
|
|
|
} else if (cpi->sf.short_circuit_low_temp_var >= 2) {
|
2016-06-24 19:42:00 +02:00
|
|
|
// For 32x16 and 16x32 blocks, the flag is set on each 16x16 block
|
|
|
|
// inside.
|
|
|
|
if ((*this_mi)->sb_type == BLOCK_16X16 ||
|
|
|
|
(*this_mi)->sb_type == BLOCK_32X16 ||
|
|
|
|
(*this_mi)->sb_type == BLOCK_16X32) {
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
if (vt->split[i].split[j].part_variances.none.variance <
|
|
|
|
(thresholds[2] >> 8))
|
|
|
|
x->variance_low[(i << 2) + j + 9] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 02:14:11 +02:00
|
|
|
static void copy_partitioning_helper(VP9_COMP *cpi, MACROBLOCK *x,
|
|
|
|
MACROBLOCKD *xd, BLOCK_SIZE bsize,
|
2017-01-25 20:31:05 +01:00
|
|
|
int mi_row, int mi_col) {
|
2016-12-19 19:39:04 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
BLOCK_SIZE *prev_part = cpi->prev_partition;
|
|
|
|
int start_pos = mi_row * cm->mi_stride + mi_col;
|
|
|
|
|
|
|
|
const int bsl = b_width_log2_lookup[bsize];
|
2017-11-09 00:12:44 +01:00
|
|
|
const int bs = (1 << bsl) >> 2;
|
2016-12-19 19:39:04 +01:00
|
|
|
BLOCK_SIZE subsize;
|
|
|
|
PARTITION_TYPE partition;
|
|
|
|
|
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
|
|
|
|
|
|
|
partition = partition_lookup[bsl][prev_part[start_pos]];
|
|
|
|
subsize = get_subsize(bsize, partition);
|
|
|
|
|
|
|
|
if (subsize < BLOCK_8X8) {
|
2017-05-16 02:14:11 +02:00
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, bsize);
|
2016-12-19 19:39:04 +01:00
|
|
|
} else {
|
|
|
|
switch (partition) {
|
2017-05-16 02:14:11 +02:00
|
|
|
case PARTITION_NONE:
|
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, bsize);
|
|
|
|
break;
|
2016-12-19 19:39:04 +01:00
|
|
|
case PARTITION_HORZ:
|
2017-05-16 02:14:11 +02:00
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
|
|
|
|
set_block_size(cpi, x, xd, mi_row + bs, mi_col, subsize);
|
2016-12-19 19:39:04 +01:00
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
2017-05-16 02:14:11 +02:00
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, subsize);
|
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col + bs, subsize);
|
2016-12-19 19:39:04 +01:00
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
2017-05-16 02:14:11 +02:00
|
|
|
copy_partitioning_helper(cpi, x, xd, subsize, mi_row, mi_col);
|
|
|
|
copy_partitioning_helper(cpi, x, xd, subsize, mi_row + bs, mi_col);
|
|
|
|
copy_partitioning_helper(cpi, x, xd, subsize, mi_row, mi_col + bs);
|
|
|
|
copy_partitioning_helper(cpi, x, xd, subsize, mi_row + bs, mi_col + bs);
|
2016-12-19 19:39:04 +01:00
|
|
|
break;
|
|
|
|
default: assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 02:14:11 +02:00
|
|
|
static int copy_partitioning(VP9_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
|
|
|
|
int mi_row, int mi_col, int segment_id,
|
|
|
|
int sb_offset) {
|
2017-05-18 23:12:24 +02:00
|
|
|
int svc_copy_allowed = 1;
|
2017-05-16 02:14:11 +02:00
|
|
|
int frames_since_key_thresh = 1;
|
2017-05-18 23:12:24 +02:00
|
|
|
if (cpi->use_svc) {
|
|
|
|
// For SVC, don't allow copy if base spatial layer is key frame, or if
|
|
|
|
// frame is not a temporal enhancement layer frame.
|
2017-05-16 02:14:11 +02:00
|
|
|
int layer = LAYER_IDS_TO_IDX(0, cpi->svc.temporal_layer_id,
|
|
|
|
cpi->svc.number_temporal_layers);
|
|
|
|
const LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
|
2017-11-29 21:48:20 +01:00
|
|
|
if (lc->is_key_frame || !cpi->svc.non_reference_frame) svc_copy_allowed = 0;
|
2017-05-16 02:14:11 +02:00
|
|
|
frames_since_key_thresh = cpi->svc.number_spatial_layers << 1;
|
|
|
|
}
|
2017-05-18 23:12:24 +02:00
|
|
|
if (cpi->rc.frames_since_key > frames_since_key_thresh && svc_copy_allowed &&
|
|
|
|
!cpi->resize_pending && segment_id == CR_SEGMENT_ID_BASE &&
|
2017-01-25 20:31:05 +01:00
|
|
|
cpi->prev_segment_id[sb_offset] == CR_SEGMENT_ID_BASE &&
|
|
|
|
cpi->copied_frame_cnt[sb_offset] < cpi->max_copied_frame) {
|
|
|
|
if (cpi->prev_partition != NULL) {
|
2017-05-16 02:14:11 +02:00
|
|
|
copy_partitioning_helper(cpi, x, xd, BLOCK_64X64, mi_row, mi_col);
|
2017-01-25 20:31:05 +01:00
|
|
|
cpi->copied_frame_cnt[sb_offset] += 1;
|
|
|
|
memcpy(x->variance_low, &(cpi->prev_variance_low[sb_offset * 25]),
|
|
|
|
sizeof(x->variance_low));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-14 02:21:26 +01:00
|
|
|
static int scale_partitioning_svc(VP9_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
|
|
|
|
BLOCK_SIZE bsize, int mi_row, int mi_col,
|
2017-11-09 00:12:44 +01:00
|
|
|
int mi_row_high, int mi_col_high) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
SVC *const svc = &cpi->svc;
|
|
|
|
BLOCK_SIZE *prev_part = svc->prev_partition_svc;
|
|
|
|
// Variables with _high are for higher resolution.
|
|
|
|
int bsize_high = 0;
|
|
|
|
int subsize_high = 0;
|
2017-11-14 02:21:26 +01:00
|
|
|
const int bsl_high = b_width_log2_lookup[bsize];
|
|
|
|
const int bs_high = (1 << bsl_high) >> 2;
|
|
|
|
const int has_rows = (mi_row_high + bs_high) < cm->mi_rows;
|
|
|
|
const int has_cols = (mi_col_high + bs_high) < cm->mi_cols;
|
|
|
|
|
|
|
|
const int row_boundary_block_scale_factor[BLOCK_SIZES] = {
|
|
|
|
13, 13, 13, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0
|
|
|
|
};
|
|
|
|
const int col_boundary_block_scale_factor[BLOCK_SIZES] = {
|
|
|
|
13, 13, 13, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0
|
|
|
|
};
|
|
|
|
int start_pos;
|
|
|
|
BLOCK_SIZE bsize_low;
|
|
|
|
PARTITION_TYPE partition_high;
|
|
|
|
|
|
|
|
if (mi_row_high >= cm->mi_rows || mi_col_high >= cm->mi_cols) return 0;
|
|
|
|
if (mi_row >= (cm->mi_rows >> 1) || mi_col >= (cm->mi_cols >> 1)) return 0;
|
2017-11-09 00:12:44 +01:00
|
|
|
|
|
|
|
// Find corresponding (mi_col/mi_row) block down-scaled by 2x2.
|
2017-11-14 02:21:26 +01:00
|
|
|
start_pos = mi_row * (svc->mi_stride[svc->spatial_layer_id - 1]) + mi_col;
|
|
|
|
bsize_low = prev_part[start_pos];
|
|
|
|
// The block size is too big for boundaries. Do variance based partitioning.
|
|
|
|
if ((!has_rows || !has_cols) && bsize_low > BLOCK_16X16) return 1;
|
2017-11-09 00:12:44 +01:00
|
|
|
|
2017-11-17 18:47:03 +01:00
|
|
|
// For reference frames: return 1 (do variance-based partitioning) if the
|
|
|
|
// superblock is not low source sad and lower-resoln bsize is below 32x32.
|
|
|
|
if (!cpi->svc.non_reference_frame && !x->skip_low_source_sad &&
|
|
|
|
bsize_low < BLOCK_32X32)
|
|
|
|
return 1;
|
|
|
|
|
2017-11-09 00:12:44 +01:00
|
|
|
// Scale up block size by 2x2. Force 64x64 for size larger than 32x32.
|
2017-11-14 02:21:26 +01:00
|
|
|
if (bsize_low < BLOCK_32X32) {
|
|
|
|
bsize_high = bsize_low + 3;
|
|
|
|
} else if (bsize_low >= BLOCK_32X32) {
|
2017-11-09 00:12:44 +01:00
|
|
|
bsize_high = BLOCK_64X64;
|
|
|
|
}
|
2017-11-14 02:21:26 +01:00
|
|
|
// Scale up blocks on boundary.
|
|
|
|
if (!has_cols && has_rows) {
|
|
|
|
bsize_high = bsize_low + row_boundary_block_scale_factor[bsize_low];
|
|
|
|
} else if (has_cols && !has_rows) {
|
|
|
|
bsize_high = bsize_low + col_boundary_block_scale_factor[bsize_low];
|
|
|
|
} else if (!has_cols && !has_rows) {
|
|
|
|
bsize_high = bsize_low;
|
|
|
|
}
|
2017-11-09 00:12:44 +01:00
|
|
|
|
2017-11-14 02:21:26 +01:00
|
|
|
partition_high = partition_lookup[bsl_high][bsize_high];
|
|
|
|
subsize_high = get_subsize(bsize, partition_high);
|
|
|
|
|
|
|
|
if (subsize_high < BLOCK_8X8) {
|
2017-11-09 00:12:44 +01:00
|
|
|
set_block_size(cpi, x, xd, mi_row_high, mi_col_high, bsize_high);
|
|
|
|
} else {
|
2017-11-14 02:21:26 +01:00
|
|
|
const int bsl = b_width_log2_lookup[bsize];
|
|
|
|
const int bs = (1 << bsl) >> 2;
|
|
|
|
switch (partition_high) {
|
2017-11-09 00:12:44 +01:00
|
|
|
case PARTITION_NONE:
|
|
|
|
set_block_size(cpi, x, xd, mi_row_high, mi_col_high, bsize_high);
|
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
|
|
|
set_block_size(cpi, x, xd, mi_row_high, mi_col_high, subsize_high);
|
|
|
|
if (subsize_high < BLOCK_64X64)
|
2017-11-14 02:21:26 +01:00
|
|
|
set_block_size(cpi, x, xd, mi_row_high + bs_high, mi_col_high,
|
2017-11-09 00:12:44 +01:00
|
|
|
subsize_high);
|
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
|
|
|
set_block_size(cpi, x, xd, mi_row_high, mi_col_high, subsize_high);
|
|
|
|
if (subsize_high < BLOCK_64X64)
|
|
|
|
set_block_size(cpi, x, xd, mi_row_high, mi_col_high + bs_high,
|
|
|
|
subsize_high);
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
2017-11-14 02:21:26 +01:00
|
|
|
if (scale_partitioning_svc(cpi, x, xd, subsize_high, mi_row, mi_col,
|
|
|
|
mi_row_high, mi_col_high))
|
|
|
|
return 1;
|
|
|
|
if (scale_partitioning_svc(cpi, x, xd, subsize_high, mi_row + (bs >> 1),
|
|
|
|
mi_col, mi_row_high + bs_high, mi_col_high))
|
|
|
|
return 1;
|
|
|
|
if (scale_partitioning_svc(cpi, x, xd, subsize_high, mi_row,
|
|
|
|
mi_col + (bs >> 1), mi_row_high,
|
|
|
|
mi_col_high + bs_high))
|
|
|
|
return 1;
|
|
|
|
if (scale_partitioning_svc(cpi, x, xd, subsize_high, mi_row + (bs >> 1),
|
|
|
|
mi_col + (bs >> 1), mi_row_high + bs_high,
|
|
|
|
mi_col_high + bs_high))
|
|
|
|
return 1;
|
2017-11-09 00:12:44 +01:00
|
|
|
break;
|
|
|
|
default: assert(0);
|
|
|
|
}
|
|
|
|
}
|
2017-11-14 02:21:26 +01:00
|
|
|
|
|
|
|
return 0;
|
2017-11-09 00:12:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void update_partition_svc(VP9_COMP *cpi, BLOCK_SIZE bsize, int mi_row,
|
|
|
|
int mi_col) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
BLOCK_SIZE *prev_part = cpi->svc.prev_partition_svc;
|
|
|
|
int start_pos = mi_row * cm->mi_stride + mi_col;
|
|
|
|
const int bsl = b_width_log2_lookup[bsize];
|
|
|
|
const int bs = (1 << bsl) >> 2;
|
|
|
|
BLOCK_SIZE subsize;
|
|
|
|
PARTITION_TYPE partition;
|
|
|
|
const MODE_INFO *mi = NULL;
|
|
|
|
int xx, yy;
|
|
|
|
|
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
|
|
|
|
|
|
|
mi = cm->mi_grid_visible[start_pos];
|
|
|
|
partition = partition_lookup[bsl][mi->sb_type];
|
|
|
|
subsize = get_subsize(bsize, partition);
|
|
|
|
if (subsize < BLOCK_8X8) {
|
|
|
|
prev_part[start_pos] = bsize;
|
|
|
|
} else {
|
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
|
|
|
prev_part[start_pos] = bsize;
|
|
|
|
if (bsize == BLOCK_64X64) {
|
|
|
|
for (xx = 0; xx < 8; xx += 4)
|
|
|
|
for (yy = 0; yy < 8; yy += 4) {
|
|
|
|
if ((mi_row + xx < cm->mi_rows) && (mi_col + yy < cm->mi_cols))
|
|
|
|
prev_part[start_pos + xx * cm->mi_stride + yy] = bsize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
|
|
|
prev_part[start_pos] = subsize;
|
|
|
|
if (mi_row + bs < cm->mi_rows)
|
|
|
|
prev_part[start_pos + bs * cm->mi_stride] = subsize;
|
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
|
|
|
prev_part[start_pos] = subsize;
|
|
|
|
if (mi_col + bs < cm->mi_cols) prev_part[start_pos + bs] = subsize;
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
|
|
|
update_partition_svc(cpi, subsize, mi_row, mi_col);
|
|
|
|
update_partition_svc(cpi, subsize, mi_row + bs, mi_col);
|
|
|
|
update_partition_svc(cpi, subsize, mi_row, mi_col + bs);
|
|
|
|
update_partition_svc(cpi, subsize, mi_row + bs, mi_col + bs);
|
|
|
|
break;
|
|
|
|
default: assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-30 05:01:44 +01:00
|
|
|
static void update_prev_partition_helper(VP9_COMP *cpi, BLOCK_SIZE bsize,
|
|
|
|
int mi_row, int mi_col) {
|
2016-12-19 19:39:04 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
BLOCK_SIZE *prev_part = cpi->prev_partition;
|
|
|
|
int start_pos = mi_row * cm->mi_stride + mi_col;
|
|
|
|
const int bsl = b_width_log2_lookup[bsize];
|
2017-11-09 00:12:44 +01:00
|
|
|
const int bs = (1 << bsl) >> 2;
|
2016-12-19 19:39:04 +01:00
|
|
|
BLOCK_SIZE subsize;
|
|
|
|
PARTITION_TYPE partition;
|
|
|
|
const MODE_INFO *mi = NULL;
|
|
|
|
|
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
|
|
|
|
|
|
|
mi = cm->mi_grid_visible[start_pos];
|
|
|
|
partition = partition_lookup[bsl][mi->sb_type];
|
|
|
|
subsize = get_subsize(bsize, partition);
|
|
|
|
if (subsize < BLOCK_8X8) {
|
|
|
|
prev_part[start_pos] = bsize;
|
|
|
|
} else {
|
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE: prev_part[start_pos] = bsize; break;
|
|
|
|
case PARTITION_HORZ:
|
|
|
|
prev_part[start_pos] = subsize;
|
|
|
|
if (mi_row + bs < cm->mi_rows)
|
|
|
|
prev_part[start_pos + bs * cm->mi_stride] = subsize;
|
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
|
|
|
prev_part[start_pos] = subsize;
|
|
|
|
if (mi_col + bs < cm->mi_cols) prev_part[start_pos + bs] = subsize;
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
2017-11-30 05:01:44 +01:00
|
|
|
update_prev_partition_helper(cpi, subsize, mi_row, mi_col);
|
|
|
|
update_prev_partition_helper(cpi, subsize, mi_row + bs, mi_col);
|
|
|
|
update_prev_partition_helper(cpi, subsize, mi_row, mi_col + bs);
|
|
|
|
update_prev_partition_helper(cpi, subsize, mi_row + bs, mi_col + bs);
|
2016-12-19 19:39:04 +01:00
|
|
|
break;
|
|
|
|
default: assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-30 05:01:44 +01:00
|
|
|
static void update_prev_partition(VP9_COMP *cpi, MACROBLOCK *x, int segment_id,
|
|
|
|
int mi_row, int mi_col, int sb_offset) {
|
|
|
|
update_prev_partition_helper(cpi, BLOCK_64X64, mi_row, mi_col);
|
|
|
|
cpi->prev_segment_id[sb_offset] = segment_id;
|
|
|
|
memcpy(&(cpi->prev_variance_low[sb_offset * 25]), x->variance_low,
|
|
|
|
sizeof(x->variance_low));
|
|
|
|
// Reset the counter for copy partitioning
|
|
|
|
cpi->copied_frame_cnt[sb_offset] = 0;
|
|
|
|
}
|
|
|
|
|
2016-06-27 23:08:34 +02:00
|
|
|
static void chroma_check(VP9_COMP *cpi, MACROBLOCK *x, int bsize,
|
|
|
|
unsigned int y_sad, int is_key_frame) {
|
|
|
|
int i;
|
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2017-04-21 19:10:05 +02:00
|
|
|
|
|
|
|
if (is_key_frame) return;
|
|
|
|
|
2017-03-24 19:31:19 +01:00
|
|
|
// For speed >= 8, avoid the chroma check if y_sad is above threshold.
|
2017-04-21 19:10:05 +02:00
|
|
|
if (cpi->oxcf.speed >= 8) {
|
|
|
|
if (y_sad > cpi->vbp_thresholds[1] &&
|
|
|
|
(!cpi->noise_estimate.enabled ||
|
|
|
|
vp9_noise_estimate_extract_level(&cpi->noise_estimate) < kMedium))
|
|
|
|
return;
|
|
|
|
}
|
2016-06-27 23:08:34 +02:00
|
|
|
|
|
|
|
for (i = 1; i <= 2; ++i) {
|
|
|
|
unsigned int uv_sad = UINT_MAX;
|
2016-07-27 05:43:23 +02:00
|
|
|
struct macroblock_plane *p = &x->plane[i];
|
2016-06-27 23:08:34 +02:00
|
|
|
struct macroblockd_plane *pd = &xd->plane[i];
|
|
|
|
const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
|
|
|
|
|
|
|
|
if (bs != BLOCK_INVALID)
|
2016-07-27 05:43:23 +02:00
|
|
|
uv_sad = cpi->fn_ptr[bs].sdf(p->src.buf, p->src.stride, pd->dst.buf,
|
|
|
|
pd->dst.stride);
|
2016-06-27 23:08:34 +02:00
|
|
|
|
|
|
|
// TODO(marpan): Investigate if we should lower this threshold if
|
|
|
|
// superblock is detected as skin.
|
|
|
|
x->color_sensitivity[i - 1] = uv_sad > (y_sad >> 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-31 03:57:44 +02:00
|
|
|
static uint64_t avg_source_sad(VP9_COMP *cpi, MACROBLOCK *x, int shift,
|
|
|
|
int sb_offset) {
|
2017-03-23 22:37:47 +01:00
|
|
|
unsigned int tmp_sse;
|
|
|
|
uint64_t tmp_sad;
|
|
|
|
unsigned int tmp_variance;
|
|
|
|
const BLOCK_SIZE bsize = BLOCK_64X64;
|
|
|
|
uint8_t *src_y = cpi->Source->y_buffer;
|
|
|
|
int src_ystride = cpi->Source->y_stride;
|
|
|
|
uint8_t *last_src_y = cpi->Last_Source->y_buffer;
|
|
|
|
int last_src_ystride = cpi->Last_Source->y_stride;
|
|
|
|
uint64_t avg_source_sad_threshold = 10000;
|
|
|
|
uint64_t avg_source_sad_threshold2 = 12000;
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
2017-07-31 03:57:44 +02:00
|
|
|
if (cpi->common.use_highbitdepth) return 0;
|
2017-03-23 22:37:47 +01:00
|
|
|
#endif
|
|
|
|
src_y += shift;
|
|
|
|
last_src_y += shift;
|
|
|
|
tmp_sad =
|
|
|
|
cpi->fn_ptr[bsize].sdf(src_y, src_ystride, last_src_y, last_src_ystride);
|
|
|
|
tmp_variance = vpx_variance64x64(src_y, src_ystride, last_src_y,
|
|
|
|
last_src_ystride, &tmp_sse);
|
|
|
|
// Note: tmp_sse - tmp_variance = ((sum * sum) >> 12)
|
|
|
|
if (tmp_sad < avg_source_sad_threshold)
|
|
|
|
x->content_state_sb = ((tmp_sse - tmp_variance) < 25) ? kLowSadLowSumdiff
|
|
|
|
: kLowSadHighSumdiff;
|
|
|
|
else
|
|
|
|
x->content_state_sb = ((tmp_sse - tmp_variance) < 25) ? kHighSadLowSumdiff
|
|
|
|
: kHighSadHighSumdiff;
|
2017-04-14 20:32:19 +02:00
|
|
|
|
|
|
|
// Detect large lighting change.
|
2017-07-29 01:34:04 +02:00
|
|
|
if (cpi->oxcf.content != VP9E_CONTENT_SCREEN &&
|
2017-08-22 23:46:39 +02:00
|
|
|
cpi->oxcf.rc_mode == VPX_CBR && tmp_variance < (tmp_sse >> 3) &&
|
|
|
|
(tmp_sse - tmp_variance) > 10000)
|
2017-04-14 20:32:19 +02:00
|
|
|
x->content_state_sb = kLowVarHighSumdiff;
|
2017-07-18 01:04:04 +02:00
|
|
|
else if (tmp_sad > (avg_source_sad_threshold << 1))
|
2017-06-22 05:39:59 +02:00
|
|
|
x->content_state_sb = kVeryHighSad;
|
|
|
|
|
2017-03-23 22:37:47 +01:00
|
|
|
if (cpi->content_state_sb_fd != NULL) {
|
|
|
|
if (tmp_sad < avg_source_sad_threshold2) {
|
|
|
|
// Cap the increment to 255.
|
|
|
|
if (cpi->content_state_sb_fd[sb_offset] < 255)
|
|
|
|
cpi->content_state_sb_fd[sb_offset]++;
|
|
|
|
} else {
|
|
|
|
cpi->content_state_sb_fd[sb_offset] = 0;
|
|
|
|
}
|
|
|
|
}
|
2017-07-31 03:57:44 +02:00
|
|
|
return tmp_sad;
|
2017-03-23 22:37:47 +01:00
|
|
|
}
|
|
|
|
|
2014-11-12 23:51:49 +01:00
|
|
|
// This function chooses partitioning based on the variance between source and
|
2015-02-18 18:40:34 +01:00
|
|
|
// reconstructed last, where variance is computed for down-sampled inputs.
|
2016-07-27 05:43:23 +02:00
|
|
|
static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
|
|
|
|
MACROBLOCK *x, int mi_row, int mi_col) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2014-11-12 23:51:49 +01:00
|
|
|
int i, j, k, m;
|
2014-03-04 20:15:35 +01:00
|
|
|
v64x64 vt;
|
2017-10-31 03:21:24 +01:00
|
|
|
v16x16 *vt2 = NULL;
|
2015-04-16 02:48:20 +02:00
|
|
|
int force_split[21];
|
2015-12-09 21:26:48 +01:00
|
|
|
int avg_32x32;
|
2016-10-14 19:02:49 +02:00
|
|
|
int max_var_32x32 = 0;
|
|
|
|
int min_var_32x32 = INT_MAX;
|
|
|
|
int var_32x32;
|
2015-12-09 21:26:48 +01:00
|
|
|
int avg_16x16[4];
|
2017-03-20 17:16:23 +01:00
|
|
|
int maxvar_16x16[4];
|
|
|
|
int minvar_16x16[4];
|
2016-10-21 20:11:34 +02:00
|
|
|
int64_t threshold_4x4avg;
|
2016-10-14 19:02:49 +02:00
|
|
|
NOISE_LEVEL noise_level = kLow;
|
2017-02-13 19:16:42 +01:00
|
|
|
int content_state = 0;
|
2014-03-04 20:15:35 +01:00
|
|
|
uint8_t *s;
|
|
|
|
const uint8_t *d;
|
|
|
|
int sp;
|
|
|
|
int dp;
|
2017-11-10 00:24:10 +01:00
|
|
|
int compute_minmax_variance = 1;
|
2016-06-27 23:08:34 +02:00
|
|
|
unsigned int y_sad = UINT_MAX;
|
|
|
|
BLOCK_SIZE bsize = BLOCK_64X64;
|
2016-05-20 22:45:46 +02:00
|
|
|
// Ref frame used in partitioning.
|
|
|
|
MV_REFERENCE_FRAME ref_frame_partition = LAST_FRAME;
|
2014-03-04 20:15:35 +01:00
|
|
|
int pixels_wide = 64, pixels_high = 64;
|
2016-07-27 05:43:23 +02:00
|
|
|
int64_t thresholds[4] = { cpi->vbp_thresholds[0], cpi->vbp_thresholds[1],
|
|
|
|
cpi->vbp_thresholds[2], cpi->vbp_thresholds[3] };
|
2015-02-09 19:21:17 +01:00
|
|
|
|
2015-12-16 17:57:05 +01:00
|
|
|
// For the variance computation under SVC mode, we treat the frame as key if
|
|
|
|
// the reference (base layer frame) is key frame (i.e., is_key_frame == 1).
|
2016-07-27 05:43:23 +02:00
|
|
|
const int is_key_frame =
|
|
|
|
(cm->frame_type == KEY_FRAME ||
|
|
|
|
(is_one_pass_cbr_svc(cpi) &&
|
|
|
|
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame));
|
2015-01-06 02:13:13 +01:00
|
|
|
// Always use 4x4 partition for key frame.
|
2015-12-16 17:57:05 +01:00
|
|
|
const int use_4x4_partition = cm->frame_type == KEY_FRAME;
|
2015-02-09 19:21:17 +01:00
|
|
|
const int low_res = (cm->width <= 352 && cm->height <= 288);
|
2015-01-06 02:13:13 +01:00
|
|
|
int variance4x4downsample[16];
|
2016-03-16 23:56:35 +01:00
|
|
|
int segment_id;
|
2017-01-13 20:28:27 +01:00
|
|
|
int sb_offset = (cm->mi_stride >> 3) * (mi_row >> 3) + (mi_col >> 3);
|
2017-01-23 21:10:01 +01:00
|
|
|
|
2016-03-16 23:56:35 +01:00
|
|
|
set_offsets(cpi, tile, x, mi_row, mi_col, BLOCK_64X64);
|
|
|
|
segment_id = xd->mi[0]->segment_id;
|
2015-01-28 20:34:24 +01:00
|
|
|
|
2017-11-10 00:24:10 +01:00
|
|
|
if (cpi->oxcf.speed >= 8 || (cpi->use_svc && cpi->svc.non_reference_frame))
|
|
|
|
compute_minmax_variance = 0;
|
|
|
|
|
2017-11-30 05:01:44 +01:00
|
|
|
memset(x->variance_low, 0, sizeof(x->variance_low));
|
|
|
|
|
2017-03-23 22:37:47 +01:00
|
|
|
if (cpi->sf.use_source_sad && !is_key_frame) {
|
2017-01-23 21:10:01 +01:00
|
|
|
int sb_offset2 = ((cm->mi_cols + 7) >> 3) * (mi_row >> 3) + (mi_col >> 3);
|
2017-03-23 22:37:47 +01:00
|
|
|
content_state = x->content_state_sb;
|
2017-02-13 19:16:42 +01:00
|
|
|
x->skip_low_source_sad = (content_state == kLowSadLowSumdiff ||
|
|
|
|
content_state == kLowSadHighSumdiff)
|
|
|
|
? 1
|
|
|
|
: 0;
|
2017-04-14 20:32:19 +02:00
|
|
|
x->lowvar_highsumdiff = (content_state == kLowVarHighSumdiff) ? 1 : 0;
|
2017-03-23 22:37:47 +01:00
|
|
|
if (cpi->content_state_sb_fd != NULL)
|
|
|
|
x->last_sb_high_content = cpi->content_state_sb_fd[sb_offset2];
|
2017-11-09 00:12:44 +01:00
|
|
|
|
2017-11-15 04:52:54 +01:00
|
|
|
// For SVC on top spatial layer: use/scale the partition from
|
|
|
|
// the lower spatial resolution if svc_use_lowres_part is enabled.
|
|
|
|
if (cpi->sf.svc_use_lowres_part &&
|
|
|
|
cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1 &&
|
2017-11-14 02:21:26 +01:00
|
|
|
cpi->svc.prev_partition_svc != NULL && content_state != kVeryHighSad) {
|
|
|
|
if (!scale_partitioning_svc(cpi, x, xd, BLOCK_64X64, mi_row >> 1,
|
2017-11-30 05:01:44 +01:00
|
|
|
mi_col >> 1, mi_row, mi_col)) {
|
|
|
|
if (cpi->sf.copy_partition_flag) {
|
|
|
|
update_prev_partition(cpi, x, segment_id, mi_row, mi_col, sb_offset);
|
|
|
|
}
|
2017-11-14 02:21:26 +01:00
|
|
|
return 0;
|
2017-11-30 05:01:44 +01:00
|
|
|
}
|
2017-11-09 00:12:44 +01:00
|
|
|
}
|
2017-02-13 19:16:42 +01:00
|
|
|
// If source_sad is low copy the partition without computing the y_sad.
|
|
|
|
if (x->skip_low_source_sad && cpi->sf.copy_partition_flag &&
|
2017-05-16 02:14:11 +02:00
|
|
|
copy_partitioning(cpi, x, xd, mi_row, mi_col, segment_id, sb_offset)) {
|
2017-07-13 23:49:39 +02:00
|
|
|
x->sb_use_mv_part = 1;
|
2017-11-15 04:52:54 +01:00
|
|
|
if (cpi->sf.svc_use_lowres_part &&
|
|
|
|
cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 2)
|
2017-11-09 00:12:44 +01:00
|
|
|
update_partition_svc(cpi, BLOCK_64X64, mi_row, mi_col);
|
2017-01-25 20:31:05 +01:00
|
|
|
return 0;
|
2017-01-23 21:10:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-27 21:03:12 +01:00
|
|
|
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled &&
|
|
|
|
cyclic_refresh_segment_id_boosted(segment_id)) {
|
|
|
|
int q = vp9_get_qindex(&cm->seg, segment_id, cm->base_qindex);
|
|
|
|
set_vbp_thresholds(cpi, thresholds, q, content_state);
|
2017-02-13 19:16:42 +01:00
|
|
|
} else {
|
|
|
|
set_vbp_thresholds(cpi, thresholds, cm->base_qindex, content_state);
|
|
|
|
}
|
|
|
|
|
2016-11-14 19:22:00 +01:00
|
|
|
// For non keyframes, disable 4x4 average for low resolution when speed = 8
|
|
|
|
threshold_4x4avg = (cpi->oxcf.speed < 8) ? thresholds[1] << 1 : INT64_MAX;
|
2016-10-21 20:11:34 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (xd->mb_to_right_edge < 0) pixels_wide += (xd->mb_to_right_edge >> 3);
|
|
|
|
if (xd->mb_to_bottom_edge < 0) pixels_high += (xd->mb_to_bottom_edge >> 3);
|
2014-03-04 20:15:35 +01:00
|
|
|
|
|
|
|
s = x->plane[0].src.buf;
|
|
|
|
sp = x->plane[0].src.stride;
|
|
|
|
|
2016-01-22 20:45:31 +01:00
|
|
|
// Index for force_split: 0 for 64x64, 1-4 for 32x32 blocks,
|
|
|
|
// 5-20 for the 16x16 blocks.
|
|
|
|
force_split[0] = 0;
|
|
|
|
|
2015-12-16 17:57:05 +01:00
|
|
|
if (!is_key_frame) {
|
2015-05-22 01:15:37 +02:00
|
|
|
// In the case of spatial/temporal scalable coding, the assumption here is
|
|
|
|
// that the temporal reference frame will always be of type LAST_FRAME.
|
|
|
|
// TODO(marpan): If that assumption is broken, we need to revisit this code.
|
2016-01-20 01:40:20 +01:00
|
|
|
MODE_INFO *mi = xd->mi[0];
|
2016-08-03 02:37:32 +02:00
|
|
|
YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
|
2015-03-11 23:44:26 +01:00
|
|
|
|
2015-05-22 01:15:37 +02:00
|
|
|
const YV12_BUFFER_CONFIG *yv12_g = NULL;
|
2016-12-19 19:39:04 +01:00
|
|
|
unsigned int y_sad_g, y_sad_thr, y_sad_last;
|
2016-07-27 05:43:23 +02:00
|
|
|
bsize = BLOCK_32X32 + (mi_col + 4 < cm->mi_cols) * 2 +
|
|
|
|
(mi_row + 4 < cm->mi_rows);
|
2015-03-11 23:44:26 +01:00
|
|
|
|
2015-02-18 18:40:34 +01:00
|
|
|
assert(yv12 != NULL);
|
2015-05-22 01:15:37 +02:00
|
|
|
|
|
|
|
if (!(is_one_pass_cbr_svc(cpi) && cpi->svc.spatial_layer_id)) {
|
|
|
|
// For now, GOLDEN will not be used for non-zero spatial layers, since
|
|
|
|
// it may not be a temporal reference.
|
|
|
|
yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
|
|
|
|
}
|
|
|
|
|
2017-02-22 18:49:17 +01:00
|
|
|
// Only compute y_sad_g (sad for golden reference) for speed < 8.
|
|
|
|
if (cpi->oxcf.speed < 8 && yv12_g && yv12_g != yv12 &&
|
|
|
|
(cpi->ref_frame_flags & VP9_GOLD_FLAG)) {
|
2015-03-06 22:45:39 +01:00
|
|
|
vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
|
|
|
|
&cm->frame_refs[GOLDEN_FRAME - 1].sf);
|
2016-07-27 05:43:23 +02:00
|
|
|
y_sad_g = cpi->fn_ptr[bsize].sdf(
|
|
|
|
x->plane[0].src.buf, x->plane[0].src.stride, xd->plane[0].pre[0].buf,
|
|
|
|
xd->plane[0].pre[0].stride);
|
2015-03-06 22:45:39 +01:00
|
|
|
} else {
|
|
|
|
y_sad_g = UINT_MAX;
|
|
|
|
}
|
2015-03-11 23:44:26 +01:00
|
|
|
|
2016-08-03 02:37:32 +02:00
|
|
|
if (cpi->oxcf.lag_in_frames > 0 && cpi->oxcf.rc_mode == VPX_VBR &&
|
|
|
|
cpi->rc.is_src_frame_alt_ref) {
|
|
|
|
yv12 = get_ref_frame_buffer(cpi, ALTREF_FRAME);
|
|
|
|
vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col,
|
|
|
|
&cm->frame_refs[ALTREF_FRAME - 1].sf);
|
|
|
|
mi->ref_frame[0] = ALTREF_FRAME;
|
|
|
|
y_sad_g = UINT_MAX;
|
|
|
|
} else {
|
|
|
|
vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col,
|
|
|
|
&cm->frame_refs[LAST_FRAME - 1].sf);
|
|
|
|
mi->ref_frame[0] = LAST_FRAME;
|
|
|
|
}
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->ref_frame[1] = NONE;
|
|
|
|
mi->sb_type = BLOCK_64X64;
|
|
|
|
mi->mv[0].as_int = 0;
|
|
|
|
mi->interp_filter = BILINEAR;
|
2015-03-11 23:44:26 +01:00
|
|
|
|
2017-07-13 23:49:39 +02:00
|
|
|
if (cpi->oxcf.speed >= 8 && !low_res &&
|
|
|
|
x->content_state_sb != kVeryHighSad) {
|
2017-04-05 02:47:03 +02:00
|
|
|
y_sad = cpi->fn_ptr[bsize].sdf(
|
|
|
|
x->plane[0].src.buf, x->plane[0].src.stride, xd->plane[0].pre[0].buf,
|
|
|
|
xd->plane[0].pre[0].stride);
|
2017-07-13 23:49:39 +02:00
|
|
|
} else {
|
2017-04-05 02:47:03 +02:00
|
|
|
y_sad = vp9_int_pro_motion_estimation(cpi, x, bsize, mi_row, mi_col);
|
2017-07-13 23:49:39 +02:00
|
|
|
x->sb_use_mv_part = 1;
|
|
|
|
x->sb_mvcol_part = mi->mv[0].as_mv.col;
|
|
|
|
x->sb_mvrow_part = mi->mv[0].as_mv.row;
|
|
|
|
}
|
2017-04-05 02:47:03 +02:00
|
|
|
|
2016-12-19 19:39:04 +01:00
|
|
|
y_sad_last = y_sad;
|
2016-06-15 19:14:14 +02:00
|
|
|
// Pick ref frame for partitioning, bias last frame when y_sad_g and y_sad
|
|
|
|
// are close if short_circuit_low_temp_var is on.
|
|
|
|
y_sad_thr = cpi->sf.short_circuit_low_temp_var ? (y_sad * 7) >> 3 : y_sad;
|
|
|
|
if (y_sad_g < y_sad_thr) {
|
2015-03-06 22:45:39 +01:00
|
|
|
vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
|
|
|
|
&cm->frame_refs[GOLDEN_FRAME - 1].sf);
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->ref_frame[0] = GOLDEN_FRAME;
|
|
|
|
mi->mv[0].as_int = 0;
|
2015-03-06 22:45:39 +01:00
|
|
|
y_sad = y_sad_g;
|
2016-05-20 22:45:46 +02:00
|
|
|
ref_frame_partition = GOLDEN_FRAME;
|
2015-03-06 22:45:39 +01:00
|
|
|
} else {
|
2016-01-20 01:40:20 +01:00
|
|
|
x->pred_mv[LAST_FRAME] = mi->mv[0].as_mv;
|
2016-05-20 22:45:46 +02:00
|
|
|
ref_frame_partition = LAST_FRAME;
|
2015-03-06 22:45:39 +01:00
|
|
|
}
|
Integral projection based motion estimation
This commit introduces a new block match motion estimation
using integral projection measurement. The 2-D block and the nearby
region is projected onto the horizontal and vertical 1-D vectors,
respectively. It then runs vector match, instead of block match,
over the two separate 1-D vectors to locate the motion compensated
reference block.
This process is run per 64x64 block to align the reference before
choosing partitioning in speed 6. The overall CPU cycle cost due
to this additional 64x64 block match (SSE2 version) takes around 2%
at low bit-rate rtc speed 6. When strong motion activities exist in
the video sequence, it substantially improves the partition
selection accuracy, thereby achieving better compression performance
and lower CPU cycles.
The experiments were tested in RTC speed -6 setting:
cloud 1080p 500 kbps
17006 b/f, 37.086 dB, 5386 ms ->
16669 b/f, 37.970 dB, 5085 ms (>0.9dB gain and 6% faster)
pedestrian_area 1080p 500 kbps
53537 b/f, 36.771 dB, 18706 ms ->
51897 b/f, 36.792 dB, 18585 ms (4% bit-rate savings)
blue_sky 1080p 500 kbps
70214 b/f, 33.600 dB, 13979 ms ->
53885 b/f, 33.645 dB, 10878 ms (30% bit-rate savings, 25% faster)
jimred 400 kbps
13380 b/f, 36.014 dB, 5723 ms ->
13377 b/f, 36.087 dB, 5831 ms (2% bit-rate savings, 2% slower)
Change-Id: Iffdb6ea5b16b77016bfa3dd3904d284168ae649c
2015-02-13 20:23:45 +01:00
|
|
|
|
2016-02-22 23:17:03 +01:00
|
|
|
set_ref_ptrs(cm, xd, mi->ref_frame[0], mi->ref_frame[1]);
|
2015-02-04 19:02:14 +01:00
|
|
|
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, BLOCK_64X64);
|
2015-01-21 18:32:23 +01:00
|
|
|
|
2017-06-22 02:30:53 +02:00
|
|
|
if (cpi->use_skin_detection)
|
|
|
|
x->sb_is_skin =
|
|
|
|
skin_sb_split(cpi, x, low_res, mi_row, mi_col, force_split);
|
2016-04-30 00:19:28 +02:00
|
|
|
|
2014-03-04 20:15:35 +01:00
|
|
|
d = xd->plane[0].dst.buf;
|
|
|
|
dp = xd->plane[0].dst.stride;
|
2015-04-16 02:48:20 +02:00
|
|
|
|
|
|
|
// If the y_sad is very small, take 64x64 as partition and exit.
|
|
|
|
// Don't check on boosted segment for now, as 64x64 is suppressed there.
|
2016-07-27 05:43:23 +02:00
|
|
|
if (segment_id == CR_SEGMENT_ID_BASE && y_sad < cpi->vbp_threshold_sad) {
|
2015-04-16 02:48:20 +02:00
|
|
|
const int block_width = num_8x8_blocks_wide_lookup[BLOCK_64X64];
|
|
|
|
const int block_height = num_8x8_blocks_high_lookup[BLOCK_64X64];
|
|
|
|
if (mi_col + block_width / 2 < cm->mi_cols &&
|
|
|
|
mi_row + block_height / 2 < cm->mi_rows) {
|
2015-06-29 18:27:11 +02:00
|
|
|
set_block_size(cpi, x, xd, mi_row, mi_col, BLOCK_64X64);
|
2017-01-13 20:28:27 +01:00
|
|
|
x->variance_low[0] = 1;
|
2016-06-27 23:08:34 +02:00
|
|
|
chroma_check(cpi, x, bsize, y_sad, is_key_frame);
|
2017-11-15 04:52:54 +01:00
|
|
|
if (cpi->sf.svc_use_lowres_part &&
|
|
|
|
cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 2)
|
2017-11-09 00:12:44 +01:00
|
|
|
update_partition_svc(cpi, BLOCK_64X64, mi_row, mi_col);
|
2017-11-30 05:01:44 +01:00
|
|
|
if (cpi->sf.copy_partition_flag) {
|
|
|
|
update_prev_partition(cpi, x, segment_id, mi_row, mi_col, sb_offset);
|
|
|
|
}
|
2015-04-16 02:48:20 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2016-12-19 19:39:04 +01:00
|
|
|
|
|
|
|
// If the y_sad is small enough, copy the partition of the superblock in the
|
|
|
|
// last frame to current frame only if the last frame is not a keyframe.
|
2017-01-13 23:20:59 +01:00
|
|
|
// Stop the copy every cpi->max_copied_frame to refresh the partition.
|
2016-12-19 19:39:04 +01:00
|
|
|
// TODO(jianj) : tune the threshold.
|
2017-01-25 20:31:05 +01:00
|
|
|
if (cpi->sf.copy_partition_flag && y_sad_last < cpi->vbp_threshold_copy &&
|
2017-05-16 02:14:11 +02:00
|
|
|
copy_partitioning(cpi, x, xd, mi_row, mi_col, segment_id, sb_offset)) {
|
2017-01-25 20:31:05 +01:00
|
|
|
chroma_check(cpi, x, bsize, y_sad, is_key_frame);
|
2017-11-15 04:52:54 +01:00
|
|
|
if (cpi->sf.svc_use_lowres_part &&
|
|
|
|
cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 2)
|
2017-11-09 00:12:44 +01:00
|
|
|
update_partition_svc(cpi, BLOCK_64X64, mi_row, mi_col);
|
2017-01-25 20:31:05 +01:00
|
|
|
return 0;
|
2016-12-19 19:39:04 +01:00
|
|
|
}
|
2014-03-04 20:15:35 +01:00
|
|
|
} else {
|
|
|
|
d = VP9_VAR_OFFS;
|
|
|
|
dp = 0;
|
2014-09-24 15:36:34 +02:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
|
|
|
|
switch (xd->bd) {
|
2016-07-27 05:43:23 +02:00
|
|
|
case 10: d = CONVERT_TO_BYTEPTR(VP9_HIGH_VAR_OFFS_10); break;
|
|
|
|
case 12: d = CONVERT_TO_BYTEPTR(VP9_HIGH_VAR_OFFS_12); break;
|
2014-09-24 15:36:34 +02:00
|
|
|
case 8:
|
2016-07-27 05:43:23 +02:00
|
|
|
default: d = CONVERT_TO_BYTEPTR(VP9_HIGH_VAR_OFFS_8); break;
|
2014-09-24 15:36:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
2017-11-01 00:53:46 +01:00
|
|
|
if (low_res && threshold_4x4avg < INT64_MAX)
|
|
|
|
CHECK_MEM_ERROR(cm, vt2, vpx_calloc(16, sizeof(*vt2)));
|
2015-01-06 02:13:13 +01:00
|
|
|
// Fill in the entire tree of 8x8 (or 4x4 under some conditions) variances
|
|
|
|
// for splits.
|
2014-03-04 20:15:35 +01:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
const int x32_idx = ((i & 1) << 5);
|
|
|
|
const int y32_idx = ((i >> 1) << 5);
|
2015-01-06 02:13:13 +01:00
|
|
|
const int i2 = i << 2;
|
2015-03-16 03:19:29 +01:00
|
|
|
force_split[i + 1] = 0;
|
2015-12-09 21:26:48 +01:00
|
|
|
avg_16x16[i] = 0;
|
2017-03-20 17:16:23 +01:00
|
|
|
maxvar_16x16[i] = 0;
|
|
|
|
minvar_16x16[i] = INT_MAX;
|
2014-03-04 20:15:35 +01:00
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
const int x16_idx = x32_idx + ((j & 1) << 4);
|
|
|
|
const int y16_idx = y32_idx + ((j >> 1) << 4);
|
2015-04-16 02:48:20 +02:00
|
|
|
const int split_index = 5 + i2 + j;
|
2014-03-04 20:15:35 +01:00
|
|
|
v16x16 *vst = &vt.split[i].split[j];
|
2015-04-16 02:48:20 +02:00
|
|
|
force_split[split_index] = 0;
|
2015-01-06 02:13:13 +01:00
|
|
|
variance4x4downsample[i2 + j] = 0;
|
2015-02-04 21:53:33 +01:00
|
|
|
if (!is_key_frame) {
|
2015-04-02 21:17:51 +02:00
|
|
|
fill_variance_8x8avg(s, sp, d, dp, x16_idx, y16_idx, vst,
|
2014-10-16 15:36:07 +02:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
2016-07-27 05:43:23 +02:00
|
|
|
xd->cur_buf->flags,
|
2015-03-16 19:01:00 +01:00
|
|
|
#endif
|
2016-07-27 05:43:23 +02:00
|
|
|
pixels_wide, pixels_high, is_key_frame);
|
2015-01-06 02:13:13 +01:00
|
|
|
fill_variance_tree(&vt.split[i].split[j], BLOCK_16X16);
|
2015-04-16 02:48:20 +02:00
|
|
|
get_variance(&vt.split[i].split[j].part_variances.none);
|
2015-12-09 21:26:48 +01:00
|
|
|
avg_16x16[i] += vt.split[i].split[j].part_variances.none.variance;
|
2017-03-20 17:16:23 +01:00
|
|
|
if (vt.split[i].split[j].part_variances.none.variance < minvar_16x16[i])
|
|
|
|
minvar_16x16[i] = vt.split[i].split[j].part_variances.none.variance;
|
|
|
|
if (vt.split[i].split[j].part_variances.none.variance > maxvar_16x16[i])
|
|
|
|
maxvar_16x16[i] = vt.split[i].split[j].part_variances.none.variance;
|
2016-07-27 05:43:23 +02:00
|
|
|
if (vt.split[i].split[j].part_variances.none.variance > thresholds[2]) {
|
2015-04-16 02:48:20 +02:00
|
|
|
// 16X16 variance is above threshold for split, so force split to 8x8
|
|
|
|
// for this 16x16 block (this also forces splits for upper levels).
|
|
|
|
force_split[split_index] = 1;
|
|
|
|
force_split[i + 1] = 1;
|
|
|
|
force_split[0] = 1;
|
2017-11-10 00:24:10 +01:00
|
|
|
} else if (compute_minmax_variance &&
|
2015-12-01 00:34:57 +01:00
|
|
|
vt.split[i].split[j].part_variances.none.variance >
|
2016-07-27 05:43:23 +02:00
|
|
|
thresholds[1] &&
|
2015-04-16 02:48:20 +02:00
|
|
|
!cyclic_refresh_segment_id_boosted(segment_id)) {
|
|
|
|
// We have some nominal amount of 16x16 variance (based on average),
|
|
|
|
// compute the minmax over the 8x8 sub-blocks, and if above threshold,
|
|
|
|
// force split to 8x8 block for this 16x16 block.
|
|
|
|
int minmax = compute_minmax_8x8(s, sp, d, dp, x16_idx, y16_idx,
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
xd->cur_buf->flags,
|
|
|
|
#endif
|
|
|
|
pixels_wide, pixels_high);
|
2017-07-14 01:09:11 +02:00
|
|
|
int thresh_minmax = (int)cpi->vbp_threshold_minmax;
|
|
|
|
if (x->content_state_sb == kVeryHighSad)
|
|
|
|
thresh_minmax = thresh_minmax << 1;
|
|
|
|
if (minmax > thresh_minmax) {
|
2015-04-16 02:48:20 +02:00
|
|
|
force_split[split_index] = 1;
|
|
|
|
force_split[i + 1] = 1;
|
|
|
|
force_split[0] = 1;
|
|
|
|
}
|
|
|
|
}
|
2015-01-06 02:13:13 +01:00
|
|
|
}
|
2015-12-16 17:57:05 +01:00
|
|
|
if (is_key_frame || (low_res &&
|
2016-07-27 05:43:23 +02:00
|
|
|
vt.split[i].split[j].part_variances.none.variance >
|
2016-10-21 20:11:34 +02:00
|
|
|
threshold_4x4avg)) {
|
2015-04-16 02:48:20 +02:00
|
|
|
force_split[split_index] = 0;
|
2015-01-06 02:13:13 +01:00
|
|
|
// Go down to 4x4 down-sampling for variance.
|
|
|
|
variance4x4downsample[i2 + j] = 1;
|
|
|
|
for (k = 0; k < 4; k++) {
|
|
|
|
int x8_idx = x16_idx + ((k & 1) << 3);
|
|
|
|
int y8_idx = y16_idx + ((k >> 1) << 3);
|
2016-07-27 05:43:23 +02:00
|
|
|
v8x8 *vst2 = is_key_frame ? &vst->split[k] : &vt2[i2 + j].split[k];
|
2015-04-02 21:17:51 +02:00
|
|
|
fill_variance_4x4avg(s, sp, d, dp, x8_idx, y8_idx, vst2,
|
2014-12-16 11:55:49 +01:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
2015-04-02 21:17:51 +02:00
|
|
|
xd->cur_buf->flags,
|
2014-12-16 11:55:49 +01:00
|
|
|
#endif
|
2016-07-27 05:43:23 +02:00
|
|
|
pixels_wide, pixels_high, is_key_frame);
|
2014-10-08 01:36:14 +02:00
|
|
|
}
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-20 17:16:23 +01:00
|
|
|
if (cpi->noise_estimate.enabled)
|
|
|
|
noise_level = vp9_noise_estimate_extract_level(&cpi->noise_estimate);
|
2014-03-04 20:15:35 +01:00
|
|
|
// Fill the rest of the variance tree by summing split partition values.
|
2015-12-09 21:26:48 +01:00
|
|
|
avg_32x32 = 0;
|
2014-03-04 20:15:35 +01:00
|
|
|
for (i = 0; i < 4; i++) {
|
2015-01-06 02:13:13 +01:00
|
|
|
const int i2 = i << 2;
|
2014-03-04 20:15:35 +01:00
|
|
|
for (j = 0; j < 4; j++) {
|
2015-01-06 02:13:13 +01:00
|
|
|
if (variance4x4downsample[i2 + j] == 1) {
|
2016-07-27 05:43:23 +02:00
|
|
|
v16x16 *vtemp = (!is_key_frame) ? &vt2[i2 + j] : &vt.split[i].split[j];
|
|
|
|
for (m = 0; m < 4; m++) fill_variance_tree(&vtemp->split[m], BLOCK_8X8);
|
2015-01-06 02:13:13 +01:00
|
|
|
fill_variance_tree(vtemp, BLOCK_16X16);
|
2015-12-03 02:15:41 +01:00
|
|
|
// If variance of this 16x16 block is above the threshold, force block
|
|
|
|
// to split. This also forces a split on the upper levels.
|
|
|
|
get_variance(&vtemp->part_variances.none);
|
|
|
|
if (vtemp->part_variances.none.variance > thresholds[2]) {
|
|
|
|
force_split[5 + i2 + j] = 1;
|
|
|
|
force_split[i + 1] = 1;
|
|
|
|
force_split[0] = 1;
|
|
|
|
}
|
2014-11-12 23:51:49 +01:00
|
|
|
}
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
fill_variance_tree(&vt.split[i], BLOCK_32X32);
|
2015-12-09 21:26:48 +01:00
|
|
|
// If variance of this 32x32 block is above the threshold, or if its above
|
|
|
|
// (some threshold of) the average variance over the sub-16x16 blocks, then
|
|
|
|
// force this block to split. This also forces a split on the upper
|
|
|
|
// (64x64) level.
|
2015-04-16 02:48:20 +02:00
|
|
|
if (!force_split[i + 1]) {
|
|
|
|
get_variance(&vt.split[i].part_variances.none);
|
2016-10-14 19:02:49 +02:00
|
|
|
var_32x32 = vt.split[i].part_variances.none.variance;
|
|
|
|
max_var_32x32 = VPXMAX(var_32x32, max_var_32x32);
|
|
|
|
min_var_32x32 = VPXMIN(var_32x32, min_var_32x32);
|
2015-12-09 21:26:48 +01:00
|
|
|
if (vt.split[i].part_variances.none.variance > thresholds[1] ||
|
|
|
|
(!is_key_frame &&
|
2016-07-27 05:43:23 +02:00
|
|
|
vt.split[i].part_variances.none.variance > (thresholds[1] >> 1) &&
|
|
|
|
vt.split[i].part_variances.none.variance > (avg_16x16[i] >> 1))) {
|
2015-04-16 02:48:20 +02:00
|
|
|
force_split[i + 1] = 1;
|
|
|
|
force_split[0] = 1;
|
2017-03-20 17:16:23 +01:00
|
|
|
} else if (!is_key_frame && noise_level < kLow && cm->height <= 360 &&
|
|
|
|
(maxvar_16x16[i] - minvar_16x16[i]) > (thresholds[1] >> 1) &&
|
|
|
|
maxvar_16x16[i] > thresholds[1]) {
|
|
|
|
force_split[i + 1] = 1;
|
|
|
|
force_split[0] = 1;
|
2015-04-16 02:48:20 +02:00
|
|
|
}
|
2016-10-14 19:02:49 +02:00
|
|
|
avg_32x32 += var_32x32;
|
2015-03-16 03:19:29 +01:00
|
|
|
}
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
2015-04-16 02:48:20 +02:00
|
|
|
if (!force_split[0]) {
|
2015-03-16 03:19:29 +01:00
|
|
|
fill_variance_tree(&vt, BLOCK_64X64);
|
2015-04-16 02:48:20 +02:00
|
|
|
get_variance(&vt.part_variances.none);
|
2015-12-09 21:26:48 +01:00
|
|
|
// If variance of this 64x64 block is above (some threshold of) the average
|
|
|
|
// variance over the sub-32x32 blocks, then force this block to split.
|
2016-10-14 19:02:49 +02:00
|
|
|
// Only checking this for noise level >= medium for now.
|
|
|
|
if (!is_key_frame && noise_level >= kMedium &&
|
2017-01-14 00:13:36 +01:00
|
|
|
vt.part_variances.none.variance > (9 * avg_32x32) >> 5)
|
2016-10-14 19:02:49 +02:00
|
|
|
force_split[0] = 1;
|
|
|
|
// Else if the maximum 32x32 variance minus the miniumum 32x32 variance in
|
|
|
|
// a 64x64 block is greater than threshold and the maximum 32x32 variance is
|
|
|
|
// above a miniumum threshold, then force the split of a 64x64 block
|
|
|
|
// Only check this for low noise.
|
|
|
|
else if (!is_key_frame && noise_level < kMedium &&
|
|
|
|
(max_var_32x32 - min_var_32x32) > 3 * (thresholds[0] >> 3) &&
|
|
|
|
max_var_32x32 > thresholds[0] >> 1)
|
2015-12-09 21:26:48 +01:00
|
|
|
force_split[0] = 1;
|
2015-04-16 02:48:20 +02:00
|
|
|
}
|
2014-03-04 20:15:35 +01:00
|
|
|
|
2015-04-16 02:48:20 +02:00
|
|
|
// Now go through the entire structure, splitting every block size until
|
2014-11-12 23:51:49 +01:00
|
|
|
// we get to one that's got a variance lower than our threshold.
|
2016-07-27 05:43:23 +02:00
|
|
|
if (mi_col + 8 > cm->mi_cols || mi_row + 8 > cm->mi_rows ||
|
2015-06-29 18:27:11 +02:00
|
|
|
!set_vt_partitioning(cpi, x, xd, &vt, BLOCK_64X64, mi_row, mi_col,
|
2015-04-02 22:57:22 +02:00
|
|
|
thresholds[0], BLOCK_16X16, force_split[0])) {
|
2014-03-04 20:15:35 +01:00
|
|
|
for (i = 0; i < 4; ++i) {
|
|
|
|
const int x32_idx = ((i & 1) << 2);
|
|
|
|
const int y32_idx = ((i >> 1) << 2);
|
2015-01-06 02:13:13 +01:00
|
|
|
const int i2 = i << 2;
|
2015-06-29 18:27:11 +02:00
|
|
|
if (!set_vt_partitioning(cpi, x, xd, &vt.split[i], BLOCK_32X32,
|
2015-01-06 02:13:13 +01:00
|
|
|
(mi_row + y32_idx), (mi_col + x32_idx),
|
2015-04-02 22:57:22 +02:00
|
|
|
thresholds[1], BLOCK_16X16,
|
|
|
|
force_split[i + 1])) {
|
2014-03-04 20:15:35 +01:00
|
|
|
for (j = 0; j < 4; ++j) {
|
|
|
|
const int x16_idx = ((j & 1) << 1);
|
|
|
|
const int y16_idx = ((j >> 1) << 1);
|
2015-01-06 02:13:13 +01:00
|
|
|
// For inter frames: if variance4x4downsample[] == 1 for this 16x16
|
|
|
|
// block, then the variance is based on 4x4 down-sampling, so use vt2
|
|
|
|
// in set_vt_partioning(), otherwise use vt.
|
2016-07-27 05:43:23 +02:00
|
|
|
v16x16 *vtemp = (!is_key_frame && variance4x4downsample[i2 + j] == 1)
|
|
|
|
? &vt2[i2 + j]
|
|
|
|
: &vt.split[i].split[j];
|
|
|
|
if (!set_vt_partitioning(
|
|
|
|
cpi, x, xd, vtemp, BLOCK_16X16, mi_row + y32_idx + y16_idx,
|
|
|
|
mi_col + x32_idx + x16_idx, thresholds[2], cpi->vbp_bsize_min,
|
|
|
|
force_split[5 + i2 + j])) {
|
2014-03-04 20:15:35 +01:00
|
|
|
for (k = 0; k < 4; ++k) {
|
|
|
|
const int x8_idx = (k & 1);
|
|
|
|
const int y8_idx = (k >> 1);
|
2015-01-06 02:13:13 +01:00
|
|
|
if (use_4x4_partition) {
|
2015-06-29 18:27:11 +02:00
|
|
|
if (!set_vt_partitioning(cpi, x, xd, &vtemp->split[k],
|
2014-11-12 23:51:49 +01:00
|
|
|
BLOCK_8X8,
|
|
|
|
mi_row + y32_idx + y16_idx + y8_idx,
|
2015-01-06 02:13:13 +01:00
|
|
|
mi_col + x32_idx + x16_idx + x8_idx,
|
2015-04-02 22:57:22 +02:00
|
|
|
thresholds[3], BLOCK_8X8, 0)) {
|
2016-07-27 05:43:23 +02:00
|
|
|
set_block_size(
|
|
|
|
cpi, x, xd, (mi_row + y32_idx + y16_idx + y8_idx),
|
|
|
|
(mi_col + x32_idx + x16_idx + x8_idx), BLOCK_4X4);
|
2014-11-12 23:51:49 +01:00
|
|
|
}
|
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
set_block_size(
|
|
|
|
cpi, x, xd, (mi_row + y32_idx + y16_idx + y8_idx),
|
|
|
|
(mi_col + x32_idx + x16_idx + x8_idx), BLOCK_8X8);
|
2015-01-06 02:13:13 +01:00
|
|
|
}
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-06-03 00:41:58 +02:00
|
|
|
|
2016-12-19 19:39:04 +01:00
|
|
|
if (cm->frame_type != KEY_FRAME && cpi->sf.copy_partition_flag) {
|
2017-11-30 05:01:44 +01:00
|
|
|
update_prev_partition(cpi, x, segment_id, mi_row, mi_col, sb_offset);
|
2016-12-19 19:39:04 +01:00
|
|
|
}
|
|
|
|
|
2017-11-09 00:12:44 +01:00
|
|
|
if (cm->frame_type != KEY_FRAME && cpi->sf.svc_use_lowres_part &&
|
2017-11-15 04:52:54 +01:00
|
|
|
cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 2)
|
2017-11-09 00:12:44 +01:00
|
|
|
update_partition_svc(cpi, BLOCK_64X64, mi_row, mi_col);
|
|
|
|
|
2016-06-03 00:41:58 +02:00
|
|
|
if (cpi->sf.short_circuit_low_temp_var) {
|
2016-08-23 23:17:28 +02:00
|
|
|
set_low_temp_var_flag(cpi, x, xd, &vt, thresholds, ref_frame_partition,
|
|
|
|
mi_col, mi_row);
|
2016-06-03 00:41:58 +02:00
|
|
|
}
|
2016-06-27 23:08:34 +02:00
|
|
|
|
|
|
|
chroma_check(cpi, x, bsize, y_sad, is_key_frame);
|
2017-10-31 03:21:24 +01:00
|
|
|
if (vt2) vpx_free(vt2);
|
2015-04-16 02:48:20 +02:00
|
|
|
return 0;
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void update_state(VP9_COMP *cpi, ThreadData *td, PICK_MODE_CONTEXT *ctx,
|
2014-03-14 22:35:47 +01:00
|
|
|
int mi_row, int mi_col, BLOCK_SIZE bsize,
|
|
|
|
int output_enabled) {
|
2013-01-06 03:20:25 +01:00
|
|
|
int i, x_idx, y;
|
2013-08-06 20:04:31 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-11-21 20:11:06 +01:00
|
|
|
RD_COUNTS *const rdc = &td->rd_counts;
|
|
|
|
MACROBLOCK *const x = &td->mb;
|
2013-08-06 20:04:31 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-11-01 20:53:37 +01:00
|
|
|
struct macroblock_plane *const p = x->plane;
|
|
|
|
struct macroblockd_plane *const pd = xd->plane;
|
2012-07-14 00:21:29 +02:00
|
|
|
MODE_INFO *mi = &ctx->mic;
|
2016-01-20 01:40:20 +01:00
|
|
|
MODE_INFO *const xdmi = xd->mi[0];
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO *mi_addr = xd->mi[0];
|
2014-03-14 22:35:47 +01:00
|
|
|
const struct segmentation *const seg = &cm->seg;
|
2016-01-20 01:40:20 +01:00
|
|
|
const int bw = num_8x8_blocks_wide_lookup[mi->sb_type];
|
|
|
|
const int bh = num_8x8_blocks_high_lookup[mi->sb_type];
|
2015-08-18 03:19:22 +02:00
|
|
|
const int x_mis = VPXMIN(bw, cm->mi_cols - mi_col);
|
|
|
|
const int y_mis = VPXMIN(bh, cm->mi_rows - mi_row);
|
2016-07-27 05:43:23 +02:00
|
|
|
MV_REF *const frame_mvs = cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
|
2014-10-28 00:19:04 +01:00
|
|
|
int w, h;
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2014-04-02 01:18:47 +02:00
|
|
|
const int mis = cm->mi_stride;
|
2013-07-23 15:51:44 +02:00
|
|
|
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
2013-08-05 21:15:52 +02:00
|
|
|
const int mi_height = num_8x8_blocks_high_lookup[bsize];
|
2013-11-07 23:56:58 +01:00
|
|
|
int max_plane;
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
assert(mi->sb_type == bsize);
|
2013-06-28 19:36:20 +02:00
|
|
|
|
2014-03-25 18:33:02 +01:00
|
|
|
*mi_addr = *mi;
|
2015-06-29 18:27:11 +02:00
|
|
|
*x->mbmi_ext = ctx->mbmi_ext;
|
2014-03-25 18:33:02 +01:00
|
|
|
|
2014-04-03 15:34:43 +02:00
|
|
|
// If segmentation in use
|
2014-11-27 11:50:56 +01:00
|
|
|
if (seg->enabled) {
|
2014-04-03 15:34:43 +02:00
|
|
|
// For in frame complexity AQ copy the segment id from the segment map.
|
|
|
|
if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const uint8_t *const map =
|
|
|
|
seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
|
|
|
|
mi_addr->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
|
2014-04-03 15:34:43 +02:00
|
|
|
}
|
|
|
|
// Else for cyclic refresh mode update the segment map, set the segment id
|
|
|
|
// and then update the quantizer.
|
2014-08-14 18:55:31 +02:00
|
|
|
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
|
2016-07-27 05:43:23 +02:00
|
|
|
vp9_cyclic_refresh_update_segment(cpi, xd->mi[0], mi_row, mi_col, bsize,
|
|
|
|
ctx->rate, ctx->dist, x->skip, p);
|
2014-04-03 15:34:43 +02:00
|
|
|
}
|
2014-03-14 22:35:47 +01:00
|
|
|
}
|
2013-11-22 18:21:53 +01:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
max_plane = is_inter_block(xdmi) ? MAX_MB_PLANE : 1;
|
2013-11-07 23:56:58 +01:00
|
|
|
for (i = 0; i < max_plane; ++i) {
|
2013-11-01 20:53:37 +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-01 20:53:37 +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-01 20:53:37 +01:00
|
|
|
}
|
|
|
|
|
2013-11-07 23:56:58 +01:00
|
|
|
for (i = max_plane; i < MAX_MB_PLANE; ++i) {
|
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][2];
|
2013-11-27 03:52:10 +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
|
|
|
}
|
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Restore the coding context of the MB to that that was in place
|
|
|
|
// when the mode was picked for it
|
2013-08-06 20:04:31 +02:00
|
|
|
for (y = 0; y < mi_height; y++)
|
|
|
|
for (x_idx = 0; x_idx < mi_width; x_idx++)
|
2016-07-27 05:43:23 +02:00
|
|
|
if ((xd->mb_to_right_edge >> (3 + MI_SIZE_LOG2)) + mi_width > x_idx &&
|
|
|
|
(xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height > y) {
|
2015-04-21 14:36:58 +02:00
|
|
|
xd->mi[x_idx + y * mis] = mi_addr;
|
2013-11-22 18:21:53 +01:00
|
|
|
}
|
2013-08-06 20:04:31 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->oxcf.aq_mode != NO_AQ) vp9_init_plane_quantizers(cpi, x);
|
2013-10-07 20:20:10 +02:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
if (is_inter_block(xdmi) && xdmi->sb_type < BLOCK_8X8) {
|
|
|
|
xdmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
|
|
|
|
xdmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
|
|
|
|
2013-01-07 20:02:14 +01:00
|
|
|
x->skip = ctx->skip;
|
2016-01-20 01:40:20 +01:00
|
|
|
memcpy(x->zcoeff_blk[xdmi->tx_size], ctx->zcoeff_blk,
|
2015-08-12 19:41:51 +02:00
|
|
|
sizeof(ctx->zcoeff_blk[0]) * ctx->num_4x4_blk);
|
2013-09-21 01:29:24 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (!output_enabled) return;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2012-07-03 22:57:27 +02:00
|
|
|
#if CONFIG_INTERNAL_STATS
|
2014-02-14 23:46:29 +01:00
|
|
|
if (frame_is_intra_only(cm)) {
|
2012-07-14 00:21:29 +02:00
|
|
|
static const int kf_mode_index[] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
THR_DC /*DC_PRED*/, THR_V_PRED /*V_PRED*/,
|
|
|
|
THR_H_PRED /*H_PRED*/, THR_D45_PRED /*D45_PRED*/,
|
|
|
|
THR_D135_PRED /*D135_PRED*/, THR_D117_PRED /*D117_PRED*/,
|
|
|
|
THR_D153_PRED /*D153_PRED*/, THR_D207_PRED /*D207_PRED*/,
|
|
|
|
THR_D63_PRED /*D63_PRED*/, THR_TM /*TM_PRED*/,
|
2012-07-14 00:21:29 +02:00
|
|
|
};
|
2016-01-22 19:57:16 +01:00
|
|
|
++cpi->mode_chosen_counts[kf_mode_index[xdmi->mode]];
|
2012-07-14 00:21:29 +02:00
|
|
|
} else {
|
|
|
|
// Note how often each mode chosen as best
|
2014-02-14 23:46:29 +01:00
|
|
|
++cpi->mode_chosen_counts[ctx->best_mode_index];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!frame_is_intra_only(cm)) {
|
2016-01-20 01:40:20 +01:00
|
|
|
if (is_inter_block(xdmi)) {
|
2014-11-21 20:11:06 +01:00
|
|
|
vp9_update_mv_count(td);
|
2014-02-05 20:04:53 +01:00
|
|
|
|
|
|
|
if (cm->interp_filter == SWITCHABLE) {
|
2016-07-21 20:47:51 +02:00
|
|
|
const int ctx = get_pred_context_switchable_interp(xd);
|
2016-01-20 01:40:20 +01:00
|
|
|
++td->counts->switchable_interp[ctx][xdmi->interp_filter];
|
2014-02-05 20:04:53 +01:00
|
|
|
}
|
2012-11-30 01:39:15 +01:00
|
|
|
}
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
rdc->comp_pred_diff[SINGLE_REFERENCE] += ctx->single_pred_diff;
|
|
|
|
rdc->comp_pred_diff[COMPOUND_REFERENCE] += ctx->comp_pred_diff;
|
|
|
|
rdc->comp_pred_diff[REFERENCE_MODE_SELECT] += ctx->hybrid_pred_diff;
|
2013-07-08 23:49:33 +02:00
|
|
|
|
2014-02-05 20:04:53 +01:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
|
2014-11-21 20:11:06 +01:00
|
|
|
rdc->filter_diff[i] += ctx->best_filter_diff[i];
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2014-10-28 00:19:04 +01:00
|
|
|
|
|
|
|
for (h = 0; h < y_mis; ++h) {
|
|
|
|
MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
|
|
|
|
for (w = 0; w < x_mis; ++w) {
|
|
|
|
MV_REF *const mv = frame_mv + w;
|
2016-01-20 01:40:20 +01:00
|
|
|
mv->ref_frame[0] = mi->ref_frame[0];
|
|
|
|
mv->ref_frame[1] = mi->ref_frame[1];
|
|
|
|
mv->mv[0].as_int = mi->mv[0].as_int;
|
|
|
|
mv->mv[1].as_int = mi->mv[1].as_int;
|
2014-10-28 00:19:04 +01:00
|
|
|
}
|
|
|
|
}
|
2012-04-07 01:38:34 +02:00
|
|
|
}
|
|
|
|
|
2013-06-19 23:26:49 +02:00
|
|
|
void vp9_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src,
|
2013-10-01 20:54:10 +02:00
|
|
|
int mi_row, int mi_col) {
|
2016-07-27 05:43:23 +02:00
|
|
|
uint8_t *const buffers[3] = { src->y_buffer, src->u_buffer, src->v_buffer };
|
|
|
|
const int strides[3] = { src->y_stride, src->uv_stride, src->uv_stride };
|
2013-05-16 02:55:08 +02:00
|
|
|
int i;
|
|
|
|
|
2013-12-13 05:33:06 +01:00
|
|
|
// Set current frame pointer.
|
|
|
|
x->e_mbd.cur_buf = src;
|
|
|
|
|
2013-10-01 20:54:10 +02:00
|
|
|
for (i = 0; i < MAX_MB_PLANE; i++)
|
|
|
|
setup_pred_plane(&x->plane[i].src, buffers[i], strides[i], mi_row, mi_col,
|
2013-06-19 23:26:49 +02:00
|
|
|
NULL, x->e_mbd.plane[i].subsampling_x,
|
2013-05-16 02:55:08 +02:00
|
|
|
x->e_mbd.plane[i].subsampling_y);
|
2013-04-24 01:22:47 +02:00
|
|
|
}
|
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
static void set_mode_info_seg_skip(MACROBLOCK *x, TX_MODE tx_mode,
|
|
|
|
RD_COST *rd_cost, BLOCK_SIZE bsize) {
|
2014-05-30 02:48:28 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2016-01-20 01:40:20 +01:00
|
|
|
MODE_INFO *const mi = xd->mi[0];
|
2014-05-30 02:48:28 +02:00
|
|
|
INTERP_FILTER filter_ref;
|
|
|
|
|
2016-07-21 20:47:51 +02:00
|
|
|
filter_ref = get_pred_context_switchable_interp(xd);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (filter_ref == SWITCHABLE_FILTERS) filter_ref = EIGHTTAP;
|
2014-05-30 02:48:28 +02:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->sb_type = bsize;
|
|
|
|
mi->mode = ZEROMV;
|
|
|
|
mi->tx_size =
|
2015-08-18 03:19:22 +02:00
|
|
|
VPXMIN(max_txsize_lookup[bsize], tx_mode_to_biggest_tx_size[tx_mode]);
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->skip = 1;
|
|
|
|
mi->uv_mode = DC_PRED;
|
|
|
|
mi->ref_frame[0] = LAST_FRAME;
|
|
|
|
mi->ref_frame[1] = NONE;
|
|
|
|
mi->mv[0].as_int = 0;
|
|
|
|
mi->interp_filter = filter_ref;
|
2014-05-30 02:48:28 +02:00
|
|
|
|
2015-04-21 14:36:58 +02:00
|
|
|
xd->mi[0]->bmi[0].as_mv[0].as_int = 0;
|
2014-05-30 02:48:28 +02:00
|
|
|
x->skip = 1;
|
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
vp9_rd_cost_init(rd_cost);
|
2014-05-30 02:48:28 +02:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static int set_segment_rdmult(VP9_COMP *const cpi, MACROBLOCK *const x,
|
|
|
|
int8_t segment_id) {
|
2014-11-27 11:50:56 +01:00
|
|
|
int segment_qindex;
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
vp9_init_plane_quantizers(cpi, x);
|
2015-08-10 20:28:04 +02:00
|
|
|
vpx_clear_system_state();
|
2016-06-22 21:20:06 +02:00
|
|
|
segment_qindex = vp9_get_qindex(&cm->seg, segment_id, cm->base_qindex);
|
2014-11-27 11:50:56 +01:00
|
|
|
return vp9_compute_rd_mult(cpi, segment_qindex + cm->y_dc_delta_q);
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void rd_pick_sb_modes(VP9_COMP *cpi, TileDataEnc *tile_data,
|
|
|
|
MACROBLOCK *const x, int mi_row, int mi_col,
|
|
|
|
RD_COST *rd_cost, BLOCK_SIZE bsize,
|
|
|
|
PICK_MODE_CONTEXT *ctx, int64_t best_rd) {
|
2013-07-11 00:57:28 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-10-27 19:11:50 +01:00
|
|
|
TileInfo *const tile_info = &tile_data->tile_info;
|
2013-07-11 00:57:28 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2016-01-20 01:40:20 +01:00
|
|
|
MODE_INFO *mi;
|
2013-11-01 20:53:37 +01:00
|
|
|
struct macroblock_plane *const p = x->plane;
|
|
|
|
struct macroblockd_plane *const pd = xd->plane;
|
2014-03-10 18:58:32 +01:00
|
|
|
const AQ_MODE aq_mode = cpi->oxcf.aq_mode;
|
2014-03-14 19:03:58 +01:00
|
|
|
int i, orig_rdmult;
|
2013-10-17 20:04:57 +02:00
|
|
|
|
2015-08-10 20:28:04 +02:00
|
|
|
vpx_clear_system_state();
|
2012-08-20 23:43:34 +02:00
|
|
|
|
2013-08-20 21:55:41 +02:00
|
|
|
// Use the lower precision, but faster, 32x32 fdct for mode selection.
|
2013-08-08 00:22:51 +02:00
|
|
|
x->use_lp32x32fdct = 1;
|
2013-06-14 20:28:56 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
|
2016-01-20 01:40:20 +01:00
|
|
|
mi = xd->mi[0];
|
|
|
|
mi->sb_type = bsize;
|
2013-07-31 18:33:58 +02:00
|
|
|
|
2013-11-01 20:53:37 +01:00
|
|
|
for (i = 0; i < MAX_MB_PLANE; ++i) {
|
2013-11-06 06:07:08 +01:00
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][0];
|
2013-11-27 03:52:10 +01:00
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][0];
|
2013-11-06 06:07:08 +01:00
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][0];
|
2013-12-04 02:59:32 +01:00
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][0];
|
2013-11-01 20:53:37 +01:00
|
|
|
}
|
2013-11-06 06:07:08 +01:00
|
|
|
ctx->is_coded = 0;
|
Early termination in encoding partition search
In the partition search, the encoder checks all possible
partitionings in the superblock's partition search tree.
This patch proposed a set of criteria for partition search
early termination, which effectively decided whether or
not to terminate the search in current branch based on the
"skippable" result of the quantized transform coefficients.
The "skippable" information was gathered during the
partition mode search, and no overhead calculations were
introduced.
This patch gives significant encoding speed gains without
sacrificing the quality.
Borg test results:
1. At speed 1,
stdhd set: psnr: +0.074%, ssim: +0.093%;
derf set: psnr: -0.024%, ssim: +0.011%;
2. At speed 2,
stdhd set: psnr: +0.033%, ssim: +0.100%;
derf set: psnr: -0.062%, ssim: +0.003%;
3. At speed 3,
stdhd set: psnr: +0.060%, ssim: +0.190%;
derf set: psnr: -0.064%, ssim: -0.002%;
4. At speed 4,
stdhd set: psnr: +0.070%, ssim: +0.143%;
derf set: psnr: -0.104%, ssim: +0.039%;
The speedup ranges from several percent to 60+%.
speed1 speed2 speed3 speed4
(1080p, 100f):
old_town_cross: 48.2% 23.9% 20.8% 16.5%
park_joy: 11.4% 17.8% 29.4% 18.2%
pedestrian_area: 10.7% 4.0% 4.2% 2.4%
(720p, 200f):
mobcal: 68.1% 36.3% 34.4% 17.7%
parkrun: 15.8% 24.2% 37.1% 16.8%
shields: 45.1% 32.8% 30.1% 9.6%
(cif, 300f)
bus: 3.7% 10.4% 14.0% 7.9%
deadline: 13.6% 14.8% 12.6% 10.9%
mobile: 5.3% 11.5% 14.7% 10.7%
Change-Id: I246c38fb952ad762ce5e365711235b605f470a66
2014-08-15 02:25:21 +02:00
|
|
|
ctx->skippable = 0;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
ctx->pred_pixel_ready = 0;
|
2013-11-07 23:56:58 +01:00
|
|
|
x->skip_recode = 0;
|
2013-11-01 20:53:37 +01:00
|
|
|
|
2013-08-22 14:51:04 +02:00
|
|
|
// Set to zero to make sure we do not use the previous encoded frame stats
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->skip = 0;
|
2013-08-22 14:51:04 +02:00
|
|
|
|
2014-09-24 15:36:34 +02:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
|
2016-07-27 05:43:23 +02:00
|
|
|
x->source_variance = vp9_high_get_sby_perpixel_variance(
|
|
|
|
cpi, &x->plane[0].src, bsize, xd->bd);
|
2014-09-24 15:36:34 +02:00
|
|
|
} else {
|
|
|
|
x->source_variance =
|
2016-07-27 05:43:23 +02:00
|
|
|
vp9_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
|
2014-09-24 15:36:34 +02:00
|
|
|
}
|
|
|
|
#else
|
2015-03-06 18:21:36 +01:00
|
|
|
x->source_variance =
|
2016-07-27 05:43:23 +02:00
|
|
|
vp9_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
|
2014-09-24 15:36:34 +02:00
|
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
2013-08-22 14:51:04 +02:00
|
|
|
|
2014-04-09 22:00:02 +02:00
|
|
|
// Save rdmult before it might be changed, so it can be restored later.
|
|
|
|
orig_rdmult = x->rdmult;
|
|
|
|
|
2016-08-18 15:15:25 +02:00
|
|
|
if ((cpi->sf.tx_domain_thresh > 0.0) || (cpi->sf.quant_opt_thresh > 0.0)) {
|
|
|
|
double logvar = vp9_log_block_var(cpi, x, bsize);
|
|
|
|
// Check block complexity as part of descision on using pixel or transform
|
|
|
|
// domain distortion in rd tests.
|
|
|
|
x->block_tx_domain = cpi->sf.allow_txfm_domain_distortion &&
|
|
|
|
(logvar >= cpi->sf.tx_domain_thresh);
|
|
|
|
|
|
|
|
// Check block complexity as part of descision on using quantized
|
|
|
|
// coefficient optimisation inside the rd loop.
|
|
|
|
x->block_qcoeff_opt =
|
|
|
|
cpi->sf.allow_quant_coeff_opt && (logvar <= cpi->sf.quant_opt_thresh);
|
|
|
|
} else {
|
|
|
|
x->block_tx_domain = cpi->sf.allow_txfm_domain_distortion;
|
|
|
|
x->block_qcoeff_opt = cpi->sf.allow_quant_coeff_opt;
|
|
|
|
}
|
|
|
|
|
2014-03-10 18:58:32 +01:00
|
|
|
if (aq_mode == VARIANCE_AQ) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const int energy =
|
|
|
|
bsize <= BLOCK_16X16 ? x->mb_energy : vp9_block_energy(cpi, x, bsize);
|
2016-07-16 00:38:52 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cm->frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame ||
|
2016-07-16 00:38:52 +02:00
|
|
|
cpi->force_update_segmentation ||
|
2014-02-03 13:47:01 +01:00
|
|
|
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->segment_id = vp9_vaq_segment_id(energy);
|
2014-02-03 13:47:01 +01:00
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
const uint8_t *const map =
|
|
|
|
cm->seg.update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
|
2014-02-03 13:47:01 +01:00
|
|
|
}
|
2016-01-20 01:40:20 +01:00
|
|
|
x->rdmult = set_segment_rdmult(cpi, x, mi->segment_id);
|
2016-07-19 00:44:40 +02:00
|
|
|
} else if (aq_mode == LOOKAHEAD_AQ) {
|
|
|
|
const uint8_t *const map = cpi->segmentation_map;
|
|
|
|
|
|
|
|
// I do not change rdmult here consciously.
|
|
|
|
mi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
|
2015-12-17 00:34:07 +01:00
|
|
|
} else if (aq_mode == EQUATOR360_AQ) {
|
2016-07-16 00:38:52 +02:00
|
|
|
if (cm->frame_type == KEY_FRAME || cpi->force_update_segmentation) {
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->segment_id = vp9_360aq_segment_id(mi_row, cm->mi_rows);
|
2015-12-17 00:34:07 +01:00
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
const uint8_t *const map =
|
|
|
|
cm->seg.update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
|
2015-12-17 00:34:07 +01:00
|
|
|
}
|
2016-01-20 01:40:20 +01:00
|
|
|
x->rdmult = set_segment_rdmult(cpi, x, mi->segment_id);
|
2014-03-10 18:58:32 +01:00
|
|
|
} else if (aq_mode == COMPLEXITY_AQ) {
|
2016-01-20 01:40:20 +01:00
|
|
|
x->rdmult = set_segment_rdmult(cpi, x, mi->segment_id);
|
2014-04-04 00:51:40 +02:00
|
|
|
} else if (aq_mode == CYCLIC_REFRESH_AQ) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const uint8_t *const map =
|
|
|
|
cm->seg.update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
|
2015-03-24 02:20:35 +01:00
|
|
|
// If segment is boosted, use rdmult for that segment.
|
|
|
|
if (cyclic_refresh_segment_id_boosted(
|
2015-06-16 02:30:54 +02:00
|
|
|
get_segment_id(cm, map, bsize, mi_row, mi_col)))
|
2014-03-26 19:00:35 +01:00
|
|
|
x->rdmult = vp9_cyclic_refresh_get_rdmult(cpi->cyclic_refresh);
|
2013-10-17 20:04:57 +02:00
|
|
|
}
|
2013-10-07 20:20:10 +02:00
|
|
|
|
2013-07-11 00:57:28 +02:00
|
|
|
// Find best coding mode & reconstruct the MB so it is available
|
|
|
|
// as a predictor for MBs that follow in the SB
|
2013-10-03 18:07:24 +02:00
|
|
|
if (frame_is_intra_only(cm)) {
|
2014-10-09 21:32:56 +02:00
|
|
|
vp9_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, best_rd);
|
2013-09-28 01:02:49 +02:00
|
|
|
} else {
|
2014-05-31 01:02:46 +02:00
|
|
|
if (bsize >= BLOCK_8X8) {
|
2016-01-20 01:40:20 +01:00
|
|
|
if (segfeature_active(&cm->seg, mi->segment_id, SEG_LVL_SKIP))
|
Tile based adaptive mode search in RD loop
Make the spatially adaptive mode search in rate-distortion
optimization loop inter tile independent. Experiments suggest that
this does not significantly change the coding staticstics.
Single tile, speed 3:
pedestrian_area 1080p 1500 kbps
59192 b/f, 40.611 dB, 101689 ms
blue_sky 1080p 1500 kbps
58505 b/f, 36.347 dB, 62458 ms
mobile_cal 720p 1000 kbps
13335 b/f, 35.646 dB, 45655 ms
as compared to 4 column tiles, speed 3:
pedestrian_area 1080p 1500 kbps
59329 b/f, 40.597 dB, 101917 ms
blue_sky 1080p 1500 kbps
58712 b/f, 36.320 dB, 62693 ms
mobile_cal 720p 1000 kbps
13191 b/f, 35.485 dB, 45319 ms
Change-Id: I35c6e1e0a859fece8f4145dec28623cbc6a12325
2014-10-24 01:54:45 +02:00
|
|
|
vp9_rd_pick_inter_mode_sb_seg_skip(cpi, tile_data, x, rd_cost, bsize,
|
2014-06-29 18:23:21 +02:00
|
|
|
ctx, best_rd);
|
2014-05-31 01:02:46 +02:00
|
|
|
else
|
2016-07-27 05:43:23 +02:00
|
|
|
vp9_rd_pick_inter_mode_sb(cpi, tile_data, x, mi_row, mi_col, rd_cost,
|
|
|
|
bsize, ctx, best_rd);
|
2014-05-31 01:02:46 +02:00
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
vp9_rd_pick_inter_mode_sub8x8(cpi, tile_data, x, mi_row, mi_col, rd_cost,
|
|
|
|
bsize, ctx, best_rd);
|
2014-05-31 01:02:46 +02:00
|
|
|
}
|
2013-09-28 01:02:49 +02:00
|
|
|
}
|
2013-10-07 20:20:10 +02:00
|
|
|
|
2014-11-27 11:50:56 +01:00
|
|
|
// Examine the resulting rate and for AQ mode 2 make a segment choice.
|
2016-07-27 05:43:23 +02:00
|
|
|
if ((rd_cost->rate != INT_MAX) && (aq_mode == COMPLEXITY_AQ) &&
|
|
|
|
(bsize >= BLOCK_16X16) &&
|
|
|
|
(cm->frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame ||
|
2014-11-27 11:50:56 +01:00
|
|
|
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref))) {
|
|
|
|
vp9_caq_select_segment(cpi, x, bsize, mi_row, mi_col, rd_cost->rate);
|
|
|
|
}
|
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
x->rdmult = orig_rdmult;
|
|
|
|
|
|
|
|
// TODO(jingning) The rate-distortion optimization flow needs to be
|
|
|
|
// refactored to provide proper exit/return handle.
|
2016-07-27 05:43:23 +02:00
|
|
|
if (rd_cost->rate == INT_MAX) rd_cost->rdcost = INT64_MAX;
|
2014-11-04 23:32:04 +01:00
|
|
|
|
|
|
|
ctx->rate = rd_cost->rate;
|
|
|
|
ctx->dist = rd_cost->dist;
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static void update_stats(VP9_COMMON *cm, ThreadData *td) {
|
|
|
|
const MACROBLOCK *x = &td->mb;
|
2014-02-08 00:19:54 +01:00
|
|
|
const MACROBLOCKD *const xd = &x->e_mbd;
|
2015-04-21 14:36:58 +02:00
|
|
|
const MODE_INFO *const mi = xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
|
2016-01-20 01:40:20 +01:00
|
|
|
const BLOCK_SIZE bsize = mi->sb_type;
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-10-03 18:07:24 +02:00
|
|
|
if (!frame_is_intra_only(cm)) {
|
2015-01-06 19:37:08 +01:00
|
|
|
FRAME_COUNTS *const counts = td->counts;
|
2016-01-20 01:40:20 +01:00
|
|
|
const int inter_block = is_inter_block(mi);
|
2016-07-27 05:43:23 +02:00
|
|
|
const int seg_ref_active =
|
|
|
|
segfeature_active(&cm->seg, mi->segment_id, SEG_LVL_REF_FRAME);
|
2014-02-08 00:19:54 +01:00
|
|
|
if (!seg_ref_active) {
|
2016-04-15 13:58:37 +02:00
|
|
|
counts->intra_inter[get_intra_inter_context(xd)][inter_block]++;
|
2014-02-08 00:19:54 +01:00
|
|
|
// If the segment reference feature is enabled we have only a single
|
|
|
|
// reference frame allowed for the segment so exclude it from
|
|
|
|
// the reference frame counts used to work out probabilities.
|
|
|
|
if (inter_block) {
|
2016-01-20 01:40:20 +01:00
|
|
|
const MV_REFERENCE_FRAME ref0 = mi->ref_frame[0];
|
2014-02-08 00:19:54 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT)
|
2016-09-16 00:07:46 +02:00
|
|
|
counts->comp_inter[vp9_get_reference_mode_context(cm, xd)]
|
|
|
|
[has_second_ref(mi)]++;
|
2014-02-08 00:19:54 +01:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
if (has_second_ref(mi)) {
|
2016-09-16 00:07:46 +02:00
|
|
|
counts->comp_ref[vp9_get_pred_context_comp_ref_p(cm, xd)]
|
|
|
|
[ref0 == GOLDEN_FRAME]++;
|
2014-02-08 00:19:54 +01:00
|
|
|
} else {
|
2016-09-16 00:07:46 +02:00
|
|
|
counts->single_ref[vp9_get_pred_context_single_ref_p1(xd)][0]
|
|
|
|
[ref0 != LAST_FRAME]++;
|
2014-02-08 00:19:54 +01:00
|
|
|
if (ref0 != LAST_FRAME)
|
2016-09-16 00:07:46 +02:00
|
|
|
counts->single_ref[vp9_get_pred_context_single_ref_p2(xd)][1]
|
|
|
|
[ref0 != GOLDEN_FRAME]++;
|
2014-02-08 00:19:54 +01:00
|
|
|
}
|
2013-06-06 22:44:34 +02:00
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|
2015-01-06 19:37:08 +01:00
|
|
|
if (inter_block &&
|
2016-01-20 01:40:20 +01:00
|
|
|
!segfeature_active(&cm->seg, mi->segment_id, SEG_LVL_SKIP)) {
|
|
|
|
const int mode_ctx = mbmi_ext->mode_context[mi->ref_frame[0]];
|
2015-01-06 19:37:08 +01:00
|
|
|
if (bsize >= BLOCK_8X8) {
|
2016-01-20 01:40:20 +01:00
|
|
|
const PREDICTION_MODE mode = mi->mode;
|
2015-01-06 19:37:08 +01:00
|
|
|
++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)];
|
|
|
|
} else {
|
|
|
|
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
|
|
|
|
int idx, idy;
|
|
|
|
for (idy = 0; idy < 2; idy += num_4x4_h) {
|
|
|
|
for (idx = 0; idx < 2; idx += num_4x4_w) {
|
|
|
|
const int j = idy * 2 + idx;
|
|
|
|
const PREDICTION_MODE b_mode = mi->bmi[j].as_mode;
|
|
|
|
++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static void restore_context(MACROBLOCK *const x, int mi_row, int mi_col,
|
2013-05-08 23:24:43 +02:00
|
|
|
ENTROPY_CONTEXT a[16 * MAX_MB_PLANE],
|
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE],
|
2013-06-19 23:26:49 +02:00
|
|
|
PARTITION_CONTEXT sa[8], PARTITION_CONTEXT sl[8],
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize) {
|
2013-08-05 21:15:52 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2013-05-08 23:24:43 +02:00
|
|
|
int p;
|
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-07-23 15:51:44 +02:00
|
|
|
int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
int mi_height = num_8x8_blocks_high_lookup[bsize];
|
2013-05-08 23:24:43 +02:00
|
|
|
for (p = 0; p < MAX_MB_PLANE; p++) {
|
2016-07-27 05:43:23 +02:00
|
|
|
memcpy(xd->above_context[p] + ((mi_col * 2) >> xd->plane[p].subsampling_x),
|
|
|
|
a + num_4x4_blocks_wide * p,
|
|
|
|
(sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide) >>
|
|
|
|
xd->plane[p].subsampling_x);
|
|
|
|
memcpy(xd->left_context[p] +
|
|
|
|
((mi_row & MI_MASK) * 2 >> xd->plane[p].subsampling_y),
|
|
|
|
l + num_4x4_blocks_high * p,
|
|
|
|
(sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high) >>
|
|
|
|
xd->plane[p].subsampling_y);
|
2013-07-23 15:51:44 +02:00
|
|
|
}
|
2015-04-24 05:42:19 +02:00
|
|
|
memcpy(xd->above_seg_context + mi_col, sa,
|
|
|
|
sizeof(*xd->above_seg_context) * mi_width);
|
|
|
|
memcpy(xd->left_seg_context + (mi_row & MI_MASK), sl,
|
|
|
|
sizeof(xd->left_seg_context[0]) * mi_height);
|
2013-07-02 03:18:50 +02:00
|
|
|
}
|
2014-07-07 19:28:05 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static void save_context(MACROBLOCK *const x, int mi_row, int mi_col,
|
2013-06-19 23:26:49 +02:00
|
|
|
ENTROPY_CONTEXT a[16 * MAX_MB_PLANE],
|
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE],
|
|
|
|
PARTITION_CONTEXT sa[8], PARTITION_CONTEXT sl[8],
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE bsize) {
|
2013-08-05 21:15:52 +02:00
|
|
|
const MACROBLOCKD *const xd = &x->e_mbd;
|
2013-05-31 00:13:08 +02:00
|
|
|
int p;
|
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-07-23 15:51:44 +02:00
|
|
|
int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
int mi_height = num_8x8_blocks_high_lookup[bsize];
|
2013-05-31 00:13:08 +02:00
|
|
|
|
|
|
|
// buffer the above/left context information of the block in search.
|
|
|
|
for (p = 0; p < MAX_MB_PLANE; ++p) {
|
2016-07-27 05:43:23 +02:00
|
|
|
memcpy(a + num_4x4_blocks_wide * p,
|
|
|
|
xd->above_context[p] + (mi_col * 2 >> xd->plane[p].subsampling_x),
|
|
|
|
(sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_wide) >>
|
|
|
|
xd->plane[p].subsampling_x);
|
|
|
|
memcpy(l + num_4x4_blocks_high * p,
|
|
|
|
xd->left_context[p] +
|
|
|
|
((mi_row & MI_MASK) * 2 >> xd->plane[p].subsampling_y),
|
|
|
|
(sizeof(ENTROPY_CONTEXT) * num_4x4_blocks_high) >>
|
|
|
|
xd->plane[p].subsampling_y);
|
2013-07-23 15:51:44 +02:00
|
|
|
}
|
2015-04-24 05:42:19 +02:00
|
|
|
memcpy(sa, xd->above_seg_context + mi_col,
|
|
|
|
sizeof(*xd->above_seg_context) * mi_width);
|
|
|
|
memcpy(sl, xd->left_seg_context + (mi_row & MI_MASK),
|
|
|
|
sizeof(xd->left_seg_context[0]) * mi_height);
|
2013-07-23 15:51:44 +02:00
|
|
|
}
|
2013-05-08 23:24:43 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void encode_b(VP9_COMP *cpi, const TileInfo *const tile, ThreadData *td,
|
2013-10-25 17:18:04 +02:00
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
int output_enabled, BLOCK_SIZE bsize,
|
|
|
|
PICK_MODE_CONTEXT *ctx) {
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
|
|
|
set_offsets(cpi, tile, x, mi_row, mi_col, bsize);
|
|
|
|
update_state(cpi, td, ctx, mi_row, mi_col, bsize, output_enabled);
|
|
|
|
encode_superblock(cpi, td, tp, output_enabled, mi_row, mi_col, bsize, ctx);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-04-28 17:59:13 +02:00
|
|
|
if (output_enabled) {
|
2014-11-21 20:11:06 +01:00
|
|
|
update_stats(&cpi->common, td);
|
2013-04-23 19:12:18 +02:00
|
|
|
|
2013-04-28 17:59:13 +02:00
|
|
|
(*tp)->token = EOSB_TOKEN;
|
|
|
|
(*tp)++;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void encode_sb(VP9_COMP *cpi, ThreadData *td, const TileInfo *const tile,
|
2013-10-25 17:18:04 +02:00
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
2016-07-27 05:43:23 +02:00
|
|
|
int output_enabled, BLOCK_SIZE bsize, PC_TREE *pc_tree) {
|
2013-11-12 00:58:57 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-03-21 00:08:54 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
|
|
|
|
2014-10-07 21:30:33 +02:00
|
|
|
const int bsl = b_width_log2_lookup[bsize], hbs = (1 << bsl) / 4;
|
2013-12-11 23:38:22 +01:00
|
|
|
int ctx;
|
2013-07-23 15:51:44 +02:00
|
|
|
PARTITION_TYPE partition;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
BLOCK_SIZE subsize = bsize;
|
2013-04-23 19:12:18 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
2013-01-07 20:41:49 +01:00
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize >= BLOCK_8X8) {
|
2014-03-21 20:12:55 +01:00
|
|
|
ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
subsize = get_subsize(bsize, pc_tree->partitioning);
|
2013-12-11 23:38:22 +01:00
|
|
|
} else {
|
|
|
|
ctx = 0;
|
|
|
|
subsize = BLOCK_4X4;
|
2013-05-01 01:13:20 +02:00
|
|
|
}
|
2013-12-11 23:38:22 +01:00
|
|
|
|
|
|
|
partition = partition_lookup[bsl][subsize];
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
if (output_enabled && bsize != BLOCK_4X4)
|
2014-11-21 20:11:06 +01:00
|
|
|
td->counts->partition[ctx][partition]++;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-07-23 15:51:44 +02:00
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b(cpi, tile, td, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
&pc_tree->none);
|
2013-07-23 15:51:44 +02:00
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b(cpi, tile, td, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
&pc_tree->vertical[0]);
|
|
|
|
if (mi_col + hbs < cm->mi_cols && bsize > BLOCK_8X8) {
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b(cpi, tile, td, tp, mi_row, mi_col + hbs, output_enabled,
|
|
|
|
subsize, &pc_tree->vertical[1]);
|
2013-12-11 23:38:22 +01:00
|
|
|
}
|
2013-07-23 15:51:44 +02:00
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b(cpi, tile, td, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
&pc_tree->horizontal[0]);
|
|
|
|
if (mi_row + hbs < cm->mi_rows && bsize > BLOCK_8X8) {
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b(cpi, tile, td, tp, mi_row + hbs, mi_col, output_enabled,
|
|
|
|
subsize, &pc_tree->horizontal[1]);
|
2013-12-11 23:38:22 +01:00
|
|
|
}
|
2013-07-23 15:51:44 +02:00
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
if (bsize == BLOCK_8X8) {
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b(cpi, tile, td, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->leaf_split[0]);
|
|
|
|
} else {
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_sb(cpi, td, tile, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->split[0]);
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_sb(cpi, td, tile, tp, mi_row, mi_col + hbs, output_enabled,
|
|
|
|
subsize, pc_tree->split[1]);
|
|
|
|
encode_sb(cpi, td, tile, tp, mi_row + hbs, mi_col, output_enabled,
|
|
|
|
subsize, pc_tree->split[2]);
|
|
|
|
encode_sb(cpi, td, tile, tp, mi_row + hbs, mi_col + hbs, output_enabled,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
subsize, pc_tree->split[3]);
|
|
|
|
}
|
2013-07-23 15:51:44 +02:00
|
|
|
break;
|
2016-07-27 05:43:23 +02:00
|
|
|
default: assert(0 && "Invalid partition type."); break;
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
2013-04-23 19:12:18 +02:00
|
|
|
|
2013-10-21 21:02:19 +02:00
|
|
|
if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
|
2014-03-21 20:12:55 +01:00
|
|
|
update_partition_context(xd, mi_row, mi_col, subsize, bsize);
|
2012-04-07 01:38:34 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2013-08-31 01:39:26 +02:00
|
|
|
// Check to see if the given partition size is allowed for a specified number
|
|
|
|
// of 8x8 block rows and columns remaining in the image.
|
|
|
|
// If not then return the largest allowed partition size
|
2016-07-27 05:43:23 +02:00
|
|
|
static BLOCK_SIZE find_partition_size(BLOCK_SIZE bsize, int rows_left,
|
|
|
|
int cols_left, int *bh, int *bw) {
|
2014-01-10 22:48:44 +01:00
|
|
|
if (rows_left <= 0 || cols_left <= 0) {
|
2015-08-18 03:19:22 +02:00
|
|
|
return VPXMIN(bsize, BLOCK_8X8);
|
2013-08-31 01:39:26 +02:00
|
|
|
} else {
|
2014-02-28 18:15:36 +01:00
|
|
|
for (; bsize > 0; bsize -= 3) {
|
2013-08-31 01:39:26 +02:00
|
|
|
*bh = num_8x8_blocks_high_lookup[bsize];
|
|
|
|
*bw = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
if ((*bh <= rows_left) && (*bw <= cols_left)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bsize;
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void set_partial_b64x64_partition(MODE_INFO *mi, int mis, int bh_in,
|
|
|
|
int bw_in, int row8x8_remaining,
|
|
|
|
int col8x8_remaining, BLOCK_SIZE bsize,
|
|
|
|
MODE_INFO **mi_8x8) {
|
2014-04-15 19:02:33 +02:00
|
|
|
int bh = bh_in;
|
|
|
|
int r, c;
|
|
|
|
for (r = 0; r < MI_BLOCK_SIZE; r += bh) {
|
|
|
|
int bw = bw_in;
|
|
|
|
for (c = 0; c < MI_BLOCK_SIZE; c += bw) {
|
|
|
|
const int index = r * mis + c;
|
2015-04-21 14:36:58 +02:00
|
|
|
mi_8x8[index] = mi + index;
|
2016-07-27 05:43:23 +02:00
|
|
|
mi_8x8[index]->sb_type = find_partition_size(
|
|
|
|
bsize, row8x8_remaining - r, col8x8_remaining - c, &bh, &bw);
|
2014-04-15 19:02:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-31 01:39:26 +02:00
|
|
|
// This function attempts to set all mode info entries in a given SB64
|
|
|
|
// to the same block partition size.
|
|
|
|
// However, at the bottom and right borders of the image the requested size
|
|
|
|
// may not be allowed in which case this code attempts to choose the largest
|
|
|
|
// allowable partition.
|
2014-03-04 20:15:35 +01:00
|
|
|
static void set_fixed_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **mi_8x8, int mi_row, int mi_col,
|
2014-03-04 20:15:35 +01:00
|
|
|
BLOCK_SIZE bsize) {
|
2013-06-20 16:46:51 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-04-02 01:18:47 +02:00
|
|
|
const int mis = cm->mi_stride;
|
2014-04-15 19:49:27 +02:00
|
|
|
const int row8x8_remaining = tile->mi_row_end - mi_row;
|
|
|
|
const int col8x8_remaining = tile->mi_col_end - mi_col;
|
2013-05-31 00:13:08 +02:00
|
|
|
int block_row, block_col;
|
2014-01-10 22:48:44 +01:00
|
|
|
MODE_INFO *mi_upper_left = cm->mi + mi_row * mis + mi_col;
|
2013-09-11 19:45:44 +02:00
|
|
|
int bh = num_8x8_blocks_high_lookup[bsize];
|
|
|
|
int bw = num_8x8_blocks_wide_lookup[bsize];
|
2013-08-31 01:39:26 +02:00
|
|
|
|
|
|
|
assert((row8x8_remaining > 0) && (col8x8_remaining > 0));
|
|
|
|
|
|
|
|
// Apply the requested partition size to the SB64 if it is all "in image"
|
|
|
|
if ((col8x8_remaining >= MI_BLOCK_SIZE) &&
|
|
|
|
(row8x8_remaining >= MI_BLOCK_SIZE)) {
|
2013-09-11 19:45:44 +02:00
|
|
|
for (block_row = 0; block_row < MI_BLOCK_SIZE; block_row += bh) {
|
|
|
|
for (block_col = 0; block_col < MI_BLOCK_SIZE; block_col += bw) {
|
|
|
|
int index = block_row * mis + block_col;
|
2015-04-21 14:36:58 +02:00
|
|
|
mi_8x8[index] = mi_upper_left + index;
|
2016-01-20 01:40:20 +01:00
|
|
|
mi_8x8[index]->sb_type = bsize;
|
2013-08-31 01:39:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Else this is a partial SB64.
|
2014-04-15 19:02:33 +02:00
|
|
|
set_partial_b64x64_partition(mi_upper_left, mis, bh, bw, row8x8_remaining,
|
2016-07-27 05:43:23 +02:00
|
|
|
col8x8_remaining, bsize, mi_8x8);
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
}
|
2013-09-11 19:45:44 +02:00
|
|
|
|
2015-06-13 03:57:47 +02:00
|
|
|
static const struct {
|
2014-04-02 02:32:20 +02:00
|
|
|
int row;
|
|
|
|
int col;
|
|
|
|
} coord_lookup[16] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
// 32x32 index = 0
|
|
|
|
{ 0, 0 },
|
|
|
|
{ 0, 2 },
|
|
|
|
{ 2, 0 },
|
|
|
|
{ 2, 2 },
|
|
|
|
// 32x32 index = 1
|
|
|
|
{ 0, 4 },
|
|
|
|
{ 0, 6 },
|
|
|
|
{ 2, 4 },
|
|
|
|
{ 2, 6 },
|
|
|
|
// 32x32 index = 2
|
|
|
|
{ 4, 0 },
|
|
|
|
{ 4, 2 },
|
|
|
|
{ 6, 0 },
|
|
|
|
{ 6, 2 },
|
|
|
|
// 32x32 index = 3
|
|
|
|
{ 4, 4 },
|
|
|
|
{ 4, 6 },
|
|
|
|
{ 6, 4 },
|
|
|
|
{ 6, 6 },
|
2014-04-02 02:32:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static void set_source_var_based_partition(VP9_COMP *cpi,
|
|
|
|
const TileInfo *const tile,
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x,
|
2016-07-27 05:43:23 +02:00
|
|
|
MODE_INFO **mi_8x8, int mi_row,
|
|
|
|
int mi_col) {
|
2014-04-02 02:32:20 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-04-09 19:46:54 +02:00
|
|
|
const int mis = cm->mi_stride;
|
2014-04-11 01:22:52 +02:00
|
|
|
const int row8x8_remaining = tile->mi_row_end - mi_row;
|
|
|
|
const int col8x8_remaining = tile->mi_col_end - mi_col;
|
2014-04-02 02:32:20 +02:00
|
|
|
MODE_INFO *mi_upper_left = cm->mi + mi_row * mis + mi_col;
|
|
|
|
|
2014-04-11 00:57:38 +02:00
|
|
|
vp9_setup_src_planes(x, cpi->Source, mi_row, mi_col);
|
|
|
|
|
2014-04-02 02:32:20 +02:00
|
|
|
assert((row8x8_remaining > 0) && (col8x8_remaining > 0));
|
|
|
|
|
|
|
|
// In-image SB64
|
|
|
|
if ((col8x8_remaining >= MI_BLOCK_SIZE) &&
|
|
|
|
(row8x8_remaining >= MI_BLOCK_SIZE)) {
|
|
|
|
int i, j;
|
|
|
|
int index;
|
|
|
|
diff d32[4];
|
2014-05-02 00:14:39 +02:00
|
|
|
const int offset = (mi_row >> 1) * cm->mb_cols + (mi_col >> 1);
|
|
|
|
int is_larger_better = 0;
|
|
|
|
int use32x32 = 0;
|
2014-07-01 17:58:05 +02:00
|
|
|
unsigned int thr = cpi->source_var_thresh;
|
2014-05-02 00:14:39 +02:00
|
|
|
|
2015-04-24 05:47:40 +02:00
|
|
|
memset(d32, 0, 4 * sizeof(diff));
|
2014-04-02 02:32:20 +02:00
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
2014-05-02 00:14:39 +02:00
|
|
|
diff *d16[4];
|
2014-04-02 02:32:20 +02:00
|
|
|
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
int b_mi_row = coord_lookup[i * 4 + j].row;
|
|
|
|
int b_mi_col = coord_lookup[i * 4 + j].col;
|
2016-07-27 05:43:23 +02:00
|
|
|
int boffset = b_mi_row / 2 * cm->mb_cols + b_mi_col / 2;
|
2014-04-02 02:32:20 +02:00
|
|
|
|
2014-05-02 00:14:39 +02:00
|
|
|
d16[j] = cpi->source_diff_var + offset + boffset;
|
2014-04-02 02:32:20 +02:00
|
|
|
|
|
|
|
index = b_mi_row * mis + b_mi_col;
|
2015-04-21 14:36:58 +02:00
|
|
|
mi_8x8[index] = mi_upper_left + index;
|
2016-01-20 01:40:20 +01:00
|
|
|
mi_8x8[index]->sb_type = BLOCK_16X16;
|
2014-04-02 02:32:20 +02:00
|
|
|
|
|
|
|
// TODO(yunqingwang): If d16[j].var is very large, use 8x8 partition
|
|
|
|
// size to further improve quality.
|
|
|
|
}
|
|
|
|
|
2014-05-02 00:14:39 +02:00
|
|
|
is_larger_better = (d16[0]->var < thr) && (d16[1]->var < thr) &&
|
2016-07-27 05:43:23 +02:00
|
|
|
(d16[2]->var < thr) && (d16[3]->var < thr);
|
2014-05-02 00:14:39 +02:00
|
|
|
|
|
|
|
// Use 32x32 partition
|
|
|
|
if (is_larger_better) {
|
|
|
|
use32x32 += 1;
|
2014-04-02 02:32:20 +02:00
|
|
|
|
2014-05-02 00:14:39 +02:00
|
|
|
for (j = 0; j < 4; j++) {
|
|
|
|
d32[i].sse += d16[j]->sse;
|
|
|
|
d32[i].sum += d16[j]->sum;
|
2014-04-02 02:32:20 +02:00
|
|
|
}
|
|
|
|
|
2016-09-01 11:01:33 +02:00
|
|
|
d32[i].var =
|
|
|
|
(unsigned int)(d32[i].sse -
|
|
|
|
(unsigned int)(((int64_t)d32[i].sum * d32[i].sum) >>
|
|
|
|
10));
|
2014-04-02 02:32:20 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
index = coord_lookup[i * 4].row * mis + coord_lookup[i * 4].col;
|
2015-04-21 14:36:58 +02:00
|
|
|
mi_8x8[index] = mi_upper_left + index;
|
2016-01-20 01:40:20 +01:00
|
|
|
mi_8x8[index]->sb_type = BLOCK_32X32;
|
2014-04-02 02:32:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-02 00:14:39 +02:00
|
|
|
if (use32x32 == 4) {
|
|
|
|
thr <<= 1;
|
|
|
|
is_larger_better = (d32[0].var < thr) && (d32[1].var < thr) &&
|
2016-07-27 05:43:23 +02:00
|
|
|
(d32[2].var < thr) && (d32[3].var < thr);
|
2014-05-02 00:14:39 +02:00
|
|
|
|
|
|
|
// Use 64x64 partition
|
|
|
|
if (is_larger_better) {
|
2015-04-21 14:36:58 +02:00
|
|
|
mi_8x8[0] = mi_upper_left;
|
2016-01-20 01:40:20 +01:00
|
|
|
mi_8x8[0]->sb_type = BLOCK_64X64;
|
2014-04-02 02:32:20 +02:00
|
|
|
}
|
|
|
|
}
|
2016-07-27 05:43:23 +02:00
|
|
|
} else { // partial in-image SB64
|
2014-04-15 19:02:33 +02:00
|
|
|
int bh = num_8x8_blocks_high_lookup[BLOCK_16X16];
|
|
|
|
int bw = num_8x8_blocks_wide_lookup[BLOCK_16X16];
|
2016-07-27 05:43:23 +02:00
|
|
|
set_partial_b64x64_partition(mi_upper_left, mis, bh, bw, row8x8_remaining,
|
|
|
|
col8x8_remaining, BLOCK_16X16, mi_8x8);
|
2014-04-02 02:32:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static void update_state_rt(VP9_COMP *cpi, ThreadData *td,
|
2016-07-27 05:43:23 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx, int mi_row, int mi_col,
|
|
|
|
int bsize) {
|
2014-01-10 20:51:20 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-01-29 17:39:39 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO *const mi = xd->mi[0];
|
2015-12-21 19:35:05 +01:00
|
|
|
struct macroblock_plane *const p = x->plane;
|
2014-03-14 22:35:47 +01:00
|
|
|
const struct segmentation *const seg = &cm->seg;
|
2016-01-20 01:40:20 +01:00
|
|
|
const int bw = num_8x8_blocks_wide_lookup[mi->sb_type];
|
|
|
|
const int bh = num_8x8_blocks_high_lookup[mi->sb_type];
|
2015-08-18 03:19:22 +02:00
|
|
|
const int x_mis = VPXMIN(bw, cm->mi_cols - mi_col);
|
|
|
|
const int y_mis = VPXMIN(bh, cm->mi_rows - mi_row);
|
2014-01-10 20:51:20 +01:00
|
|
|
|
2015-04-21 14:36:58 +02:00
|
|
|
*(xd->mi[0]) = ctx->mic;
|
2015-06-29 18:27:11 +02:00
|
|
|
*(x->mbmi_ext) = ctx->mbmi_ext;
|
2014-09-12 00:37:08 +02:00
|
|
|
|
2016-06-24 19:17:51 +02:00
|
|
|
if (seg->enabled && cpi->oxcf.aq_mode != NO_AQ) {
|
2014-10-03 23:41:12 +02:00
|
|
|
// For in frame complexity AQ or variance AQ, copy segment_id from
|
|
|
|
// segmentation_map.
|
2016-06-24 19:17:51 +02:00
|
|
|
if (cpi->oxcf.aq_mode != CYCLIC_REFRESH_AQ) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const uint8_t *const map =
|
|
|
|
seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col);
|
2014-10-03 23:41:12 +02:00
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
// Setting segmentation map for cyclic_refresh.
|
2016-01-20 01:40:20 +01:00
|
|
|
vp9_cyclic_refresh_update_segment(cpi, mi, mi_row, mi_col, bsize,
|
2015-12-21 19:35:05 +01:00
|
|
|
ctx->rate, ctx->dist, x->skip, p);
|
2014-10-03 23:41:12 +02:00
|
|
|
}
|
2014-03-14 22:35:47 +01:00
|
|
|
vp9_init_plane_quantizers(cpi, x);
|
|
|
|
}
|
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
if (is_inter_block(mi)) {
|
2014-11-21 20:11:06 +01:00
|
|
|
vp9_update_mv_count(td);
|
2014-03-15 01:05:35 +01:00
|
|
|
if (cm->interp_filter == SWITCHABLE) {
|
2016-07-21 20:47:51 +02:00
|
|
|
const int pred_ctx = get_pred_context_switchable_interp(xd);
|
2016-01-20 01:40:20 +01:00
|
|
|
++td->counts->switchable_interp[pred_ctx][mi->interp_filter];
|
2014-01-29 17:39:39 +01:00
|
|
|
}
|
2014-12-22 22:38:34 +01:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
if (mi->sb_type < BLOCK_8X8) {
|
|
|
|
mi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
|
|
|
|
mi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
|
2014-12-22 22:38:34 +01:00
|
|
|
}
|
2014-01-29 17:39:39 +01:00
|
|
|
}
|
2014-04-01 01:54:33 +02:00
|
|
|
|
2016-08-03 02:37:32 +02:00
|
|
|
if (cm->use_prev_frame_mvs || !cm->error_resilient_mode ||
|
2016-07-27 05:43:23 +02:00
|
|
|
(cpi->svc.use_base_mv && cpi->svc.number_spatial_layers > 1 &&
|
|
|
|
cpi->svc.spatial_layer_id != cpi->svc.number_spatial_layers - 1)) {
|
2014-12-09 21:09:36 +01:00
|
|
|
MV_REF *const frame_mvs =
|
|
|
|
cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
|
|
|
|
int w, h;
|
|
|
|
|
|
|
|
for (h = 0; h < y_mis; ++h) {
|
|
|
|
MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
|
|
|
|
for (w = 0; w < x_mis; ++w) {
|
|
|
|
MV_REF *const mv = frame_mv + w;
|
2016-01-20 01:40:20 +01:00
|
|
|
mv->ref_frame[0] = mi->ref_frame[0];
|
|
|
|
mv->ref_frame[1] = mi->ref_frame[1];
|
|
|
|
mv->mv[0].as_int = mi->mv[0].as_int;
|
|
|
|
mv->mv[1].as_int = mi->mv[1].as_int;
|
2014-12-09 21:09:36 +01:00
|
|
|
}
|
2014-10-28 00:19:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-01 01:54:33 +02:00
|
|
|
x->skip = ctx->skip;
|
2016-01-20 01:40:20 +01:00
|
|
|
x->skip_txfm[0] = mi->segment_id ? 0 : ctx->skip_txfm[0];
|
2014-01-29 17:39:39 +01:00
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static void encode_b_rt(VP9_COMP *cpi, ThreadData *td,
|
2016-07-27 05:43:23 +02:00
|
|
|
const TileInfo *const tile, TOKENEXTRA **tp, int mi_row,
|
|
|
|
int mi_col, int output_enabled, BLOCK_SIZE bsize,
|
2014-11-21 20:11:06 +01:00
|
|
|
PICK_MODE_CONTEXT *ctx) {
|
|
|
|
MACROBLOCK *const x = &td->mb;
|
|
|
|
set_offsets(cpi, tile, x, mi_row, mi_col, bsize);
|
|
|
|
update_state_rt(cpi, td, ctx, mi_row, mi_col, bsize);
|
2014-01-29 17:39:39 +01:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_superblock(cpi, td, tp, output_enabled, mi_row, mi_col, bsize, ctx);
|
|
|
|
update_stats(&cpi->common, td);
|
2014-01-29 17:39:39 +01:00
|
|
|
|
|
|
|
(*tp)->token = EOSB_TOKEN;
|
|
|
|
(*tp)++;
|
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static void encode_sb_rt(VP9_COMP *cpi, ThreadData *td,
|
2016-07-27 05:43:23 +02:00
|
|
|
const TileInfo *const tile, TOKENEXTRA **tp,
|
|
|
|
int mi_row, int mi_col, int output_enabled,
|
|
|
|
BLOCK_SIZE bsize, PC_TREE *pc_tree) {
|
2014-01-29 17:39:39 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-03-21 00:08:54 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
|
|
|
|
2014-10-07 21:30:33 +02:00
|
|
|
const int bsl = b_width_log2_lookup[bsize], hbs = (1 << bsl) / 4;
|
2014-01-29 17:39:39 +01:00
|
|
|
int ctx;
|
|
|
|
PARTITION_TYPE partition;
|
|
|
|
BLOCK_SIZE subsize;
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
|
|
|
if (bsize >= BLOCK_8X8) {
|
2014-04-02 01:18:47 +02:00
|
|
|
const int idx_str = xd->mi_stride * mi_row + mi_col;
|
2016-07-27 05:43:23 +02:00
|
|
|
MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str;
|
2014-03-21 20:12:55 +01:00
|
|
|
ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2016-01-20 01:40:20 +01:00
|
|
|
subsize = mi_8x8[0]->sb_type;
|
2014-01-10 20:51:20 +01:00
|
|
|
} else {
|
2014-01-29 17:39:39 +01:00
|
|
|
ctx = 0;
|
|
|
|
subsize = BLOCK_4X4;
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
partition = partition_lookup[bsl][subsize];
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
if (output_enabled && bsize != BLOCK_4X4)
|
2014-11-21 20:11:06 +01:00
|
|
|
td->counts->partition[ctx][partition]++;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
2014-01-10 20:51:20 +01:00
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
&pc_tree->none);
|
2014-01-10 20:51:20 +01:00
|
|
|
break;
|
2014-01-29 17:39:39 +01:00
|
|
|
case PARTITION_VERT:
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
&pc_tree->vertical[0]);
|
|
|
|
if (mi_col + hbs < cm->mi_cols && bsize > BLOCK_8X8) {
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile, tp, mi_row, mi_col + hbs, output_enabled,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
subsize, &pc_tree->vertical[1]);
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
break;
|
2014-01-29 17:39:39 +01:00
|
|
|
case PARTITION_HORZ:
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
&pc_tree->horizontal[0]);
|
|
|
|
if (mi_row + hbs < cm->mi_rows && bsize > BLOCK_8X8) {
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile, tp, mi_row + hbs, mi_col, output_enabled,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
subsize, &pc_tree->horizontal[1]);
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
2014-01-29 17:39:39 +01:00
|
|
|
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_sb_rt(cpi, td, tile, tp, mi_row, mi_col, output_enabled, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->split[0]);
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_sb_rt(cpi, td, tile, tp, mi_row, mi_col + hbs, output_enabled,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
subsize, pc_tree->split[1]);
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_sb_rt(cpi, td, tile, tp, mi_row + hbs, mi_col, output_enabled,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
subsize, pc_tree->split[2]);
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_sb_rt(cpi, td, tile, tp, mi_row + hbs, mi_col + hbs,
|
|
|
|
output_enabled, subsize, pc_tree->split[3]);
|
2014-01-10 20:51:20 +01:00
|
|
|
break;
|
2016-07-27 05:43:23 +02:00
|
|
|
default: assert(0 && "Invalid partition type."); break;
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
|
2014-03-21 20:12:55 +01:00
|
|
|
update_partition_context(xd, mi_row, mi_col, subsize, bsize);
|
2014-01-10 20:51:20 +01:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void rd_use_partition(VP9_COMP *cpi, ThreadData *td,
|
|
|
|
TileDataEnc *tile_data, MODE_INFO **mi_8x8,
|
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
|
|
|
BLOCK_SIZE bsize, int *rate, int64_t *dist,
|
2014-05-12 18:53:11 +02:00
|
|
|
int do_recon, PC_TREE *pc_tree) {
|
2013-11-12 00:58:57 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-10-27 19:11:50 +01:00
|
|
|
TileInfo *const tile_info = &tile_data->tile_info;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-03-21 00:08:54 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2014-04-02 01:18:47 +02:00
|
|
|
const int mis = cm->mi_stride;
|
2014-10-07 21:30:33 +02:00
|
|
|
const int bsl = b_width_log2_lookup[bsize];
|
2014-03-21 22:24:03 +01:00
|
|
|
const int mi_step = num_4x4_blocks_wide_lookup[bsize] / 2;
|
2014-01-10 22:48:44 +01:00
|
|
|
const int bss = (1 << bsl) / 4;
|
2013-05-31 00:13:08 +02:00
|
|
|
int i, pl;
|
2013-07-10 23:27:20 +02:00
|
|
|
PARTITION_TYPE partition = PARTITION_NONE;
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE subsize;
|
2013-05-31 00:13:08 +02:00
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
|
|
|
|
PARTITION_CONTEXT sl[8], sa[8];
|
2014-10-14 19:26:28 +02:00
|
|
|
RD_COST last_part_rdc, none_rdc, chosen_rdc;
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE sub_subsize = BLOCK_4X4;
|
2013-07-02 03:18:50 +02:00
|
|
|
int splits_below = 0;
|
2016-01-20 01:40:20 +01:00
|
|
|
BLOCK_SIZE bs_type = mi_8x8[0]->sb_type;
|
2014-03-19 01:00:30 +01:00
|
|
|
int do_partition_search = 1;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx = &pc_tree->none;
|
2013-05-31 00:13:08 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
2013-05-31 00:13:08 +02:00
|
|
|
|
2014-03-21 22:24:03 +01:00
|
|
|
assert(num_4x4_blocks_wide_lookup[bsize] ==
|
|
|
|
num_4x4_blocks_high_lookup[bsize]);
|
|
|
|
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_reset(&last_part_rdc);
|
|
|
|
vp9_rd_cost_reset(&none_rdc);
|
|
|
|
vp9_rd_cost_reset(&chosen_rdc);
|
|
|
|
|
2013-07-23 15:51:44 +02:00
|
|
|
partition = partition_lookup[bsl][bs_type];
|
2013-05-31 00:13:08 +02:00
|
|
|
subsize = get_subsize(bsize, partition);
|
|
|
|
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = partition;
|
2014-11-21 20:11:06 +01:00
|
|
|
save_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2016-06-24 19:17:51 +02:00
|
|
|
if (bsize == BLOCK_16X16 && cpi->oxcf.aq_mode != NO_AQ) {
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
|
2013-10-07 20:20:10 +02:00
|
|
|
x->mb_energy = vp9_block_energy(cpi, x, bsize);
|
|
|
|
}
|
|
|
|
|
2014-03-19 01:00:30 +01:00
|
|
|
if (do_partition_search &&
|
|
|
|
cpi->sf.partition_search_type == SEARCH_PARTITION &&
|
2014-02-26 02:22:34 +01:00
|
|
|
cpi->sf.adjust_partitioning_from_last_frame) {
|
2013-07-02 03:18:50 +02:00
|
|
|
// Check if any of the sub blocks are further split.
|
2013-08-06 00:23:49 +02:00
|
|
|
if (partition == PARTITION_SPLIT && subsize > BLOCK_8X8) {
|
2013-07-02 03:18:50 +02:00
|
|
|
sub_subsize = get_subsize(subsize, PARTITION_SPLIT);
|
|
|
|
splits_below = 1;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
int jj = i >> 1, ii = i & 0x01;
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO *this_mi = mi_8x8[jj * bss * mis + ii * bss];
|
2016-01-20 01:40:20 +01:00
|
|
|
if (this_mi && this_mi->sb_type >= sub_subsize) {
|
2013-07-02 03:18:50 +02:00
|
|
|
splits_below = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If partition is not none try none unless each of the 4 splits are split
|
|
|
|
// even further..
|
|
|
|
if (partition != PARTITION_NONE && !splits_below &&
|
2014-03-21 22:24:03 +01:00
|
|
|
mi_row + (mi_step >> 1) < cm->mi_rows &&
|
|
|
|
mi_col + (mi_step >> 1) < cm->mi_cols) {
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = PARTITION_NONE;
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &none_rdc, bsize, ctx,
|
|
|
|
INT64_MAX);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2014-03-21 20:12:55 +01:00
|
|
|
pl = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2014-02-26 16:46:56 +01:00
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
if (none_rdc.rate < INT_MAX) {
|
|
|
|
none_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE];
|
2016-07-27 05:43:23 +02:00
|
|
|
none_rdc.rdcost =
|
|
|
|
RDCOST(x->rdmult, x->rddiv, none_rdc.rate, none_rdc.dist);
|
2014-02-26 16:46:56 +01:00
|
|
|
}
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
2016-01-20 01:40:20 +01:00
|
|
|
mi_8x8[0]->sb_type = bs_type;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = partition;
|
2013-07-02 03:18:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 00:13:08 +02:00
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc, bsize,
|
|
|
|
ctx, INT64_MAX);
|
2013-05-31 00:13:08 +02:00
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
2014-11-21 20:11:06 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc,
|
2016-07-27 05:43:23 +02:00
|
|
|
subsize, &pc_tree->horizontal[0], INT64_MAX);
|
|
|
|
if (last_part_rdc.rate != INT_MAX && bsize >= BLOCK_8X8 &&
|
|
|
|
mi_row + (mi_step >> 1) < cm->mi_rows) {
|
2014-10-14 19:26:28 +02:00
|
|
|
RD_COST tmp_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx = &pc_tree->horizontal[0];
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_init(&tmp_rdc);
|
2014-11-21 20:11:06 +01:00
|
|
|
update_state(cpi, td, ctx, mi_row, mi_col, subsize, 0);
|
|
|
|
encode_superblock(cpi, td, tp, 0, mi_row, mi_col, subsize, ctx);
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row + (mi_step >> 1), mi_col,
|
|
|
|
&tmp_rdc, subsize, &pc_tree->horizontal[1], INT64_MAX);
|
2014-10-09 21:32:56 +02:00
|
|
|
if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_reset(&last_part_rdc);
|
2013-07-22 15:39:39 +02:00
|
|
|
break;
|
|
|
|
}
|
2014-10-09 21:32:56 +02:00
|
|
|
last_part_rdc.rate += tmp_rdc.rate;
|
|
|
|
last_part_rdc.dist += tmp_rdc.dist;
|
|
|
|
last_part_rdc.rdcost += tmp_rdc.rdcost;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
2014-11-21 20:11:06 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc,
|
2014-10-09 21:32:56 +02:00
|
|
|
subsize, &pc_tree->vertical[0], INT64_MAX);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (last_part_rdc.rate != INT_MAX && bsize >= BLOCK_8X8 &&
|
|
|
|
mi_col + (mi_step >> 1) < cm->mi_cols) {
|
2014-10-14 19:26:28 +02:00
|
|
|
RD_COST tmp_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx = &pc_tree->vertical[0];
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_init(&tmp_rdc);
|
2014-11-21 20:11:06 +01:00
|
|
|
update_state(cpi, td, ctx, mi_row, mi_col, subsize, 0);
|
|
|
|
encode_superblock(cpi, td, tp, 0, mi_row, mi_col, subsize, ctx);
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + (mi_step >> 1),
|
|
|
|
&tmp_rdc, subsize,
|
|
|
|
&pc_tree->vertical[bsize > BLOCK_8X8], INT64_MAX);
|
2014-10-09 21:32:56 +02:00
|
|
|
if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_reset(&last_part_rdc);
|
2013-07-22 15:39:39 +02:00
|
|
|
break;
|
|
|
|
}
|
2014-10-09 21:32:56 +02:00
|
|
|
last_part_rdc.rate += tmp_rdc.rate;
|
|
|
|
last_part_rdc.dist += tmp_rdc.dist;
|
|
|
|
last_part_rdc.rdcost += tmp_rdc.rdcost;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
if (bsize == BLOCK_8X8) {
|
2014-11-21 20:11:06 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc,
|
2014-10-09 21:32:56 +02:00
|
|
|
subsize, pc_tree->leaf_split[0], INT64_MAX);
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
break;
|
|
|
|
}
|
2014-10-09 21:32:56 +02:00
|
|
|
last_part_rdc.rate = 0;
|
|
|
|
last_part_rdc.dist = 0;
|
|
|
|
last_part_rdc.rdcost = 0;
|
2013-05-31 00:13:08 +02:00
|
|
|
for (i = 0; i < 4; i++) {
|
2014-03-21 22:24:03 +01:00
|
|
|
int x_idx = (i & 1) * (mi_step >> 1);
|
|
|
|
int y_idx = (i >> 1) * (mi_step >> 1);
|
2013-05-31 00:13:08 +02:00
|
|
|
int jj = i >> 1, ii = i & 0x01;
|
2014-10-14 19:26:28 +02:00
|
|
|
RD_COST tmp_rdc;
|
2013-05-31 00:13:08 +02:00
|
|
|
if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
|
|
|
|
continue;
|
|
|
|
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_init(&tmp_rdc);
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_use_partition(cpi, td, tile_data, mi_8x8 + jj * bss * mis + ii * bss,
|
|
|
|
tp, mi_row + y_idx, mi_col + x_idx, subsize,
|
|
|
|
&tmp_rdc.rate, &tmp_rdc.dist, i != 3,
|
|
|
|
pc_tree->split[i]);
|
2014-10-09 21:32:56 +02:00
|
|
|
if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_reset(&last_part_rdc);
|
2013-07-20 02:38:55 +02:00
|
|
|
break;
|
|
|
|
}
|
2014-10-09 21:32:56 +02:00
|
|
|
last_part_rdc.rate += tmp_rdc.rate;
|
|
|
|
last_part_rdc.dist += tmp_rdc.dist;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
break;
|
2016-07-27 05:43:23 +02:00
|
|
|
default: assert(0); break;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
2013-10-21 21:02:19 +02:00
|
|
|
|
2014-03-21 20:12:55 +01:00
|
|
|
pl = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2014-10-09 21:32:56 +02:00
|
|
|
if (last_part_rdc.rate < INT_MAX) {
|
|
|
|
last_part_rdc.rate += cpi->partition_cost[pl][partition];
|
2016-07-27 05:43:23 +02:00
|
|
|
last_part_rdc.rdcost =
|
|
|
|
RDCOST(x->rdmult, x->rddiv, last_part_rdc.rate, last_part_rdc.dist);
|
2014-02-26 16:46:56 +01:00
|
|
|
}
|
2013-07-20 02:38:55 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (do_partition_search && cpi->sf.adjust_partitioning_from_last_frame &&
|
|
|
|
cpi->sf.partition_search_type == SEARCH_PARTITION &&
|
|
|
|
partition != PARTITION_SPLIT && bsize > BLOCK_8X8 &&
|
|
|
|
(mi_row + mi_step < cm->mi_rows ||
|
|
|
|
mi_row + (mi_step >> 1) == cm->mi_rows) &&
|
|
|
|
(mi_col + mi_step < cm->mi_cols ||
|
|
|
|
mi_col + (mi_step >> 1) == cm->mi_cols)) {
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE split_subsize = get_subsize(bsize, PARTITION_SPLIT);
|
2014-10-09 21:32:56 +02:00
|
|
|
chosen_rdc.rate = 0;
|
|
|
|
chosen_rdc.dist = 0;
|
2014-11-21 20:11:06 +01:00
|
|
|
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = PARTITION_SPLIT;
|
2013-07-02 03:18:50 +02:00
|
|
|
|
|
|
|
// Split partition.
|
|
|
|
for (i = 0; i < 4; i++) {
|
2014-03-21 22:24:03 +01:00
|
|
|
int x_idx = (i & 1) * (mi_step >> 1);
|
|
|
|
int y_idx = (i >> 1) * (mi_step >> 1);
|
2014-10-09 21:32:56 +02:00
|
|
|
RD_COST tmp_rdc;
|
2013-07-02 03:18:50 +02:00
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
|
|
|
|
PARTITION_CONTEXT sl[8], sa[8];
|
|
|
|
|
2013-11-12 00:58:57 +01:00
|
|
|
if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols))
|
2013-07-02 03:18:50 +02:00
|
|
|
continue;
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
save_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->split[i]->partitioning = PARTITION_NONE;
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row + y_idx, mi_col + x_idx,
|
|
|
|
&tmp_rdc, split_subsize, &pc_tree->split[i]->none,
|
|
|
|
INT64_MAX);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_reset(&chosen_rdc);
|
2013-07-22 15:39:39 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
chosen_rdc.rate += tmp_rdc.rate;
|
|
|
|
chosen_rdc.dist += tmp_rdc.dist;
|
2014-02-25 02:34:27 +01:00
|
|
|
|
2013-07-22 15:39:39 +02:00
|
|
|
if (i != 3)
|
2016-07-27 05:43:23 +02:00
|
|
|
encode_sb(cpi, td, tile_info, tp, mi_row + y_idx, mi_col + x_idx, 0,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
split_subsize, pc_tree->split[i]);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2014-03-21 20:12:55 +01:00
|
|
|
pl = partition_plane_context(xd, mi_row + y_idx, mi_col + x_idx,
|
2013-12-10 23:34:32 +01:00
|
|
|
split_subsize);
|
2014-10-09 21:32:56 +02:00
|
|
|
chosen_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE];
|
2013-07-02 03:18:50 +02:00
|
|
|
}
|
2014-03-21 20:12:55 +01:00
|
|
|
pl = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2014-10-09 21:32:56 +02:00
|
|
|
if (chosen_rdc.rate < INT_MAX) {
|
|
|
|
chosen_rdc.rate += cpi->partition_cost[pl][PARTITION_SPLIT];
|
2016-07-27 05:43:23 +02:00
|
|
|
chosen_rdc.rdcost =
|
|
|
|
RDCOST(x->rdmult, x->rddiv, chosen_rdc.rate, chosen_rdc.dist);
|
2013-07-22 15:39:39 +02:00
|
|
|
}
|
2013-07-02 03:18:50 +02:00
|
|
|
}
|
|
|
|
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
// If last_part is better set the partitioning to that.
|
2014-10-09 21:32:56 +02:00
|
|
|
if (last_part_rdc.rdcost < chosen_rdc.rdcost) {
|
2016-01-20 01:40:20 +01:00
|
|
|
mi_8x8[0]->sb_type = bsize;
|
2016-07-27 05:43:23 +02:00
|
|
|
if (bsize >= BLOCK_8X8) pc_tree->partitioning = partition;
|
2014-10-09 21:32:56 +02:00
|
|
|
chosen_rdc = last_part_rdc;
|
2013-07-02 03:18:50 +02:00
|
|
|
}
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
// If none was better set the partitioning to that.
|
2014-10-09 21:32:56 +02:00
|
|
|
if (none_rdc.rdcost < chosen_rdc.rdcost) {
|
2016-07-27 05:43:23 +02:00
|
|
|
if (bsize >= BLOCK_8X8) pc_tree->partitioning = PARTITION_NONE;
|
2014-10-09 21:32:56 +02:00
|
|
|
chosen_rdc = none_rdc;
|
2013-07-02 03:18:50 +02:00
|
|
|
}
|
2013-05-31 00:13:08 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-05-31 00:13:08 +02:00
|
|
|
|
2013-07-02 03:18:50 +02:00
|
|
|
// We must have chosen a partitioning and encoding or we'll fail later on.
|
|
|
|
// No other opportunities for success.
|
2014-10-03 23:41:12 +02:00
|
|
|
if (bsize == BLOCK_64X64)
|
2014-10-09 21:32:56 +02:00
|
|
|
assert(chosen_rdc.rate < INT_MAX && chosen_rdc.dist < INT64_MAX);
|
2013-07-02 03:18:50 +02:00
|
|
|
|
2013-11-22 18:21:53 +01:00
|
|
|
if (do_recon) {
|
|
|
|
int output_enabled = (bsize == BLOCK_64X64);
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree);
|
2013-11-22 18:21:53 +01:00
|
|
|
}
|
2013-07-20 02:38:55 +02:00
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
*rate = chosen_rdc.rate;
|
|
|
|
*dist = chosen_rdc.dist;
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
|
|
|
|
2013-08-27 20:05:08 +02:00
|
|
|
static const BLOCK_SIZE min_partition_size[BLOCK_SIZES] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
BLOCK_4X4, BLOCK_4X4, BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
|
|
|
|
BLOCK_4X4, BLOCK_8X8, BLOCK_8X8, BLOCK_8X8, BLOCK_16X16,
|
|
|
|
BLOCK_16X16, BLOCK_16X16, BLOCK_16X16
|
2013-08-27 20:05:08 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const BLOCK_SIZE max_partition_size[BLOCK_SIZES] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
BLOCK_8X8, BLOCK_16X16, BLOCK_16X16, BLOCK_16X16, BLOCK_32X32,
|
|
|
|
BLOCK_32X32, BLOCK_32X32, BLOCK_64X64, BLOCK_64X64, BLOCK_64X64,
|
|
|
|
BLOCK_64X64, BLOCK_64X64, BLOCK_64X64
|
2013-08-27 20:05:08 +02:00
|
|
|
};
|
2013-07-24 15:07:37 +02:00
|
|
|
|
2013-08-16 17:54:12 +02:00
|
|
|
// Look at all the mode_info entries for blocks that are part of this
|
|
|
|
// partition and find the min and max values for sb_type.
|
|
|
|
// At the moment this is designed to work on a 64x64 SB but could be
|
|
|
|
// adjusted to use a size parameter.
|
|
|
|
//
|
|
|
|
// The min and max are assumed to have been initialized prior to calling this
|
|
|
|
// function so repeat calls can accumulate a min and max of more than one sb64.
|
2015-04-21 14:36:58 +02:00
|
|
|
static void get_sb_partition_size_range(MACROBLOCKD *xd, MODE_INFO **mi_8x8,
|
2014-08-07 23:55:54 +02:00
|
|
|
BLOCK_SIZE *min_block_size,
|
2014-08-14 05:07:39 +02:00
|
|
|
BLOCK_SIZE *max_block_size,
|
|
|
|
int bs_hist[BLOCK_SIZES]) {
|
2013-08-16 17:54:12 +02:00
|
|
|
int sb_width_in_blocks = MI_BLOCK_SIZE;
|
2016-07-27 05:43:23 +02:00
|
|
|
int sb_height_in_blocks = MI_BLOCK_SIZE;
|
2013-08-16 17:54:12 +02:00
|
|
|
int i, j;
|
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
// Check the sb_type for each block that belongs to this region.
|
|
|
|
for (i = 0; i < sb_height_in_blocks; ++i) {
|
|
|
|
for (j = 0; j < sb_width_in_blocks; ++j) {
|
2016-07-27 05:43:23 +02:00
|
|
|
MODE_INFO *mi = mi_8x8[index + j];
|
2016-01-20 01:40:20 +01:00
|
|
|
BLOCK_SIZE sb_type = mi ? mi->sb_type : 0;
|
2014-08-14 05:07:39 +02:00
|
|
|
bs_hist[sb_type]++;
|
2015-08-18 03:19:22 +02:00
|
|
|
*min_block_size = VPXMIN(*min_block_size, sb_type);
|
|
|
|
*max_block_size = VPXMAX(*max_block_size, sb_type);
|
2013-08-16 17:54:12 +02:00
|
|
|
}
|
2014-04-02 01:18:47 +02:00
|
|
|
index += xd->mi_stride;
|
2013-08-16 17:54:12 +02:00
|
|
|
}
|
|
|
|
}
|
2013-07-24 15:07:37 +02:00
|
|
|
|
2014-02-11 02:19:36 +01:00
|
|
|
// Next square block size less or equal than current block size.
|
|
|
|
static const BLOCK_SIZE next_square_size[BLOCK_SIZES] = {
|
2016-07-27 05:43:23 +02:00
|
|
|
BLOCK_4X4, BLOCK_4X4, BLOCK_4X4, BLOCK_8X8, BLOCK_8X8,
|
|
|
|
BLOCK_8X8, BLOCK_16X16, BLOCK_16X16, BLOCK_16X16, BLOCK_32X32,
|
|
|
|
BLOCK_32X32, BLOCK_32X32, BLOCK_64X64
|
2014-02-11 02:19:36 +01:00
|
|
|
};
|
|
|
|
|
2013-08-01 18:04:15 +02:00
|
|
|
// Look at neighboring blocks and set a min and max partition size based on
|
2013-07-24 15:07:37 +02:00
|
|
|
// what they chose.
|
2013-10-25 17:18:04 +02:00
|
|
|
static void rd_auto_partition_range(VP9_COMP *cpi, const TileInfo *const tile,
|
2016-07-27 05:43:23 +02:00
|
|
|
MACROBLOCKD *const xd, int mi_row,
|
|
|
|
int mi_col, BLOCK_SIZE *min_block_size,
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE *max_block_size) {
|
2014-03-26 18:48:01 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **mi = xd->mi;
|
2016-03-30 13:47:39 +02:00
|
|
|
const int left_in_image = !!xd->left_mi;
|
|
|
|
const int above_in_image = !!xd->above_mi;
|
2014-05-14 21:14:02 +02:00
|
|
|
const int row8x8_remaining = tile->mi_row_end - mi_row;
|
|
|
|
const int col8x8_remaining = tile->mi_col_end - mi_col;
|
2013-09-27 13:59:06 +02:00
|
|
|
int bh, bw;
|
2014-03-20 00:19:16 +01:00
|
|
|
BLOCK_SIZE min_size = BLOCK_4X4;
|
|
|
|
BLOCK_SIZE max_size = BLOCK_64X64;
|
2016-07-27 05:43:23 +02:00
|
|
|
int bs_hist[BLOCK_SIZES] = { 0 };
|
2014-08-14 05:07:39 +02:00
|
|
|
|
2013-09-27 13:59:06 +02:00
|
|
|
// Trap case where we do not have a prediction.
|
2014-03-20 00:19:16 +01:00
|
|
|
if (left_in_image || above_in_image || cm->frame_type != KEY_FRAME) {
|
2013-09-27 13:59:06 +02:00
|
|
|
// Default "min to max" and "max to min"
|
2014-03-20 00:19:16 +01:00
|
|
|
min_size = BLOCK_64X64;
|
|
|
|
max_size = BLOCK_4X4;
|
2013-09-27 13:59:06 +02:00
|
|
|
|
|
|
|
// NOTE: each call to get_sb_partition_size_range() uses the previous
|
|
|
|
// passed in values for min and max as a starting point.
|
|
|
|
// Find the min and max partition used in previous frame at this location
|
2014-03-20 00:19:16 +01:00
|
|
|
if (cm->frame_type != KEY_FRAME) {
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **prev_mi =
|
|
|
|
&cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col];
|
2014-08-14 05:07:39 +02:00
|
|
|
get_sb_partition_size_range(xd, prev_mi, &min_size, &max_size, bs_hist);
|
2013-09-27 13:59:06 +02:00
|
|
|
}
|
|
|
|
// Find the min and max partition sizes used in the left SB64
|
|
|
|
if (left_in_image) {
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **left_sb64_mi = &mi[-MI_BLOCK_SIZE];
|
2014-08-14 05:07:39 +02:00
|
|
|
get_sb_partition_size_range(xd, left_sb64_mi, &min_size, &max_size,
|
|
|
|
bs_hist);
|
2013-09-27 13:59:06 +02:00
|
|
|
}
|
|
|
|
// Find the min and max partition sizes used in the above SB64.
|
|
|
|
if (above_in_image) {
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **above_sb64_mi = &mi[-xd->mi_stride * MI_BLOCK_SIZE];
|
2014-08-14 05:07:39 +02:00
|
|
|
get_sb_partition_size_range(xd, above_sb64_mi, &min_size, &max_size,
|
|
|
|
bs_hist);
|
2014-03-20 00:19:16 +01:00
|
|
|
}
|
2014-08-14 05:07:39 +02:00
|
|
|
|
2015-05-01 12:31:13 +02:00
|
|
|
// Adjust observed min and max for "relaxed" auto partition case.
|
2014-03-20 00:19:16 +01:00
|
|
|
if (cpi->sf.auto_min_max_partition_size == RELAXED_NEIGHBORING_MIN_MAX) {
|
|
|
|
min_size = min_partition_size[min_size];
|
|
|
|
max_size = max_partition_size[max_size];
|
2013-09-04 00:46:22 +02:00
|
|
|
}
|
2013-07-24 15:07:37 +02:00
|
|
|
}
|
2013-09-27 13:59:06 +02:00
|
|
|
|
2014-03-20 00:19:16 +01:00
|
|
|
// Check border cases where max and min from neighbors may not be legal.
|
2016-07-27 05:43:23 +02:00
|
|
|
max_size = find_partition_size(max_size, row8x8_remaining, col8x8_remaining,
|
2014-03-20 00:19:16 +01:00
|
|
|
&bh, &bw);
|
2015-06-17 18:14:25 +02:00
|
|
|
// Test for blocks at the edge of the active image.
|
|
|
|
// This may be the actual edge of the image or where there are formatting
|
|
|
|
// bars.
|
2015-06-24 12:36:51 +02:00
|
|
|
if (vp9_active_edge_sb(cpi, mi_row, mi_col)) {
|
2015-06-17 18:14:25 +02:00
|
|
|
min_size = BLOCK_4X4;
|
|
|
|
} else {
|
2015-08-18 03:19:22 +02:00
|
|
|
min_size =
|
|
|
|
VPXMIN(cpi->sf.rd_auto_partition_min_limit, VPXMIN(min_size, max_size));
|
2015-06-17 18:14:25 +02:00
|
|
|
}
|
2014-02-11 02:19:36 +01:00
|
|
|
|
|
|
|
// When use_square_partition_only is true, make sure at least one square
|
|
|
|
// partition is allowed by selecting the next smaller square size as
|
|
|
|
// *min_block_size.
|
|
|
|
if (cpi->sf.use_square_partition_only &&
|
2014-03-20 00:19:16 +01:00
|
|
|
next_square_size[max_size] < min_size) {
|
2016-07-27 05:43:23 +02:00
|
|
|
min_size = next_square_size[max_size];
|
2014-02-11 02:19:36 +01:00
|
|
|
}
|
2014-08-14 05:07:39 +02:00
|
|
|
|
2014-03-20 00:19:16 +01:00
|
|
|
*min_block_size = min_size;
|
|
|
|
*max_block_size = max_size;
|
2013-07-24 15:07:37 +02:00
|
|
|
}
|
2013-05-08 23:24:43 +02:00
|
|
|
|
2014-07-29 18:50:03 +02:00
|
|
|
// TODO(jingning) refactor functions setting partition search range
|
2016-07-27 05:43:23 +02:00
|
|
|
static void set_partition_range(VP9_COMMON *cm, MACROBLOCKD *xd, int mi_row,
|
|
|
|
int mi_col, BLOCK_SIZE bsize,
|
2014-07-29 18:50:03 +02:00
|
|
|
BLOCK_SIZE *min_bs, BLOCK_SIZE *max_bs) {
|
2016-07-27 05:43:23 +02:00
|
|
|
int mi_width = num_8x8_blocks_wide_lookup[bsize];
|
2014-07-29 18:50:03 +02:00
|
|
|
int mi_height = num_8x8_blocks_high_lookup[bsize];
|
|
|
|
int idx, idy;
|
|
|
|
|
|
|
|
MODE_INFO *mi;
|
2014-09-12 00:37:08 +02:00
|
|
|
const int idx_str = cm->mi_stride * mi_row + mi_col;
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **prev_mi = &cm->prev_mi_grid_visible[idx_str];
|
2014-07-29 18:50:03 +02:00
|
|
|
BLOCK_SIZE bs, min_size, max_size;
|
|
|
|
|
|
|
|
min_size = BLOCK_64X64;
|
|
|
|
max_size = BLOCK_4X4;
|
|
|
|
|
|
|
|
if (prev_mi) {
|
|
|
|
for (idy = 0; idy < mi_height; ++idy) {
|
|
|
|
for (idx = 0; idx < mi_width; ++idx) {
|
2015-04-21 14:36:58 +02:00
|
|
|
mi = prev_mi[idy * cm->mi_stride + idx];
|
2016-01-20 01:40:20 +01:00
|
|
|
bs = mi ? mi->sb_type : bsize;
|
2015-08-18 03:19:22 +02:00
|
|
|
min_size = VPXMIN(min_size, bs);
|
|
|
|
max_size = VPXMAX(max_size, bs);
|
2014-07-29 18:50:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-30 13:47:39 +02:00
|
|
|
if (xd->left_mi) {
|
2014-07-29 18:50:03 +02:00
|
|
|
for (idy = 0; idy < mi_height; ++idy) {
|
2015-04-21 14:36:58 +02:00
|
|
|
mi = xd->mi[idy * cm->mi_stride - 1];
|
2016-01-20 01:40:20 +01:00
|
|
|
bs = mi ? mi->sb_type : bsize;
|
2015-08-18 03:19:22 +02:00
|
|
|
min_size = VPXMIN(min_size, bs);
|
|
|
|
max_size = VPXMAX(max_size, bs);
|
2014-07-29 18:50:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-30 13:47:39 +02:00
|
|
|
if (xd->above_mi) {
|
2014-07-29 18:50:03 +02:00
|
|
|
for (idx = 0; idx < mi_width; ++idx) {
|
2015-04-21 14:36:58 +02:00
|
|
|
mi = xd->mi[idx - cm->mi_stride];
|
2016-01-20 01:40:20 +01:00
|
|
|
bs = mi ? mi->sb_type : bsize;
|
2015-08-18 03:19:22 +02:00
|
|
|
min_size = VPXMIN(min_size, bs);
|
|
|
|
max_size = VPXMAX(max_size, bs);
|
2014-07-29 18:50:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (min_size == max_size) {
|
|
|
|
min_size = min_partition_size[min_size];
|
|
|
|
max_size = max_partition_size[max_size];
|
|
|
|
}
|
|
|
|
|
|
|
|
*min_bs = min_size;
|
|
|
|
*max_bs = max_size;
|
|
|
|
}
|
|
|
|
|
2013-09-12 19:06:47 +02:00
|
|
|
static INLINE void store_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
|
2015-04-24 05:42:19 +02:00
|
|
|
memcpy(ctx->pred_mv, x->pred_mv, sizeof(x->pred_mv));
|
2013-09-12 19:06:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE void load_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
|
2015-04-24 05:42:19 +02:00
|
|
|
memcpy(x->pred_mv, ctx->pred_mv, sizeof(x->pred_mv));
|
2013-09-12 19:06:47 +02:00
|
|
|
}
|
|
|
|
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
#if CONFIG_FP_MB_STATS
|
2016-07-27 05:43:23 +02:00
|
|
|
const int num_16x16_blocks_wide_lookup[BLOCK_SIZES] = { 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
1, 2, 2, 2, 4, 4 };
|
|
|
|
const int num_16x16_blocks_high_lookup[BLOCK_SIZES] = { 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
2, 1, 2, 4, 2, 4 };
|
|
|
|
const int qindex_skip_threshold_lookup[BLOCK_SIZES] = {
|
|
|
|
0, 10, 10, 30, 40, 40, 60, 80, 80, 90, 100, 100, 120
|
|
|
|
};
|
|
|
|
const int qindex_split_threshold_lookup[BLOCK_SIZES] = {
|
|
|
|
0, 3, 3, 7, 15, 15, 30, 40, 40, 60, 80, 80, 120
|
|
|
|
};
|
|
|
|
const int complexity_16x16_blocks_threshold[BLOCK_SIZES] = {
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 6
|
|
|
|
};
|
2014-08-05 23:39:06 +02:00
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
MV_ZERO = 0,
|
|
|
|
MV_LEFT = 1,
|
|
|
|
MV_UP = 2,
|
|
|
|
MV_RIGHT = 3,
|
|
|
|
MV_DOWN = 4,
|
|
|
|
MV_INVALID
|
|
|
|
} MOTION_DIRECTION;
|
|
|
|
|
|
|
|
static INLINE MOTION_DIRECTION get_motion_direction_fp(uint8_t fp_byte) {
|
|
|
|
if (fp_byte & FPMB_MOTION_ZERO_MASK) {
|
|
|
|
return MV_ZERO;
|
|
|
|
} else if (fp_byte & FPMB_MOTION_LEFT_MASK) {
|
|
|
|
return MV_LEFT;
|
|
|
|
} else if (fp_byte & FPMB_MOTION_RIGHT_MASK) {
|
|
|
|
return MV_RIGHT;
|
|
|
|
} else if (fp_byte & FPMB_MOTION_UP_MASK) {
|
|
|
|
return MV_UP;
|
|
|
|
} else {
|
|
|
|
return MV_DOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE int get_motion_inconsistency(MOTION_DIRECTION this_mv,
|
|
|
|
MOTION_DIRECTION that_mv) {
|
|
|
|
if (this_mv == that_mv) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return abs(this_mv - that_mv) == 2 ? 2 : 1;
|
|
|
|
}
|
|
|
|
}
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
#endif
|
|
|
|
|
2017-03-21 17:47:55 +01:00
|
|
|
// Calculate the score used in machine-learning based partition search early
|
|
|
|
// termination.
|
|
|
|
static double compute_score(VP9_COMMON *const cm, MACROBLOCKD *const xd,
|
|
|
|
PICK_MODE_CONTEXT *ctx, int mi_row, int mi_col,
|
|
|
|
BLOCK_SIZE bsize) {
|
|
|
|
const double *clf;
|
|
|
|
const double *mean;
|
|
|
|
const double *sd;
|
|
|
|
const int mag_mv =
|
|
|
|
abs(ctx->mic.mv[0].as_mv.col) + abs(ctx->mic.mv[0].as_mv.row);
|
|
|
|
const int left_in_image = !!xd->left_mi;
|
|
|
|
const int above_in_image = !!xd->above_mi;
|
|
|
|
MODE_INFO **prev_mi =
|
|
|
|
&cm->prev_mi_grid_visible[mi_col + cm->mi_stride * mi_row];
|
|
|
|
int above_par = 0; // above_partitioning
|
|
|
|
int left_par = 0; // left_partitioning
|
|
|
|
int last_par = 0; // last_partitioning
|
|
|
|
BLOCK_SIZE context_size;
|
|
|
|
double score;
|
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
assert(b_width_log2_lookup[bsize] == b_height_log2_lookup[bsize]);
|
|
|
|
|
|
|
|
if (above_in_image) {
|
|
|
|
context_size = xd->above_mi->sb_type;
|
|
|
|
if (context_size < bsize)
|
|
|
|
above_par = 2;
|
|
|
|
else if (context_size == bsize)
|
|
|
|
above_par = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (left_in_image) {
|
|
|
|
context_size = xd->left_mi->sb_type;
|
|
|
|
if (context_size < bsize)
|
|
|
|
left_par = 2;
|
|
|
|
else if (context_size == bsize)
|
|
|
|
left_par = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prev_mi) {
|
|
|
|
context_size = prev_mi[0]->sb_type;
|
|
|
|
if (context_size < bsize)
|
|
|
|
last_par = 2;
|
|
|
|
else if (context_size == bsize)
|
|
|
|
last_par = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bsize == BLOCK_64X64)
|
|
|
|
offset = 0;
|
|
|
|
else if (bsize == BLOCK_32X32)
|
|
|
|
offset = 8;
|
|
|
|
else if (bsize == BLOCK_16X16)
|
|
|
|
offset = 16;
|
|
|
|
|
|
|
|
// early termination score calculation
|
|
|
|
clf = &classifiers[offset];
|
|
|
|
mean = &train_mean[offset];
|
|
|
|
sd = &train_stdm[offset];
|
|
|
|
score = clf[0] * (((double)ctx->rate - mean[0]) / sd[0]) +
|
|
|
|
clf[1] * (((double)ctx->dist - mean[1]) / sd[1]) +
|
|
|
|
clf[2] * (((double)mag_mv / 2 - mean[2]) * sd[2]) +
|
|
|
|
clf[3] * (((double)(left_par + above_par) / 2 - mean[3]) * sd[3]) +
|
|
|
|
clf[4] * (((double)ctx->sum_y_eobs - mean[4]) / sd[4]) +
|
|
|
|
clf[5] * (((double)cm->base_qindex - mean[5]) * sd[5]) +
|
|
|
|
clf[6] * (((double)last_par - mean[6]) * sd[6]) + clf[7];
|
|
|
|
return score;
|
|
|
|
}
|
|
|
|
|
2013-05-08 23:24:43 +02:00
|
|
|
// TODO(jingning,jimbankoski,rbultje): properly skip partition types that are
|
2013-08-01 18:04:15 +02:00
|
|
|
// unlikely to be selected depending on previous rate-distortion optimization
|
2013-05-08 23:24:43 +02:00
|
|
|
// results, for encoding speed-up.
|
2014-11-21 20:11:06 +01:00
|
|
|
static void rd_pick_partition(VP9_COMP *cpi, ThreadData *td,
|
2016-07-27 05:43:23 +02:00
|
|
|
TileDataEnc *tile_data, TOKENEXTRA **tp,
|
|
|
|
int mi_row, int mi_col, BLOCK_SIZE bsize,
|
|
|
|
RD_COST *rd_cost, int64_t best_rd,
|
|
|
|
PC_TREE *pc_tree) {
|
2013-11-12 00:58:57 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-10-27 19:11:50 +01:00
|
|
|
TileInfo *const tile_info = &tile_data->tile_info;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-03-21 00:08:54 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2014-03-21 22:24:03 +01:00
|
|
|
const int mi_step = num_8x8_blocks_wide_lookup[bsize] / 2;
|
2013-06-19 23:26:49 +02:00
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
|
2013-05-08 23:24:43 +02:00
|
|
|
PARTITION_CONTEXT sl[8], sa[8];
|
|
|
|
TOKENEXTRA *tp_orig = *tp;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx = &pc_tree->none;
|
2016-03-01 00:20:12 +01:00
|
|
|
int i;
|
|
|
|
const int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2013-08-27 20:05:08 +02:00
|
|
|
BLOCK_SIZE subsize;
|
2014-10-14 19:26:28 +02:00
|
|
|
RD_COST this_rdc, sum_rdc, best_rdc;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
int do_split = bsize >= BLOCK_8X8;
|
|
|
|
int do_rect = 1;
|
2016-07-21 20:47:51 +02:00
|
|
|
INTERP_FILTER pred_interp_filter;
|
2014-08-05 23:39:06 +02:00
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// Override skipping rectangular partition operations for edge blocks
|
2014-03-21 22:24:03 +01:00
|
|
|
const int force_horz_split = (mi_row + mi_step >= cm->mi_rows);
|
|
|
|
const int force_vert_split = (mi_col + mi_step >= cm->mi_cols);
|
2013-12-02 21:54:21 +01:00
|
|
|
const int xss = x->e_mbd.plane[1].subsampling_x;
|
|
|
|
const int yss = x->e_mbd.plane[1].subsampling_y;
|
Speed feature to skip split partition based on var
Adds a speed feature to disable split partition search based on a
given threshold on the source variance. A tighter threshold derived
from the threshold provided is used to also disable horizontal and
vertical partitions.
Results on derfraw300:
threshold = 16, psnr = -0.057%, speedup ~1% (football)
threshold = 32, psnr = -0.150%, speedup ~4-5% (football)
threshold = 64, psnr = -0.570%, speedup ~10-12% (football)
Results on stdhdraw250:
threshold = 32, psnr = -0.18%, speedup is somewhat more than derf
because of a larger number of smoother blocks at higher resolution.
Based on these results, a threshold of 32 is chosen for speed 1,
and a threshold of 64 is chosen for speeds 2 and above.
Change-Id: If08912fb6c67fd4242d12a0d094783a99f52f6c6
2013-08-03 02:15:38 +02:00
|
|
|
|
2014-11-20 18:24:50 +01:00
|
|
|
BLOCK_SIZE min_size = x->min_partition_size;
|
|
|
|
BLOCK_SIZE max_size = x->max_partition_size;
|
2014-07-29 20:03:00 +02:00
|
|
|
|
2014-08-05 23:39:06 +02:00
|
|
|
#if CONFIG_FP_MB_STATS
|
|
|
|
unsigned int src_diff_var = UINT_MAX;
|
|
|
|
int none_complexity = 0;
|
|
|
|
#endif
|
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
int partition_none_allowed = !force_horz_split && !force_vert_split;
|
2016-07-27 05:43:23 +02:00
|
|
|
int partition_horz_allowed =
|
|
|
|
!force_vert_split && yss <= xss && bsize >= BLOCK_8X8;
|
|
|
|
int partition_vert_allowed =
|
|
|
|
!force_horz_split && xss <= yss && bsize >= BLOCK_8X8;
|
2015-09-23 12:13:52 +02:00
|
|
|
|
2017-03-08 21:24:15 +01:00
|
|
|
int64_t dist_breakout_thr = cpi->sf.partition_search_breakout_thr.dist;
|
|
|
|
int rate_breakout_thr = cpi->sf.partition_search_breakout_thr.rate;
|
2015-09-23 12:13:52 +02:00
|
|
|
|
|
|
|
(void)*tp_orig;
|
2013-07-10 23:27:20 +02:00
|
|
|
|
2013-11-06 22:34:23 +01:00
|
|
|
assert(num_8x8_blocks_wide_lookup[bsize] ==
|
2016-07-27 05:43:23 +02:00
|
|
|
num_8x8_blocks_high_lookup[bsize]);
|
2013-05-08 23:24:43 +02:00
|
|
|
|
2015-09-23 12:13:52 +02:00
|
|
|
// Adjust dist breakout threshold according to the partition size.
|
2016-07-27 05:43:23 +02:00
|
|
|
dist_breakout_thr >>=
|
|
|
|
8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
|
2015-09-23 12:13:52 +02:00
|
|
|
rate_breakout_thr *= num_pels_log2_lookup[bsize];
|
|
|
|
|
2014-10-14 19:26:28 +02:00
|
|
|
vp9_rd_cost_init(&this_rdc);
|
|
|
|
vp9_rd_cost_init(&sum_rdc);
|
|
|
|
vp9_rd_cost_reset(&best_rdc);
|
|
|
|
best_rdc.rdcost = best_rd;
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
|
2014-07-31 20:50:00 +02:00
|
|
|
|
2016-07-19 00:44:40 +02:00
|
|
|
if (bsize == BLOCK_16X16 && cpi->oxcf.aq_mode != NO_AQ &&
|
|
|
|
cpi->oxcf.aq_mode != LOOKAHEAD_AQ)
|
2013-10-07 20:20:10 +02:00
|
|
|
x->mb_energy = vp9_block_energy(cpi, x, bsize);
|
2014-07-29 18:50:03 +02:00
|
|
|
|
|
|
|
if (cpi->sf.cb_partition_search && bsize == BLOCK_16X16) {
|
2016-07-27 05:43:23 +02:00
|
|
|
int cb_partition_search_ctrl =
|
|
|
|
((pc_tree->index == 0 || pc_tree->index == 3) +
|
|
|
|
get_chessboard_index(cm->current_video_frame)) &
|
|
|
|
0x1;
|
2014-07-29 18:50:03 +02:00
|
|
|
|
|
|
|
if (cb_partition_search_ctrl && bsize > min_size && bsize < max_size)
|
|
|
|
set_partition_range(cm, xd, mi_row, mi_col, bsize, &min_size, &max_size);
|
|
|
|
}
|
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// Determine partition types in search according to the speed features.
|
|
|
|
// The threshold set here has to be of square block size.
|
|
|
|
if (cpi->sf.auto_min_max_partition_size) {
|
2014-07-29 20:03:00 +02:00
|
|
|
partition_none_allowed &= (bsize <= max_size && bsize >= min_size);
|
2016-07-27 05:43:23 +02:00
|
|
|
partition_horz_allowed &=
|
|
|
|
((bsize <= max_size && bsize > min_size) || force_horz_split);
|
|
|
|
partition_vert_allowed &=
|
|
|
|
((bsize <= max_size && bsize > min_size) || force_vert_split);
|
2014-07-29 20:03:00 +02:00
|
|
|
do_split &= bsize > min_size;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
2015-09-23 12:13:52 +02:00
|
|
|
|
2015-10-15 20:33:41 +02:00
|
|
|
if (cpi->sf.use_square_partition_only &&
|
|
|
|
bsize > cpi->sf.use_square_only_threshold) {
|
2015-11-25 01:40:27 +01:00
|
|
|
if (cpi->use_svc) {
|
|
|
|
if (!vp9_active_h_edge(cpi, mi_row, mi_step) || x->e_mbd.lossless)
|
|
|
|
partition_horz_allowed &= force_horz_split;
|
|
|
|
if (!vp9_active_v_edge(cpi, mi_row, mi_step) || x->e_mbd.lossless)
|
|
|
|
partition_vert_allowed &= force_vert_split;
|
|
|
|
} else {
|
2015-09-23 12:13:52 +02:00
|
|
|
partition_horz_allowed &= force_horz_split;
|
|
|
|
partition_vert_allowed &= force_vert_split;
|
2015-11-25 01:40:27 +01:00
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
save_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-05-08 23:24:43 +02:00
|
|
|
|
2014-08-05 23:39:06 +02:00
|
|
|
#if CONFIG_FP_MB_STATS
|
|
|
|
if (cpi->use_fp_mb_stats) {
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
|
2016-07-27 05:43:23 +02:00
|
|
|
src_diff_var = get_sby_perpixel_diff_variance(cpi, &x->plane[0].src, mi_row,
|
|
|
|
mi_col, bsize);
|
2014-08-05 23:39:06 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if CONFIG_FP_MB_STATS
|
|
|
|
// Decide whether we shall split directly and skip searching NONE by using
|
|
|
|
// the first pass block statistics
|
|
|
|
if (cpi->use_fp_mb_stats && bsize >= BLOCK_32X32 && do_split &&
|
|
|
|
partition_none_allowed && src_diff_var > 4 &&
|
|
|
|
cm->base_qindex < qindex_split_threshold_lookup[bsize]) {
|
|
|
|
int mb_row = mi_row >> 1;
|
|
|
|
int mb_col = mi_col >> 1;
|
|
|
|
int mb_row_end =
|
2015-08-18 03:19:22 +02:00
|
|
|
VPXMIN(mb_row + num_16x16_blocks_high_lookup[bsize], cm->mb_rows);
|
2014-08-05 23:39:06 +02:00
|
|
|
int mb_col_end =
|
2015-08-18 03:19:22 +02:00
|
|
|
VPXMIN(mb_col + num_16x16_blocks_wide_lookup[bsize], cm->mb_cols);
|
2014-08-05 23:39:06 +02:00
|
|
|
int r, c;
|
|
|
|
|
|
|
|
// compute a complexity measure, basically measure inconsistency of motion
|
|
|
|
// vectors obtained from the first pass in the current block
|
2016-07-27 05:43:23 +02:00
|
|
|
for (r = mb_row; r < mb_row_end; r++) {
|
2014-08-05 23:39:06 +02:00
|
|
|
for (c = mb_col; c < mb_col_end; c++) {
|
|
|
|
const int mb_index = r * cm->mb_cols + c;
|
|
|
|
|
|
|
|
MOTION_DIRECTION this_mv;
|
|
|
|
MOTION_DIRECTION right_mv;
|
|
|
|
MOTION_DIRECTION bottom_mv;
|
|
|
|
|
|
|
|
this_mv =
|
|
|
|
get_motion_direction_fp(cpi->twopass.this_frame_mb_stats[mb_index]);
|
|
|
|
|
|
|
|
// to its right
|
|
|
|
if (c != mb_col_end - 1) {
|
|
|
|
right_mv = get_motion_direction_fp(
|
|
|
|
cpi->twopass.this_frame_mb_stats[mb_index + 1]);
|
|
|
|
none_complexity += get_motion_inconsistency(this_mv, right_mv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// to its bottom
|
|
|
|
if (r != mb_row_end - 1) {
|
|
|
|
bottom_mv = get_motion_direction_fp(
|
|
|
|
cpi->twopass.this_frame_mb_stats[mb_index + cm->mb_cols]);
|
|
|
|
none_complexity += get_motion_inconsistency(this_mv, bottom_mv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// do not count its left and top neighbors to avoid double counting
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (none_complexity > complexity_16x16_blocks_threshold[bsize]) {
|
|
|
|
partition_none_allowed = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// PARTITION_NONE
|
|
|
|
if (partition_none_allowed) {
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &this_rdc, bsize, ctx,
|
|
|
|
best_rdc.rdcost);
|
2014-10-09 21:32:56 +02:00
|
|
|
if (this_rdc.rate != INT_MAX) {
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
if (bsize >= BLOCK_8X8) {
|
2014-10-09 21:32:56 +02:00
|
|
|
this_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE];
|
2016-07-27 05:43:23 +02:00
|
|
|
this_rdc.rdcost =
|
|
|
|
RDCOST(x->rdmult, x->rddiv, this_rdc.rate, this_rdc.dist);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
2014-08-05 23:39:06 +02:00
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
if (this_rdc.rdcost < best_rdc.rdcost) {
|
2017-03-16 23:45:07 +01:00
|
|
|
MODE_INFO *mi = xd->mi[0];
|
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
best_rdc = this_rdc;
|
2016-07-27 05:43:23 +02:00
|
|
|
if (bsize >= BLOCK_8X8) pc_tree->partitioning = PARTITION_NONE;
|
2013-09-07 01:59:55 +02:00
|
|
|
|
2017-02-27 23:26:15 +01:00
|
|
|
if (!cpi->sf.ml_partition_search_early_termination) {
|
|
|
|
// If all y, u, v transform blocks in this partition are skippable,
|
|
|
|
// and the dist & rate are within the thresholds, the partition search
|
|
|
|
// is terminated for current branch of the partition search tree.
|
|
|
|
if (!x->e_mbd.lossless && ctx->skippable &&
|
|
|
|
((best_rdc.dist < (dist_breakout_thr >> 2)) ||
|
|
|
|
(best_rdc.dist < dist_breakout_thr &&
|
|
|
|
best_rdc.rate < rate_breakout_thr))) {
|
|
|
|
do_split = 0;
|
|
|
|
do_rect = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Currently, the machine-learning based partition search early
|
|
|
|
// termination is only used while bsize is 16x16, 32x32 or 64x64,
|
|
|
|
// VPXMIN(cm->width, cm->height) >= 480, and speed = 0.
|
2017-03-16 23:45:07 +01:00
|
|
|
if (!x->e_mbd.lossless &&
|
|
|
|
!segfeature_active(&cm->seg, mi->segment_id, SEG_LVL_SKIP) &&
|
|
|
|
ctx->mic.mode >= INTRA_MODES && bsize >= BLOCK_16X16) {
|
2017-03-21 17:47:55 +01:00
|
|
|
if (compute_score(cm, xd, ctx, mi_row, mi_col, bsize) < 0.0) {
|
2017-02-27 23:26:15 +01:00
|
|
|
do_split = 0;
|
|
|
|
do_rect = 0;
|
|
|
|
}
|
|
|
|
}
|
2013-09-07 01:59:55 +02:00
|
|
|
}
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
|
|
|
|
#if CONFIG_FP_MB_STATS
|
|
|
|
// Check if every 16x16 first pass block statistics has zero
|
|
|
|
// motion and the corresponding first pass residue is small enough.
|
|
|
|
// If that is the case, check the difference variance between the
|
|
|
|
// current frame and the last frame. If the variance is small enough,
|
|
|
|
// stop further splitting in RD optimization
|
|
|
|
if (cpi->use_fp_mb_stats && do_split != 0 &&
|
|
|
|
cm->base_qindex > qindex_skip_threshold_lookup[bsize]) {
|
|
|
|
int mb_row = mi_row >> 1;
|
|
|
|
int mb_col = mi_col >> 1;
|
|
|
|
int mb_row_end =
|
2015-08-18 03:19:22 +02:00
|
|
|
VPXMIN(mb_row + num_16x16_blocks_high_lookup[bsize], cm->mb_rows);
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
int mb_col_end =
|
2015-08-18 03:19:22 +02:00
|
|
|
VPXMIN(mb_col + num_16x16_blocks_wide_lookup[bsize], cm->mb_cols);
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
int r, c;
|
|
|
|
|
|
|
|
int skip = 1;
|
|
|
|
for (r = mb_row; r < mb_row_end; r++) {
|
|
|
|
for (c = mb_col; c < mb_col_end; c++) {
|
|
|
|
const int mb_index = r * cm->mb_cols + c;
|
2014-07-31 18:01:06 +02:00
|
|
|
if (!(cpi->twopass.this_frame_mb_stats[mb_index] &
|
|
|
|
FPMB_MOTION_ZERO_MASK) ||
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
!(cpi->twopass.this_frame_mb_stats[mb_index] &
|
2014-07-31 18:01:06 +02:00
|
|
|
FPMB_ERROR_SMALL_MASK)) {
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
skip = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (skip == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-06-22 21:20:06 +02:00
|
|
|
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
if (skip) {
|
2014-08-05 23:39:06 +02:00
|
|
|
if (src_diff_var == UINT_MAX) {
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
|
2014-08-05 23:39:06 +02:00
|
|
|
src_diff_var = get_sby_perpixel_diff_variance(
|
2014-11-21 20:11:06 +01:00
|
|
|
cpi, &x->plane[0].src, mi_row, mi_col, bsize);
|
2014-08-05 23:39:06 +02:00
|
|
|
}
|
|
|
|
if (src_diff_var < 8) {
|
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition
SPLIT, HORZ, VERT after the search for partition NONE is done
in RD optimization. It uses the first pass block-wise statistics
to make the decision. If all 16x16 blocks in the current partition
have zero motions and small residues from the frist pass statistics,
and it has small difference variance, further partition search is
skipped.
For speed 2 setting, experiments on general youtube clips show that
the speedup varies from 1% - 10%, 5% on average. On the performance
side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%.
For hard stdhd clips:
park_joy_1080p, 502952 ms -> 503307 ms (-0.07%)
pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%)
This feature is under the compilation flag CONFIG_FP_MB_STATS and
it is off in current setting.
Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
2014-07-30 04:49:47 +02:00
|
|
|
do_split = 0;
|
|
|
|
do_rect = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
|
|
|
}
|
2014-11-21 20:11:06 +01:00
|
|
|
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2013-09-12 19:06:47 +02:00
|
|
|
// store estimated motion vector
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search) store_pred_mv(x, ctx);
|
2013-09-12 19:06:47 +02:00
|
|
|
|
2016-07-09 18:47:34 +02:00
|
|
|
// If the interp_filter is marked as SWITCHABLE_FILTERS, it was for an
|
|
|
|
// intra block and used for context purposes.
|
|
|
|
if (ctx->mic.interp_filter == SWITCHABLE_FILTERS) {
|
2016-07-21 20:47:51 +02:00
|
|
|
pred_interp_filter = EIGHTTAP;
|
|
|
|
} else {
|
|
|
|
pred_interp_filter = ctx->mic.interp_filter;
|
2016-07-09 18:47:34 +02:00
|
|
|
}
|
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// PARTITION_SPLIT
|
|
|
|
// TODO(jingning): use the motion vectors given by the above search as
|
|
|
|
// the starting point of motion search in the following partition type check.
|
|
|
|
if (do_split) {
|
|
|
|
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
if (bsize == BLOCK_8X8) {
|
|
|
|
i = 4;
|
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && partition_none_allowed)
|
2016-07-21 20:47:51 +02:00
|
|
|
pc_tree->leaf_split[0]->pred_interp_filter = pred_interp_filter;
|
2014-11-21 20:11:06 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc, subsize,
|
2014-10-09 21:32:56 +02:00
|
|
|
pc_tree->leaf_split[0], best_rdc.rdcost);
|
2016-06-22 21:20:06 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (sum_rdc.rate == INT_MAX) sum_rdc.rdcost = INT64_MAX;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
} else {
|
2014-10-09 21:32:56 +02:00
|
|
|
for (i = 0; i < 4 && sum_rdc.rdcost < best_rdc.rdcost; ++i) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const int x_idx = (i & 1) * mi_step;
|
2016-06-22 21:20:06 +02:00
|
|
|
const int y_idx = (i >> 1) * mi_step;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
|
|
|
|
if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols)
|
|
|
|
continue;
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx);
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
|
2014-07-29 18:50:03 +02:00
|
|
|
pc_tree->split[i]->index = i;
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_partition(cpi, td, tile_data, tp, mi_row + y_idx,
|
|
|
|
mi_col + x_idx, subsize, &this_rdc,
|
2014-10-09 21:32:56 +02:00
|
|
|
best_rdc.rdcost - sum_rdc.rdcost, pc_tree->split[i]);
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
if (this_rdc.rate == INT_MAX) {
|
|
|
|
sum_rdc.rdcost = INT64_MAX;
|
|
|
|
break;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
} else {
|
2014-10-09 21:32:56 +02:00
|
|
|
sum_rdc.rate += this_rdc.rate;
|
|
|
|
sum_rdc.dist += this_rdc.dist;
|
|
|
|
sum_rdc.rdcost += this_rdc.rdcost;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
}
|
2013-07-17 18:56:46 +02:00
|
|
|
}
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
2014-04-17 23:44:02 +02:00
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost && i == 4) {
|
|
|
|
sum_rdc.rate += cpi->partition_cost[pl][PARTITION_SPLIT];
|
2016-07-27 05:43:23 +02:00
|
|
|
sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
|
2014-08-05 23:39:06 +02:00
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost) {
|
|
|
|
best_rdc = sum_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = PARTITION_SPLIT;
|
2015-09-23 12:13:52 +02:00
|
|
|
|
|
|
|
// Rate and distortion based partition search termination clause.
|
2017-02-27 23:26:15 +01:00
|
|
|
if (!cpi->sf.ml_partition_search_early_termination &&
|
|
|
|
!x->e_mbd.lossless && ((best_rdc.dist < (dist_breakout_thr >> 2)) ||
|
2016-07-27 05:43:23 +02:00
|
|
|
(best_rdc.dist < dist_breakout_thr &&
|
|
|
|
best_rdc.rate < rate_breakout_thr))) {
|
2015-09-23 12:13:52 +02:00
|
|
|
do_rect = 0;
|
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
2013-09-30 20:58:22 +02:00
|
|
|
} else {
|
|
|
|
// skip rectangular partition test when larger block size
|
|
|
|
// gives better rd cost
|
2015-09-23 12:13:52 +02:00
|
|
|
if ((cpi->sf.less_rectangular_check) &&
|
|
|
|
((bsize > cpi->sf.use_square_only_threshold) ||
|
|
|
|
(best_rdc.dist < dist_breakout_thr)))
|
2013-09-30 20:58:22 +02:00
|
|
|
do_rect &= !partition_none_allowed;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
2014-11-21 20:11:06 +01:00
|
|
|
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-05-08 23:24:43 +02:00
|
|
|
}
|
2014-04-17 23:44:02 +02:00
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// PARTITION_HORZ
|
2015-06-24 12:36:51 +02:00
|
|
|
if (partition_horz_allowed &&
|
|
|
|
(do_rect || vp9_active_h_edge(cpi, mi_row, mi_step))) {
|
2015-09-23 12:13:52 +02:00
|
|
|
subsize = get_subsize(bsize, PARTITION_HORZ);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx);
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2016-07-21 20:47:51 +02:00
|
|
|
pc_tree->horizontal[0].pred_interp_filter = pred_interp_filter;
|
2014-11-21 20:11:06 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc, subsize,
|
2014-10-09 21:32:56 +02:00
|
|
|
&pc_tree->horizontal[0], best_rdc.rdcost);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
|
2014-10-09 21:32:56 +02:00
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost && mi_row + mi_step < cm->mi_rows &&
|
2014-10-09 04:34:00 +02:00
|
|
|
bsize > BLOCK_8X8) {
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx = &pc_tree->horizontal[0];
|
2014-11-21 20:11:06 +01:00
|
|
|
update_state(cpi, td, ctx, mi_row, mi_col, subsize, 0);
|
|
|
|
encode_superblock(cpi, td, tp, 0, mi_row, mi_col, subsize, ctx);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx);
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2016-07-21 20:47:51 +02:00
|
|
|
pc_tree->horizontal[1].pred_interp_filter = pred_interp_filter;
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row + mi_step, mi_col, &this_rdc,
|
|
|
|
subsize, &pc_tree->horizontal[1],
|
2014-10-09 21:32:56 +02:00
|
|
|
best_rdc.rdcost - sum_rdc.rdcost);
|
|
|
|
if (this_rdc.rate == INT_MAX) {
|
|
|
|
sum_rdc.rdcost = INT64_MAX;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
} else {
|
2014-10-09 21:32:56 +02:00
|
|
|
sum_rdc.rate += this_rdc.rate;
|
|
|
|
sum_rdc.dist += this_rdc.dist;
|
|
|
|
sum_rdc.rdcost += this_rdc.rdcost;
|
2013-06-20 18:24:04 +02:00
|
|
|
}
|
2013-04-17 18:25:06 +02:00
|
|
|
}
|
2014-10-09 21:32:56 +02:00
|
|
|
|
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost) {
|
|
|
|
sum_rdc.rate += cpi->partition_cost[pl][PARTITION_HORZ];
|
|
|
|
sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
|
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost) {
|
|
|
|
best_rdc = sum_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = PARTITION_HORZ;
|
2015-09-23 12:13:52 +02:00
|
|
|
|
|
|
|
if ((cpi->sf.less_rectangular_check) &&
|
|
|
|
(bsize > cpi->sf.use_square_only_threshold))
|
|
|
|
do_rect = 0;
|
2013-07-17 18:56:46 +02:00
|
|
|
}
|
|
|
|
}
|
2014-11-21 20:11:06 +01:00
|
|
|
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
2016-06-22 21:20:06 +02:00
|
|
|
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
// PARTITION_VERT
|
2015-06-24 12:36:51 +02:00
|
|
|
if (partition_vert_allowed &&
|
|
|
|
(do_rect || vp9_active_v_edge(cpi, mi_col, mi_step))) {
|
2015-09-23 12:13:52 +02:00
|
|
|
subsize = get_subsize(bsize, PARTITION_VERT);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx);
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2016-07-21 20:47:51 +02:00
|
|
|
pc_tree->vertical[0].pred_interp_filter = pred_interp_filter;
|
2014-11-21 20:11:06 +01:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc, subsize,
|
2014-10-09 21:32:56 +02:00
|
|
|
&pc_tree->vertical[0], best_rdc.rdcost);
|
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost && mi_col + mi_step < cm->mi_cols &&
|
2014-10-09 04:34:00 +02:00
|
|
|
bsize > BLOCK_8X8) {
|
2014-11-21 20:11:06 +01:00
|
|
|
update_state(cpi, td, &pc_tree->vertical[0], mi_row, mi_col, subsize, 0);
|
|
|
|
encode_superblock(cpi, td, tp, 0, mi_row, mi_col, subsize,
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
&pc_tree->vertical[0]);
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->sf.adaptive_motion_search) load_pred_mv(x, ctx);
|
2014-01-24 21:26:57 +01:00
|
|
|
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
|
2013-12-13 02:31:04 +01:00
|
|
|
partition_none_allowed)
|
2016-07-21 20:47:51 +02:00
|
|
|
pc_tree->vertical[1].pred_interp_filter = pred_interp_filter;
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + mi_step, &this_rdc,
|
|
|
|
subsize, &pc_tree->vertical[1],
|
|
|
|
best_rdc.rdcost - sum_rdc.rdcost);
|
2014-10-09 21:32:56 +02:00
|
|
|
if (this_rdc.rate == INT_MAX) {
|
|
|
|
sum_rdc.rdcost = INT64_MAX;
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
} else {
|
2014-10-09 21:32:56 +02:00
|
|
|
sum_rdc.rate += this_rdc.rate;
|
|
|
|
sum_rdc.dist += this_rdc.dist;
|
|
|
|
sum_rdc.rdcost += this_rdc.rdcost;
|
2013-06-27 21:07:07 +02:00
|
|
|
}
|
Refactor rd_pick_partition for parameter control
This commit changes the partition search order of superblocks from
{SPLIT, NONE, HORZ, VERT} to {NONE, SPLIT, HORZ, VERT} for
consistency with that of sub8x8 partition search. It enable the use
of early termination in partition search for all block sizes.
For ped_area_1080p 50 frames coded at 4000 kbps, it makes the runtime
goes down from 844305ms -> 818003ms (3% speed-up) at speed 0.
This will further move towards making the in-search partition types
configurable, hence unifying various speed-up approaches.
Some speed 1 and 2 features are turned off during the refactoring
process, including:
disable_split_var_thresh
using_small_partition_info
Stricter constraints are applied to use_square_partition_only for
right/bottom boundary blocks. Will bring back/refine these features
subsequently. At this point, it makes derf set at speed 1 about
0.45% higher in compression performance, and 9% down in run-time.
Change-Id: I3db9f9d1d1a0d6cbe2e50e49bd9eda1cf705f37c
2013-08-20 23:34:17 +02:00
|
|
|
}
|
2014-10-09 21:32:56 +02:00
|
|
|
|
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost) {
|
|
|
|
sum_rdc.rate += cpi->partition_cost[pl][PARTITION_VERT];
|
2016-07-27 05:43:23 +02:00
|
|
|
sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
|
2014-10-09 21:32:56 +02:00
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost) {
|
|
|
|
best_rdc = sum_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = PARTITION_VERT;
|
2013-06-27 21:07:07 +02:00
|
|
|
}
|
|
|
|
}
|
2014-11-21 20:11:06 +01:00
|
|
|
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
|
2013-05-08 23:24:43 +02:00
|
|
|
}
|
2014-08-05 23:39:06 +02:00
|
|
|
|
2014-02-12 20:54:04 +01:00
|
|
|
// TODO(jbb): This code added so that we avoid static analysis
|
|
|
|
// warning related to the fact that best_rd isn't used after this
|
|
|
|
// point. This code should be refactored so that the duplicate
|
|
|
|
// checks occur in some sub function and thus are used...
|
2016-07-27 05:43:23 +02:00
|
|
|
(void)best_rd;
|
2014-10-09 21:32:56 +02:00
|
|
|
*rd_cost = best_rdc;
|
|
|
|
|
|
|
|
if (best_rdc.rate < INT_MAX && best_rdc.dist < INT64_MAX &&
|
|
|
|
pc_tree->index != 3) {
|
2013-11-22 18:21:53 +01:00
|
|
|
int output_enabled = (bsize == BLOCK_64X64);
|
2016-07-27 05:43:23 +02:00
|
|
|
encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize,
|
|
|
|
pc_tree);
|
2013-11-22 18:21:53 +01:00
|
|
|
}
|
2014-04-17 23:44:02 +02:00
|
|
|
|
2013-08-06 00:23:49 +02:00
|
|
|
if (bsize == BLOCK_64X64) {
|
2013-05-08 23:24:43 +02:00
|
|
|
assert(tp_orig < *tp);
|
2014-10-09 21:32:56 +02:00
|
|
|
assert(best_rdc.rate < INT_MAX);
|
|
|
|
assert(best_rdc.dist < INT64_MAX);
|
2013-05-11 02:06:37 +02:00
|
|
|
} else {
|
2013-05-08 23:24:43 +02:00
|
|
|
assert(tp_orig == *tp);
|
2013-05-11 02:06:37 +02:00
|
|
|
}
|
2013-05-08 23:24:43 +02:00
|
|
|
}
|
2013-04-17 18:25:06 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void encode_rd_sb_row(VP9_COMP *cpi, ThreadData *td,
|
|
|
|
TileDataEnc *tile_data, int mi_row,
|
2014-10-27 19:11:50 +01:00
|
|
|
TOKENEXTRA **tp) {
|
2014-01-08 23:51:00 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-10-27 19:11:50 +01:00
|
|
|
TileInfo *const tile_info = &tile_data->tile_info;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-11-20 18:24:50 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2014-04-04 00:51:40 +02:00
|
|
|
SPEED_FEATURES *const sf = &cpi->sf;
|
2016-06-22 21:20:06 +02:00
|
|
|
const int mi_col_start = tile_info->mi_col_start;
|
|
|
|
const int mi_col_end = tile_info->mi_col_end;
|
2013-05-08 23:24:43 +02:00
|
|
|
int mi_col;
|
2017-02-10 11:55:50 +01:00
|
|
|
const int sb_row = mi_row >> MI_BLOCK_SIZE_LOG2;
|
|
|
|
const int num_sb_cols =
|
|
|
|
get_num_cols(tile_data->tile_info, MI_BLOCK_SIZE_LOG2);
|
|
|
|
int sb_col_in_tile;
|
2012-04-07 01:38:34 +02:00
|
|
|
|
2013-05-08 23:24:43 +02:00
|
|
|
// Initialize the left context for the new SB row
|
2015-04-24 05:47:40 +02:00
|
|
|
memset(&xd->left_context, 0, sizeof(xd->left_context));
|
|
|
|
memset(xd->left_seg_context, 0, sizeof(xd->left_seg_context));
|
2013-05-08 23:24:43 +02:00
|
|
|
|
|
|
|
// Code each SB in the row
|
2017-02-10 11:55:50 +01:00
|
|
|
for (mi_col = mi_col_start, sb_col_in_tile = 0; mi_col < mi_col_end;
|
|
|
|
mi_col += MI_BLOCK_SIZE, sb_col_in_tile++) {
|
2015-03-09 18:45:38 +01:00
|
|
|
const struct segmentation *const seg = &cm->seg;
|
2013-06-21 21:54:52 +02:00
|
|
|
int dummy_rate;
|
|
|
|
int64_t dummy_dist;
|
2014-10-09 21:32:56 +02:00
|
|
|
RD_COST dummy_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
int i;
|
2015-03-09 18:45:38 +01:00
|
|
|
int seg_skip = 0;
|
2014-02-24 23:05:06 +01:00
|
|
|
|
2014-09-24 19:24:18 +02:00
|
|
|
const int idx_str = cm->mi_stride * mi_row + mi_col;
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **mi = cm->mi_grid_visible + idx_str;
|
2014-09-24 19:24:18 +02:00
|
|
|
|
2017-02-10 11:55:50 +01:00
|
|
|
(*(cpi->row_mt_sync_read_ptr))(&tile_data->row_mt_sync, sb_row,
|
2017-03-28 20:27:31 +02:00
|
|
|
sb_col_in_tile);
|
2017-02-10 11:55:50 +01:00
|
|
|
|
2014-04-04 00:51:40 +02:00
|
|
|
if (sf->adaptive_pred_interp_filter) {
|
2016-07-27 05:43:23 +02:00
|
|
|
for (i = 0; i < 64; ++i) td->leaf_tree[i].pred_interp_filter = SWITCHABLE;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
|
|
|
|
for (i = 0; i < 64; ++i) {
|
2014-11-21 20:11:06 +01:00
|
|
|
td->pc_tree[i].vertical[0].pred_interp_filter = SWITCHABLE;
|
|
|
|
td->pc_tree[i].vertical[1].pred_interp_filter = SWITCHABLE;
|
|
|
|
td->pc_tree[i].horizontal[0].pred_interp_filter = SWITCHABLE;
|
|
|
|
td->pc_tree[i].horizontal[1].pred_interp_filter = SWITCHABLE;
|
2014-02-24 23:05:06 +01:00
|
|
|
}
|
2013-12-13 02:31:04 +01:00
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
vp9_zero(x->pred_mv);
|
|
|
|
td->pc_root->index = 0;
|
2013-09-16 21:44:50 +02:00
|
|
|
|
2015-03-09 18:45:38 +01:00
|
|
|
if (seg->enabled) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const uint8_t *const map =
|
|
|
|
seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
|
2015-06-16 02:30:54 +02:00
|
|
|
int segment_id = get_segment_id(cm, map, BLOCK_64X64, mi_row, mi_col);
|
2015-06-11 13:20:55 +02:00
|
|
|
seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
|
2015-03-09 18:45:38 +01:00
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
x->source_variance = UINT_MAX;
|
2015-03-09 18:45:38 +01:00
|
|
|
if (sf->partition_search_type == FIXED_PARTITION || seg_skip) {
|
|
|
|
const BLOCK_SIZE bsize =
|
|
|
|
seg_skip ? BLOCK_64X64 : sf->always_this_block_size;
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, BLOCK_64X64);
|
2015-03-09 18:45:38 +01:00
|
|
|
set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, BLOCK_64X64,
|
|
|
|
&dummy_rate, &dummy_dist, 1, td->pc_root);
|
2014-10-16 00:45:27 +02:00
|
|
|
} else if (cpi->partition_search_skippable_frame) {
|
2014-09-24 19:24:18 +02:00
|
|
|
BLOCK_SIZE bsize;
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, BLOCK_64X64);
|
|
|
|
bsize = get_rd_var_based_fixed_partition(cpi, x, mi_row, mi_col);
|
2014-10-27 19:11:50 +01:00
|
|
|
set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, BLOCK_64X64,
|
|
|
|
&dummy_rate, &dummy_dist, 1, td->pc_root);
|
2014-10-16 00:45:27 +02:00
|
|
|
} else if (sf->partition_search_type == VAR_BASED_PARTITION &&
|
2014-11-12 23:51:49 +01:00
|
|
|
cm->frame_type != KEY_FRAME) {
|
2014-11-21 20:11:06 +01:00
|
|
|
choose_partitioning(cpi, tile_info, x, mi_row, mi_col);
|
2016-07-27 05:43:23 +02:00
|
|
|
rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, BLOCK_64X64,
|
|
|
|
&dummy_rate, &dummy_dist, 1, td->pc_root);
|
2013-06-20 16:17:01 +02:00
|
|
|
} else {
|
2013-07-24 15:07:37 +02:00
|
|
|
// If required set upper and lower partition size limits
|
2014-04-04 00:51:40 +02:00
|
|
|
if (sf->auto_min_max_partition_size) {
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, BLOCK_64X64);
|
|
|
|
rd_auto_partition_range(cpi, tile_info, xd, mi_row, mi_col,
|
2016-07-27 05:43:23 +02:00
|
|
|
&x->min_partition_size, &x->max_partition_size);
|
2013-07-24 15:07:37 +02:00
|
|
|
}
|
2014-11-21 20:11:06 +01:00
|
|
|
rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, BLOCK_64X64,
|
|
|
|
&dummy_rdc, INT64_MAX, td->pc_root);
|
2013-05-31 00:13:08 +02:00
|
|
|
}
|
2017-02-10 11:55:50 +01:00
|
|
|
(*(cpi->row_mt_sync_write_ptr))(&tile_data->row_mt_sync, sb_row,
|
|
|
|
sb_col_in_tile, num_sb_cols);
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2011-09-30 17:45:16 +02:00
|
|
|
}
|
|
|
|
|
2012-10-31 01:53:32 +01:00
|
|
|
static void init_encode_frame_mb_context(VP9_COMP *cpi) {
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &cpi->td.mb;
|
2013-07-08 23:54:04 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
|
|
|
const int aligned_mi_cols = mi_cols_aligned_to_sb(cm->mi_cols);
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2012-07-14 00:21:29 +02:00
|
|
|
// Copy data over into macro block data structures.
|
2013-04-24 01:22:47 +02:00
|
|
|
vp9_setup_src_planes(x, cpi->Source, 0, 0);
|
2013-04-20 04:16:14 +02:00
|
|
|
|
2014-02-01 02:35:53 +01:00
|
|
|
vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
|
2011-06-08 17:00:59 +02:00
|
|
|
|
2013-04-29 19:37:25 +02:00
|
|
|
// Note: this memset assumes above_context[0], [1] and [2]
|
|
|
|
// are allocated as part of the same buffer.
|
2015-04-24 05:47:40 +02:00
|
|
|
memset(xd->above_context[0], 0,
|
2016-07-27 05:43:23 +02:00
|
|
|
sizeof(*xd->above_context[0]) * 2 * aligned_mi_cols * MAX_MB_PLANE);
|
2015-04-24 05:47:40 +02:00
|
|
|
memset(xd->above_seg_context, 0,
|
|
|
|
sizeof(*xd->above_seg_context) * aligned_mi_cols);
|
2011-06-08 17:00:59 +02:00
|
|
|
}
|
2013-02-20 16:27:35 +01:00
|
|
|
|
2012-10-31 01:53:32 +01:00
|
|
|
static int check_dual_ref_flags(VP9_COMP *cpi) {
|
2013-08-14 20:20:33 +02:00
|
|
|
const int ref_flags = cpi->ref_frame_flags;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2015-06-11 13:20:55 +02:00
|
|
|
if (segfeature_active(&cpi->common.seg, 1, SEG_LVL_REF_FRAME)) {
|
2012-07-14 00:21:29 +02:00
|
|
|
return 0;
|
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
return (!!(ref_flags & VP9_GOLD_FLAG) + !!(ref_flags & VP9_LAST_FLAG) +
|
|
|
|
!!(ref_flags & VP9_ALT_FLAG)) >= 2;
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2012-03-22 18:03:14 +01:00
|
|
|
}
|
|
|
|
|
2014-06-12 20:57:26 +02:00
|
|
|
static void reset_skip_tx_size(VP9_COMMON *cm, TX_SIZE max_tx_size) {
|
2013-04-26 20:57:17 +02:00
|
|
|
int mi_row, mi_col;
|
2014-04-02 01:18:47 +02:00
|
|
|
const int mis = cm->mi_stride;
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **mi_ptr = cm->mi_grid_visible;
|
2012-10-12 03:19:20 +02:00
|
|
|
|
2014-03-24 16:51:45 +01:00
|
|
|
for (mi_row = 0; mi_row < cm->mi_rows; ++mi_row, mi_ptr += mis) {
|
|
|
|
for (mi_col = 0; mi_col < cm->mi_cols; ++mi_col) {
|
2016-01-20 01:40:20 +01:00
|
|
|
if (mi_ptr[mi_col]->tx_size > max_tx_size)
|
|
|
|
mi_ptr[mi_col]->tx_size = max_tx_size;
|
2013-09-11 19:45:44 +02:00
|
|
|
}
|
2012-10-12 03:19:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-10 18:38:25 +01:00
|
|
|
static MV_REFERENCE_FRAME get_frame_type(const VP9_COMP *cpi) {
|
2013-10-03 18:07:24 +02:00
|
|
|
if (frame_is_intra_only(&cpi->common))
|
2014-01-31 20:08:27 +01:00
|
|
|
return INTRA_FRAME;
|
2013-12-13 18:32:05 +01:00
|
|
|
else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
|
2014-01-31 20:08:27 +01:00
|
|
|
return ALTREF_FRAME;
|
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 (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
|
2014-01-31 20:08:27 +01:00
|
|
|
return GOLDEN_FRAME;
|
2014-07-22 21:12:16 +02:00
|
|
|
else
|
|
|
|
return LAST_FRAME;
|
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
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static TX_MODE select_tx_mode(const VP9_COMP *cpi, MACROBLOCKD *const xd) {
|
2016-07-27 05:43:23 +02:00
|
|
|
if (xd->lossless) return ONLY_4X4;
|
|
|
|
if (cpi->common.frame_type == KEY_FRAME && cpi->sf.use_nonrd_pick_mode)
|
2015-02-04 02:50:48 +01:00
|
|
|
return ALLOW_16X16;
|
2014-08-13 19:43:43 +02:00
|
|
|
if (cpi->sf.tx_size_search_method == USE_LARGESTALL)
|
|
|
|
return ALLOW_32X32;
|
2016-07-27 05:43:23 +02:00
|
|
|
else if (cpi->sf.tx_size_search_method == USE_FULL_RD ||
|
2014-08-13 19:43:43 +02:00
|
|
|
cpi->sf.tx_size_search_method == USE_TX_8X8)
|
|
|
|
return TX_MODE_SELECT;
|
|
|
|
else
|
|
|
|
return cpi->common.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
|
|
|
}
|
2014-02-12 21:48:15 +01:00
|
|
|
|
2014-12-04 18:29:24 +01:00
|
|
|
static void hybrid_intra_mode_search(VP9_COMP *cpi, MACROBLOCK *const x,
|
|
|
|
RD_COST *rd_cost, BLOCK_SIZE bsize,
|
|
|
|
PICK_MODE_CONTEXT *ctx) {
|
2017-10-12 02:13:39 +02:00
|
|
|
if (!cpi->sf.nonrd_keyframe && bsize < BLOCK_16X16)
|
2014-12-04 18:29:24 +01:00
|
|
|
vp9_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, INT64_MAX);
|
|
|
|
else
|
|
|
|
vp9_pick_intra_mode(cpi, x, rd_cost, bsize, ctx);
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void nonrd_pick_sb_modes(VP9_COMP *cpi, TileDataEnc *tile_data,
|
|
|
|
MACROBLOCK *const x, int mi_row, int mi_col,
|
|
|
|
RD_COST *rd_cost, BLOCK_SIZE bsize,
|
|
|
|
PICK_MODE_CONTEXT *ctx) {
|
2014-01-29 17:39:39 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-10-27 19:11:50 +01:00
|
|
|
TileInfo *const tile_info = &tile_data->tile_info;
|
2014-03-04 20:15:35 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2016-01-20 01:40:20 +01:00
|
|
|
MODE_INFO *mi;
|
2016-02-11 21:36:49 +01:00
|
|
|
ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE];
|
|
|
|
BLOCK_SIZE bs = VPXMAX(bsize, BLOCK_8X8); // processing unit block size
|
|
|
|
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bs];
|
|
|
|
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bs];
|
|
|
|
int plane;
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, bsize);
|
2016-01-20 01:40:20 +01:00
|
|
|
mi = xd->mi[0];
|
|
|
|
mi->sb_type = bsize;
|
2014-03-19 19:25:40 +01:00
|
|
|
|
2016-02-11 21:36:49 +01:00
|
|
|
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
|
|
|
struct macroblockd_plane *pd = &xd->plane[plane];
|
|
|
|
memcpy(a + num_4x4_blocks_wide * plane, pd->above_context,
|
|
|
|
(sizeof(a[0]) * num_4x4_blocks_wide) >> pd->subsampling_x);
|
|
|
|
memcpy(l + num_4x4_blocks_high * plane, pd->left_context,
|
|
|
|
(sizeof(l[0]) * num_4x4_blocks_high) >> pd->subsampling_y);
|
|
|
|
}
|
|
|
|
|
2014-06-30 18:49:48 +02:00
|
|
|
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled)
|
2016-01-20 01:40:20 +01:00
|
|
|
if (cyclic_refresh_segment_id_boosted(mi->segment_id))
|
2014-04-17 18:58:17 +02:00
|
|
|
x->rdmult = vp9_cyclic_refresh_get_rdmult(cpi->cyclic_refresh);
|
|
|
|
|
2014-11-20 20:28:00 +01:00
|
|
|
if (cm->frame_type == KEY_FRAME)
|
2014-12-04 18:29:24 +01:00
|
|
|
hybrid_intra_mode_search(cpi, x, rd_cost, bsize, ctx);
|
2016-01-20 01:40:20 +01:00
|
|
|
else if (segfeature_active(&cm->seg, mi->segment_id, SEG_LVL_SKIP))
|
2014-10-22 01:31:37 +02:00
|
|
|
set_mode_info_seg_skip(x, cm->tx_mode, rd_cost, bsize);
|
2014-12-22 22:38:34 +01:00
|
|
|
else if (bsize >= BLOCK_8X8)
|
2016-07-27 05:43:23 +02:00
|
|
|
vp9_pick_inter_mode(cpi, x, tile_data, mi_row, mi_col, rd_cost, bsize, ctx);
|
2014-12-22 22:38:34 +01:00
|
|
|
else
|
2016-07-27 05:43:23 +02:00
|
|
|
vp9_pick_inter_mode_sub8x8(cpi, x, mi_row, mi_col, rd_cost, bsize, ctx);
|
2014-06-30 18:49:48 +02:00
|
|
|
|
2014-03-21 19:05:39 +01:00
|
|
|
duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
|
2014-10-22 01:31:37 +02:00
|
|
|
|
2016-02-11 21:36:49 +01:00
|
|
|
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
|
|
|
|
struct macroblockd_plane *pd = &xd->plane[plane];
|
|
|
|
memcpy(pd->above_context, a + num_4x4_blocks_wide * plane,
|
|
|
|
(sizeof(a[0]) * num_4x4_blocks_wide) >> pd->subsampling_x);
|
|
|
|
memcpy(pd->left_context, l + num_4x4_blocks_high * plane,
|
|
|
|
(sizeof(l[0]) * num_4x4_blocks_high) >> pd->subsampling_y);
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (rd_cost->rate == INT_MAX) vp9_rd_cost_reset(rd_cost);
|
2014-11-04 23:32:04 +01:00
|
|
|
|
|
|
|
ctx->rate = rd_cost->rate;
|
|
|
|
ctx->dist = rd_cost->dist;
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void fill_mode_info_sb(VP9_COMMON *cm, MACROBLOCK *x, int mi_row,
|
|
|
|
int mi_col, BLOCK_SIZE bsize, PC_TREE *pc_tree) {
|
2014-03-21 19:05:39 +01:00
|
|
|
MACROBLOCKD *xd = &x->e_mbd;
|
2014-10-07 21:30:33 +02:00
|
|
|
int bsl = b_width_log2_lookup[bsize], hbs = (1 << bsl) / 4;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
PARTITION_TYPE partition = pc_tree->partitioning;
|
2015-02-09 18:48:44 +01:00
|
|
|
BLOCK_SIZE subsize = get_subsize(bsize, partition);
|
2014-03-21 19:05:39 +01:00
|
|
|
|
|
|
|
assert(bsize >= BLOCK_8X8);
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
2014-03-25 19:05:50 +01:00
|
|
|
|
2014-03-21 19:05:39 +01:00
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2015-06-29 18:27:11 +02:00
|
|
|
set_mode_info_offsets(cm, x, xd, mi_row, mi_col);
|
2015-04-21 14:36:58 +02:00
|
|
|
*(xd->mi[0]) = pc_tree->none.mic;
|
2015-06-29 18:27:11 +02:00
|
|
|
*(x->mbmi_ext) = pc_tree->none.mbmi_ext;
|
2014-03-21 19:05:39 +01:00
|
|
|
duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, bsize);
|
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
2015-06-29 18:27:11 +02:00
|
|
|
set_mode_info_offsets(cm, x, xd, mi_row, mi_col);
|
2015-04-21 14:36:58 +02:00
|
|
|
*(xd->mi[0]) = pc_tree->vertical[0].mic;
|
2015-06-29 18:27:11 +02:00
|
|
|
*(x->mbmi_ext) = pc_tree->vertical[0].mbmi_ext;
|
2015-02-09 18:48:44 +01:00
|
|
|
duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, subsize);
|
2014-03-21 19:05:39 +01:00
|
|
|
|
|
|
|
if (mi_col + hbs < cm->mi_cols) {
|
2015-06-29 18:27:11 +02:00
|
|
|
set_mode_info_offsets(cm, x, xd, mi_row, mi_col + hbs);
|
2015-04-21 14:36:58 +02:00
|
|
|
*(xd->mi[0]) = pc_tree->vertical[1].mic;
|
2015-06-29 18:27:11 +02:00
|
|
|
*(x->mbmi_ext) = pc_tree->vertical[1].mbmi_ext;
|
2015-02-09 18:48:44 +01:00
|
|
|
duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col + hbs, subsize);
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
2015-06-29 18:27:11 +02:00
|
|
|
set_mode_info_offsets(cm, x, xd, mi_row, mi_col);
|
2015-04-21 14:36:58 +02:00
|
|
|
*(xd->mi[0]) = pc_tree->horizontal[0].mic;
|
2015-06-29 18:27:11 +02:00
|
|
|
*(x->mbmi_ext) = pc_tree->horizontal[0].mbmi_ext;
|
2015-02-09 18:48:44 +01:00
|
|
|
duplicate_mode_info_in_sb(cm, xd, mi_row, mi_col, subsize);
|
2014-03-21 19:05:39 +01:00
|
|
|
if (mi_row + hbs < cm->mi_rows) {
|
2015-06-29 18:27:11 +02:00
|
|
|
set_mode_info_offsets(cm, x, xd, mi_row + hbs, mi_col);
|
2015-04-21 14:36:58 +02:00
|
|
|
*(xd->mi[0]) = pc_tree->horizontal[1].mic;
|
2015-06-29 18:27:11 +02:00
|
|
|
*(x->mbmi_ext) = pc_tree->horizontal[1].mbmi_ext;
|
2015-02-09 18:48:44 +01:00
|
|
|
duplicate_mode_info_in_sb(cm, xd, mi_row + hbs, mi_col, subsize);
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
break;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
case PARTITION_SPLIT: {
|
2015-02-09 18:48:44 +01:00
|
|
|
fill_mode_info_sb(cm, x, mi_row, mi_col, subsize, pc_tree->split[0]);
|
2014-03-21 19:05:39 +01:00
|
|
|
fill_mode_info_sb(cm, x, mi_row, mi_col + hbs, subsize,
|
2015-02-09 18:48:44 +01:00
|
|
|
pc_tree->split[1]);
|
2014-03-21 19:05:39 +01:00
|
|
|
fill_mode_info_sb(cm, x, mi_row + hbs, mi_col, subsize,
|
2015-02-09 18:48:44 +01:00
|
|
|
pc_tree->split[2]);
|
2014-03-21 19:05:39 +01:00
|
|
|
fill_mode_info_sb(cm, x, mi_row + hbs, mi_col + hbs, subsize,
|
2015-02-09 18:48:44 +01:00
|
|
|
pc_tree->split[3]);
|
2014-03-21 19:05:39 +01:00
|
|
|
break;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
}
|
2016-07-27 05:43:23 +02:00
|
|
|
default: break;
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-30 00:37:16 +01:00
|
|
|
// Reset the prediction pixel ready flag recursively.
|
|
|
|
static void pred_pixel_ready_reset(PC_TREE *pc_tree, BLOCK_SIZE bsize) {
|
|
|
|
pc_tree->none.pred_pixel_ready = 0;
|
|
|
|
pc_tree->horizontal[0].pred_pixel_ready = 0;
|
|
|
|
pc_tree->horizontal[1].pred_pixel_ready = 0;
|
|
|
|
pc_tree->vertical[0].pred_pixel_ready = 0;
|
|
|
|
pc_tree->vertical[1].pred_pixel_ready = 0;
|
|
|
|
|
|
|
|
if (bsize > BLOCK_8X8) {
|
|
|
|
BLOCK_SIZE subsize = get_subsize(bsize, PARTITION_SPLIT);
|
|
|
|
int i;
|
2016-07-27 05:43:23 +02:00
|
|
|
for (i = 0; i < 4; ++i) pred_pixel_ready_reset(pc_tree->split[i], subsize);
|
2014-10-30 00:37:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static void nonrd_pick_partition(VP9_COMP *cpi, ThreadData *td,
|
2016-07-27 05:43:23 +02:00
|
|
|
TileDataEnc *tile_data, TOKENEXTRA **tp,
|
|
|
|
int mi_row, int mi_col, BLOCK_SIZE bsize,
|
|
|
|
RD_COST *rd_cost, int do_recon,
|
|
|
|
int64_t best_rd, PC_TREE *pc_tree) {
|
2014-08-07 23:55:54 +02:00
|
|
|
const SPEED_FEATURES *const sf = &cpi->sf;
|
2014-03-21 19:05:39 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-10-27 19:11:50 +01:00
|
|
|
TileInfo *const tile_info = &tile_data->tile_info;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-03-21 19:05:39 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
|
|
|
const int ms = num_8x8_blocks_wide_lookup[bsize] / 2;
|
|
|
|
TOKENEXTRA *tp_orig = *tp;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
PICK_MODE_CONTEXT *ctx = &pc_tree->none;
|
2014-03-21 19:05:39 +01:00
|
|
|
int i;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
BLOCK_SIZE subsize = bsize;
|
2014-10-22 01:31:37 +02:00
|
|
|
RD_COST this_rdc, sum_rdc, best_rdc;
|
2014-03-21 19:05:39 +01:00
|
|
|
int do_split = bsize >= BLOCK_8X8;
|
|
|
|
int do_rect = 1;
|
|
|
|
// Override skipping rectangular partition operations for edge blocks
|
|
|
|
const int force_horz_split = (mi_row + ms >= cm->mi_rows);
|
|
|
|
const int force_vert_split = (mi_col + ms >= cm->mi_cols);
|
|
|
|
const int xss = x->e_mbd.plane[1].subsampling_x;
|
|
|
|
const int yss = x->e_mbd.plane[1].subsampling_y;
|
|
|
|
|
|
|
|
int partition_none_allowed = !force_horz_split && !force_vert_split;
|
2016-07-27 05:43:23 +02:00
|
|
|
int partition_horz_allowed =
|
|
|
|
!force_vert_split && yss <= xss && bsize >= BLOCK_8X8;
|
|
|
|
int partition_vert_allowed =
|
|
|
|
!force_horz_split && xss <= yss && bsize >= BLOCK_8X8;
|
|
|
|
(void)*tp_orig;
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2017-08-08 19:34:47 +02:00
|
|
|
// Avoid checking for rectangular partitions for speed >= 6.
|
|
|
|
if (cpi->oxcf.speed >= 6) do_rect = 0;
|
|
|
|
|
2014-03-21 19:05:39 +01:00
|
|
|
assert(num_8x8_blocks_wide_lookup[bsize] ==
|
2016-07-27 05:43:23 +02:00
|
|
|
num_8x8_blocks_high_lookup[bsize]);
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
vp9_rd_cost_init(&sum_rdc);
|
|
|
|
vp9_rd_cost_reset(&best_rdc);
|
|
|
|
best_rdc.rdcost = best_rd;
|
|
|
|
|
2014-03-21 19:05:39 +01:00
|
|
|
// Determine partition types in search according to the speed features.
|
|
|
|
// The threshold set here has to be of square block size.
|
2014-08-07 23:55:54 +02:00
|
|
|
if (sf->auto_min_max_partition_size) {
|
2016-07-27 05:43:23 +02:00
|
|
|
partition_none_allowed &=
|
|
|
|
(bsize <= x->max_partition_size && bsize >= x->min_partition_size);
|
|
|
|
partition_horz_allowed &=
|
|
|
|
((bsize <= x->max_partition_size && bsize > x->min_partition_size) ||
|
|
|
|
force_horz_split);
|
|
|
|
partition_vert_allowed &=
|
|
|
|
((bsize <= x->max_partition_size && bsize > x->min_partition_size) ||
|
|
|
|
force_vert_split);
|
2014-11-20 18:24:50 +01:00
|
|
|
do_split &= bsize > x->min_partition_size;
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
2014-08-07 23:55:54 +02:00
|
|
|
if (sf->use_square_partition_only) {
|
2014-03-21 19:05:39 +01:00
|
|
|
partition_horz_allowed &= force_horz_split;
|
|
|
|
partition_vert_allowed &= force_vert_split;
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
ctx->pred_pixel_ready =
|
|
|
|
!(partition_vert_allowed || partition_horz_allowed || do_split);
|
2014-10-30 00:37:16 +01:00
|
|
|
|
2014-03-21 19:05:39 +01:00
|
|
|
// PARTITION_NONE
|
|
|
|
if (partition_none_allowed) {
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &this_rdc, bsize,
|
|
|
|
ctx);
|
2016-01-20 01:40:20 +01:00
|
|
|
ctx->mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
ctx->mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
ctx->skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
ctx->skip = x->skip;
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
if (this_rdc.rate != INT_MAX) {
|
2014-03-25 17:54:32 +01:00
|
|
|
int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2014-10-22 01:31:37 +02:00
|
|
|
this_rdc.rate += cpi->partition_cost[pl][PARTITION_NONE];
|
2016-07-27 05:43:23 +02:00
|
|
|
this_rdc.rdcost =
|
|
|
|
RDCOST(x->rdmult, x->rddiv, this_rdc.rate, this_rdc.dist);
|
2014-10-22 01:31:37 +02:00
|
|
|
if (this_rdc.rdcost < best_rdc.rdcost) {
|
2017-03-08 21:24:15 +01:00
|
|
|
int64_t dist_breakout_thr = sf->partition_search_breakout_thr.dist;
|
|
|
|
int64_t rate_breakout_thr = sf->partition_search_breakout_thr.rate;
|
2014-10-15 21:18:48 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
dist_breakout_thr >>=
|
|
|
|
8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
|
2014-10-15 21:18:48 +02:00
|
|
|
|
|
|
|
rate_breakout_thr *= num_pels_log2_lookup[bsize];
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
best_rdc = this_rdc;
|
2016-07-27 05:43:23 +02:00
|
|
|
if (bsize >= BLOCK_8X8) pc_tree->partitioning = PARTITION_NONE;
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (!x->e_mbd.lossless && this_rdc.rate < rate_breakout_thr &&
|
2014-10-22 01:31:37 +02:00
|
|
|
this_rdc.dist < dist_breakout_thr) {
|
2014-03-21 19:05:39 +01:00
|
|
|
do_split = 0;
|
|
|
|
do_rect = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// store estimated motion vector
|
2014-03-25 06:31:03 +01:00
|
|
|
store_pred_mv(x, ctx);
|
2014-03-21 19:05:39 +01:00
|
|
|
|
|
|
|
// PARTITION_SPLIT
|
|
|
|
if (do_split) {
|
2014-03-25 17:54:32 +01:00
|
|
|
int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2014-10-22 01:31:37 +02:00
|
|
|
sum_rdc.rate += cpi->partition_cost[pl][PARTITION_SPLIT];
|
|
|
|
sum_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
|
2014-03-21 19:05:39 +01:00
|
|
|
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
2014-10-22 01:31:37 +02:00
|
|
|
for (i = 0; i < 4 && sum_rdc.rdcost < best_rdc.rdcost; ++i) {
|
2014-03-21 19:05:39 +01:00
|
|
|
const int x_idx = (i & 1) * ms;
|
|
|
|
const int y_idx = (i >> 1) * ms;
|
|
|
|
|
|
|
|
if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols)
|
|
|
|
continue;
|
2014-03-25 06:31:03 +01:00
|
|
|
load_pred_mv(x, ctx);
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_partition(cpi, td, tile_data, tp, mi_row + y_idx,
|
|
|
|
mi_col + x_idx, subsize, &this_rdc, 0,
|
2014-10-22 01:31:37 +02:00
|
|
|
best_rdc.rdcost - sum_rdc.rdcost, pc_tree->split[i]);
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
if (this_rdc.rate == INT_MAX) {
|
|
|
|
vp9_rd_cost_reset(&sum_rdc);
|
2014-03-21 19:05:39 +01:00
|
|
|
} else {
|
2014-10-22 01:31:37 +02:00
|
|
|
sum_rdc.rate += this_rdc.rate;
|
|
|
|
sum_rdc.dist += this_rdc.dist;
|
|
|
|
sum_rdc.rdcost += this_rdc.rdcost;
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost) {
|
|
|
|
best_rdc = sum_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = PARTITION_SPLIT;
|
2014-03-21 19:05:39 +01:00
|
|
|
} else {
|
|
|
|
// skip rectangular partition test when larger block size
|
|
|
|
// gives better rd cost
|
2016-07-27 05:43:23 +02:00
|
|
|
if (sf->less_rectangular_check) do_rect &= !partition_none_allowed;
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// PARTITION_HORZ
|
|
|
|
if (partition_horz_allowed && do_rect) {
|
|
|
|
subsize = get_subsize(bsize, PARTITION_HORZ);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (sf->adaptive_motion_search) load_pred_mv(x, ctx);
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->horizontal[0].pred_pixel_ready = 1;
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc, subsize,
|
2014-07-08 17:36:25 +02:00
|
|
|
&pc_tree->horizontal[0]);
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->horizontal[0].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->horizontal[0].mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->horizontal[0].skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->horizontal[0].skip = x->skip;
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost && mi_row + ms < cm->mi_rows) {
|
2014-03-25 06:31:03 +01:00
|
|
|
load_pred_mv(x, ctx);
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->horizontal[1].pred_pixel_ready = 1;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row + ms, mi_col, &this_rdc,
|
|
|
|
subsize, &pc_tree->horizontal[1]);
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->horizontal[1].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->horizontal[1].mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->horizontal[1].skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->horizontal[1].skip = x->skip;
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
if (this_rdc.rate == INT_MAX) {
|
|
|
|
vp9_rd_cost_reset(&sum_rdc);
|
2014-03-21 19:05:39 +01:00
|
|
|
} else {
|
2014-03-25 17:54:32 +01:00
|
|
|
int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2014-10-22 01:31:37 +02:00
|
|
|
this_rdc.rate += cpi->partition_cost[pl][PARTITION_HORZ];
|
|
|
|
sum_rdc.rate += this_rdc.rate;
|
|
|
|
sum_rdc.dist += this_rdc.dist;
|
2016-07-27 05:43:23 +02:00
|
|
|
sum_rdc.rdcost =
|
|
|
|
RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
2014-10-22 01:31:37 +02:00
|
|
|
|
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost) {
|
|
|
|
best_rdc = sum_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = PARTITION_HORZ;
|
2014-10-30 00:37:16 +01:00
|
|
|
} else {
|
|
|
|
pred_pixel_ready_reset(pc_tree, bsize);
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// PARTITION_VERT
|
|
|
|
if (partition_vert_allowed && do_rect) {
|
|
|
|
subsize = get_subsize(bsize, PARTITION_VERT);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (sf->adaptive_motion_search) load_pred_mv(x, ctx);
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->vertical[0].pred_pixel_ready = 1;
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &sum_rdc, subsize,
|
2014-07-08 17:36:25 +02:00
|
|
|
&pc_tree->vertical[0]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->vertical[0].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->vertical[0].mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->vertical[0].skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->vertical[0].skip = x->skip;
|
2014-10-22 01:31:37 +02:00
|
|
|
|
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost && mi_col + ms < cm->mi_cols) {
|
2014-03-25 06:31:03 +01:00
|
|
|
load_pred_mv(x, ctx);
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->vertical[1].pred_pixel_ready = 1;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + ms, &this_rdc,
|
|
|
|
subsize, &pc_tree->vertical[1]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->vertical[1].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->vertical[1].mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->vertical[1].skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->vertical[1].skip = x->skip;
|
2014-10-22 01:31:37 +02:00
|
|
|
|
|
|
|
if (this_rdc.rate == INT_MAX) {
|
|
|
|
vp9_rd_cost_reset(&sum_rdc);
|
2014-03-21 19:05:39 +01:00
|
|
|
} else {
|
2014-03-25 17:54:32 +01:00
|
|
|
int pl = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2014-10-22 01:31:37 +02:00
|
|
|
sum_rdc.rate += cpi->partition_cost[pl][PARTITION_VERT];
|
|
|
|
sum_rdc.rate += this_rdc.rate;
|
|
|
|
sum_rdc.dist += this_rdc.dist;
|
2016-07-27 05:43:23 +02:00
|
|
|
sum_rdc.rdcost =
|
|
|
|
RDCOST(x->rdmult, x->rddiv, sum_rdc.rate, sum_rdc.dist);
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
2014-10-22 01:31:37 +02:00
|
|
|
|
|
|
|
if (sum_rdc.rdcost < best_rdc.rdcost) {
|
|
|
|
best_rdc = sum_rdc;
|
add a context tree structure to encoder
This patch sets up a quad_tree structure (pc_tree) for holding all of
pick_mode_context data we use at any square block size during encoding
or picking modes. That includes contexts for 2 horizontal and 2 vertical
splits, one none, and pointers to 4 sub pc_tree nodes corresponding
to split. It also includes a pointer to the current chosen partitioning.
This replaces code that held an index for every level in the pick
modes array including: sb_index, mb_index,
b_index, ab_index.
These were used as stateful indexes that pointed to the current pick mode
contexts you had at each level stored in the following arrays
array ab4x4_context[][][],
sb8x4_context[][][], sb4x8_context[][][], sb8x8_context[][][],
sb8x16_context[][][], sb16x8_context[][][], mb_context[][], sb32x16[][],
sb16x32[], sb32_context[], sb32x64_context[], sb64x32_context[],
sb64_context
and the partitioning that had been stored in the following:
b_partitioning, mb_partitioning, sb_partitioning, and sb64_partitioning.
Prior to this patch before doing an encode you had to set the appropriate
index for your block size ( switch statement), update it ( up to 3
lookups for the index array value) and then make your call into a recursive
function at which point you'd have to call get_context which then
had to do a switch statement based on the blocksize, and then up to 3
lookups based upon the block size to find the context to use.
With the new code the context for the block size is passed around directly
avoiding the extraneous switch statements and multi dimensional array
look ups that were listed above. At any level in the search all of the
contexts are local to the pc_tree you are working on (in?).
In addition in most places code that used to call sub functions and
then check if the block size was 4x4 and index was > 0 and return
now don't preferring instead to call the right none function on the inside.
Change-Id: I06e39318269d9af2ce37961b3f95e181b57f5ed9
2014-04-17 16:30:55 +02:00
|
|
|
pc_tree->partitioning = PARTITION_VERT;
|
2014-10-30 00:37:16 +01:00
|
|
|
} else {
|
|
|
|
pred_pixel_ready_reset(pc_tree, bsize);
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
*rd_cost = best_rdc;
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
if (best_rdc.rate == INT_MAX) {
|
|
|
|
vp9_rd_cost_reset(rd_cost);
|
2014-03-25 19:05:50 +01:00
|
|
|
return;
|
2014-10-22 01:31:37 +02:00
|
|
|
}
|
2014-03-25 19:05:50 +01:00
|
|
|
|
2014-03-21 19:05:39 +01:00
|
|
|
// update mode info array
|
2015-02-09 18:48:44 +01:00
|
|
|
fill_mode_info_sb(cm, x, mi_row, mi_col, bsize, pc_tree);
|
2014-03-21 19:05:39 +01:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
if (best_rdc.rate < INT_MAX && best_rdc.dist < INT64_MAX && do_recon) {
|
2014-03-21 19:05:39 +01:00
|
|
|
int output_enabled = (bsize == BLOCK_64X64);
|
2016-07-27 05:43:23 +02:00
|
|
|
encode_sb_rt(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled, bsize,
|
|
|
|
pc_tree);
|
2014-03-21 19:05:39 +01:00
|
|
|
}
|
|
|
|
|
2015-02-19 18:54:08 +01:00
|
|
|
if (bsize == BLOCK_64X64 && do_recon) {
|
2014-03-21 19:05:39 +01:00
|
|
|
assert(tp_orig < *tp);
|
2014-10-22 01:31:37 +02:00
|
|
|
assert(best_rdc.rate < INT_MAX);
|
|
|
|
assert(best_rdc.dist < INT64_MAX);
|
2014-03-21 19:05:39 +01:00
|
|
|
} else {
|
|
|
|
assert(tp_orig == *tp);
|
|
|
|
}
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void nonrd_select_partition(VP9_COMP *cpi, ThreadData *td,
|
|
|
|
TileDataEnc *tile_data, MODE_INFO **mi,
|
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
BLOCK_SIZE bsize, int output_enabled,
|
2014-10-22 01:31:37 +02:00
|
|
|
RD_COST *rd_cost, PC_TREE *pc_tree) {
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-10-27 19:11:50 +01:00
|
|
|
TileInfo *const tile_info = &tile_data->tile_info;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
|
|
|
const int bsl = b_width_log2_lookup[bsize], hbs = (1 << bsl) / 4;
|
|
|
|
const int mis = cm->mi_stride;
|
|
|
|
PARTITION_TYPE partition;
|
|
|
|
BLOCK_SIZE subsize;
|
2014-10-22 01:31:37 +02:00
|
|
|
RD_COST this_rdc;
|
2017-08-08 19:34:47 +02:00
|
|
|
BLOCK_SIZE subsize_ref =
|
|
|
|
(cpi->sf.adapt_partition_source_sad) ? BLOCK_8X8 : BLOCK_16X16;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
|
2014-10-22 01:31:37 +02:00
|
|
|
vp9_rd_cost_reset(&this_rdc);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
subsize = (bsize >= BLOCK_8X8) ? mi[0]->sb_type : BLOCK_4X4;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
partition = partition_lookup[bsl][subsize];
|
|
|
|
|
2015-07-07 20:43:15 +02:00
|
|
|
if (bsize == BLOCK_32X32 && subsize == BLOCK_32X32) {
|
|
|
|
x->max_partition_size = BLOCK_32X32;
|
|
|
|
x->min_partition_size = BLOCK_16X16;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, bsize, rd_cost,
|
|
|
|
0, INT64_MAX, pc_tree);
|
2015-07-07 20:43:15 +02:00
|
|
|
} else if (bsize == BLOCK_32X32 && partition != PARTITION_NONE &&
|
2017-08-08 19:34:47 +02:00
|
|
|
subsize >= subsize_ref) {
|
2014-11-20 18:24:50 +01:00
|
|
|
x->max_partition_size = BLOCK_32X32;
|
|
|
|
x->min_partition_size = BLOCK_8X8;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, bsize, rd_cost,
|
|
|
|
0, INT64_MAX, pc_tree);
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
} else if (bsize == BLOCK_16X16 && partition != PARTITION_NONE) {
|
2014-11-20 18:24:50 +01:00
|
|
|
x->max_partition_size = BLOCK_16X16;
|
|
|
|
x->min_partition_size = BLOCK_8X8;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, bsize, rd_cost,
|
|
|
|
0, INT64_MAX, pc_tree);
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
} else {
|
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->none.pred_pixel_ready = 1;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, rd_cost, subsize,
|
|
|
|
&pc_tree->none);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->none.mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->none.mbmi_ext = *x->mbmi_ext;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
pc_tree->none.skip_txfm[0] = x->skip_txfm[0];
|
|
|
|
pc_tree->none.skip = x->skip;
|
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->vertical[0].pred_pixel_ready = 1;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, rd_cost, subsize,
|
|
|
|
&pc_tree->vertical[0]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->vertical[0].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->vertical[0].mbmi_ext = *x->mbmi_ext;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
pc_tree->vertical[0].skip_txfm[0] = x->skip_txfm[0];
|
|
|
|
pc_tree->vertical[0].skip = x->skip;
|
|
|
|
if (mi_col + hbs < cm->mi_cols) {
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->vertical[1].pred_pixel_ready = 1;
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + hbs,
|
2014-10-22 01:31:37 +02:00
|
|
|
&this_rdc, subsize, &pc_tree->vertical[1]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->vertical[1].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->vertical[1].mbmi_ext = *x->mbmi_ext;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
pc_tree->vertical[1].skip_txfm[0] = x->skip_txfm[0];
|
|
|
|
pc_tree->vertical[1].skip = x->skip;
|
2014-10-22 01:31:37 +02:00
|
|
|
if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
|
|
|
rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
|
|
|
rd_cost->rate += this_rdc.rate;
|
|
|
|
rd_cost->dist += this_rdc.dist;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->horizontal[0].pred_pixel_ready = 1;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, rd_cost, subsize,
|
|
|
|
&pc_tree->horizontal[0]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->horizontal[0].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->horizontal[0].mbmi_ext = *x->mbmi_ext;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
pc_tree->horizontal[0].skip_txfm[0] = x->skip_txfm[0];
|
|
|
|
pc_tree->horizontal[0].skip = x->skip;
|
|
|
|
if (mi_row + hbs < cm->mi_rows) {
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->horizontal[1].pred_pixel_ready = 1;
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row + hbs, mi_col,
|
2014-12-12 02:17:53 +01:00
|
|
|
&this_rdc, subsize, &pc_tree->horizontal[1]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->horizontal[1].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->horizontal[1].mbmi_ext = *x->mbmi_ext;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
pc_tree->horizontal[1].skip_txfm[0] = x->skip_txfm[0];
|
|
|
|
pc_tree->horizontal[1].skip = x->skip;
|
2014-10-22 01:31:37 +02:00
|
|
|
if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
|
|
|
rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
|
|
|
rd_cost->rate += this_rdc.rate;
|
|
|
|
rd_cost->dist += this_rdc.dist;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
|
|
|
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_select_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
2014-10-22 01:31:37 +02:00
|
|
|
subsize, output_enabled, rd_cost,
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
pc_tree->split[0]);
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_select_partition(cpi, td, tile_data, mi + hbs, tp, mi_row,
|
|
|
|
mi_col + hbs, subsize, output_enabled, &this_rdc,
|
|
|
|
pc_tree->split[1]);
|
2014-10-22 01:31:37 +02:00
|
|
|
if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
|
|
|
rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
|
|
|
rd_cost->rate += this_rdc.rate;
|
|
|
|
rd_cost->dist += this_rdc.dist;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
}
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_select_partition(cpi, td, tile_data, mi + hbs * mis, tp,
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
mi_row + hbs, mi_col, subsize, output_enabled,
|
2014-10-22 01:31:37 +02:00
|
|
|
&this_rdc, pc_tree->split[2]);
|
|
|
|
if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
|
|
|
rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
|
|
|
rd_cost->rate += this_rdc.rate;
|
|
|
|
rd_cost->dist += this_rdc.dist;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
}
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_select_partition(cpi, td, tile_data, mi + hbs * mis + hbs, tp,
|
2014-10-22 01:31:37 +02:00
|
|
|
mi_row + hbs, mi_col + hbs, subsize,
|
|
|
|
output_enabled, &this_rdc, pc_tree->split[3]);
|
|
|
|
if (this_rdc.rate != INT_MAX && this_rdc.dist != INT64_MAX &&
|
|
|
|
rd_cost->rate != INT_MAX && rd_cost->dist != INT64_MAX) {
|
|
|
|
rd_cost->rate += this_rdc.rate;
|
|
|
|
rd_cost->dist += this_rdc.dist;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
}
|
|
|
|
break;
|
2016-07-27 05:43:23 +02:00
|
|
|
default: assert(0 && "Invalid partition type."); break;
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-04 23:32:04 +01:00
|
|
|
if (bsize == BLOCK_64X64 && output_enabled)
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_sb_rt(cpi, td, tile_info, tp, mi_row, mi_col, 1, bsize, pc_tree);
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void nonrd_use_partition(VP9_COMP *cpi, ThreadData *td,
|
|
|
|
TileDataEnc *tile_data, MODE_INFO **mi,
|
|
|
|
TOKENEXTRA **tp, int mi_row, int mi_col,
|
2014-03-15 01:10:32 +01:00
|
|
|
BLOCK_SIZE bsize, int output_enabled,
|
2014-12-09 03:43:36 +01:00
|
|
|
RD_COST *dummy_cost, PC_TREE *pc_tree) {
|
2014-03-04 20:15:35 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-11-06 20:53:18 +01:00
|
|
|
TileInfo *tile_info = &tile_data->tile_info;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-03-26 21:00:06 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2014-10-07 21:30:33 +02:00
|
|
|
const int bsl = b_width_log2_lookup[bsize], hbs = (1 << bsl) / 4;
|
2014-04-02 01:18:47 +02:00
|
|
|
const int mis = cm->mi_stride;
|
2014-03-04 20:15:35 +01:00
|
|
|
PARTITION_TYPE partition;
|
|
|
|
BLOCK_SIZE subsize;
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
|
2014-03-04 20:15:35 +01:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
subsize = (bsize >= BLOCK_8X8) ? mi[0]->sb_type : BLOCK_4X4;
|
2014-03-04 20:15:35 +01:00
|
|
|
partition = partition_lookup[bsl][subsize];
|
|
|
|
|
2014-11-06 20:53:18 +01:00
|
|
|
if (output_enabled && bsize != BLOCK_4X4) {
|
|
|
|
int ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
|
2014-11-21 20:11:06 +01:00
|
|
|
td->counts->partition[ctx][partition]++;
|
2014-11-06 20:53:18 +01:00
|
|
|
}
|
|
|
|
|
2014-03-04 20:15:35 +01:00
|
|
|
switch (partition) {
|
|
|
|
case PARTITION_NONE:
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->none.pred_pixel_ready = 1;
|
2014-12-09 03:43:36 +01:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, dummy_cost,
|
2014-07-08 17:36:25 +02:00
|
|
|
subsize, &pc_tree->none);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->none.mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->none.mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->none.skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->none.skip = x->skip;
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled,
|
|
|
|
subsize, &pc_tree->none);
|
2014-03-04 20:15:35 +01:00
|
|
|
break;
|
|
|
|
case PARTITION_VERT:
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->vertical[0].pred_pixel_ready = 1;
|
2014-12-09 03:43:36 +01:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, dummy_cost,
|
2014-07-08 17:36:25 +02:00
|
|
|
subsize, &pc_tree->vertical[0]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->vertical[0].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->vertical[0].mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->vertical[0].skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->vertical[0].skip = x->skip;
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled,
|
|
|
|
subsize, &pc_tree->vertical[0]);
|
2015-01-02 19:10:49 +01:00
|
|
|
if (mi_col + hbs < cm->mi_cols && bsize > BLOCK_8X8) {
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->vertical[1].pred_pixel_ready = 1;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col + hbs, dummy_cost,
|
|
|
|
subsize, &pc_tree->vertical[1]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->vertical[1].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->vertical[1].mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->vertical[1].skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->vertical[1].skip = x->skip;
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col + hbs,
|
2014-11-06 20:53:18 +01:00
|
|
|
output_enabled, subsize, &pc_tree->vertical[1]);
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_HORZ:
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->horizontal[0].pred_pixel_ready = 1;
|
2014-12-09 03:43:36 +01:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, dummy_cost,
|
2014-07-08 17:36:25 +02:00
|
|
|
subsize, &pc_tree->horizontal[0]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->horizontal[0].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->horizontal[0].mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->horizontal[0].skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->horizontal[0].skip = x->skip;
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled,
|
|
|
|
subsize, &pc_tree->horizontal[0]);
|
2014-11-06 20:53:18 +01:00
|
|
|
|
2015-01-02 19:10:49 +01:00
|
|
|
if (mi_row + hbs < cm->mi_rows && bsize > BLOCK_8X8) {
|
2014-10-30 00:37:16 +01:00
|
|
|
pc_tree->horizontal[1].pred_pixel_ready = 1;
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row + hbs, mi_col, dummy_cost,
|
|
|
|
subsize, &pc_tree->horizontal[1]);
|
2016-01-20 01:40:20 +01:00
|
|
|
pc_tree->horizontal[1].mic = *xd->mi[0];
|
2015-06-29 18:27:11 +02:00
|
|
|
pc_tree->horizontal[1].mbmi_ext = *x->mbmi_ext;
|
2014-08-06 00:42:12 +02:00
|
|
|
pc_tree->horizontal[1].skip_txfm[0] = x->skip_txfm[0];
|
2014-06-20 19:15:37 +02:00
|
|
|
pc_tree->horizontal[1].skip = x->skip;
|
2014-11-21 20:11:06 +01:00
|
|
|
encode_b_rt(cpi, td, tile_info, tp, mi_row + hbs, mi_col,
|
2014-11-06 20:53:18 +01:00
|
|
|
output_enabled, subsize, &pc_tree->horizontal[1]);
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PARTITION_SPLIT:
|
|
|
|
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
2014-12-09 20:31:45 +01:00
|
|
|
if (bsize == BLOCK_8X8) {
|
|
|
|
nonrd_pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, dummy_cost,
|
|
|
|
subsize, pc_tree->leaf_split[0]);
|
2016-07-27 05:43:23 +02:00
|
|
|
encode_b_rt(cpi, td, tile_info, tp, mi_row, mi_col, output_enabled,
|
|
|
|
subsize, pc_tree->leaf_split[0]);
|
2014-12-09 20:31:45 +01:00
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, subsize,
|
|
|
|
output_enabled, dummy_cost, pc_tree->split[0]);
|
|
|
|
nonrd_use_partition(cpi, td, tile_data, mi + hbs, tp, mi_row,
|
|
|
|
mi_col + hbs, subsize, output_enabled, dummy_cost,
|
|
|
|
pc_tree->split[1]);
|
2014-12-09 20:31:45 +01:00
|
|
|
nonrd_use_partition(cpi, td, tile_data, mi + hbs * mis, tp,
|
|
|
|
mi_row + hbs, mi_col, subsize, output_enabled,
|
|
|
|
dummy_cost, pc_tree->split[2]);
|
|
|
|
nonrd_use_partition(cpi, td, tile_data, mi + hbs * mis + hbs, tp,
|
|
|
|
mi_row + hbs, mi_col + hbs, subsize, output_enabled,
|
|
|
|
dummy_cost, pc_tree->split[3]);
|
|
|
|
}
|
2014-03-04 20:15:35 +01:00
|
|
|
break;
|
2016-07-27 05:43:23 +02:00
|
|
|
default: assert(0 && "Invalid partition type."); break;
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
2014-11-06 20:53:18 +01:00
|
|
|
if (partition != PARTITION_SPLIT || bsize == BLOCK_8X8)
|
|
|
|
update_partition_context(xd, mi_row, mi_col, subsize, bsize);
|
2014-03-04 20:15:35 +01:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void encode_nonrd_sb_row(VP9_COMP *cpi, ThreadData *td,
|
|
|
|
TileDataEnc *tile_data, int mi_row,
|
2014-10-27 19:11:50 +01:00
|
|
|
TOKENEXTRA **tp) {
|
2014-08-07 23:55:54 +02:00
|
|
|
SPEED_FEATURES *const sf = &cpi->sf;
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-10-27 19:11:50 +01:00
|
|
|
TileInfo *const tile_info = &tile_data->tile_info;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-08-07 23:55:54 +02:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2016-06-22 21:20:06 +02:00
|
|
|
const int mi_col_start = tile_info->mi_col_start;
|
|
|
|
const int mi_col_end = tile_info->mi_col_end;
|
2014-01-29 17:39:39 +01:00
|
|
|
int mi_col;
|
2017-02-13 20:36:02 +01:00
|
|
|
const int sb_row = mi_row >> MI_BLOCK_SIZE_LOG2;
|
|
|
|
const int num_sb_cols =
|
|
|
|
get_num_cols(tile_data->tile_info, MI_BLOCK_SIZE_LOG2);
|
|
|
|
int sb_col_in_tile;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
|
|
|
// Initialize the left context for the new SB row
|
2015-04-24 05:47:40 +02:00
|
|
|
memset(&xd->left_context, 0, sizeof(xd->left_context));
|
|
|
|
memset(xd->left_seg_context, 0, sizeof(xd->left_seg_context));
|
2014-01-29 17:39:39 +01:00
|
|
|
|
|
|
|
// Code each SB in the row
|
2017-02-13 20:36:02 +01:00
|
|
|
for (mi_col = mi_col_start, sb_col_in_tile = 0; mi_col < mi_col_end;
|
|
|
|
mi_col += MI_BLOCK_SIZE, ++sb_col_in_tile) {
|
2015-03-09 18:45:38 +01:00
|
|
|
const struct segmentation *const seg = &cm->seg;
|
2014-10-22 01:31:37 +02:00
|
|
|
RD_COST dummy_rdc;
|
2014-04-02 01:18:47 +02:00
|
|
|
const int idx_str = cm->mi_stride * mi_row + mi_col;
|
2015-04-21 14:36:58 +02:00
|
|
|
MODE_INFO **mi = cm->mi_grid_visible + idx_str;
|
2015-03-09 18:45:38 +01:00
|
|
|
PARTITION_SEARCH_TYPE partition_search_type = sf->partition_search_type;
|
|
|
|
BLOCK_SIZE bsize = BLOCK_64X64;
|
|
|
|
int seg_skip = 0;
|
2017-02-13 20:36:02 +01:00
|
|
|
|
|
|
|
(*(cpi->row_mt_sync_read_ptr))(&tile_data->row_mt_sync, sb_row,
|
2017-03-28 20:27:31 +02:00
|
|
|
sb_col_in_tile);
|
2017-02-13 20:36:02 +01:00
|
|
|
|
2017-07-11 01:16:05 +02:00
|
|
|
if (cpi->use_skin_detection) {
|
|
|
|
vp9_compute_skin_sb(cpi, BLOCK_16X16, mi_row, mi_col);
|
|
|
|
}
|
|
|
|
|
2014-04-17 18:58:17 +02:00
|
|
|
x->source_variance = UINT_MAX;
|
|
|
|
vp9_zero(x->pred_mv);
|
2014-10-22 01:31:37 +02:00
|
|
|
vp9_rd_cost_init(&dummy_rdc);
|
2015-01-21 18:32:23 +01:00
|
|
|
x->color_sensitivity[0] = 0;
|
|
|
|
x->color_sensitivity[1] = 0;
|
2016-01-22 20:45:31 +01:00
|
|
|
x->sb_is_skin = 0;
|
2017-01-17 19:39:26 +01:00
|
|
|
x->skip_low_source_sad = 0;
|
2017-04-14 20:32:19 +02:00
|
|
|
x->lowvar_highsumdiff = 0;
|
2017-03-23 22:37:47 +01:00
|
|
|
x->content_state_sb = 0;
|
2017-07-13 23:49:39 +02:00
|
|
|
x->sb_use_mv_part = 0;
|
|
|
|
x->sb_mvcol_part = 0;
|
|
|
|
x->sb_mvrow_part = 0;
|
2017-07-29 04:11:53 +02:00
|
|
|
x->sb_pickmode_part = 0;
|
2017-09-21 19:59:33 +02:00
|
|
|
x->arf_frame_usage = 0;
|
|
|
|
x->lastgolden_frame_usage = 0;
|
2014-02-13 18:39:03 +01:00
|
|
|
|
2015-03-09 18:45:38 +01:00
|
|
|
if (seg->enabled) {
|
2016-07-27 05:43:23 +02:00
|
|
|
const uint8_t *const map =
|
|
|
|
seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
|
2015-06-16 02:30:54 +02:00
|
|
|
int segment_id = get_segment_id(cm, map, BLOCK_64X64, mi_row, mi_col);
|
2015-06-11 13:20:55 +02:00
|
|
|
seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
|
2015-03-09 18:45:38 +01:00
|
|
|
if (seg_skip) {
|
|
|
|
partition_search_type = FIXED_PARTITION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-23 22:37:47 +01:00
|
|
|
if (cpi->compute_source_sad_onepass && cpi->sf.use_source_sad) {
|
|
|
|
int shift = cpi->Source->y_stride * (mi_row << 3) + (mi_col << 3);
|
|
|
|
int sb_offset2 = ((cm->mi_cols + 7) >> 3) * (mi_row >> 3) + (mi_col >> 3);
|
2017-07-31 03:57:44 +02:00
|
|
|
int64_t source_sad = avg_source_sad(cpi, x, shift, sb_offset2);
|
2017-08-22 01:39:56 +02:00
|
|
|
if (sf->adapt_partition_source_sad &&
|
2017-09-19 02:30:49 +02:00
|
|
|
(cpi->oxcf.rc_mode == VPX_VBR && !cpi->rc.is_src_frame_alt_ref &&
|
2017-08-22 01:39:56 +02:00
|
|
|
source_sad > sf->adapt_partition_thresh &&
|
2017-10-03 19:55:55 +02:00
|
|
|
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)))
|
2017-07-31 03:57:44 +02:00
|
|
|
partition_search_type = REFERENCE_PARTITION;
|
2017-03-23 22:37:47 +01:00
|
|
|
}
|
|
|
|
|
2014-03-13 23:51:36 +01:00
|
|
|
// Set the partition type of the 64X64 block
|
2015-03-09 18:45:38 +01:00
|
|
|
switch (partition_search_type) {
|
2014-03-20 22:06:54 +01:00
|
|
|
case VAR_BASED_PARTITION:
|
2014-12-22 22:38:34 +01:00
|
|
|
// TODO(jingning, marpan): The mode decision and encoding process
|
|
|
|
// support both intra and inter sub8x8 block coding for RTC mode.
|
|
|
|
// Tune the thresholds accordingly to use sub8x8 block coding for
|
|
|
|
// coding performance improvement.
|
2014-11-21 20:11:06 +01:00
|
|
|
choose_partitioning(cpi, tile_info, x, mi_row, mi_col);
|
|
|
|
nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
|
|
|
BLOCK_64X64, 1, &dummy_rdc, td->pc_root);
|
2014-03-20 22:06:54 +01:00
|
|
|
break;
|
2014-04-02 02:32:20 +02:00
|
|
|
case SOURCE_VAR_BASED_PARTITION:
|
2014-11-21 20:11:06 +01:00
|
|
|
set_source_var_based_partition(cpi, tile_info, x, mi, mi_row, mi_col);
|
|
|
|
nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
|
|
|
BLOCK_64X64, 1, &dummy_rdc, td->pc_root);
|
2014-04-02 02:32:20 +02:00
|
|
|
break;
|
2014-03-20 22:06:54 +01:00
|
|
|
case FIXED_PARTITION:
|
2016-07-27 05:43:23 +02:00
|
|
|
if (!seg_skip) bsize = sf->always_this_block_size;
|
2014-10-27 19:11:50 +01:00
|
|
|
set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
|
|
|
BLOCK_64X64, 1, &dummy_rdc, td->pc_root);
|
2014-03-20 22:06:54 +01:00
|
|
|
break;
|
|
|
|
case REFERENCE_PARTITION:
|
2017-07-29 04:11:53 +02:00
|
|
|
x->sb_pickmode_part = 1;
|
2014-11-21 20:11:06 +01:00
|
|
|
set_offsets(cpi, tile_info, x, mi_row, mi_col, BLOCK_64X64);
|
2017-04-10 23:56:46 +02:00
|
|
|
// Use nonrd_pick_partition on scene-cut for VBR mode.
|
2016-06-08 22:03:29 +02:00
|
|
|
// nonrd_pick_partition does not support 4x4 partition, so avoid it
|
|
|
|
// on key frame for now.
|
|
|
|
if ((cpi->oxcf.rc_mode == VPX_VBR && cpi->rc.high_source_sad &&
|
2017-10-06 19:53:40 +02:00
|
|
|
cpi->oxcf.speed < 6 && cm->frame_type != KEY_FRAME &&
|
|
|
|
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame))) {
|
2015-06-20 01:40:01 +02:00
|
|
|
// Use lower max_partition_size for low resoultions.
|
|
|
|
if (cm->width <= 352 && cm->height <= 288)
|
|
|
|
x->max_partition_size = BLOCK_32X32;
|
|
|
|
else
|
|
|
|
x->max_partition_size = BLOCK_64X64;
|
2015-03-14 00:51:29 +01:00
|
|
|
x->min_partition_size = BLOCK_8X8;
|
2014-11-21 20:11:06 +01:00
|
|
|
nonrd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col,
|
2016-07-27 05:43:23 +02:00
|
|
|
BLOCK_64X64, &dummy_rdc, 1, INT64_MAX,
|
|
|
|
td->pc_root);
|
2014-03-19 19:25:40 +01:00
|
|
|
} else {
|
2014-11-21 20:11:06 +01:00
|
|
|
choose_partitioning(cpi, tile_info, x, mi_row, mi_col);
|
2015-06-23 00:20:28 +02:00
|
|
|
// TODO(marpan): Seems like nonrd_select_partition does not support
|
|
|
|
// 4x4 partition. Since 4x4 is used on key frame, use this switch
|
|
|
|
// for now.
|
|
|
|
if (cm->frame_type == KEY_FRAME)
|
|
|
|
nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
|
|
|
BLOCK_64X64, 1, &dummy_rdc, td->pc_root);
|
|
|
|
else
|
|
|
|
nonrd_select_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col,
|
|
|
|
BLOCK_64X64, 1, &dummy_rdc, td->pc_root);
|
2014-03-19 19:25:40 +01:00
|
|
|
}
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
|
2014-03-20 22:06:54 +01:00
|
|
|
break;
|
2016-07-27 05:43:23 +02:00
|
|
|
default: assert(0); break;
|
2014-03-19 19:25:40 +01:00
|
|
|
}
|
2017-02-13 20:36:02 +01:00
|
|
|
|
2017-09-21 19:59:33 +02:00
|
|
|
// Update ref_frame usage for inter frame if this group is ARF group.
|
|
|
|
if (!cpi->rc.is_src_frame_alt_ref && !cpi->refresh_golden_frame &&
|
|
|
|
!cpi->refresh_alt_ref_frame && cpi->rc.alt_ref_gf_group &&
|
|
|
|
cpi->sf.use_altref_onepass) {
|
|
|
|
int sboffset = ((cm->mi_cols + 7) >> 3) * (mi_row >> 3) + (mi_col >> 3);
|
|
|
|
if (cpi->count_arf_frame_usage != NULL)
|
|
|
|
cpi->count_arf_frame_usage[sboffset] = x->arf_frame_usage;
|
|
|
|
if (cpi->count_lastgolden_frame_usage != NULL)
|
|
|
|
cpi->count_lastgolden_frame_usage[sboffset] = x->lastgolden_frame_usage;
|
|
|
|
}
|
|
|
|
|
2017-02-13 20:36:02 +01:00
|
|
|
(*(cpi->row_mt_sync_write_ptr))(&tile_data->row_mt_sync, sb_row,
|
|
|
|
sb_col_in_tile, num_sb_cols);
|
2014-01-29 17:39:39 +01:00
|
|
|
}
|
|
|
|
}
|
2014-02-10 20:25:23 +01:00
|
|
|
// end RTC play code
|
2014-01-29 17:39:39 +01:00
|
|
|
|
2017-07-22 22:01:49 +02:00
|
|
|
static INLINE uint32_t variance(const diff *const d) {
|
|
|
|
return d->sse - (uint32_t)(((int64_t)d->sum * d->sum) >> 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
static INLINE uint32_t variance_highbd(diff *const d) {
|
|
|
|
const int64_t var = (int64_t)d->sse - (((int64_t)d->sum * d->sum) >> 8);
|
|
|
|
return (var >= 0) ? (uint32_t)var : 0;
|
|
|
|
}
|
|
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
|
2014-05-02 00:14:39 +02:00
|
|
|
static int set_var_thresh_from_histogram(VP9_COMP *cpi) {
|
2014-08-07 23:55:54 +02:00
|
|
|
const SPEED_FEATURES *const sf = &cpi->sf;
|
|
|
|
const VP9_COMMON *const cm = &cpi->common;
|
2014-05-02 00:14:39 +02:00
|
|
|
|
|
|
|
const uint8_t *src = cpi->Source->y_buffer;
|
|
|
|
const uint8_t *last_src = cpi->Last_Source->y_buffer;
|
|
|
|
const int src_stride = cpi->Source->y_stride;
|
|
|
|
const int last_stride = cpi->Last_Source->y_stride;
|
|
|
|
|
|
|
|
// Pick cutoff threshold
|
2016-07-27 05:43:23 +02:00
|
|
|
const int cutoff = (VPXMIN(cm->width, cm->height) >= 720)
|
|
|
|
? (cm->MBs * VAR_HIST_LARGE_CUT_OFF / 100)
|
|
|
|
: (cm->MBs * VAR_HIST_SMALL_CUT_OFF / 100);
|
2015-05-02 22:24:16 +02:00
|
|
|
DECLARE_ALIGNED(16, int, hist[VAR_HIST_BINS]);
|
2014-05-02 00:14:39 +02:00
|
|
|
diff *var16 = cpi->source_diff_var;
|
|
|
|
|
|
|
|
int sum = 0;
|
|
|
|
int i, j;
|
|
|
|
|
2015-04-24 05:47:40 +02:00
|
|
|
memset(hist, 0, VAR_HIST_BINS * sizeof(hist[0]));
|
2014-05-02 00:14:39 +02:00
|
|
|
|
|
|
|
for (i = 0; i < cm->mb_rows; i++) {
|
|
|
|
for (j = 0; j < cm->mb_cols; j++) {
|
2014-09-24 15:36:34 +02:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if (cm->use_highbitdepth) {
|
|
|
|
switch (cm->bit_depth) {
|
|
|
|
case VPX_BITS_8:
|
2015-05-15 20:52:03 +02:00
|
|
|
vpx_highbd_8_get16x16var(src, src_stride, last_src, last_stride,
|
2016-07-27 05:43:23 +02:00
|
|
|
&var16->sse, &var16->sum);
|
2017-07-22 22:01:49 +02:00
|
|
|
var16->var = variance(var16);
|
2014-09-24 15:36:34 +02:00
|
|
|
break;
|
|
|
|
case VPX_BITS_10:
|
2015-05-15 20:52:03 +02:00
|
|
|
vpx_highbd_10_get16x16var(src, src_stride, last_src, last_stride,
|
2016-07-27 05:43:23 +02:00
|
|
|
&var16->sse, &var16->sum);
|
2017-07-22 22:01:49 +02:00
|
|
|
var16->var = variance_highbd(var16);
|
2014-09-24 15:36:34 +02:00
|
|
|
break;
|
|
|
|
case VPX_BITS_12:
|
2015-05-15 20:52:03 +02:00
|
|
|
vpx_highbd_12_get16x16var(src, src_stride, last_src, last_stride,
|
2014-10-08 21:43:22 +02:00
|
|
|
&var16->sse, &var16->sum);
|
2017-07-22 22:01:49 +02:00
|
|
|
var16->var = variance_highbd(var16);
|
2014-09-24 15:36:34 +02:00
|
|
|
break;
|
|
|
|
default:
|
2016-07-27 05:43:23 +02:00
|
|
|
assert(0 &&
|
|
|
|
"cm->bit_depth should be VPX_BITS_8, VPX_BITS_10"
|
2014-09-24 15:36:34 +02:00
|
|
|
" or VPX_BITS_12");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
2016-07-27 05:43:23 +02:00
|
|
|
vpx_get16x16var(src, src_stride, last_src, last_stride, &var16->sse,
|
|
|
|
&var16->sum);
|
2017-07-22 22:01:49 +02:00
|
|
|
var16->var = variance(var16);
|
2014-09-24 15:36:34 +02:00
|
|
|
}
|
|
|
|
#else
|
2016-07-27 05:43:23 +02:00
|
|
|
vpx_get16x16var(src, src_stride, last_src, last_stride, &var16->sse,
|
|
|
|
&var16->sum);
|
2017-07-22 22:01:49 +02:00
|
|
|
var16->var = variance(var16);
|
2014-09-24 15:36:34 +02:00
|
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
2014-05-02 00:14:39 +02:00
|
|
|
|
|
|
|
if (var16->var >= VAR_HIST_MAX_BG_VAR)
|
|
|
|
hist[VAR_HIST_BINS - 1]++;
|
|
|
|
else
|
|
|
|
hist[var16->var / VAR_HIST_FACTOR]++;
|
|
|
|
|
|
|
|
src += 16;
|
|
|
|
last_src += 16;
|
|
|
|
var16++;
|
|
|
|
}
|
|
|
|
|
|
|
|
src = src - cm->mb_cols * 16 + 16 * src_stride;
|
|
|
|
last_src = last_src - cm->mb_cols * 16 + 16 * last_stride;
|
|
|
|
}
|
|
|
|
|
|
|
|
cpi->source_var_thresh = 0;
|
|
|
|
|
|
|
|
if (hist[VAR_HIST_BINS - 1] < cutoff) {
|
|
|
|
for (i = 0; i < VAR_HIST_BINS - 1; i++) {
|
|
|
|
sum += hist[i];
|
|
|
|
|
|
|
|
if (sum > cutoff) {
|
|
|
|
cpi->source_var_thresh = (i + 1) * VAR_HIST_FACTOR;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sf->search_type_check_frequency;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void source_var_based_partition_search_method(VP9_COMP *cpi) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
SPEED_FEATURES *const sf = &cpi->sf;
|
|
|
|
|
|
|
|
if (cm->frame_type == KEY_FRAME) {
|
|
|
|
// For key frame, use SEARCH_PARTITION.
|
|
|
|
sf->partition_search_type = SEARCH_PARTITION;
|
|
|
|
} else if (cm->intra_only) {
|
|
|
|
sf->partition_search_type = FIXED_PARTITION;
|
|
|
|
} else {
|
|
|
|
if (cm->last_width != cm->width || cm->last_height != cm->height) {
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->source_diff_var) vpx_free(cpi->source_diff_var);
|
2014-05-02 00:14:39 +02:00
|
|
|
|
2014-12-03 21:37:36 +01:00
|
|
|
CHECK_MEM_ERROR(cm, cpi->source_diff_var,
|
|
|
|
vpx_calloc(cm->MBs, sizeof(diff)));
|
|
|
|
}
|
2014-05-02 00:14:39 +02:00
|
|
|
|
|
|
|
if (!cpi->frames_till_next_var_check)
|
|
|
|
cpi->frames_till_next_var_check = set_var_thresh_from_histogram(cpi);
|
|
|
|
|
|
|
|
if (cpi->frames_till_next_var_check > 0) {
|
|
|
|
sf->partition_search_type = FIXED_PARTITION;
|
|
|
|
cpi->frames_till_next_var_check--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
static int get_skip_encode_frame(const VP9_COMMON *cm, ThreadData *const td) {
|
2014-04-15 00:19:43 +02:00
|
|
|
unsigned int intra_count = 0, inter_count = 0;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
for (j = 0; j < INTRA_INTER_CONTEXTS; ++j) {
|
2014-11-21 20:11:06 +01:00
|
|
|
intra_count += td->counts->intra_inter[j][0];
|
|
|
|
inter_count += td->counts->intra_inter[j][1];
|
2014-04-15 00:19:43 +02:00
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
return (intra_count << 2) < inter_count && cm->frame_type != KEY_FRAME &&
|
|
|
|
cm->show_frame;
|
2014-04-15 00:19:43 +02:00
|
|
|
}
|
|
|
|
|
2014-12-03 00:47:41 +01:00
|
|
|
void vp9_init_tile_data(VP9_COMP *cpi) {
|
Tile based adaptive mode search in RD loop
Make the spatially adaptive mode search in rate-distortion
optimization loop inter tile independent. Experiments suggest that
this does not significantly change the coding staticstics.
Single tile, speed 3:
pedestrian_area 1080p 1500 kbps
59192 b/f, 40.611 dB, 101689 ms
blue_sky 1080p 1500 kbps
58505 b/f, 36.347 dB, 62458 ms
mobile_cal 720p 1000 kbps
13335 b/f, 35.646 dB, 45655 ms
as compared to 4 column tiles, speed 3:
pedestrian_area 1080p 1500 kbps
59329 b/f, 40.597 dB, 101917 ms
blue_sky 1080p 1500 kbps
58712 b/f, 36.320 dB, 62693 ms
mobile_cal 720p 1000 kbps
13191 b/f, 35.485 dB, 45319 ms
Change-Id: I35c6e1e0a859fece8f4145dec28623cbc6a12325
2014-10-24 01:54:45 +02:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-06-06 03:03:40 +02:00
|
|
|
const int tile_cols = 1 << cm->log2_tile_cols;
|
|
|
|
const int tile_rows = 1 << cm->log2_tile_rows;
|
|
|
|
int tile_col, tile_row;
|
2014-11-26 01:53:47 +01:00
|
|
|
TOKENEXTRA *pre_tok = cpi->tile_tok[0][0];
|
2017-02-02 09:49:29 +01:00
|
|
|
TOKENLIST *tplist = cpi->tplist[0][0];
|
2014-10-16 21:29:48 +02:00
|
|
|
int tile_tok = 0;
|
2017-02-02 09:49:29 +01:00
|
|
|
int tplist_count = 0;
|
2014-10-16 21:29:48 +02:00
|
|
|
|
2015-06-11 20:30:18 +02:00
|
|
|
if (cpi->tile_data == NULL || cpi->allocated_tiles < tile_cols * tile_rows) {
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cpi->tile_data != NULL) vpx_free(cpi->tile_data);
|
|
|
|
CHECK_MEM_ERROR(cm, cpi->tile_data, vpx_malloc(tile_cols * tile_rows *
|
|
|
|
sizeof(*cpi->tile_data)));
|
2015-06-11 20:30:18 +02:00
|
|
|
cpi->allocated_tiles = tile_cols * tile_rows;
|
|
|
|
|
Tile based adaptive mode search in RD loop
Make the spatially adaptive mode search in rate-distortion
optimization loop inter tile independent. Experiments suggest that
this does not significantly change the coding staticstics.
Single tile, speed 3:
pedestrian_area 1080p 1500 kbps
59192 b/f, 40.611 dB, 101689 ms
blue_sky 1080p 1500 kbps
58505 b/f, 36.347 dB, 62458 ms
mobile_cal 720p 1000 kbps
13335 b/f, 35.646 dB, 45655 ms
as compared to 4 column tiles, speed 3:
pedestrian_area 1080p 1500 kbps
59329 b/f, 40.597 dB, 101917 ms
blue_sky 1080p 1500 kbps
58712 b/f, 36.320 dB, 62693 ms
mobile_cal 720p 1000 kbps
13191 b/f, 35.485 dB, 45319 ms
Change-Id: I35c6e1e0a859fece8f4145dec28623cbc6a12325
2014-10-24 01:54:45 +02:00
|
|
|
for (tile_row = 0; tile_row < tile_rows; ++tile_row)
|
2014-11-26 01:53:47 +01:00
|
|
|
for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
|
|
|
|
TileDataEnc *tile_data =
|
|
|
|
&cpi->tile_data[tile_row * tile_cols + tile_col];
|
|
|
|
int i, j;
|
|
|
|
for (i = 0; i < BLOCK_SIZES; ++i) {
|
|
|
|
for (j = 0; j < MAX_MODES; ++j) {
|
2017-03-14 21:45:20 +01:00
|
|
|
tile_data->thresh_freq_fact[i][j] = RD_THRESH_INIT_FACT;
|
2014-11-26 01:53:47 +01:00
|
|
|
tile_data->mode_map[i][j] = j;
|
|
|
|
}
|
|
|
|
}
|
2017-02-10 11:55:50 +01:00
|
|
|
#if CONFIG_MULTITHREAD
|
2017-03-14 21:45:20 +01:00
|
|
|
tile_data->row_base_thresh_freq_fact = NULL;
|
2017-02-10 11:55:50 +01:00
|
|
|
#endif
|
2014-11-26 01:53:47 +01:00
|
|
|
}
|
Tile based adaptive mode search in RD loop
Make the spatially adaptive mode search in rate-distortion
optimization loop inter tile independent. Experiments suggest that
this does not significantly change the coding staticstics.
Single tile, speed 3:
pedestrian_area 1080p 1500 kbps
59192 b/f, 40.611 dB, 101689 ms
blue_sky 1080p 1500 kbps
58505 b/f, 36.347 dB, 62458 ms
mobile_cal 720p 1000 kbps
13335 b/f, 35.646 dB, 45655 ms
as compared to 4 column tiles, speed 3:
pedestrian_area 1080p 1500 kbps
59329 b/f, 40.597 dB, 101917 ms
blue_sky 1080p 1500 kbps
58712 b/f, 36.320 dB, 62693 ms
mobile_cal 720p 1000 kbps
13191 b/f, 35.485 dB, 45319 ms
Change-Id: I35c6e1e0a859fece8f4145dec28623cbc6a12325
2014-10-24 01:54:45 +02:00
|
|
|
}
|
|
|
|
|
2014-10-16 21:29:48 +02:00
|
|
|
for (tile_row = 0; tile_row < tile_rows; ++tile_row) {
|
|
|
|
for (tile_col = 0; tile_col < tile_cols; ++tile_col) {
|
2017-02-10 11:55:50 +01:00
|
|
|
TileDataEnc *this_tile = &cpi->tile_data[tile_row * tile_cols + tile_col];
|
|
|
|
TileInfo *tile_info = &this_tile->tile_info;
|
2014-10-27 19:11:50 +01:00
|
|
|
vp9_tile_init(tile_info, cm, tile_row, tile_col);
|
2014-10-16 21:29:48 +02:00
|
|
|
|
2014-11-26 01:53:47 +01:00
|
|
|
cpi->tile_tok[tile_row][tile_col] = pre_tok + tile_tok;
|
|
|
|
pre_tok = cpi->tile_tok[tile_row][tile_col];
|
2014-10-27 19:11:50 +01:00
|
|
|
tile_tok = allocated_tokens(*tile_info);
|
2017-02-02 09:49:29 +01:00
|
|
|
|
|
|
|
cpi->tplist[tile_row][tile_col] = tplist + tplist_count;
|
|
|
|
tplist = cpi->tplist[tile_row][tile_col];
|
|
|
|
tplist_count = get_num_vert_units(*tile_info, MI_BLOCK_SIZE_LOG2);
|
2014-10-16 21:29:48 +02:00
|
|
|
}
|
|
|
|
}
|
2014-11-26 01:53:47 +01:00
|
|
|
}
|
|
|
|
|
2017-02-02 09:49:29 +01:00
|
|
|
void vp9_encode_sb_row(VP9_COMP *cpi, ThreadData *td, int tile_row,
|
|
|
|
int tile_col, int mi_row) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
const int tile_cols = 1 << cm->log2_tile_cols;
|
|
|
|
TileDataEnc *this_tile = &cpi->tile_data[tile_row * tile_cols + tile_col];
|
|
|
|
const TileInfo *const tile_info = &this_tile->tile_info;
|
|
|
|
TOKENEXTRA *tok = NULL;
|
|
|
|
int tile_sb_row;
|
|
|
|
int tile_mb_cols = (tile_info->mi_col_end - tile_info->mi_col_start + 1) >> 1;
|
|
|
|
|
|
|
|
tile_sb_row = mi_cols_aligned_to_sb(mi_row - tile_info->mi_row_start) >>
|
|
|
|
MI_BLOCK_SIZE_LOG2;
|
|
|
|
get_start_tok(cpi, tile_row, tile_col, mi_row, &tok);
|
|
|
|
cpi->tplist[tile_row][tile_col][tile_sb_row].start = tok;
|
|
|
|
|
|
|
|
if (cpi->sf.use_nonrd_pick_mode)
|
|
|
|
encode_nonrd_sb_row(cpi, td, this_tile, mi_row, &tok);
|
|
|
|
else
|
|
|
|
encode_rd_sb_row(cpi, td, this_tile, mi_row, &tok);
|
|
|
|
|
|
|
|
cpi->tplist[tile_row][tile_col][tile_sb_row].stop = tok;
|
|
|
|
cpi->tplist[tile_row][tile_col][tile_sb_row].count =
|
|
|
|
(unsigned int)(cpi->tplist[tile_row][tile_col][tile_sb_row].stop -
|
|
|
|
cpi->tplist[tile_row][tile_col][tile_sb_row].start);
|
|
|
|
assert(tok - cpi->tplist[tile_row][tile_col][tile_sb_row].start <=
|
|
|
|
get_token_alloc(MI_BLOCK_SIZE >> 1, tile_mb_cols));
|
|
|
|
|
|
|
|
(void)tile_mb_cols;
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
void vp9_encode_tile(VP9_COMP *cpi, ThreadData *td, int tile_row,
|
|
|
|
int tile_col) {
|
2014-12-03 00:47:41 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
const int tile_cols = 1 << cm->log2_tile_cols;
|
2016-07-27 05:43:23 +02:00
|
|
|
TileDataEnc *this_tile = &cpi->tile_data[tile_row * tile_cols + tile_col];
|
|
|
|
const TileInfo *const tile_info = &this_tile->tile_info;
|
2016-06-22 21:20:06 +02:00
|
|
|
const int mi_row_start = tile_info->mi_row_start;
|
|
|
|
const int mi_row_end = tile_info->mi_row_end;
|
2014-12-03 00:47:41 +01:00
|
|
|
int mi_row;
|
|
|
|
|
2017-02-02 09:49:29 +01:00
|
|
|
for (mi_row = mi_row_start; mi_row < mi_row_end; mi_row += MI_BLOCK_SIZE)
|
|
|
|
vp9_encode_sb_row(cpi, td, tile_row, tile_col, mi_row);
|
2014-12-03 00:47:41 +01:00
|
|
|
}
|
|
|
|
|
2014-11-26 01:53:47 +01:00
|
|
|
static void encode_tiles(VP9_COMP *cpi) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
const int tile_cols = 1 << cm->log2_tile_cols;
|
|
|
|
const int tile_rows = 1 << cm->log2_tile_rows;
|
|
|
|
int tile_col, tile_row;
|
|
|
|
|
2014-12-03 00:47:41 +01:00
|
|
|
vp9_init_tile_data(cpi);
|
2014-06-06 03:03:40 +02:00
|
|
|
|
2014-12-03 00:47:41 +01:00
|
|
|
for (tile_row = 0; tile_row < tile_rows; ++tile_row)
|
|
|
|
for (tile_col = 0; tile_col < tile_cols; ++tile_col)
|
|
|
|
vp9_encode_tile(cpi, &cpi->td, tile_row, tile_col);
|
2014-06-06 03:03:40 +02:00
|
|
|
}
|
|
|
|
|
2014-07-17 20:54:43 +02:00
|
|
|
#if CONFIG_FP_MB_STATS
|
|
|
|
static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats,
|
|
|
|
VP9_COMMON *cm, uint8_t **this_frame_mb_stats) {
|
|
|
|
uint8_t *mb_stats_in = firstpass_mb_stats->mb_stats_start +
|
2016-07-27 05:43:23 +02:00
|
|
|
cm->current_video_frame * cm->MBs * sizeof(uint8_t);
|
2014-07-17 20:54:43 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (mb_stats_in > firstpass_mb_stats->mb_stats_end) return EOF;
|
2014-07-17 20:54:43 +02:00
|
|
|
|
|
|
|
*this_frame_mb_stats = mb_stats_in;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-02-10 20:25:23 +01:00
|
|
|
static void encode_frame_internal(VP9_COMP *cpi) {
|
2014-04-08 00:51:48 +02:00
|
|
|
SPEED_FEATURES *const sf = &cpi->sf;
|
2014-11-21 20:11:06 +01:00
|
|
|
ThreadData *const td = &cpi->td;
|
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-02-10 20:25:23 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
2015-04-21 14:36:58 +02:00
|
|
|
xd->mi = cm->mi_grid_visible;
|
|
|
|
xd->mi[0] = cm->mi;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
vp9_zero(*td->counts);
|
2016-09-19 19:04:47 +02:00
|
|
|
vp9_zero(cpi->td.rd_counts);
|
2015-10-14 11:38:49 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
xd->lossless = cm->base_qindex == 0 && cm->y_dc_delta_q == 0 &&
|
|
|
|
cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0;
|
2014-06-03 21:52:49 +02:00
|
|
|
|
2014-09-24 15:36:34 +02:00
|
|
|
#if CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if (cm->use_highbitdepth)
|
2017-06-30 00:07:55 +02:00
|
|
|
x->fwd_txfm4x4 = xd->lossless ? vp9_highbd_fwht4x4 : vpx_highbd_fdct4x4;
|
2014-10-24 09:48:02 +02:00
|
|
|
else
|
2017-06-30 00:07:55 +02:00
|
|
|
x->fwd_txfm4x4 = xd->lossless ? vp9_fwht4x4 : vpx_fdct4x4;
|
2017-07-01 00:29:46 +02:00
|
|
|
x->highbd_inv_txfm_add =
|
2016-07-27 05:43:23 +02:00
|
|
|
xd->lossless ? vp9_highbd_iwht4x4_add : vp9_highbd_idct4x4_add;
|
2014-09-24 15:36:34 +02:00
|
|
|
#else
|
2017-06-30 00:07:55 +02:00
|
|
|
x->fwd_txfm4x4 = xd->lossless ? vp9_fwht4x4 : vpx_fdct4x4;
|
2014-09-24 15:36:34 +02:00
|
|
|
#endif // CONFIG_VP9_HIGHBITDEPTH
|
2017-07-01 00:29:46 +02:00
|
|
|
x->inv_txfm_add = xd->lossless ? vp9_iwht4x4_add : vp9_idct4x4_add;
|
2014-06-03 21:52:49 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (xd->lossless) x->optimize = 0;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
2015-02-04 02:50:48 +01:00
|
|
|
cm->tx_mode = select_tx_mode(cpi, xd);
|
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
vp9_frame_init_quantizer(cpi);
|
|
|
|
|
|
|
|
vp9_initialize_rd_consts(cpi);
|
2015-03-07 00:17:59 +01:00
|
|
|
vp9_initialize_me_consts(cpi, x, cm->base_qindex);
|
2014-01-29 17:39:39 +01:00
|
|
|
init_encode_frame_mb_context(cpi);
|
2016-07-27 05:43:23 +02:00
|
|
|
cm->use_prev_frame_mvs =
|
|
|
|
!cm->error_resilient_mode && cm->width == cm->last_width &&
|
|
|
|
cm->height == cm->last_height && !cm->intra_only && cm->last_show_frame;
|
2014-12-04 23:44:23 +01:00
|
|
|
// Special case: set prev_mi to NULL when the previous mode info
|
|
|
|
// context cannot be used.
|
2016-07-27 05:43:23 +02:00
|
|
|
cm->prev_mi =
|
|
|
|
cm->use_prev_frame_mvs ? cm->prev_mip + cm->mi_stride + 1 : NULL;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
2014-07-02 01:10:44 +02:00
|
|
|
x->quant_fp = cpi->sf.use_quant_fp;
|
2014-08-06 00:42:12 +02:00
|
|
|
vp9_zero(x->skip_txfm);
|
2014-04-08 00:51:48 +02:00
|
|
|
if (sf->use_nonrd_pick_mode) {
|
2014-02-13 20:41:08 +01:00
|
|
|
// Initialize internal buffer pointers for rtc coding, where non-RD
|
|
|
|
// mode decision is used and hence no buffer pointer swap needed.
|
|
|
|
int i;
|
|
|
|
struct macroblock_plane *const p = x->plane;
|
|
|
|
struct macroblockd_plane *const pd = xd->plane;
|
2014-11-21 20:11:06 +01:00
|
|
|
PICK_MODE_CONTEXT *ctx = &cpi->td.pc_root->none;
|
2014-02-13 20:41:08 +01:00
|
|
|
|
|
|
|
for (i = 0; i < MAX_MB_PLANE; ++i) {
|
|
|
|
p[i].coeff = ctx->coeff_pbuf[i][0];
|
|
|
|
p[i].qcoeff = ctx->qcoeff_pbuf[i][0];
|
|
|
|
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][0];
|
|
|
|
p[i].eobs = ctx->eobs_pbuf[i][0];
|
|
|
|
}
|
2014-03-14 20:07:21 +01:00
|
|
|
vp9_zero(x->zcoeff_blk);
|
2014-04-02 02:32:20 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cm->frame_type != KEY_FRAME && cpi->rc.frames_since_golden == 0 &&
|
2016-08-03 02:37:32 +02:00
|
|
|
!(cpi->oxcf.lag_in_frames > 0 && cpi->oxcf.rc_mode == VPX_VBR) &&
|
2015-08-05 22:53:26 +02:00
|
|
|
!cpi->use_svc)
|
2015-04-15 19:49:07 +02:00
|
|
|
cpi->ref_frame_flags &= (~VP9_GOLD_FLAG);
|
|
|
|
|
2014-05-02 00:14:39 +02:00
|
|
|
if (sf->partition_search_type == SOURCE_VAR_BASED_PARTITION)
|
|
|
|
source_var_based_partition_search_method(cpi);
|
2014-02-13 20:41:08 +01:00
|
|
|
}
|
|
|
|
|
2014-01-29 17:39:39 +01:00
|
|
|
{
|
|
|
|
struct vpx_usec_timer emr_timer;
|
|
|
|
vpx_usec_timer_start(&emr_timer);
|
|
|
|
|
2014-07-17 20:54:43 +02:00
|
|
|
#if CONFIG_FP_MB_STATS
|
2016-06-22 21:20:06 +02:00
|
|
|
if (cpi->use_fp_mb_stats) {
|
|
|
|
input_fpmb_stats(&cpi->twopass.firstpass_mb_stats, cm,
|
|
|
|
&cpi->twopass.this_frame_mb_stats);
|
|
|
|
}
|
2014-07-17 20:54:43 +02:00
|
|
|
#endif
|
|
|
|
|
2017-02-24 20:40:22 +01:00
|
|
|
if (!cpi->row_mt) {
|
2017-02-10 11:55:50 +01:00
|
|
|
cpi->row_mt_sync_read_ptr = vp9_row_mt_sync_read_dummy;
|
|
|
|
cpi->row_mt_sync_write_ptr = vp9_row_mt_sync_write_dummy;
|
|
|
|
// If allowed, encoding tiles in parallel with one thread handling one
|
|
|
|
// tile when row based multi-threading is disabled.
|
|
|
|
if (VPXMIN(cpi->oxcf.max_threads, 1 << cm->log2_tile_cols) > 1)
|
|
|
|
vp9_encode_tiles_mt(cpi);
|
|
|
|
else
|
|
|
|
encode_tiles(cpi);
|
|
|
|
} else {
|
|
|
|
cpi->row_mt_sync_read_ptr = vp9_row_mt_sync_read;
|
|
|
|
cpi->row_mt_sync_write_ptr = vp9_row_mt_sync_write;
|
|
|
|
vp9_encode_tiles_row_mt(cpi);
|
|
|
|
}
|
2014-01-29 17:39:39 +01:00
|
|
|
|
|
|
|
vpx_usec_timer_mark(&emr_timer);
|
|
|
|
cpi->time_encode_sb_row += vpx_usec_timer_elapsed(&emr_timer);
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
sf->skip_encode_frame =
|
|
|
|
sf->skip_encode_sb ? get_skip_encode_frame(cm, td) : 0;
|
2014-01-29 17:39:39 +01:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
// Keep record of the total distortion this time around for future use
|
|
|
|
cpi->last_frame_distortion = cpi->frame_distortion;
|
|
|
|
#endif
|
|
|
|
}
|
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
|
|
|
|
2014-05-02 00:00:25 +02:00
|
|
|
static INTERP_FILTER get_interp_filter(
|
|
|
|
const int64_t threshes[SWITCHABLE_FILTER_CONTEXTS], int is_alt_ref) {
|
2016-07-27 05:43:23 +02:00
|
|
|
if (!is_alt_ref && threshes[EIGHTTAP_SMOOTH] > threshes[EIGHTTAP] &&
|
2014-05-02 00:00:25 +02:00
|
|
|
threshes[EIGHTTAP_SMOOTH] > threshes[EIGHTTAP_SHARP] &&
|
|
|
|
threshes[EIGHTTAP_SMOOTH] > threshes[SWITCHABLE - 1]) {
|
|
|
|
return EIGHTTAP_SMOOTH;
|
|
|
|
} else if (threshes[EIGHTTAP_SHARP] > threshes[EIGHTTAP] &&
|
|
|
|
threshes[EIGHTTAP_SHARP] > threshes[SWITCHABLE - 1]) {
|
|
|
|
return EIGHTTAP_SHARP;
|
|
|
|
} else if (threshes[EIGHTTAP] > threshes[SWITCHABLE - 1]) {
|
|
|
|
return EIGHTTAP;
|
|
|
|
} else {
|
|
|
|
return SWITCHABLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-11 11:44:16 +01:00
|
|
|
static int compute_frame_aq_offset(struct VP9_COMP *cpi) {
|
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MODE_INFO **mi_8x8_ptr = cm->mi_grid_visible;
|
|
|
|
struct segmentation *const seg = &cm->seg;
|
|
|
|
|
|
|
|
int mi_row, mi_col;
|
|
|
|
int sum_delta = 0;
|
|
|
|
int map_index = 0;
|
|
|
|
int qdelta_index;
|
|
|
|
int segment_id;
|
|
|
|
|
|
|
|
for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) {
|
|
|
|
MODE_INFO **mi_8x8 = mi_8x8_ptr;
|
|
|
|
for (mi_col = 0; mi_col < cm->mi_cols; mi_col++, mi_8x8++) {
|
|
|
|
segment_id = mi_8x8[0]->segment_id;
|
|
|
|
qdelta_index = get_segdata(seg, segment_id, SEG_LVL_ALT_Q);
|
|
|
|
sum_delta += qdelta_index;
|
|
|
|
map_index++;
|
|
|
|
}
|
|
|
|
mi_8x8_ptr += cm->mi_stride;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum_delta / (cm->mi_rows * cm->mi_cols);
|
|
|
|
}
|
|
|
|
|
2012-10-31 01:53:32 +01:00
|
|
|
void vp9_encode_frame(VP9_COMP *cpi) {
|
2014-01-08 23:51:00 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2013-06-06 22:44:34 +02:00
|
|
|
|
2013-06-07 13:29:15 +02:00
|
|
|
// In the longer term the encoder should be generalized to match the
|
|
|
|
// decoder such that we allow compound where one of the 3 buffers has a
|
2013-07-24 16:58:26 +02:00
|
|
|
// different sign bias and that buffer is then the fixed ref. However, this
|
2013-06-07 13:29:15 +02:00
|
|
|
// requires further work in the rd loop. For now the only supported encoder
|
2013-08-20 21:55:41 +02:00
|
|
|
// side behavior is where the ALT ref buffer has opposite sign bias to
|
2013-06-07 13:29:15 +02:00
|
|
|
// the other two.
|
2013-10-03 18:07:24 +02:00
|
|
|
if (!frame_is_intra_only(cm)) {
|
2014-01-10 22:48:44 +01:00
|
|
|
if ((cm->ref_frame_sign_bias[ALTREF_FRAME] ==
|
2016-07-27 05:43:23 +02:00
|
|
|
cm->ref_frame_sign_bias[GOLDEN_FRAME]) ||
|
2014-01-10 22:48:44 +01:00
|
|
|
(cm->ref_frame_sign_bias[ALTREF_FRAME] ==
|
2016-07-27 05:43:23 +02:00
|
|
|
cm->ref_frame_sign_bias[LAST_FRAME])) {
|
2014-12-11 03:11:17 +01:00
|
|
|
cpi->allow_comp_inter_inter = 0;
|
2013-10-03 18:07:24 +02:00
|
|
|
} else {
|
2014-12-11 03:11:17 +01:00
|
|
|
cpi->allow_comp_inter_inter = 1;
|
2013-10-03 18:07:24 +02:00
|
|
|
cm->comp_fixed_ref = ALTREF_FRAME;
|
|
|
|
cm->comp_var_ref[0] = LAST_FRAME;
|
|
|
|
cm->comp_var_ref[1] = GOLDEN_FRAME;
|
|
|
|
}
|
2013-06-06 22:44:34 +02:00
|
|
|
}
|
|
|
|
|
2014-02-10 21:03:02 +01:00
|
|
|
if (cpi->sf.frame_parameter_update) {
|
2013-12-19 23:28:42 +01:00
|
|
|
int i;
|
2015-02-04 02:01:37 +01:00
|
|
|
RD_OPT *const rd_opt = &cpi->rd;
|
|
|
|
FRAME_COUNTS *counts = cpi->td.counts;
|
|
|
|
RD_COUNTS *const rdc = &cpi->td.rd_counts;
|
2014-04-04 00:51:40 +02:00
|
|
|
|
|
|
|
// This code does a single RD pass over the whole frame assuming
|
|
|
|
// either compound, single or hybrid prediction as per whatever has
|
|
|
|
// worked best for that type of frame in the past.
|
|
|
|
// It also predicts whether another coding mode would have worked
|
2016-06-15 03:57:29 +02:00
|
|
|
// better than this coding mode. If that is the case, it remembers
|
2014-04-04 00:51:40 +02:00
|
|
|
// that for subsequent frames.
|
2016-06-15 03:57:29 +02:00
|
|
|
// It also does the same analysis for transform size selection.
|
2014-01-31 20:08:27 +01:00
|
|
|
const MV_REFERENCE_FRAME frame_type = get_frame_type(cpi);
|
2014-05-02 00:00:25 +02:00
|
|
|
int64_t *const mode_thrs = rd_opt->prediction_type_threshes[frame_type];
|
|
|
|
int64_t *const filter_thrs = rd_opt->filter_threshes[frame_type];
|
|
|
|
const int is_alt_ref = frame_type == ALTREF_FRAME;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2012-10-09 18:18:21 +02:00
|
|
|
/* prediction (compound, single or hybrid) mode selection */
|
2014-12-11 03:11:17 +01:00
|
|
|
if (is_alt_ref || !cpi->allow_comp_inter_inter)
|
2014-04-04 00:51:40 +02:00
|
|
|
cm->reference_mode = SINGLE_REFERENCE;
|
2014-05-02 00:00:25 +02:00
|
|
|
else if (mode_thrs[COMPOUND_REFERENCE] > mode_thrs[SINGLE_REFERENCE] &&
|
2016-07-27 05:43:23 +02:00
|
|
|
mode_thrs[COMPOUND_REFERENCE] > mode_thrs[REFERENCE_MODE_SELECT] &&
|
|
|
|
check_dual_ref_flags(cpi) && cpi->static_mb_pct == 100)
|
2014-04-04 00:51:40 +02:00
|
|
|
cm->reference_mode = COMPOUND_REFERENCE;
|
2014-05-02 00:00:25 +02:00
|
|
|
else if (mode_thrs[SINGLE_REFERENCE] > mode_thrs[REFERENCE_MODE_SELECT])
|
2014-04-04 00:51:40 +02:00
|
|
|
cm->reference_mode = SINGLE_REFERENCE;
|
2012-07-14 00:21:29 +02:00
|
|
|
else
|
2014-04-04 00:51:40 +02:00
|
|
|
cm->reference_mode = REFERENCE_MODE_SELECT;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2014-05-02 00:00:25 +02:00
|
|
|
if (cm->interp_filter == SWITCHABLE)
|
|
|
|
cm->interp_filter = get_interp_filter(filter_thrs, is_alt_ref);
|
2013-07-08 23:49:33 +02:00
|
|
|
|
2014-02-10 20:25:23 +01:00
|
|
|
encode_frame_internal(cpi);
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2014-05-02 00:00:25 +02:00
|
|
|
for (i = 0; i < REFERENCE_MODES; ++i)
|
2014-11-21 20:11:06 +01:00
|
|
|
mode_thrs[i] = (mode_thrs[i] + rdc->comp_pred_diff[i] / cm->MBs) / 2;
|
2012-07-14 00:21:29 +02:00
|
|
|
|
2014-05-02 00:00:25 +02:00
|
|
|
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
|
2014-11-21 20:11:06 +01:00
|
|
|
filter_thrs[i] = (filter_thrs[i] + rdc->filter_diff[i] / cm->MBs) / 2;
|
2013-07-08 23:49:33 +02:00
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT) {
|
2012-07-14 00:21:29 +02:00
|
|
|
int single_count_zero = 0;
|
|
|
|
int comp_count_zero = 0;
|
|
|
|
|
2013-06-06 22:44:34 +02:00
|
|
|
for (i = 0; i < COMP_INTER_CONTEXTS; i++) {
|
2014-11-21 20:11:06 +01:00
|
|
|
single_count_zero += counts->comp_inter[i][0];
|
|
|
|
comp_count_zero += counts->comp_inter[i][1];
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (comp_count_zero == 0) {
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->reference_mode = SINGLE_REFERENCE;
|
2014-11-21 20:11:06 +01:00
|
|
|
vp9_zero(counts->comp_inter);
|
2012-07-14 00:21:29 +02:00
|
|
|
} else if (single_count_zero == 0) {
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->reference_mode = COMPOUND_REFERENCE;
|
2014-11-21 20:11:06 +01:00
|
|
|
vp9_zero(counts->comp_inter);
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
Dual 16x16 inter prediction.
This patch introduces the concept of dual inter16x16 prediction. A
16x16 inter-predicted macroblock can use 2 references instead of 1,
where both references use the same mvmode (new, near/est, zero). In the
case of newmv, this means that two MVs are coded instead of one. The
frame can be encoded in 3 ways: all MBs single-prediction, all MBs dual
prediction, or per-MB single/dual prediction selection ("hybrid"), in
which case a single bit is coded per-MB to indicate whether the MB uses
single or dual inter prediction.
In the future, we can (maybe?) get further gains by mixing this with
Adrian's 32x32 work, per-segment dual prediction settings, or adding
support for dual splitmv/8x8mv inter prediction.
Gain (on derf-set, CQ mode) is ~2.8% (SSIM) or ~3.6% (glb PSNR). Most
gain is at medium/high bitrates, but there's minor gains at low bitrates
also. Output was confirmed to match between encoder and decoder.
Note for optimization people: this patch introduces a 2nd version of
16x16/8x8 sixtap/bilin functions, which does an avg instead of a
store. They may want to look and make sure this is implemented to
their satisfaction so we can optimize it best in the future.
Change-ID: I59dc84b07cbb3ccf073ac0f756d03d294cb19281
2011-12-06 20:53:02 +01:00
|
|
|
}
|
2012-10-09 18:18:21 +02:00
|
|
|
|
2014-01-08 23:51:00 +01:00
|
|
|
if (cm->tx_mode == TX_MODE_SELECT) {
|
2013-06-06 20:14:04 +02:00
|
|
|
int count4x4 = 0;
|
|
|
|
int count8x8_lp = 0, count8x8_8x8p = 0;
|
|
|
|
int count16x16_16x16p = 0, count16x16_lp = 0;
|
|
|
|
int count32x32 = 0;
|
|
|
|
|
2013-07-23 21:54:04 +02:00
|
|
|
for (i = 0; i < TX_SIZE_CONTEXTS; ++i) {
|
2014-11-21 20:11:06 +01:00
|
|
|
count4x4 += counts->tx.p32x32[i][TX_4X4];
|
|
|
|
count4x4 += counts->tx.p16x16[i][TX_4X4];
|
|
|
|
count4x4 += counts->tx.p8x8[i][TX_4X4];
|
2013-06-06 20:14:04 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
count8x8_lp += counts->tx.p32x32[i][TX_8X8];
|
|
|
|
count8x8_lp += counts->tx.p16x16[i][TX_8X8];
|
|
|
|
count8x8_8x8p += counts->tx.p8x8[i][TX_8X8];
|
2013-06-06 20:14:04 +02:00
|
|
|
|
2014-11-21 20:11:06 +01:00
|
|
|
count16x16_16x16p += counts->tx.p16x16[i][TX_16X16];
|
|
|
|
count16x16_lp += counts->tx.p32x32[i][TX_16X16];
|
|
|
|
count32x32 += counts->tx.p32x32[i][TX_32X32];
|
2013-07-23 21:54:04 +02:00
|
|
|
}
|
2014-01-08 23:51:00 +01:00
|
|
|
if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0 &&
|
|
|
|
count32x32 == 0) {
|
|
|
|
cm->tx_mode = ALLOW_8X8;
|
2014-06-12 20:57:26 +02:00
|
|
|
reset_skip_tx_size(cm, TX_8X8);
|
2014-01-08 23:51:00 +01:00
|
|
|
} else if (count8x8_8x8p == 0 && count16x16_16x16p == 0 &&
|
|
|
|
count8x8_lp == 0 && count16x16_lp == 0 && count32x32 == 0) {
|
|
|
|
cm->tx_mode = ONLY_4X4;
|
2014-06-12 20:57:26 +02:00
|
|
|
reset_skip_tx_size(cm, 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
|
|
|
} else if (count8x8_lp == 0 && count16x16_lp == 0 && count4x4 == 0) {
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->tx_mode = ALLOW_32X32;
|
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
|
|
|
} else if (count32x32 == 0 && count8x8_lp == 0 && count4x4 == 0) {
|
2014-01-08 23:51:00 +01:00
|
|
|
cm->tx_mode = ALLOW_16X16;
|
2014-06-12 20:57:26 +02:00
|
|
|
reset_skip_tx_size(cm, TX_16X16);
|
2012-10-09 18:18:21 +02:00
|
|
|
}
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
} else {
|
2017-10-26 00:45:11 +02:00
|
|
|
FRAME_COUNTS *counts = cpi->td.counts;
|
2014-03-04 19:24:25 +01:00
|
|
|
cm->reference_mode = SINGLE_REFERENCE;
|
2017-10-26 00:45:11 +02:00
|
|
|
if (cpi->allow_comp_inter_inter && cpi->sf.use_compound_nonrd_pickmode &&
|
|
|
|
cpi->rc.alt_ref_gf_group && !cpi->rc.is_src_frame_alt_ref &&
|
|
|
|
cm->frame_type != KEY_FRAME)
|
|
|
|
cm->reference_mode = REFERENCE_MODE_SELECT;
|
|
|
|
|
2014-02-10 20:25:23 +01:00
|
|
|
encode_frame_internal(cpi);
|
2017-10-26 00:45:11 +02:00
|
|
|
|
|
|
|
if (cm->reference_mode == REFERENCE_MODE_SELECT) {
|
|
|
|
int single_count_zero = 0;
|
|
|
|
int comp_count_zero = 0;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < COMP_INTER_CONTEXTS; i++) {
|
|
|
|
single_count_zero += counts->comp_inter[i][0];
|
|
|
|
comp_count_zero += counts->comp_inter[i][1];
|
|
|
|
}
|
|
|
|
if (comp_count_zero == 0) {
|
|
|
|
cm->reference_mode = SINGLE_REFERENCE;
|
|
|
|
vp9_zero(counts->comp_inter);
|
|
|
|
} else if (single_count_zero == 0) {
|
|
|
|
cm->reference_mode = COMPOUND_REFERENCE;
|
|
|
|
vp9_zero(counts->comp_inter);
|
|
|
|
}
|
|
|
|
}
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
Dual 16x16 inter prediction.
This patch introduces the concept of dual inter16x16 prediction. A
16x16 inter-predicted macroblock can use 2 references instead of 1,
where both references use the same mvmode (new, near/est, zero). In the
case of newmv, this means that two MVs are coded instead of one. The
frame can be encoded in 3 ways: all MBs single-prediction, all MBs dual
prediction, or per-MB single/dual prediction selection ("hybrid"), in
which case a single bit is coded per-MB to indicate whether the MB uses
single or dual inter prediction.
In the future, we can (maybe?) get further gains by mixing this with
Adrian's 32x32 work, per-segment dual prediction settings, or adding
support for dual splitmv/8x8mv inter prediction.
Gain (on derf-set, CQ mode) is ~2.8% (SSIM) or ~3.6% (glb PSNR). Most
gain is at medium/high bitrates, but there's minor gains at low bitrates
also. Output was confirmed to match between encoder and decoder.
Note for optimization people: this patch introduces a 2nd version of
16x16/8x8 sixtap/bilin functions, which does an avg instead of a
store. They may want to look and make sure this is implemented to
their satisfaction so we can optimize it best in the future.
Change-ID: I59dc84b07cbb3ccf073ac0f756d03d294cb19281
2011-12-06 20:53:02 +01:00
|
|
|
|
2016-06-15 03:57:29 +02:00
|
|
|
// If segmented AQ is enabled compute the average AQ weighting.
|
2016-03-11 11:44:16 +01:00
|
|
|
if (cm->seg.enabled && (cpi->oxcf.aq_mode != NO_AQ) &&
|
|
|
|
(cm->seg.update_map || cm->seg.update_data)) {
|
|
|
|
cm->seg.aq_av_offset = compute_frame_aq_offset(cpi);
|
|
|
|
}
|
|
|
|
}
|
2016-06-15 03:57:29 +02:00
|
|
|
|
2014-01-10 22:48:44 +01:00
|
|
|
static void sum_intra_stats(FRAME_COUNTS *counts, const MODE_INFO *mi) {
|
2016-01-20 01:40:20 +01:00
|
|
|
const PREDICTION_MODE y_mode = mi->mode;
|
|
|
|
const PREDICTION_MODE uv_mode = mi->uv_mode;
|
|
|
|
const BLOCK_SIZE bsize = mi->sb_type;
|
2013-08-22 01:25:02 +02:00
|
|
|
|
|
|
|
if (bsize < BLOCK_8X8) {
|
2013-05-20 21:08:22 +02:00
|
|
|
int idx, idy;
|
2014-03-07 19:56:20 +01:00
|
|
|
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
|
|
|
|
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
|
|
|
|
for (idy = 0; idy < 2; idy += num_4x4_h)
|
|
|
|
for (idx = 0; idx < 2; idx += num_4x4_w)
|
2014-01-10 22:48:44 +01:00
|
|
|
++counts->y_mode[0][mi->bmi[idy * 2 + idx].as_mode];
|
2013-08-22 01:25:02 +02:00
|
|
|
} else {
|
2014-01-10 22:48:44 +01:00
|
|
|
++counts->y_mode[size_group_lookup[bsize]][y_mode];
|
2012-07-14 00:21:29 +02:00
|
|
|
}
|
2014-03-07 19:56:20 +01:00
|
|
|
|
|
|
|
++counts->uv_mode[y_mode][uv_mode];
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
2011-05-12 18:01:55 +02:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void update_zeromv_cnt(VP9_COMP *const cpi, const MODE_INFO *const mi,
|
|
|
|
int mi_row, int mi_col, BLOCK_SIZE bsize) {
|
2016-04-21 23:00:26 +02:00
|
|
|
const VP9_COMMON *const cm = &cpi->common;
|
|
|
|
MV mv = mi->mv[0].as_mv;
|
|
|
|
const int bw = num_8x8_blocks_wide_lookup[bsize];
|
|
|
|
const int bh = num_8x8_blocks_high_lookup[bsize];
|
|
|
|
const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
|
|
|
|
const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
|
|
|
|
const int block_index = mi_row * cm->mi_cols + mi_col;
|
|
|
|
int x, y;
|
|
|
|
for (y = 0; y < ymis; y++)
|
|
|
|
for (x = 0; x < xmis; x++) {
|
|
|
|
int map_offset = block_index + y * cm->mi_cols + x;
|
2016-04-25 23:34:41 +02:00
|
|
|
if (is_inter_block(mi) && mi->segment_id <= CR_SEGMENT_ID_BOOST2) {
|
2016-04-21 23:00:26 +02:00
|
|
|
if (abs(mv.row) < 8 && abs(mv.col) < 8) {
|
|
|
|
if (cpi->consec_zero_mv[map_offset] < 255)
|
2016-07-27 05:43:23 +02:00
|
|
|
cpi->consec_zero_mv[map_offset]++;
|
2016-04-21 23:00:26 +02:00
|
|
|
} else {
|
|
|
|
cpi->consec_zero_mv[map_offset] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
static void encode_superblock(VP9_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
|
|
|
|
int output_enabled, int mi_row, int mi_col,
|
|
|
|
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx) {
|
2014-01-10 22:48:44 +01:00
|
|
|
VP9_COMMON *const cm = &cpi->common;
|
2014-11-21 20:11:06 +01:00
|
|
|
MACROBLOCK *const x = &td->mb;
|
2014-01-10 22:48:44 +01:00
|
|
|
MACROBLOCKD *const xd = &x->e_mbd;
|
2016-03-01 00:16:42 +01:00
|
|
|
MODE_INFO *mi = xd->mi[0];
|
2016-07-27 05:43:23 +02:00
|
|
|
const int seg_skip =
|
|
|
|
segfeature_active(&cm->seg, mi->segment_id, SEG_LVL_SKIP);
|
2016-01-20 01:40:20 +01:00
|
|
|
x->skip_recode = !x->select_tx_size && mi->sb_type >= BLOCK_8X8 &&
|
2014-03-25 22:27:45 +01:00
|
|
|
cpi->oxcf.aq_mode != COMPLEXITY_AQ &&
|
|
|
|
cpi->oxcf.aq_mode != CYCLIC_REFRESH_AQ &&
|
|
|
|
cpi->sf.allow_skip_recode;
|
2014-03-20 16:16:35 +01:00
|
|
|
|
2014-08-07 01:11:22 +02:00
|
|
|
if (!x->skip_recode && !cpi->sf.use_nonrd_pick_mode)
|
2015-04-24 05:47:40 +02:00
|
|
|
memset(x->skip_txfm, 0, sizeof(x->skip_txfm));
|
2014-08-07 01:11:22 +02:00
|
|
|
|
2013-11-06 06:07:08 +01:00
|
|
|
x->skip_optimize = ctx->is_coded;
|
|
|
|
ctx->is_coded = 1;
|
2013-08-08 00:22:51 +02:00
|
|
|
x->use_lp32x32fdct = cpi->sf.use_lp32x32fdct;
|
2013-07-09 01:48:47 +02:00
|
|
|
x->skip_encode = (!output_enabled && cpi->sf.skip_encode_frame &&
|
2013-11-13 02:28:27 +01:00
|
|
|
x->q_index < QIDX_SKIP_THRESH);
|
2014-03-14 20:07:21 +01:00
|
|
|
|
2016-07-27 05:43:23 +02:00
|
|
|
if (x->skip_encode) return;
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
if (!is_inter_block(mi)) {
|
2014-02-12 03:06:00 +01:00
|
|
|
int plane;
|
2016-06-15 20:39:41 +02:00
|
|
|
#if CONFIG_BETTER_HW_COMPATIBILITY && CONFIG_VP9_HIGHBITDEPTH
|
|
|
|
if ((xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) &&
|
|
|
|
(xd->above_mi == NULL || xd->left_mi == NULL) &&
|
|
|
|
need_top_left[mi->uv_mode])
|
|
|
|
assert(0);
|
|
|
|
#endif // CONFIG_BETTER_HW_COMPATIBILITY && CONFIG_VP9_HIGHBITDEPTH
|
2016-01-20 01:40:20 +01:00
|
|
|
mi->skip = 1;
|
2014-02-12 03:06:00 +01:00
|
|
|
for (plane = 0; plane < MAX_MB_PLANE; ++plane)
|
2016-04-25 21:40:56 +02:00
|
|
|
vp9_encode_intra_block_plane(x, VPXMAX(bsize, BLOCK_8X8), plane, 1);
|
2016-07-27 05:43:23 +02:00
|
|
|
if (output_enabled) sum_intra_stats(td->counts, mi);
|
2016-04-08 20:38:25 +02:00
|
|
|
vp9_tokenize_sb(cpi, td, t, !output_enabled, seg_skip,
|
|
|
|
VPXMAX(bsize, BLOCK_8X8));
|
2012-11-08 20:03:00 +01:00
|
|
|
} else {
|
2014-01-03 21:50:57 +01:00
|
|
|
int ref;
|
2016-01-20 01:40:20 +01:00
|
|
|
const int is_compound = has_second_ref(mi);
|
|
|
|
set_ref_ptrs(cm, xd, mi->ref_frame[0], mi->ref_frame[1]);
|
2014-01-03 21:50:57 +01:00
|
|
|
for (ref = 0; ref < 1 + is_compound; ++ref) {
|
2016-07-27 05:43:23 +02:00
|
|
|
YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mi->ref_frame[ref]);
|
2015-02-18 18:40:34 +01:00
|
|
|
assert(cfg != NULL);
|
2014-03-03 23:58:43 +01:00
|
|
|
vp9_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
|
|
|
|
&xd->block_refs[ref]->sf);
|
2013-05-21 00:59:39 +02:00
|
|
|
}
|
Hybrid partition search for rtc coding mode
This commit re-designs the recursive partition search scheme in
rtc speed -5. It first checks if the current block is under cyclic
refresh mode. If so, apply recursive partition search. Otherwise,
perform sub-sampled pixel based partition selection. When the
pre-selection finds the partition size should be 32x32 or above,
use the partition size directly. Otherwise, apply partition search
at nearby levels around the preset partition size.
It is enabled in speed -5. The compression performance of rtc
speed -5 is improved by 9.4%. Speed wise, the run-time goes slower
from 1% to 10%.
nik_720p, 1000 kbps
33220 b/f, 38.977 dB, 10109 ms -> 33200 b/f, 39.119 dB, 10210 ms
vidyo1_720p, 1000 kbps
16536 b/f, 40.495 dB, 10119 ms -> 16536 b/f, 40.827 dB, 11287 ms
Change-Id: I65adba352e3adc03bae50854ddaea1b421653c6c
2014-10-17 17:58:28 +02:00
|
|
|
if (!(cpi->sf.reuse_inter_pred_sby && ctx->pred_pixel_ready) || seg_skip)
|
2015-08-18 03:19:22 +02:00
|
|
|
vp9_build_inter_predictors_sby(xd, mi_row, mi_col,
|
|
|
|
VPXMAX(bsize, BLOCK_8X8));
|
2014-06-20 19:11:34 +02:00
|
|
|
|
2015-08-18 03:19:22 +02:00
|
|
|
vp9_build_inter_predictors_sbuv(xd, mi_row, mi_col,
|
|
|
|
VPXMAX(bsize, BLOCK_8X8));
|
2013-01-06 03:20:25 +01:00
|
|
|
|
2015-08-18 03:19:22 +02:00
|
|
|
vp9_encode_sb(x, VPXMAX(bsize, BLOCK_8X8));
|
2016-04-08 20:38:25 +02:00
|
|
|
vp9_tokenize_sb(cpi, td, t, !output_enabled, seg_skip,
|
|
|
|
VPXMAX(bsize, BLOCK_8X8));
|
2013-01-06 03:20:25 +01:00
|
|
|
}
|
|
|
|
|
2016-07-22 21:10:46 +02:00
|
|
|
if (seg_skip) {
|
|
|
|
assert(mi->skip);
|
|
|
|
}
|
|
|
|
|
2013-01-06 03:20:25 +01:00
|
|
|
if (output_enabled) {
|
2016-07-27 05:43:23 +02:00
|
|
|
if (cm->tx_mode == TX_MODE_SELECT && mi->sb_type >= BLOCK_8X8 &&
|
2016-07-22 21:10:46 +02:00
|
|
|
!(is_inter_block(mi) && mi->skip)) {
|
2015-06-16 02:31:38 +02:00
|
|
|
++get_tx_counts(max_txsize_lookup[bsize], get_tx_size_context(xd),
|
2016-01-20 01:40:20 +01:00
|
|
|
&td->counts->tx)[mi->tx_size];
|
2013-01-06 03:20:25 +01:00
|
|
|
} else {
|
2013-06-19 23:26:49 +02:00
|
|
|
// The new intra coding scheme requires no change of transform size
|
2016-01-20 01:40:20 +01:00
|
|
|
if (is_inter_block(mi)) {
|
2016-03-01 00:16:42 +01:00
|
|
|
mi->tx_size = VPXMIN(tx_mode_to_biggest_tx_size[cm->tx_mode],
|
|
|
|
max_txsize_lookup[bsize]);
|
2013-05-17 21:50:40 +02:00
|
|
|
} else {
|
2016-03-01 00:16:42 +01:00
|
|
|
mi->tx_size = (bsize >= BLOCK_8X8) ? mi->tx_size : TX_4X4;
|
2013-05-17 21:50:40 +02:00
|
|
|
}
|
2012-11-08 20:03:00 +01:00
|
|
|
}
|
2016-06-22 21:20:06 +02:00
|
|
|
|
2016-01-20 01:40:20 +01:00
|
|
|
++td->counts->tx.tx_totals[mi->tx_size];
|
|
|
|
++td->counts->tx.tx_totals[get_uv_tx_size(mi, &xd->plane[1])];
|
2015-06-23 17:34:06 +02:00
|
|
|
if (cm->seg.enabled && cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
|
2016-01-20 01:40:20 +01:00
|
|
|
vp9_cyclic_refresh_update_sb_postencode(cpi, mi, mi_row, mi_col, bsize);
|
2016-04-21 23:00:26 +02:00
|
|
|
if (cpi->oxcf.pass == 0 && cpi->svc.temporal_layer_id == 0)
|
|
|
|
update_zeromv_cnt(cpi, mi, mi_row, mi_col, bsize);
|
2012-11-08 20:03:00 +01:00
|
|
|
}
|
2012-08-20 23:43:34 +02:00
|
|
|
}
|