Update aom to v1.0.0

Update aom to commit id d14c5bb4f336ef1842046089849dee4a301fbbf0.
This commit is contained in:
trav90 2018-10-19 21:52:15 -05:00 • committed by Roy Tam
commit 48f6d2e034
1087 changed files with 154333 additions and 265310 deletions

File diff suppressed because it is too large Load diff

View file

@ -39,21 +39,29 @@ static const double aq_c_var_thresholds[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = {
{ -3.0, -2.0, -1.0, 100.00, 100.0 }
};
#define DEFAULT_COMPLEXITY 64
static int get_aq_c_strength(int q_index, aom_bit_depth_t bit_depth) {
// Approximate base quatizer (truncated to int)
const int base_quant = av1_ac_quant(q_index, 0, bit_depth) / 4;
const int base_quant = av1_ac_quant_Q3(q_index, 0, bit_depth) / 4;
return (base_quant > 10) + (base_quant > 25);
}
void av1_setup_in_frame_q_adj(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
struct segmentation *const seg = &cm->seg;
int resolution_change =
cm->prev_frame && (cm->width != cm->prev_frame->width ||
cm->height != cm->prev_frame->height);
// Make SURE use of floating point in this function is safe.
aom_clear_system_state();
if (resolution_change) {
memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
av1_clearall_segfeatures(seg);
av1_disable_segmentation(seg);
return;
}
if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
@ -74,9 +82,6 @@ void av1_setup_in_frame_q_adj(AV1_COMP *cpi) {
av1_enable_segmentation(seg);
// Select delta coding method.
seg->abs_delta = SEGMENT_DELTADATA;
// Default segment "Q" feature is disabled so it defaults to the baseline Q.
av1_disable_segfeature(seg, DEFAULT_AQ2_SEG, SEG_LVL_ALT_Q);
@ -107,13 +112,13 @@ void av1_setup_in_frame_q_adj(AV1_COMP *cpi) {
#define DEFAULT_LV_THRESH 10.0
#define MIN_DEFAULT_LV_THRESH 8.0
#define VAR_STRENGTH_STEP 0.25
// Select a segment for the current block.
// The choice of segment for a block depends on the ratio of the projected
// bits for the block vs a target average and its spatial complexity.
void av1_caq_select_segment(const AV1_COMP *cpi, MACROBLOCK *mb, BLOCK_SIZE bs,
int mi_row, int mi_col, int projected_rate) {
const AV1_COMMON *const cm = &cpi->common;
const int num_planes = av1_num_planes(cm);
const int mi_offset = mi_row * cm->mi_cols + mi_col;
const int xmis = AOMMIN(cm->mi_cols - mi_col, mi_size_wide[bs]);
@ -126,9 +131,10 @@ void av1_caq_select_segment(const AV1_COMP *cpi, MACROBLOCK *mb, BLOCK_SIZE bs,
segment = DEFAULT_AQ2_SEG;
} else {
// Rate depends on fraction of a SB64 in frame (xmis * ymis / bw * bh).
// It is converted to bits * 256 units.
const int64_t num = (int64_t)cpi->rc.sb64_target_rate * xmis * ymis * 256;
const int denom = cm->mib_size * cm->mib_size;
// It is converted to bits << AV1_PROB_COST_SHIFT units.
const int64_t num = (int64_t)(cpi->rc.sb64_target_rate * xmis * ymis)
<< AV1_PROB_COST_SHIFT;
const int denom = cm->seq_params.mib_size * cm->seq_params.mib_size;
const int target_rate = (int)(num / denom);
double logvar;
double low_var_thresh;
@ -139,7 +145,7 @@ void av1_caq_select_segment(const AV1_COMP *cpi, MACROBLOCK *mb, BLOCK_SIZE bs,
MIN_DEFAULT_LV_THRESH)
: DEFAULT_LV_THRESH;
av1_setup_src_planes(mb, cpi->source, mi_row, mi_col);
av1_setup_src_planes(mb, cpi->source, mi_row, mi_col, num_planes);
logvar = av1_log_block_var(cpi, mb, bs);
segment = AQ_C_SEGMENTS - 1; // Just in case no break out below.

View file

@ -320,7 +320,7 @@ void av1_cyclic_refresh_check_golden_update(AV1_COMP *const cpi) {
double fraction_low = 0.0;
int low_content_frame = 0;
MODE_INFO **mi;
MB_MODE_INFO **mi;
RATE_CONTROL *const rc = &cpi->rc;
const int rows = cm->mi_rows, cols = cm->mi_cols;
int cnt1 = 0, cnt2 = 0;
@ -330,12 +330,12 @@ void av1_cyclic_refresh_check_golden_update(AV1_COMP *const cpi) {
mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
for (mi_col = 0; mi_col < cols; mi_col++) {
int16_t abs_mvr = mi[0]->mbmi.mv[0].as_mv.row >= 0
? mi[0]->mbmi.mv[0].as_mv.row
: -1 * mi[0]->mbmi.mv[0].as_mv.row;
int16_t abs_mvc = mi[0]->mbmi.mv[0].as_mv.col >= 0
? mi[0]->mbmi.mv[0].as_mv.col
: -1 * mi[0]->mbmi.mv[0].as_mv.col;
int16_t abs_mvr = mi[0]->mv[0].as_mv.row >= 0
? mi[0]->mv[0].as_mv.row
: -1 * mi[0]->mv[0].as_mv.row;
int16_t abs_mvc = mi[0]->mv[0].as_mv.col >= 0
? mi[0]->mv[0].as_mv.col
: -1 * mi[0]->mv[0].as_mv.col;
// Calculate the motion of the background.
if (abs_mvr <= 16 && abs_mvc <= 16) {
@ -389,8 +389,10 @@ static void cyclic_refresh_update_map(AV1_COMP *const cpi) {
int i, block_count, bl_index, sb_rows, sb_cols, sbs_in_frame;
int xmis, ymis, x, y;
memset(seg_map, CR_SEGMENT_ID_BASE, cm->mi_rows * cm->mi_cols);
sb_cols = (cm->mi_cols + cm->mib_size - 1) / cm->mib_size;
sb_rows = (cm->mi_rows + cm->mib_size - 1) / cm->mib_size;
sb_cols =
(cm->mi_cols + cm->seq_params.mib_size - 1) / cm->seq_params.mib_size;
sb_rows =
(cm->mi_rows + cm->seq_params.mib_size - 1) / cm->seq_params.mib_size;
sbs_in_frame = sb_cols * sb_rows;
// Number of target blocks to get the q delta (segment 1).
block_count = cr->percent_refresh * cm->mi_rows * cm->mi_cols / 100;
@ -406,8 +408,8 @@ static void cyclic_refresh_update_map(AV1_COMP *const cpi) {
// Get the mi_row/mi_col corresponding to superblock index i.
int sb_row_index = (i / sb_cols);
int sb_col_index = i - sb_row_index * sb_cols;
int mi_row = sb_row_index * cm->mib_size;
int mi_col = sb_col_index * cm->mib_size;
int mi_row = sb_row_index * cm->seq_params.mib_size;
int mi_col = sb_col_index * cm->seq_params.mib_size;
int qindex_thresh =
cpi->oxcf.content == AOM_CONTENT_SCREEN
? av1_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST2, cm->base_qindex)
@ -416,14 +418,14 @@ static void cyclic_refresh_update_map(AV1_COMP *const cpi) {
assert(mi_col >= 0 && mi_col < cm->mi_cols);
bl_index = mi_row * cm->mi_cols + mi_col;
// Loop through all MI blocks in superblock and update map.
xmis = AOMMIN(cm->mi_cols - mi_col, cm->mib_size);
ymis = AOMMIN(cm->mi_rows - mi_row, cm->mib_size);
xmis = AOMMIN(cm->mi_cols - mi_col, cm->seq_params.mib_size);
ymis = AOMMIN(cm->mi_rows - mi_row, cm->seq_params.mib_size);
for (y = 0; y < ymis; y++) {
for (x = 0; x < xmis; x++) {
const int bl_index2 = bl_index + y * cm->mi_cols + x;
// If the block is as a candidate for clean up then mark it
// for possible boost/refresh (segment 1). The segment id may get
// reset to 0 later if block gets coded anything other than ZEROMV.
// reset to 0 later if block gets coded anything other than GLOBALMV.
if (cr->map[bl_index2] == 0) {
if (cr->last_coded_q_map[bl_index2] > qindex_thresh) sum_map++;
} else if (cr->map[bl_index2] < 0) {
@ -479,6 +481,16 @@ void av1_cyclic_refresh_setup(AV1_COMP *const cpi) {
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
struct segmentation *const seg = &cm->seg;
const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc);
int resolution_change =
cm->prev_frame && (cm->width != cm->prev_frame->width ||
cm->height != cm->prev_frame->height);
if (resolution_change) {
memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
av1_clearall_segfeatures(seg);
aom_clear_system_state();
av1_disable_segmentation(seg);
return;
}
if (cm->current_video_frame == 0) cr->low_content_avg = 0.0;
// Don't apply refresh on key frame or enhancement layer frames.
if (!apply_cyclic_refresh || cm->frame_type == KEY_FRAME) {
@ -509,8 +521,6 @@ void av1_cyclic_refresh_setup(AV1_COMP *const cpi) {
// Clear down the segment map.
av1_enable_segmentation(&cm->seg);
av1_clearall_segfeatures(seg);
// Select delta coding method.
seg->abs_delta = SEGMENT_DELTADATA;
// Note: setting temporal_update has no effect, as the seg-map coding method
// (temporal or spatial) is determined in

View file

@ -19,6 +19,7 @@
#include "av1/encoder/ratectrl.h"
#include "av1/encoder/rd.h"
#include "av1/encoder/segmentation.h"
#include "av1/encoder/dwt.h"
#include "aom_ports/system_state.h"
#define ENERGY_MIN (-4)
@ -34,10 +35,8 @@ static const int segment_id[ENERGY_SPAN] = { 0, 1, 1, 2, 3, 4 };
#define SEGMENT_ID(i) segment_id[(i)-ENERGY_MIN]
DECLARE_ALIGNED(16, static const uint8_t, av1_all_zeros[MAX_SB_SIZE]) = { 0 };
#if CONFIG_HIGHBITDEPTH
DECLARE_ALIGNED(16, static const uint16_t,
av1_highbd_all_zeros[MAX_SB_SIZE]) = { 0 };
#endif
unsigned int av1_vaq_segment_id(int energy) {
ENERGY_IN_BOUNDS(energy);
@ -49,6 +48,16 @@ void av1_vaq_frame_setup(AV1_COMP *cpi) {
struct segmentation *seg = &cm->seg;
int i;
int resolution_change =
cm->prev_frame && (cm->width != cm->prev_frame->width ||
cm->height != cm->prev_frame->height);
if (resolution_change) {
memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
av1_clearall_segfeatures(seg);
aom_clear_system_state();
av1_disable_segmentation(seg);
return;
}
if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
@ -57,8 +66,6 @@ void av1_vaq_frame_setup(AV1_COMP *cpi) {
av1_enable_segmentation(seg);
av1_clearall_segfeatures(seg);
seg->abs_delta = SEGMENT_DELTADATA;
aom_clear_system_state();
for (i = 0; i < MAX_SEGMENTS; ++i) {
@ -74,11 +81,6 @@ void av1_vaq_frame_setup(AV1_COMP *cpi) {
qindex_delta = -cm->base_qindex + 1;
}
// No need to enable SEG_LVL_ALT_Q for this segment.
if (rate_ratio[i] == 1.0) {
continue;
}
av1_set_segdata(seg, i, SEG_LVL_ALT_Q, qindex_delta);
av1_enable_segfeature(seg, i, SEG_LVL_ALT_Q);
}
@ -108,7 +110,6 @@ static void aq_variance(const uint8_t *a, int a_stride, const uint8_t *b,
}
}
#if CONFIG_HIGHBITDEPTH
static void aq_highbd_variance64(const uint8_t *a8, int a_stride,
const uint8_t *b8, int b_stride, int w, int h,
uint64_t *sse, uint64_t *sum) {
@ -139,7 +140,6 @@ static void aq_highbd_8_variance(const uint8_t *a8, int a_stride,
*sse = (unsigned int)sse_long;
*sum = (int)sum_long;
}
#endif // CONFIG_HIGHBITDEPTH
static unsigned int block_variance(const AV1_COMP *const cpi, MACROBLOCK *x,
BLOCK_SIZE bs) {
@ -154,7 +154,6 @@ static unsigned int block_variance(const AV1_COMP *const cpi, MACROBLOCK *x,
const int bw = MI_SIZE * mi_size_wide[bs] - right_overflow;
const int bh = MI_SIZE * mi_size_high[bs] - bottom_overflow;
int avg;
#if CONFIG_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
aq_highbd_8_variance(x->plane[0].src.buf, x->plane[0].src.stride,
CONVERT_TO_BYTEPTR(av1_highbd_all_zeros), 0, bw, bh,
@ -165,14 +164,9 @@ static unsigned int block_variance(const AV1_COMP *const cpi, MACROBLOCK *x,
aq_variance(x->plane[0].src.buf, x->plane[0].src.stride, av1_all_zeros, 0,
bw, bh, &sse, &avg);
}
#else
aq_variance(x->plane[0].src.buf, x->plane[0].src.stride, av1_all_zeros, 0,
bw, bh, &sse, &avg);
#endif // CONFIG_HIGHBITDEPTH
var = sse - (unsigned int)(((int64_t)avg * avg) / (bw * bh));
return (unsigned int)((uint64_t)var * 256) / (bw * bh);
} else {
#if CONFIG_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
var =
cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
@ -181,10 +175,6 @@ static unsigned int block_variance(const AV1_COMP *const cpi, MACROBLOCK *x,
var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
av1_all_zeros, 0, &sse);
}
#else
var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
av1_all_zeros, 0, &sse);
#endif // CONFIG_HIGHBITDEPTH
return (unsigned int)((uint64_t)var * 256) >> num_pels_log2_lookup[bs];
}
}
@ -205,3 +195,53 @@ int av1_block_energy(const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
energy = av1_log_block_var(cpi, x, bs) - energy_midpoint;
return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
}
unsigned int haar_ac_energy(MACROBLOCK *x, BLOCK_SIZE bs) {
MACROBLOCKD *xd = &x->e_mbd;
int stride = x->plane[0].src.stride;
uint8_t *buf = x->plane[0].src.buf;
const int bw = MI_SIZE * mi_size_wide[bs];
const int bh = MI_SIZE * mi_size_high[bs];
int hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
int var = 0;
for (int r = 0; r < bh; r += 8)
for (int c = 0; c < bw; c += 8) {
var += av1_haar_ac_sad_8x8_uint8_input(buf + c + r * stride, stride, hbd);
}
return (unsigned int)((uint64_t)var * 256) >> num_pels_log2_lookup[bs];
}
double av1_log_block_wavelet_energy(MACROBLOCK *x, BLOCK_SIZE bs) {
unsigned int haar_sad = haar_ac_energy(x, bs);
aom_clear_system_state();
return log(haar_sad + 1.0);
}
int av1_block_wavelet_energy_level(const AV1_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bs) {
double energy, energy_midpoint;
aom_clear_system_state();
energy_midpoint = (cpi->oxcf.pass == 2) ? cpi->twopass.frame_avg_haar_energy
: DEFAULT_E_MIDPOINT;
energy = av1_log_block_wavelet_energy(x, bs) - energy_midpoint;
return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
}
int av1_compute_deltaq_from_energy_level(const AV1_COMP *const cpi,
int block_var_level) {
ENERGY_IN_BOUNDS(block_var_level);
const int rate_level = SEGMENT_ID(block_var_level);
const AV1_COMMON *const cm = &cpi->common;
int qindex_delta =
av1_compute_qdelta_by_rate(&cpi->rc, cm->frame_type, cm->base_qindex,
rate_ratio[rate_level], cm->bit_depth);
if ((cm->base_qindex != 0) && ((cm->base_qindex + qindex_delta) == 0)) {
qindex_delta = -cm->base_qindex + 1;
}
return qindex_delta;
}

View file

@ -23,6 +23,10 @@ void av1_vaq_frame_setup(AV1_COMP *cpi);
int av1_block_energy(const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs);
double av1_log_block_var(const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs);
int av1_compute_deltaq_from_energy_level(const AV1_COMP *const cpi,
int block_var_level);
int av1_block_wavelet_energy_level(const AV1_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bs);
#ifdef __cplusplus
} // extern "C"

View file

@ -1,42 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <arm_neon.h>
#include <assert.h>
#include "./av1_rtcd.h"
int64_t av1_block_error_fp_neon(const int16_t *coeff, const int16_t *dqcoeff,
int block_size) {
int64x2_t error = vdupq_n_s64(0);
assert(block_size >= 8);
assert((block_size % 8) == 0);
do {
const int16x8_t c = vld1q_s16(coeff);
const int16x8_t d = vld1q_s16(dqcoeff);
const int16x8_t diff = vsubq_s16(c, d);
const int16x4_t diff_lo = vget_low_s16(diff);
const int16x4_t diff_hi = vget_high_s16(diff);
// diff is 15-bits, the squares 30, so we can store 2 in 31-bits before
// accumulating them in 64-bits.
const int32x4_t err0 = vmull_s16(diff_lo, diff_lo);
const int32x4_t err1 = vmlal_s16(err0, diff_hi, diff_hi);
const int64x2_t err2 = vaddl_s32(vget_low_s32(err1), vget_high_s32(err1));
error = vaddq_s64(error, err2);
coeff += 8;
dqcoeff += 8;
block_size -= 8;
} while (block_size != 0);
return vgetq_lane_s64(error, 0) + vgetq_lane_s64(error, 1);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_FWD_TXFM1D_H_
#define AV1_FWD_TXFM1D_H_
#include "av1/common/av1_txfm.h"
#ifdef __cplusplus
extern "C" {
#endif
void av1_fdct4_new(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fdct8_new(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fdct16_new(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fdct32_new(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fdct64_new(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fadst4_new(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fadst8_new(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fadst16_new(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fidentity4_c(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fidentity8_c(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fidentity16_c(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
void av1_fidentity32_c(const int32_t *input, int32_t *output, int8_t cos_bit,
const int8_t *stage_range);
#ifdef __cplusplus
}
#endif
#endif // AV1_FWD_TXFM1D_H_

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_FWD_TXFM2D_CFG_H_
#define AV1_FWD_TXFM2D_CFG_H_
#include "av1/common/enums.h"
#include "av1/encoder/av1_fwd_txfm1d.h"
extern const int8_t *fwd_txfm_shift_ls[TX_SIZES_ALL];
extern const int8_t fwd_cos_bit_col[5][5];
extern const int8_t fwd_cos_bit_row[5][5];
#endif // AV1_FWD_TXFM2D_CFG_H_

View file

@ -0,0 +1,431 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <assert.h>
#include "config/aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"
#include "aom_dsp/txfm_common.h"
#include "av1/common/enums.h"
#include "av1/common/av1_txfm.h"
#include "av1/encoder/av1_fwd_txfm1d.h"
#include "av1/encoder/av1_fwd_txfm1d_cfg.h"
static INLINE TxfmFunc fwd_txfm_type_to_func(TXFM_TYPE txfm_type) {
switch (txfm_type) {
case TXFM_TYPE_DCT4: return av1_fdct4_new;
case TXFM_TYPE_DCT8: return av1_fdct8_new;
case TXFM_TYPE_DCT16: return av1_fdct16_new;
case TXFM_TYPE_DCT32: return av1_fdct32_new;
case TXFM_TYPE_DCT64: return av1_fdct64_new;
case TXFM_TYPE_ADST4: return av1_fadst4_new;
case TXFM_TYPE_ADST8: return av1_fadst8_new;
case TXFM_TYPE_ADST16: return av1_fadst16_new;
case TXFM_TYPE_IDENTITY4: return av1_fidentity4_c;
case TXFM_TYPE_IDENTITY8: return av1_fidentity8_c;
case TXFM_TYPE_IDENTITY16: return av1_fidentity16_c;
case TXFM_TYPE_IDENTITY32: return av1_fidentity32_c;
default: assert(0); return NULL;
}
}
void av1_gen_fwd_stage_range(int8_t *stage_range_col, int8_t *stage_range_row,
const TXFM_2D_FLIP_CFG *cfg, int bd) {
// Take the shift from the larger dimension in the rectangular case.
const int8_t *shift = cfg->shift;
// i < MAX_TXFM_STAGE_NUM will mute above array bounds warning
for (int i = 0; i < cfg->stage_num_col && i < MAX_TXFM_STAGE_NUM; ++i) {
stage_range_col[i] = cfg->stage_range_col[i] + shift[0] + bd + 1;
}
// i < MAX_TXFM_STAGE_NUM will mute above array bounds warning
for (int i = 0; i < cfg->stage_num_row && i < MAX_TXFM_STAGE_NUM; ++i) {
stage_range_row[i] = cfg->stage_range_row[i] + shift[0] + shift[1] + bd + 1;
}
}
static INLINE void fwd_txfm2d_c(const int16_t *input, int32_t *output,
const int stride, const TXFM_2D_FLIP_CFG *cfg,
int32_t *buf, int bd) {
int c, r;
// Note when assigning txfm_size_col, we use the txfm_size from the
// row configuration and vice versa. This is intentionally done to
// accurately perform rectangular transforms. When the transform is
// rectangular, the number of columns will be the same as the
// txfm_size stored in the row cfg struct. It will make no difference
// for square transforms.
const int txfm_size_col = tx_size_wide[cfg->tx_size];
const int txfm_size_row = tx_size_high[cfg->tx_size];
// Take the shift from the larger dimension in the rectangular case.
const int8_t *shift = cfg->shift;
const int rect_type = get_rect_tx_log_ratio(txfm_size_col, txfm_size_row);
int8_t stage_range_col[MAX_TXFM_STAGE_NUM];
int8_t stage_range_row[MAX_TXFM_STAGE_NUM];
assert(cfg->stage_num_col <= MAX_TXFM_STAGE_NUM);
assert(cfg->stage_num_row <= MAX_TXFM_STAGE_NUM);
av1_gen_fwd_stage_range(stage_range_col, stage_range_row, cfg, bd);
const int8_t cos_bit_col = cfg->cos_bit_col;
const int8_t cos_bit_row = cfg->cos_bit_row;
const TxfmFunc txfm_func_col = fwd_txfm_type_to_func(cfg->txfm_type_col);
const TxfmFunc txfm_func_row = fwd_txfm_type_to_func(cfg->txfm_type_row);
// use output buffer as temp buffer
int32_t *temp_in = output;
int32_t *temp_out = output + txfm_size_row;
// Columns
for (c = 0; c < txfm_size_col; ++c) {
if (cfg->ud_flip == 0) {
for (r = 0; r < txfm_size_row; ++r) temp_in[r] = input[r * stride + c];
} else {
for (r = 0; r < txfm_size_row; ++r)
// flip upside down
temp_in[r] = input[(txfm_size_row - r - 1) * stride + c];
}
av1_round_shift_array(temp_in, txfm_size_row, -shift[0]);
txfm_func_col(temp_in, temp_out, cos_bit_col, stage_range_col);
av1_round_shift_array(temp_out, txfm_size_row, -shift[1]);
if (cfg->lr_flip == 0) {
for (r = 0; r < txfm_size_row; ++r)
buf[r * txfm_size_col + c] = temp_out[r];
} else {
for (r = 0; r < txfm_size_row; ++r)
// flip from left to right
buf[r * txfm_size_col + (txfm_size_col - c - 1)] = temp_out[r];
}
}
// Rows
for (r = 0; r < txfm_size_row; ++r) {
txfm_func_row(buf + r * txfm_size_col, output + r * txfm_size_col,
cos_bit_row, stage_range_row);
av1_round_shift_array(output + r * txfm_size_col, txfm_size_col, -shift[2]);
if (abs(rect_type) == 1) {
// Multiply everything by Sqrt2 if the transform is rectangular and the
// size difference is a factor of 2.
for (c = 0; c < txfm_size_col; ++c) {
output[r * txfm_size_col + c] = round_shift(
(int64_t)output[r * txfm_size_col + c] * NewSqrt2, NewSqrt2Bits);
}
}
}
}
void av1_fwd_txfm2d_4x8_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
DECLARE_ALIGNED(32, int32_t, txfm_buf[4 * 8]);
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_4X8, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_8x4_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[8 * 4];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_8X4, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_8x16_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
DECLARE_ALIGNED(32, int32_t, txfm_buf[8 * 16]);
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_8X16, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_16x8_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[16 * 8];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_16X8, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_16x32_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
DECLARE_ALIGNED(32, int32_t, txfm_buf[16 * 32]);
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_16X32, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_32x16_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[32 * 16];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_32X16, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_4x16_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
DECLARE_ALIGNED(32, int32_t, txfm_buf[4 * 16]);
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_4X16, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_16x4_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[16 * 4];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_16X4, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_8x32_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
DECLARE_ALIGNED(32, int32_t, txfm_buf[32 * 8]);
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_8X32, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_32x8_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[32 * 8];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_32X8, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_4x4_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[4 * 4];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_4X4, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_8x8_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[8 * 8];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_8X8, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_16x16_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[16 * 16];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_16X16, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_32x32_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[32 * 32];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_32X32, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
}
void av1_fwd_txfm2d_64x64_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[64 * 64];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_64X64, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
// Zero out top-right 32x32 area.
for (int row = 0; row < 32; ++row) {
memset(output + row * 64 + 32, 0, 32 * sizeof(*output));
}
// Zero out the bottom 64x32 area.
memset(output + 32 * 64, 0, 32 * 64 * sizeof(*output));
// Re-pack non-zero coeffs in the first 32x32 indices.
for (int row = 1; row < 32; ++row) {
memcpy(output + row * 32, output + row * 64, 32 * sizeof(*output));
}
}
void av1_fwd_txfm2d_32x64_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
DECLARE_ALIGNED(32, int32_t, txfm_buf[32 * 64]);
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_32X64, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
// Zero out the bottom 32x32 area.
memset(output + 32 * 32, 0, 32 * 32 * sizeof(*output));
// Note: no repacking needed here.
}
void av1_fwd_txfm2d_64x32_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[64 * 32];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_64X32, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
// Zero out right 32x32 area.
for (int row = 0; row < 32; ++row) {
memset(output + row * 64 + 32, 0, 32 * sizeof(*output));
}
// Re-pack non-zero coeffs in the first 32x32 indices.
for (int row = 1; row < 32; ++row) {
memcpy(output + row * 32, output + row * 64, 32 * sizeof(*output));
}
}
void av1_fwd_txfm2d_16x64_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
DECLARE_ALIGNED(32, int32_t, txfm_buf[64 * 16]);
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_16X64, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
// Zero out the bottom 16x32 area.
memset(output + 16 * 32, 0, 16 * 32 * sizeof(*output));
// Note: no repacking needed here.
}
void av1_fwd_txfm2d_64x16_c(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd) {
int32_t txfm_buf[64 * 16];
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(tx_type, TX_64X16, &cfg);
fwd_txfm2d_c(input, output, stride, &cfg, txfm_buf, bd);
// Zero out right 32x16 area.
for (int row = 0; row < 16; ++row) {
memset(output + row * 64 + 32, 0, 32 * sizeof(*output));
}
// Re-pack non-zero coeffs in the first 32x16 indices.
for (int row = 1; row < 16; ++row) {
memcpy(output + row * 32, output + row * 64, 32 * sizeof(*output));
}
}
static const int8_t fwd_shift_4x4[3] = { 2, 0, 0 };
static const int8_t fwd_shift_8x8[3] = { 2, -1, 0 };
static const int8_t fwd_shift_16x16[3] = { 2, -2, 0 };
static const int8_t fwd_shift_32x32[3] = { 2, -4, 0 };
static const int8_t fwd_shift_64x64[3] = { 0, -2, -2 };
static const int8_t fwd_shift_4x8[3] = { 2, -1, 0 };
static const int8_t fwd_shift_8x4[3] = { 2, -1, 0 };
static const int8_t fwd_shift_8x16[3] = { 2, -2, 0 };
static const int8_t fwd_shift_16x8[3] = { 2, -2, 0 };
static const int8_t fwd_shift_16x32[3] = { 2, -4, 0 };
static const int8_t fwd_shift_32x16[3] = { 2, -4, 0 };
static const int8_t fwd_shift_32x64[3] = { 0, -2, -2 };
static const int8_t fwd_shift_64x32[3] = { 2, -4, -2 };
static const int8_t fwd_shift_4x16[3] = { 2, -1, 0 };
static const int8_t fwd_shift_16x4[3] = { 2, -1, 0 };
static const int8_t fwd_shift_8x32[3] = { 2, -2, 0 };
static const int8_t fwd_shift_32x8[3] = { 2, -2, 0 };
static const int8_t fwd_shift_16x64[3] = { 0, -2, 0 };
static const int8_t fwd_shift_64x16[3] = { 2, -4, 0 };
const int8_t *fwd_txfm_shift_ls[TX_SIZES_ALL] = {
fwd_shift_4x4, fwd_shift_8x8, fwd_shift_16x16, fwd_shift_32x32,
fwd_shift_64x64, fwd_shift_4x8, fwd_shift_8x4, fwd_shift_8x16,
fwd_shift_16x8, fwd_shift_16x32, fwd_shift_32x16, fwd_shift_32x64,
fwd_shift_64x32, fwd_shift_4x16, fwd_shift_16x4, fwd_shift_8x32,
fwd_shift_32x8, fwd_shift_16x64, fwd_shift_64x16,
};
const int8_t fwd_cos_bit_col[MAX_TXWH_IDX /*txw_idx*/]
[MAX_TXWH_IDX /*txh_idx*/] = {
{ 13, 13, 13, 0, 0 },
{ 13, 13, 13, 12, 0 },
{ 13, 13, 13, 12, 13 },
{ 0, 13, 13, 12, 13 },
{ 0, 0, 13, 12, 13 }
};
const int8_t fwd_cos_bit_row[MAX_TXWH_IDX /*txw_idx*/]
[MAX_TXWH_IDX /*txh_idx*/] = {
{ 13, 13, 12, 0, 0 },
{ 13, 13, 13, 12, 0 },
{ 13, 13, 12, 13, 12 },
{ 0, 12, 13, 12, 11 },
{ 0, 0, 12, 11, 10 }
};
static const int8_t fdct4_range_mult2[4] = { 0, 2, 3, 3 };
static const int8_t fdct8_range_mult2[6] = { 0, 2, 4, 5, 5, 5 };
static const int8_t fdct16_range_mult2[8] = { 0, 2, 4, 6, 7, 7, 7, 7 };
static const int8_t fdct32_range_mult2[10] = { 0, 2, 4, 6, 8, 9, 9, 9, 9, 9 };
static const int8_t fdct64_range_mult2[12] = { 0, 2, 4, 6, 8, 10,
11, 11, 11, 11, 11, 11 };
static const int8_t fadst4_range_mult2[7] = { 0, 2, 4, 3, 3, 3, 3 };
static const int8_t fadst8_range_mult2[8] = { 0, 0, 1, 3, 3, 5, 5, 5 };
static const int8_t fadst16_range_mult2[10] = { 0, 0, 1, 3, 3, 5, 5, 7, 7, 7 };
static const int8_t max_fwd_range_mult2_col[5] = { 3, 5, 7, 9, 11 };
static const int8_t fidtx4_range_mult2[1] = { 1 };
static const int8_t fidtx8_range_mult2[1] = { 2 };
static const int8_t fidtx16_range_mult2[1] = { 3 };
static const int8_t fidtx32_range_mult2[1] = { 4 };
#if 0
const int8_t fwd_idtx_range_row[MAX_TXWH_IDX /*txw_idx*/]
[MAX_TXWH_IDX /*txh_idx*/] = { { 2, 4, 5, 0, 0 },
{ 3, 4, 5, 6, 0 },
{ 4, 5, 6, 7, 8 },
{ 0, 5, 6, 7, 8 },
{ 0, 0, 7, 8,
9 } };
#endif
const int8_t *fwd_txfm_range_mult2_list[TXFM_TYPES] = {
fdct4_range_mult2, fdct8_range_mult2, fdct16_range_mult2,
fdct32_range_mult2, fdct64_range_mult2, fadst4_range_mult2,
fadst8_range_mult2, fadst16_range_mult2, fidtx4_range_mult2,
fidtx8_range_mult2, fidtx16_range_mult2, fidtx32_range_mult2
};
static INLINE void set_fwd_txfm_non_scale_range(TXFM_2D_FLIP_CFG *cfg) {
const int txh_idx = get_txh_idx(cfg->tx_size);
av1_zero(cfg->stage_range_col);
av1_zero(cfg->stage_range_row);
if (cfg->txfm_type_col != TXFM_TYPE_INVALID) {
int stage_num_col = cfg->stage_num_col;
const int8_t *range_mult2_col =
fwd_txfm_range_mult2_list[cfg->txfm_type_col];
for (int i = 0; i < stage_num_col; ++i)
cfg->stage_range_col[i] = (range_mult2_col[i] + 1) >> 1;
}
if (cfg->txfm_type_row != TXFM_TYPE_INVALID) {
int stage_num_row = cfg->stage_num_row;
const int8_t *range_mult2_row =
fwd_txfm_range_mult2_list[cfg->txfm_type_row];
for (int i = 0; i < stage_num_row; ++i)
cfg->stage_range_row[i] =
(max_fwd_range_mult2_col[txh_idx] + range_mult2_row[i] + 1) >> 1;
}
}
void av1_get_fwd_txfm_cfg(TX_TYPE tx_type, TX_SIZE tx_size,
TXFM_2D_FLIP_CFG *cfg) {
assert(cfg != NULL);
cfg->tx_size = tx_size;
set_flip_cfg(tx_type, cfg);
const TX_TYPE_1D tx_type_1d_col = vtx_tab[tx_type];
const TX_TYPE_1D tx_type_1d_row = htx_tab[tx_type];
const int txw_idx = tx_size_wide_log2[tx_size] - tx_size_wide_log2[0];
const int txh_idx = tx_size_high_log2[tx_size] - tx_size_high_log2[0];
cfg->shift = fwd_txfm_shift_ls[tx_size];
cfg->cos_bit_col = fwd_cos_bit_col[txw_idx][txh_idx];
cfg->cos_bit_row = fwd_cos_bit_row[txw_idx][txh_idx];
cfg->txfm_type_col = av1_txfm_type_ls[txh_idx][tx_type_1d_col];
cfg->txfm_type_row = av1_txfm_type_ls[txw_idx][tx_type_1d_row];
cfg->stage_num_col = av1_txfm_stage_num_list[cfg->txfm_type_col];
cfg->stage_num_row = av1_txfm_stage_num_list[cfg->txfm_type_row];
set_fwd_txfm_non_scale_range(cfg);
}

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,8 @@
#ifndef AV1_ENCODER_QUANTIZE_H_
#define AV1_ENCODER_QUANTIZE_H_
#include "./aom_config.h"
#include "config/aom_config.h"
#include "av1/common/quant_common.h"
#include "av1/common/scan.h"
#include "av1/encoder/block.h"
@ -23,33 +24,22 @@ extern "C" {
typedef struct QUANT_PARAM {
int log_scale;
#if CONFIG_NEW_QUANT
TX_SIZE tx_size;
int dq;
#endif // CONFIG_NEW_QUANT
#if CONFIG_AOM_QM
const qm_val_t *qmatrix;
const qm_val_t *iqmatrix;
#endif // CONFIG_AOM_QM
} QUANT_PARAM;
typedef void (*AV1_QUANT_FACADE)(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
// The QUANTS structure is used only for internal quantizer setup in
// av1_quantize.c.
// All of its fields use the same coefficient shift/scaling at TX.
typedef struct {
#if CONFIG_NEW_QUANT
DECLARE_ALIGNED(
16, tran_low_t,
y_cuml_bins_nuq[QUANT_PROFILES][QINDEX_RANGE][COEF_BANDS][NUQ_KNOTS]);
DECLARE_ALIGNED(
16, tran_low_t,
uv_cuml_bins_nuq[QUANT_PROFILES][QINDEX_RANGE][COEF_BANDS][NUQ_KNOTS]);
#endif // CONFIG_NEW_QUANT
// 0: dc 1: ac 2-8: ac repeated to SIMD width
DECLARE_ALIGNED(16, int16_t, y_quant[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, y_quant_shift[QINDEX_RANGE][8]);
@ -59,25 +49,36 @@ typedef struct {
// TODO(jingning): in progress of re-working the quantization. will decide
// if we want to deprecate the current use of y_quant.
DECLARE_ALIGNED(16, int16_t, y_quant_fp[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, uv_quant_fp[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, u_quant_fp[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, v_quant_fp[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, y_round_fp[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, uv_round_fp[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, u_round_fp[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, v_round_fp[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, uv_quant[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, uv_quant_shift[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, uv_zbin[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, uv_round[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, u_quant[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, v_quant[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, u_quant_shift[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, v_quant_shift[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, u_zbin[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, v_zbin[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, u_round[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, v_round[QINDEX_RANGE][8]);
} QUANTS;
// The Dequants structure is used only for internal quantizer setup in
// av1_quantize.c.
// Fields are sufffixed according to whether or not they're expressed in
// the same coefficient shift/precision as TX or a fixed Q3 format.
typedef struct {
DECLARE_ALIGNED(16, int16_t, y_dequant[QINDEX_RANGE][8]); // 8: SIMD width
DECLARE_ALIGNED(16, int16_t, uv_dequant[QINDEX_RANGE][8]); // 8: SIMD width
#if CONFIG_NEW_QUANT
DECLARE_ALIGNED(16, dequant_val_type_nuq,
y_dequant_val_nuq[QUANT_PROFILES][QINDEX_RANGE][COEF_BANDS]);
DECLARE_ALIGNED(16, dequant_val_type_nuq,
uv_dequant_val_nuq[QUANT_PROFILES][QINDEX_RANGE][COEF_BANDS]);
#endif // CONFIG_NEW_QUANT
DECLARE_ALIGNED(16, int16_t,
y_dequant_QTX[QINDEX_RANGE][8]); // 8: SIMD width
DECLARE_ALIGNED(16, int16_t,
u_dequant_QTX[QINDEX_RANGE][8]); // 8: SIMD width
DECLARE_ALIGNED(16, int16_t,
v_dequant_QTX[QINDEX_RANGE][8]); // 8: SIMD width
DECLARE_ALIGNED(16, int16_t, y_dequant_Q3[QINDEX_RANGE][8]); // 8: SIMD width
DECLARE_ALIGNED(16, int16_t, u_dequant_Q3[QINDEX_RANGE][8]); // 8: SIMD width
DECLARE_ALIGNED(16, int16_t, v_dequant_Q3[QINDEX_RANGE][8]); // 8: SIMD width
} Dequants;
struct AV1_COMP;
@ -89,8 +90,9 @@ void av1_init_plane_quantizers(const struct AV1_COMP *cpi, MACROBLOCK *x,
int segment_id);
void av1_build_quantizer(aom_bit_depth_t bit_depth, int y_dc_delta_q,
int uv_dc_delta_q, int uv_ac_delta_q,
QUANTS *const quants, Dequants *const deq);
int u_dc_delta_q, int u_ac_delta_q, int v_dc_delta_q,
int v_ac_delta_q, QUANTS *const quants,
Dequants *const deq);
void av1_init_quantizer(struct AV1_COMP *cpi);
@ -105,51 +107,22 @@ void av1_quantize_skip(intptr_t n_coeffs, tran_low_t *qcoeff_ptr,
void av1_quantize_fp_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc, const QUANT_PARAM *qparam);
void av1_quantize_b_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd, tran_low_t *dqcoeff_ptr,
uint16_t *eob_ptr, const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc, const QUANT_PARAM *qparam);
void av1_quantize_dc_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc, const QUANT_PARAM *qparam);
#if CONFIG_NEW_QUANT
void av1_quantize_fp_nuq_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
void av1_quantize_b_nuq_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc, const QUANT_PARAM *qparam);
void av1_quantize_dc_nuq_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
#endif // CONFIG_NEW_QUANT
void av1_highbd_quantize_fp_facade(const tran_low_t *coeff_ptr,
intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
@ -157,7 +130,6 @@ void av1_highbd_quantize_fp_facade(const tran_low_t *coeff_ptr,
void av1_highbd_quantize_b_facade(const tran_low_t *coeff_ptr,
intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
@ -165,31 +137,10 @@ void av1_highbd_quantize_b_facade(const tran_low_t *coeff_ptr,
void av1_highbd_quantize_dc_facade(const tran_low_t *coeff_ptr,
intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr,
const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
#if CONFIG_NEW_QUANT
void av1_highbd_quantize_fp_nuq_facade(
const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
void av1_highbd_quantize_b_nuq_facade(
const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
void av1_highbd_quantize_dc_nuq_facade(
const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
const QUANT_PARAM *qparam);
#endif // CONFIG_NEW_QUANT
#ifdef __cplusplus
} // extern "C"
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_ENCODER_BGSPRITE_H_
#define AV1_ENCODER_BGSPRITE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "av1/encoder/encoder.h"
// Creates alternate reference frame staring from source image + frames up to
// 'distance' past source frame.
// Returns 0 on success and 1 on failure.
int av1_background_sprite(AV1_COMP *cpi, int distance);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AV1_ENCODER_BGSPRITE_H_

File diff suppressed because it is too large Load diff

View file

@ -20,34 +20,24 @@ extern "C" {
struct aom_write_bit_buffer;
#if CONFIG_REFERENCE_BUFFER
void write_sequence_header(AV1_COMMON *const cm,
struct aom_write_bit_buffer *wb);
#endif
void write_sequence_header(AV1_COMP *cpi, struct aom_write_bit_buffer *wb);
void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dest, size_t *size);
uint32_t write_obu_header(OBU_TYPE obu_type, int obu_extension,
uint8_t *const dst);
void av1_encode_token_init(void);
int write_uleb_obu_size(uint32_t obu_header_size, uint32_t obu_payload_size,
uint8_t *dest);
int av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dest, size_t *size);
static INLINE int av1_preserve_existing_gf(AV1_COMP *cpi) {
#if CONFIG_EXT_REFS
// Do not swap gf and arf indices for internal overlay frames
return !cpi->multi_arf_allowed && cpi->rc.is_src_frame_alt_ref &&
!cpi->rc.is_src_frame_ext_arf;
#else
return !cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
cpi->rc.is_src_frame_alt_ref;
#endif // CONFIG_EXT_REFS
}
void av1_write_tx_type(const AV1_COMMON *const cm, const MACROBLOCKD *xd,
#if CONFIG_SUPERTX
const int supertx_enabled,
#endif
#if CONFIG_TXK_SEL
int blk_row, int blk_col, int block, int plane,
TX_SIZE tx_size,
#endif
int blk_row, int blk_col, int plane, TX_SIZE tx_size,
aom_writer *w);
#ifdef __cplusplus

View file

@ -14,9 +14,6 @@
#include "av1/common/entropymv.h"
#include "av1/common/entropy.h"
#if CONFIG_PVQ
#include "av1/encoder/encint.h"
#endif
#include "av1/common/mvref_common.h"
#include "av1/encoder/hash.h"
#if CONFIG_DIST_8X8
@ -27,12 +24,6 @@
extern "C" {
#endif
#if CONFIG_PVQ
// Maximum possible # of tx blocks in luma plane, which is currently 256,
// since there can be 16x16 of 4x4 tx.
#define MAX_PVQ_BLOCKS_IN_SB (MAX_SB_SQUARE >> 2 * OD_LOG_BSIZE0)
#endif
typedef struct {
unsigned int sse;
int sum;
@ -41,52 +32,38 @@ typedef struct {
typedef struct macroblock_plane {
DECLARE_ALIGNED(16, int16_t, src_diff[MAX_SB_SQUARE]);
#if CONFIG_PVQ
DECLARE_ALIGNED(16, int16_t, src_int16[MAX_SB_SQUARE]);
#endif
tran_low_t *qcoeff;
tran_low_t *coeff;
uint16_t *eobs;
#if CONFIG_LV_MAP
uint8_t *txb_entropy_ctx;
#endif
struct buf_2d src;
// Quantizer setings
const int16_t *quant_fp;
const int16_t *round_fp;
const int16_t *quant;
const int16_t *quant_shift;
const int16_t *zbin;
const int16_t *round;
#if CONFIG_NEW_QUANT
const cuml_bins_type_nuq *cuml_bins_nuq[QUANT_PROFILES];
#endif // CONFIG_NEW_QUANT
// These are used/accessed only in the quantization process
// RDO does not / must not depend on any of these values
// All values below share the coefficient scale/shift used in TX
const int16_t *quant_fp_QTX;
const int16_t *round_fp_QTX;
const int16_t *quant_QTX;
const int16_t *quant_shift_QTX;
const int16_t *zbin_QTX;
const int16_t *round_QTX;
const int16_t *dequant_QTX;
} MACROBLOCK_PLANE;
typedef int av1_coeff_cost[PLANE_TYPES][REF_TYPES][COEF_BANDS][COEFF_CONTEXTS]
[TAIL_TOKENS];
#if CONFIG_LV_MAP
typedef struct {
int txb_skip_cost[TXB_SKIP_CONTEXTS][2];
int nz_map_cost[SIG_COEF_CONTEXTS][2];
int eob_cost[EOB_COEF_CONTEXTS][2];
int base_eob_cost[SIG_COEF_CONTEXTS_EOB][3];
int base_cost[SIG_COEF_CONTEXTS][4];
int eob_extra_cost[EOB_COEF_CONTEXTS][2];
int dc_sign_cost[DC_SIGN_CONTEXTS][2];
int base_cost[NUM_BASE_LEVELS][COEFF_BASE_CONTEXTS][2];
#if BR_NODE
int lps_cost[LEVEL_CONTEXTS][COEFF_BASE_RANGE + 1];
int br_cost[BASE_RANGE_SETS][LEVEL_CONTEXTS][2];
#else // BR_NODE
int lps_cost[LEVEL_CONTEXTS][2];
#endif // BR_NODE
#if CONFIG_CTX1D
int eob_mode_cost[TX_CLASSES][2];
int empty_line_cost[TX_CLASSES][EMPTY_LINE_CONTEXTS][2];
int hv_eob_cost[TX_CLASSES][HV_EOB_CONTEXTS][2];
#endif
} LV_MAP_COEFF_COST;
typedef struct {
int eob_cost[2][11];
} LV_MAP_EOB_COST;
typedef struct {
tran_low_t tcoeff[MAX_MB_PLANE][MAX_SB_SQUARE];
uint16_t eobs[MAX_MB_PLANE][MAX_SB_SQUARE / (TX_SIZE_W_MIN * TX_SIZE_H_MIN)];
@ -95,20 +72,17 @@ typedef struct {
int dc_sign_ctx[MAX_MB_PLANE]
[MAX_SB_SQUARE / (TX_SIZE_W_MIN * TX_SIZE_H_MIN)];
} CB_COEFF_BUFFER;
#endif
typedef struct {
int_mv ref_mvs[MODE_CTX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
int16_t mode_context[MODE_CTX_REF_FRAMES];
#if CONFIG_LV_MAP
// TODO(angiebird): Reduce the buffer size according to sb_type
tran_low_t *tcoeff[MAX_MB_PLANE];
uint16_t *eobs[MAX_MB_PLANE];
uint8_t *txb_skip_ctx[MAX_MB_PLANE];
int *dc_sign_ctx[MAX_MB_PLANE];
#endif
uint8_t ref_mv_count[MODE_CTX_REF_FRAMES];
CANDIDATE_MV ref_mv_stack[MODE_CTX_REF_FRAMES][MAX_REF_MV_STACK_SIZE];
int_mv global_mvs[REF_FRAMES];
int16_t compound_mode_context[MODE_CTX_REF_FRAMES];
} MB_MODE_INFO_EXT;
@ -120,39 +94,119 @@ typedef struct {
} MvLimits;
typedef struct {
uint8_t best_palette_color_map[MAX_SB_SQUARE];
float kmeans_data_buf[2 * MAX_SB_SQUARE];
uint8_t best_palette_color_map[MAX_PALETTE_SQUARE];
int kmeans_data_buf[2 * MAX_PALETTE_SQUARE];
} PALETTE_BUFFER;
typedef struct {
TX_TYPE tx_type;
TX_SIZE tx_size;
#if CONFIG_VAR_TX
TX_SIZE min_tx_size;
TX_SIZE inter_tx_size[MAX_MIB_SIZE][MAX_MIB_SIZE];
uint8_t blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
#endif // CONFIG_VAR_TX
#if CONFIG_TXK_SEL
TX_TYPE txk_type[MAX_SB_SQUARE / (TX_SIZE_W_MIN * TX_SIZE_H_MIN)];
#endif // CONFIG_TXK_SEL
TX_SIZE inter_tx_size[INTER_TX_SIZE_BUF_LEN];
uint8_t blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
TX_TYPE txk_type[TXK_TYPE_BUF_LEN];
RD_STATS rd_stats;
uint32_t hash_value;
} TX_RD_INFO;
} MB_RD_INFO;
#define RD_RECORD_BUFFER_LEN 8
typedef struct {
TX_RD_INFO tx_rd_info[RD_RECORD_BUFFER_LEN]; // Circular buffer.
MB_RD_INFO tx_rd_info[RD_RECORD_BUFFER_LEN]; // Circular buffer.
int index_start;
int num;
CRC_CALCULATOR crc_calculator; // Hash function.
} TX_RD_RECORD;
CRC32C crc_calculator; // Hash function.
} MB_RD_RECORD;
typedef struct {
int64_t dist;
int64_t sse;
int rate;
uint16_t eob;
TX_TYPE tx_type;
uint16_t entropy_context;
uint8_t txb_entropy_ctx;
uint8_t valid;
uint8_t fast; // This is not being used now.
} TXB_RD_INFO;
#define TX_SIZE_RD_RECORD_BUFFER_LEN 256
typedef struct {
uint32_t hash_vals[TX_SIZE_RD_RECORD_BUFFER_LEN];
TXB_RD_INFO tx_rd_info[TX_SIZE_RD_RECORD_BUFFER_LEN];
int index_start;
int num;
} TXB_RD_RECORD;
typedef struct tx_size_rd_info_node {
TXB_RD_INFO *rd_info_array; // Points to array of size TX_TYPES.
struct tx_size_rd_info_node *children[4];
} TXB_RD_INFO_NODE;
// Region size for mode decision sampling in the first pass of partition
// search(two_pass_partition_search speed feature), in units of mi size(4).
// Used by the mode_pruning_based_on_two_pass_partition_search speed feature.
#define FIRST_PARTITION_PASS_SAMPLE_REGION 8
#define FIRST_PARTITION_PASS_SAMPLE_REGION_LOG2 3
#define FIRST_PARTITION_PASS_STATS_TABLES \
(MAX_MIB_SIZE >> FIRST_PARTITION_PASS_SAMPLE_REGION_LOG2) * \
(MAX_MIB_SIZE >> FIRST_PARTITION_PASS_SAMPLE_REGION_LOG2)
#define FIRST_PARTITION_PASS_STATS_STRIDE \
(MAX_MIB_SIZE_LOG2 - FIRST_PARTITION_PASS_SAMPLE_REGION_LOG2)
static INLINE int av1_first_partition_pass_stats_index(int mi_row, int mi_col) {
const int row =
(mi_row & MAX_MIB_MASK) >> FIRST_PARTITION_PASS_SAMPLE_REGION_LOG2;
const int col =
(mi_col & MAX_MIB_MASK) >> FIRST_PARTITION_PASS_SAMPLE_REGION_LOG2;
return (row << FIRST_PARTITION_PASS_STATS_STRIDE) + col;
}
typedef struct {
uint8_t ref0_counts[REF_FRAMES]; // Counters for ref_frame[0].
uint8_t ref1_counts[REF_FRAMES]; // Counters for ref_frame[1].
int sample_counts; // Number of samples collected.
} FIRST_PARTITION_PASS_STATS;
#define MAX_INTERP_FILTER_STATS 64
typedef struct {
InterpFilters filters;
int_mv mv[2];
int8_t ref_frames[2];
} INTERPOLATION_FILTER_STATS;
typedef struct macroblock MACROBLOCK;
struct macroblock {
struct macroblock_plane plane[MAX_MB_PLANE];
// Save the transform RD search info.
TX_RD_RECORD tx_rd_record;
// Determine if one would go with reduced complexity transform block
// search model to select prediction modes, or full complexity model
// to select transform kernel.
int rd_model;
// Indicate if the encoder is running in the first pass partition search.
// In that case, apply certain speed features therein to reduce the overhead
// cost in the first pass search.
int cb_partition_scan;
FIRST_PARTITION_PASS_STATS
first_partition_pass_stats[FIRST_PARTITION_PASS_STATS_TABLES];
// [comp_idx][saved stat_idx]
INTERPOLATION_FILTER_STATS interp_filter_stats[2][MAX_INTERP_FILTER_STATS];
int interp_filter_stats_idx[2];
// Activate constrained coding block partition search range.
int use_cb_search_range;
// Inter macroblock RD search info.
MB_RD_RECORD mb_rd_record;
// Inter transform block RD search info. for square TX sizes.
TXB_RD_RECORD txb_rd_record_8X8[(MAX_MIB_SIZE >> 1) * (MAX_MIB_SIZE >> 1)];
TXB_RD_RECORD txb_rd_record_16X16[(MAX_MIB_SIZE >> 2) * (MAX_MIB_SIZE >> 2)];
TXB_RD_RECORD txb_rd_record_32X32[(MAX_MIB_SIZE >> 3) * (MAX_MIB_SIZE >> 3)];
TXB_RD_RECORD txb_rd_record_64X64[(MAX_MIB_SIZE >> 4) * (MAX_MIB_SIZE >> 4)];
// Intra transform block RD search info. for square TX sizes.
TXB_RD_RECORD txb_rd_record_intra;
MACROBLOCKD e_mbd;
MB_MODE_INFO_EXT *mbmi_ext;
@ -173,34 +227,29 @@ struct macroblock {
int *m_search_count_ptr;
int *ex_search_count_ptr;
#if CONFIG_VAR_TX
unsigned int txb_split_count;
#endif
// These are set to their default values at the beginning, and then adjusted
// further in the encoding process.
BLOCK_SIZE min_partition_size;
BLOCK_SIZE max_partition_size;
int mv_best_ref_index[TOTAL_REFS_PER_FRAME];
unsigned int max_mv_context[TOTAL_REFS_PER_FRAME];
unsigned int max_mv_context[REF_FRAMES];
unsigned int source_variance;
unsigned int pred_sse[TOTAL_REFS_PER_FRAME];
int pred_mv_sad[TOTAL_REFS_PER_FRAME];
unsigned int pred_sse[REF_FRAMES];
int pred_mv_sad[REF_FRAMES];
int *nmvjointcost;
int nmv_vec_cost[NMV_CONTEXTS][MV_JOINTS];
int *nmvcost[NMV_CONTEXTS][2];
int *nmvcost_hp[NMV_CONTEXTS][2];
int **mv_cost_stack[NMV_CONTEXTS];
int nmv_vec_cost[MV_JOINTS];
int *nmvcost[2];
int *nmvcost_hp[2];
int **mv_cost_stack;
int **mvcost;
#if CONFIG_MOTION_VAR
int32_t *wsrc_buf;
int32_t *mask_buf;
uint8_t *above_pred_buf;
uint8_t *left_pred_buf;
#endif // CONFIG_MOTION_VAR
PALETTE_BUFFER *palette_buffer;
@ -208,108 +257,80 @@ struct macroblock {
// from extending outside the UMV borders
MvLimits mv_limits;
#if CONFIG_VAR_TX
uint8_t blk_skip[MAX_MB_PLANE][MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
uint8_t blk_skip_drl[MAX_MB_PLANE][MAX_MIB_SIZE * MAX_MIB_SIZE * 8];
#endif
uint8_t blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
uint8_t blk_skip_drl[MAX_MIB_SIZE * MAX_MIB_SIZE];
int skip;
#if CONFIG_CB4X4
int skip_chroma_rd;
#endif
int skip_cost[SKIP_CONTEXTS][2];
int skip_mode; // 0: off; 1: on
int skip_mode_cost[SKIP_CONTEXTS][2];
int compound_idx;
#if CONFIG_LV_MAP
LV_MAP_COEFF_COST coeff_costs[TX_SIZES][PLANE_TYPES];
LV_MAP_EOB_COST eob_costs[7][2];
uint16_t cb_offset;
#endif
av1_coeff_cost token_head_costs[TX_SIZES];
av1_coeff_cost token_tail_costs[TX_SIZES];
// mode costs
int intra_inter_cost[INTRA_INTER_CONTEXTS][2];
int mbmode_cost[BLOCK_SIZE_GROUPS][INTRA_MODES];
int newmv_mode_cost[NEWMV_MODE_CONTEXTS][2];
int zeromv_mode_cost[ZEROMV_MODE_CONTEXTS][2];
int zeromv_mode_cost[GLOBALMV_MODE_CONTEXTS][2];
int refmv_mode_cost[REFMV_MODE_CONTEXTS][2];
int drl_mode_cost0[DRL_MODE_CONTEXTS][2];
int comp_inter_cost[COMP_INTER_CONTEXTS][2];
int single_ref_cost[REF_CONTEXTS][SINGLE_REFS - 1][2];
int comp_ref_type_cost[COMP_REF_TYPE_CONTEXTS]
[CDF_SIZE(COMP_REFERENCE_TYPES)];
int uni_comp_ref_cost[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1]
[CDF_SIZE(2)];
// Cost for signaling ref_frame[0] (LAST_FRAME, LAST2_FRAME, LAST3_FRAME or
// GOLDEN_FRAME) in bidir-comp mode.
int comp_ref_cost[REF_CONTEXTS][FWD_REFS - 1][2];
// Cost for signaling ref_frame[1] (ALTREF_FRAME, ALTREF2_FRAME, or
// BWDREF_FRAME) in bidir-comp mode.
int comp_bwdref_cost[REF_CONTEXTS][BWD_REFS - 1][2];
int inter_compound_mode_cost[INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES];
int compound_type_cost[BLOCK_SIZES_ALL][COMPOUND_TYPES];
#if CONFIG_COMPOUND_SINGLEREF
int inter_singleref_comp_mode_cost[INTER_MODE_CONTEXTS]
[INTER_SINGLEREF_COMP_MODES];
#endif // CONFIG_COMPOUND_SINGLEREF
#if CONFIG_INTERINTRA
int compound_type_cost[BLOCK_SIZES_ALL][COMPOUND_TYPES - 1];
int wedge_idx_cost[BLOCK_SIZES_ALL][16];
int interintra_cost[BLOCK_SIZE_GROUPS][2];
int wedge_interintra_cost[BLOCK_SIZES_ALL][2];
int interintra_mode_cost[BLOCK_SIZE_GROUPS][INTERINTRA_MODES];
#endif // CONFIG_INTERINTRA
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
int motion_mode_cost[BLOCK_SIZES_ALL][MOTION_MODES];
#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
int motion_mode_cost1[BLOCK_SIZES_ALL][2];
#if CONFIG_NCOBMC_ADAPT_WEIGHT
int motion_mode_cost2[BLOCK_SIZES_ALL][OBMC_FAMILY_MODES];
#endif
#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR && CONFIG_NCOBMC_ADAPT_WEIGHT
int ncobmc_mode_cost[ADAPT_OVERLAP_BLOCKS][MAX_NCOBMC_MODES];
#endif // CONFIG_MOTION_VAR && CONFIG_NCOBMC_ADAPT_WEIGHT
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
int intra_uv_mode_cost[INTRA_MODES][UV_INTRA_MODES];
int intra_uv_mode_cost[CFL_ALLOWED_TYPES][INTRA_MODES][UV_INTRA_MODES];
int y_mode_costs[INTRA_MODES][INTRA_MODES][INTRA_MODES];
int filter_intra_cost[BLOCK_SIZES_ALL][2];
int filter_intra_mode_cost[FILTER_INTRA_MODES];
int switchable_interp_costs[SWITCHABLE_FILTER_CONTEXTS][SWITCHABLE_FILTERS];
#if CONFIG_EXT_PARTITION_TYPES
int partition_cost[PARTITION_CONTEXTS + CONFIG_UNPOISON_PARTITION_CTX]
[EXT_PARTITION_TYPES];
#else
int partition_cost[PARTITION_CONTEXTS + CONFIG_UNPOISON_PARTITION_CTX]
[PARTITION_TYPES];
#endif // CONFIG_EXT_PARTITION_TYPES
#if CONFIG_MRC_TX
int mrc_mask_inter_cost[PALETTE_SIZES][PALETTE_COLOR_INDEX_CONTEXTS]
[PALETTE_COLORS];
int mrc_mask_intra_cost[PALETTE_SIZES][PALETTE_COLOR_INDEX_CONTEXTS]
[PALETTE_COLORS];
#endif // CONFIG_MRC_TX
int palette_y_size_cost[PALETTE_BLOCK_SIZES][PALETTE_SIZES];
int palette_uv_size_cost[PALETTE_BLOCK_SIZES][PALETTE_SIZES];
int partition_cost[PARTITION_CONTEXTS][EXT_PARTITION_TYPES];
int palette_y_size_cost[PALATTE_BSIZE_CTXS][PALETTE_SIZES];
int palette_uv_size_cost[PALATTE_BSIZE_CTXS][PALETTE_SIZES];
int palette_y_color_cost[PALETTE_SIZES][PALETTE_COLOR_INDEX_CONTEXTS]
[PALETTE_COLORS];
int palette_uv_color_cost[PALETTE_SIZES][PALETTE_COLOR_INDEX_CONTEXTS]
[PALETTE_COLORS];
#if CONFIG_CFL
int palette_y_mode_cost[PALATTE_BSIZE_CTXS][PALETTE_Y_MODE_CONTEXTS][2];
int palette_uv_mode_cost[PALETTE_UV_MODE_CONTEXTS][2];
// The rate associated with each alpha codeword
int cfl_cost[CFL_JOINT_SIGNS][CFL_PRED_PLANES][CFL_ALPHABET_SIZE];
#endif // CONFIG_CFL
int tx_size_cost[TX_SIZES - 1][TX_SIZE_CONTEXTS][TX_SIZES];
#if CONFIG_EXT_TX
#if CONFIG_LGT_FROM_PRED
int intra_lgt_cost[LGT_SIZES][INTRA_MODES][2];
int inter_lgt_cost[LGT_SIZES][2];
#endif
int txfm_partition_cost[TXFM_PARTITION_CONTEXTS][2];
int inter_tx_type_costs[EXT_TX_SETS_INTER][EXT_TX_SIZES][TX_TYPES];
int intra_tx_type_costs[EXT_TX_SETS_INTRA][EXT_TX_SIZES][INTRA_MODES]
[TX_TYPES];
#else
int intra_tx_type_costs[EXT_TX_SIZES][TX_TYPES][TX_TYPES];
int inter_tx_type_costs[EXT_TX_SIZES][TX_TYPES];
#endif // CONFIG_EXT_TX
#if CONFIG_EXT_INTRA
#if CONFIG_INTRA_INTERP
int intra_filter_cost[INTRA_FILTERS + 1][INTRA_FILTERS];
#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_LOOP_RESTORATION
int angle_delta_cost[DIRECTIONAL_MODES][2 * MAX_ANGLE_DELTA + 1];
int switchable_restore_cost[RESTORE_SWITCHABLE_TYPES];
#endif // CONFIG_LOOP_RESTORATION
#if CONFIG_INTRABC
int wiener_restore_cost[2];
int sgrproj_restore_cost[2];
int intrabc_cost[2];
#endif // CONFIG_INTRABC
int optimize;
// Used to store sub partition's choices.
MV pred_mv[TOTAL_REFS_PER_FRAME];
MV pred_mv[REF_FRAMES];
// Store the best motion vector during motion search
int_mv best_mv;
@ -320,38 +341,65 @@ struct macroblock {
int use_default_intra_tx_type;
// use default transform and skip transform type search for inter modes
int use_default_inter_tx_type;
#if CONFIG_PVQ
int rate;
// 1 if neither AC nor DC is coded. Only used during RDO.
int pvq_skip[MAX_MB_PLANE];
PVQ_QUEUE *pvq_q;
// Storage for PVQ tx block encodings in a superblock.
// There can be max 16x16 of 4x4 blocks (and YUV) encode by PVQ
// 256 is the max # of 4x4 blocks in a SB (64x64), which comes from:
// 1) Since PVQ is applied to each trasnform-ed block
// 2) 4x4 is the smallest tx size in AV1
// 3) AV1 allows using smaller tx size than block (i.e. partition) size
// TODO(yushin) : The memory usage could be improved a lot, since this has
// storage for 10 bands and 128 coefficients for every 4x4 block,
PVQ_INFO pvq[MAX_PVQ_BLOCKS_IN_SB][MAX_MB_PLANE];
daala_enc_ctx daala_enc;
int pvq_speed;
int pvq_coded; // Indicates whether pvq_info needs be stored to tokenize
#endif
#if CONFIG_DIST_8X8
int using_dist_8x8;
aom_tune_metric tune_metric;
#if CONFIG_CB4X4
#if CONFIG_HIGHBITDEPTH
DECLARE_ALIGNED(16, uint16_t, decoded_8x8[8 * 8]);
#else
DECLARE_ALIGNED(16, uint8_t, decoded_8x8[8 * 8]);
#endif
#endif // CONFIG_CB4X4
DECLARE_ALIGNED(16, int16_t, pred_luma[MAX_SB_SQUARE]);
#endif // CONFIG_DIST_8X8
int comp_idx_cost[COMP_INDEX_CONTEXTS][2];
int comp_group_idx_cost[COMP_GROUP_IDX_CONTEXTS][2];
// Bit flags for pruning tx type search, tx split, etc.
int tx_search_prune[EXT_TX_SET_TYPES];
int must_find_valid_partition;
int tx_split_prune_flag; // Flag to skip tx split RD search.
};
static INLINE int is_rect_tx_allowed_bsize(BLOCK_SIZE bsize) {
static const char LUT[BLOCK_SIZES_ALL] = {
0, // BLOCK_4X4
1, // BLOCK_4X8
1, // BLOCK_8X4
0, // BLOCK_8X8
1, // BLOCK_8X16
1, // BLOCK_16X8
0, // BLOCK_16X16
1, // BLOCK_16X32
1, // BLOCK_32X16
0, // BLOCK_32X32
1, // BLOCK_32X64
1, // BLOCK_64X32
0, // BLOCK_64X64
0, // BLOCK_64X128
0, // BLOCK_128X64
0, // BLOCK_128X128
1, // BLOCK_4X16
1, // BLOCK_16X4
1, // BLOCK_8X32
1, // BLOCK_32X8
1, // BLOCK_16X64
1, // BLOCK_64X16
};
return LUT[bsize];
}
static INLINE int is_rect_tx_allowed(const MACROBLOCKD *xd,
const MB_MODE_INFO *mbmi) {
return is_rect_tx_allowed_bsize(mbmi->sb_type) &&
!xd->lossless[mbmi->segment_id];
}
static INLINE int tx_size_to_depth(TX_SIZE tx_size, BLOCK_SIZE bsize) {
TX_SIZE ctx_size = max_txsize_rect_lookup[bsize];
int depth = 0;
while (tx_size != ctx_size) {
depth++;
ctx_size = sub_tx_size_map[ctx_size];
assert(depth <= MAX_TX_DEPTH);
}
return depth;
}
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -9,9 +9,10 @@
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "./av1_rtcd.h"
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
#include "av1/common/common.h"
#include "av1/common/filter.h"
#include "aom/aom_integer.h"

View file

@ -13,32 +13,18 @@
#include "av1/encoder/encoder.h"
static const BLOCK_SIZE square[MAX_SB_SIZE_LOG2 - 1] = {
#if CONFIG_CB4X4
BLOCK_4X4,
#endif
BLOCK_8X8, BLOCK_16X16, BLOCK_32X32, BLOCK_64X64,
#if CONFIG_EXT_PARTITION
BLOCK_128X128,
#endif // CONFIG_EXT_PARTITION
BLOCK_4X4, BLOCK_8X8, BLOCK_16X16, BLOCK_32X32, BLOCK_64X64, BLOCK_128X128,
};
static void alloc_mode_context(AV1_COMMON *cm, int num_pix,
#if CONFIG_EXT_PARTITION_TYPES
PARTITION_TYPE partition,
#endif
PICK_MODE_CONTEXT *ctx) {
const int num_planes = av1_num_planes(cm);
int i;
const int num_blk = num_pix / 16;
ctx->num_4x4_blk = num_blk;
#if CONFIG_EXT_PARTITION_TYPES
ctx->partition = partition;
#endif
for (i = 0; i < MAX_MB_PLANE; ++i) {
#if CONFIG_VAR_TX
CHECK_MEM_ERROR(cm, ctx->blk_skip[i], aom_calloc(num_blk, sizeof(uint8_t)));
#endif
CHECK_MEM_ERROR(cm, ctx->blk_skip, aom_calloc(num_blk, sizeof(uint8_t)));
for (i = 0; i < num_planes; ++i) {
CHECK_MEM_ERROR(cm, ctx->coeff[i],
aom_memalign(32, num_pix * sizeof(*ctx->coeff[i])));
CHECK_MEM_ERROR(cm, ctx->qcoeff[i],
@ -47,148 +33,94 @@ static void alloc_mode_context(AV1_COMMON *cm, int num_pix,
aom_memalign(32, num_pix * sizeof(*ctx->dqcoeff[i])));
CHECK_MEM_ERROR(cm, ctx->eobs[i],
aom_memalign(32, num_blk * sizeof(*ctx->eobs[i])));
#if CONFIG_LV_MAP
CHECK_MEM_ERROR(
cm, ctx->txb_entropy_ctx[i],
aom_memalign(32, num_blk * sizeof(*ctx->txb_entropy_ctx[i])));
#endif
#if CONFIG_PVQ
CHECK_MEM_ERROR(cm, ctx->pvq_ref_coeff[i],
aom_memalign(32, num_pix * sizeof(*ctx->pvq_ref_coeff[i])));
#endif
}
for (i = 0; i < 2; ++i) {
CHECK_MEM_ERROR(
cm, ctx->color_index_map[i],
aom_memalign(32, num_pix * sizeof(*ctx->color_index_map[i])));
if (num_pix <= MAX_PALETTE_SQUARE) {
for (i = 0; i < 2; ++i) {
CHECK_MEM_ERROR(
cm, ctx->color_index_map[i],
aom_memalign(32, num_pix * sizeof(*ctx->color_index_map[i])));
}
}
#if CONFIG_MRC_TX
CHECK_MEM_ERROR(cm, ctx->mrc_mask,
aom_memalign(32, num_pix * sizeof(*ctx->mrc_mask)));
#endif // CONFIG_MRC_TX
}
static void free_mode_context(PICK_MODE_CONTEXT *ctx) {
static void free_mode_context(PICK_MODE_CONTEXT *ctx, const int num_planes) {
int i;
for (i = 0; i < MAX_MB_PLANE; ++i) {
#if CONFIG_VAR_TX
aom_free(ctx->blk_skip[i]);
ctx->blk_skip[i] = 0;
#endif
aom_free(ctx->blk_skip);
ctx->blk_skip = 0;
for (i = 0; i < num_planes; ++i) {
aom_free(ctx->coeff[i]);
ctx->coeff[i] = 0;
aom_free(ctx->qcoeff[i]);
ctx->qcoeff[i] = 0;
aom_free(ctx->dqcoeff[i]);
ctx->dqcoeff[i] = 0;
#if CONFIG_PVQ
aom_free(ctx->pvq_ref_coeff[i]);
ctx->pvq_ref_coeff[i] = 0;
#endif
aom_free(ctx->eobs[i]);
ctx->eobs[i] = 0;
#if CONFIG_LV_MAP
aom_free(ctx->txb_entropy_ctx[i]);
ctx->txb_entropy_ctx[i] = 0;
#endif
}
for (i = 0; i < 2; ++i) {
aom_free(ctx->color_index_map[i]);
ctx->color_index_map[i] = 0;
}
#if CONFIG_MRC_TX
aom_free(ctx->mrc_mask);
ctx->mrc_mask = 0;
#endif // CONFIG_MRC_TX
}
static void alloc_tree_contexts(AV1_COMMON *cm, PC_TREE *tree, int num_pix) {
#if CONFIG_EXT_PARTITION_TYPES
alloc_mode_context(cm, num_pix, PARTITION_NONE, &tree->none);
alloc_mode_context(cm, num_pix / 2, PARTITION_HORZ, &tree->horizontal[0]);
alloc_mode_context(cm, num_pix / 2, PARTITION_VERT, &tree->vertical[0]);
alloc_mode_context(cm, num_pix / 2, PARTITION_VERT, &tree->horizontal[1]);
alloc_mode_context(cm, num_pix / 2, PARTITION_VERT, &tree->vertical[1]);
alloc_mode_context(cm, num_pix / 4, PARTITION_HORZ_A, &tree->horizontala[0]);
alloc_mode_context(cm, num_pix / 4, PARTITION_HORZ_A, &tree->horizontala[1]);
alloc_mode_context(cm, num_pix / 2, PARTITION_HORZ_A, &tree->horizontala[2]);
alloc_mode_context(cm, num_pix / 2, PARTITION_HORZ_B, &tree->horizontalb[0]);
alloc_mode_context(cm, num_pix / 4, PARTITION_HORZ_B, &tree->horizontalb[1]);
alloc_mode_context(cm, num_pix / 4, PARTITION_HORZ_B, &tree->horizontalb[2]);
alloc_mode_context(cm, num_pix / 4, PARTITION_VERT_A, &tree->verticala[0]);
alloc_mode_context(cm, num_pix / 4, PARTITION_VERT_A, &tree->verticala[1]);
alloc_mode_context(cm, num_pix / 2, PARTITION_VERT_A, &tree->verticala[2]);
alloc_mode_context(cm, num_pix / 2, PARTITION_VERT_B, &tree->verticalb[0]);
alloc_mode_context(cm, num_pix / 4, PARTITION_VERT_B, &tree->verticalb[1]);
alloc_mode_context(cm, num_pix / 4, PARTITION_VERT_B, &tree->verticalb[2]);
for (int i = 0; i < 4; ++i) {
alloc_mode_context(cm, num_pix / 4, PARTITION_HORZ_4,
&tree->horizontal4[i]);
alloc_mode_context(cm, num_pix / 4, PARTITION_HORZ_4, &tree->vertical4[i]);
}
#if CONFIG_SUPERTX
alloc_mode_context(cm, num_pix, PARTITION_HORZ, &tree->horizontal_supertx);
alloc_mode_context(cm, num_pix, PARTITION_VERT, &tree->vertical_supertx);
alloc_mode_context(cm, num_pix, PARTITION_SPLIT, &tree->split_supertx);
alloc_mode_context(cm, num_pix, PARTITION_HORZ_A, &tree->horizontala_supertx);
alloc_mode_context(cm, num_pix, PARTITION_HORZ_B, &tree->horizontalb_supertx);
alloc_mode_context(cm, num_pix, PARTITION_VERT_A, &tree->verticala_supertx);
alloc_mode_context(cm, num_pix, PARTITION_VERT_B, &tree->verticalb_supertx);
#endif // CONFIG_SUPERTX
#else
static void alloc_tree_contexts(AV1_COMMON *cm, PC_TREE *tree, int num_pix,
int is_leaf) {
alloc_mode_context(cm, num_pix, &tree->none);
if (is_leaf) return;
alloc_mode_context(cm, num_pix / 2, &tree->horizontal[0]);
alloc_mode_context(cm, num_pix / 2, &tree->vertical[0]);
#if CONFIG_SUPERTX
alloc_mode_context(cm, num_pix, &tree->horizontal_supertx);
alloc_mode_context(cm, num_pix, &tree->vertical_supertx);
alloc_mode_context(cm, num_pix, &tree->split_supertx);
#endif
if (num_pix > 16) {
alloc_mode_context(cm, num_pix / 2, &tree->horizontal[1]);
alloc_mode_context(cm, num_pix / 2, &tree->vertical[1]);
} else {
memset(&tree->horizontal[1], 0, sizeof(tree->horizontal[1]));
memset(&tree->vertical[1], 0, sizeof(tree->vertical[1]));
alloc_mode_context(cm, num_pix / 2, &tree->horizontal[1]);
alloc_mode_context(cm, num_pix / 2, &tree->vertical[1]);
alloc_mode_context(cm, num_pix / 4, &tree->horizontala[0]);
alloc_mode_context(cm, num_pix / 4, &tree->horizontala[1]);
alloc_mode_context(cm, num_pix / 2, &tree->horizontala[2]);
alloc_mode_context(cm, num_pix / 2, &tree->horizontalb[0]);
alloc_mode_context(cm, num_pix / 4, &tree->horizontalb[1]);
alloc_mode_context(cm, num_pix / 4, &tree->horizontalb[2]);
alloc_mode_context(cm, num_pix / 4, &tree->verticala[0]);
alloc_mode_context(cm, num_pix / 4, &tree->verticala[1]);
alloc_mode_context(cm, num_pix / 2, &tree->verticala[2]);
alloc_mode_context(cm, num_pix / 2, &tree->verticalb[0]);
alloc_mode_context(cm, num_pix / 4, &tree->verticalb[1]);
alloc_mode_context(cm, num_pix / 4, &tree->verticalb[2]);
for (int i = 0; i < 4; ++i) {
alloc_mode_context(cm, num_pix / 4, &tree->horizontal4[i]);
alloc_mode_context(cm, num_pix / 4, &tree->vertical4[i]);
}
#endif // CONFIG_EXT_PARTITION_TYPES
}
static void free_tree_contexts(PC_TREE *tree) {
#if CONFIG_EXT_PARTITION_TYPES
static void free_tree_contexts(PC_TREE *tree, const int num_planes) {
int i;
for (i = 0; i < 3; i++) {
free_mode_context(&tree->horizontala[i]);
free_mode_context(&tree->horizontalb[i]);
free_mode_context(&tree->verticala[i]);
free_mode_context(&tree->verticalb[i]);
free_mode_context(&tree->horizontala[i], num_planes);
free_mode_context(&tree->horizontalb[i], num_planes);
free_mode_context(&tree->verticala[i], num_planes);
free_mode_context(&tree->verticalb[i], num_planes);
}
for (i = 0; i < 4; ++i) {
free_mode_context(&tree->horizontal4[i]);
free_mode_context(&tree->vertical4[i]);
free_mode_context(&tree->horizontal4[i], num_planes);
free_mode_context(&tree->vertical4[i], num_planes);
}
#endif // CONFIG_EXT_PARTITION_TYPES
free_mode_context(&tree->none);
free_mode_context(&tree->horizontal[0]);
free_mode_context(&tree->horizontal[1]);
free_mode_context(&tree->vertical[0]);
free_mode_context(&tree->vertical[1]);
#if CONFIG_SUPERTX
free_mode_context(&tree->horizontal_supertx);
free_mode_context(&tree->vertical_supertx);
free_mode_context(&tree->split_supertx);
#if CONFIG_EXT_PARTITION_TYPES
free_mode_context(&tree->horizontala_supertx);
free_mode_context(&tree->horizontalb_supertx);
free_mode_context(&tree->verticala_supertx);
free_mode_context(&tree->verticalb_supertx);
#endif // CONFIG_EXT_PARTITION_TYPES
#endif // CONFIG_SUPERTX
free_mode_context(&tree->none, num_planes);
free_mode_context(&tree->horizontal[0], num_planes);
free_mode_context(&tree->horizontal[1], num_planes);
free_mode_context(&tree->vertical[0], num_planes);
free_mode_context(&tree->vertical[1], num_planes);
}
// This function sets up a tree of contexts such that at each square
@ -197,65 +129,25 @@ static void free_tree_contexts(PC_TREE *tree) {
// represents the state of our search.
void av1_setup_pc_tree(AV1_COMMON *cm, ThreadData *td) {
int i, j;
#if CONFIG_CB4X4
#if CONFIG_EXT_PARTITION
const int tree_nodes_inc = 1024;
#else
const int tree_nodes_inc = 256;
#endif // CONFIG_EXT_PARTITION
const int leaf_factor = 4;
#else
const int tree_nodes_inc = 0;
const int leaf_factor = 1;
#endif
#if CONFIG_EXT_PARTITION
const int leaf_nodes = 256 * leaf_factor;
const int tree_nodes = tree_nodes_inc + 256 + 64 + 16 + 4 + 1;
#else
const int leaf_nodes = 64 * leaf_factor;
const int tree_nodes = tree_nodes_inc + 64 + 16 + 4 + 1;
#endif // CONFIG_EXT_PARTITION
int pc_tree_index = 0;
PC_TREE *this_pc;
int square_index = 1;
int nodes;
#if !CONFIG_CB4X4
aom_free(td->leaf_tree);
CHECK_MEM_ERROR(cm, td->leaf_tree,
aom_calloc(leaf_nodes, sizeof(*td->leaf_tree)));
PICK_MODE_CONTEXT *this_leaf = &td->leaf_tree[0];
#endif
aom_free(td->pc_tree);
CHECK_MEM_ERROR(cm, td->pc_tree,
aom_calloc(tree_nodes, sizeof(*td->pc_tree)));
this_pc = &td->pc_tree[0];
#if !CONFIG_CB4X4
// 4x4 blocks smaller than 8x8 but in the same 8x8 block share the same
// context so we only need to allocate 1 for each 8x8 block.
for (i = 0; i < leaf_nodes; ++i) {
#if CONFIG_EXT_PARTITION_TYPES
alloc_mode_context(cm, 4, PARTITION_NONE, &td->leaf_tree[i]);
#else
alloc_mode_context(cm, 16, &td->leaf_tree[i]);
#endif
}
#endif
// Sets up all the leaf nodes in the tree.
for (pc_tree_index = 0; pc_tree_index < leaf_nodes; ++pc_tree_index) {
PC_TREE *const tree = &td->pc_tree[pc_tree_index];
tree->block_size = square[0];
#if CONFIG_CB4X4
alloc_tree_contexts(cm, tree, 16);
#else
alloc_tree_contexts(cm, tree, 4);
#endif
#if !CONFIG_CB4X4
tree->leaf_split[0] = this_leaf++;
for (j = 1; j < 4; j++) tree->leaf_split[j] = tree->leaf_split[0];
#endif
alloc_tree_contexts(cm, tree, 16, 1);
}
// Each node has 4 leaf nodes, fill each block_size level of the tree
@ -263,11 +155,7 @@ void av1_setup_pc_tree(AV1_COMMON *cm, ThreadData *td) {
for (nodes = leaf_nodes >> 2; nodes > 0; nodes >>= 2) {
for (i = 0; i < nodes; ++i) {
PC_TREE *const tree = &td->pc_tree[pc_tree_index];
#if CONFIG_CB4X4
alloc_tree_contexts(cm, tree, 16 << (2 * square_index));
#else
alloc_tree_contexts(cm, tree, 4 << (2 * square_index));
#endif
alloc_tree_contexts(cm, tree, 16 << (2 * square_index), 0);
tree->block_size = square[square_index];
for (j = 0; j < 4; j++) tree->split[j] = this_pc++;
++pc_tree_index;
@ -286,35 +174,41 @@ void av1_setup_pc_tree(AV1_COMMON *cm, ThreadData *td) {
}
}
void av1_free_pc_tree(ThreadData *td) {
#if CONFIG_CB4X4
#if CONFIG_EXT_PARTITION
void av1_free_pc_tree(ThreadData *td, const int num_planes) {
const int tree_nodes_inc = 1024;
#else
const int tree_nodes_inc = 256;
#endif // CONFIG_EXT_PARTITION
#else
const int tree_nodes_inc = 0;
#endif
#if CONFIG_EXT_PARTITION
const int tree_nodes = tree_nodes_inc + 256 + 64 + 16 + 4 + 1;
#else
const int tree_nodes = tree_nodes_inc + 64 + 16 + 4 + 1;
#endif // CONFIG_EXT_PARTITION
int i;
for (i = 0; i < tree_nodes; ++i) free_tree_contexts(&td->pc_tree[i]);
for (i = 0; i < tree_nodes; ++i)
free_tree_contexts(&td->pc_tree[i], num_planes);
aom_free(td->pc_tree);
td->pc_tree = NULL;
#if !CONFIG_CB4X4
const int leaf_factor = 1;
#if CONFIG_EXT_PARTITION
const int leaf_nodes = 256 * leaf_factor;
#else
const int leaf_nodes = 64 * leaf_factor;
#endif // CONFIG_EXT_PARTITION
for (i = 0; i < leaf_nodes; ++i) free_mode_context(&td->leaf_tree[i]);
aom_free(td->leaf_tree);
td->leaf_tree = NULL;
#endif
}
void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx,
PICK_MODE_CONTEXT *src_ctx) {
dst_ctx->mic = src_ctx->mic;
dst_ctx->mbmi_ext = src_ctx->mbmi_ext;
dst_ctx->num_4x4_blk = src_ctx->num_4x4_blk;
dst_ctx->skip = src_ctx->skip;
dst_ctx->skippable = src_ctx->skippable;
dst_ctx->best_mode_index = src_ctx->best_mode_index;
memcpy(dst_ctx->blk_skip, src_ctx->blk_skip,
sizeof(uint8_t) * src_ctx->num_4x4_blk);
dst_ctx->hybrid_pred_diff = src_ctx->hybrid_pred_diff;
dst_ctx->comp_pred_diff = src_ctx->comp_pred_diff;
dst_ctx->single_pred_diff = src_ctx->single_pred_diff;
dst_ctx->rate = src_ctx->rate;
dst_ctx->dist = src_ctx->dist;
dst_ctx->rdcost = src_ctx->rdcost;
dst_ctx->rd_mode_is_ready = src_ctx->rd_mode_is_ready;
memcpy(dst_ctx->pred_mv, src_ctx->pred_mv, sizeof(MV) * REF_FRAMES);
dst_ctx->pred_interp_filter = src_ctx->pred_interp_filter;
dst_ctx->partition = src_ctx->partition;
}

View file

@ -23,28 +23,29 @@ struct AV1_COMP;
struct AV1Common;
struct ThreadData;
typedef enum {
// Search all the partition types in this plane.
SEARCH_FULL_PLANE = 0,
// Only search none_partition coding block.
NONE_PARTITION_PLANE = 1,
// Search all the partition types in this plane except split.
SEARCH_SAME_PLANE = 2,
// Skip search partition on this plane. Go split directly.
SPLIT_PLANE = 3,
} CB_TREE_SEARCH;
// Structure to hold snapshot of coding context during the mode picking process
typedef struct {
MODE_INFO mic;
MB_MODE_INFO mic;
MB_MODE_INFO_EXT mbmi_ext;
uint8_t *color_index_map[2];
#if CONFIG_MRC_TX
uint8_t *mrc_mask;
#endif // CONFIG_MRC_TX
#if CONFIG_VAR_TX
uint8_t *blk_skip[MAX_MB_PLANE];
#endif
uint8_t *blk_skip;
tran_low_t *coeff[MAX_MB_PLANE];
tran_low_t *qcoeff[MAX_MB_PLANE];
tran_low_t *dqcoeff[MAX_MB_PLANE];
#if CONFIG_PVQ
tran_low_t *pvq_ref_coeff[MAX_MB_PLANE];
#endif
uint16_t *eobs[MAX_MB_PLANE];
#if CONFIG_LV_MAP
uint8_t *txb_entropy_ctx[MAX_MB_PLANE];
#endif
int num_4x4_blk;
int skip;
@ -60,16 +61,27 @@ typedef struct {
// scope of refactoring.
int rate;
int64_t dist;
int64_t rdcost;
int rd_mode_is_ready; // Flag to indicate whether rd pick mode decision has
// been made.
// motion vector cache for adaptive motion search control in partition
// search loop
MV pred_mv[TOTAL_REFS_PER_FRAME];
MV pred_mv[REF_FRAMES];
InterpFilter pred_interp_filter;
#if CONFIG_EXT_PARTITION_TYPES
PARTITION_TYPE partition;
#endif
} PICK_MODE_CONTEXT;
typedef struct {
int valid;
int split;
int skip;
int64_t rdcost;
int sub_block_split[4];
int sub_block_skip[4];
int64_t sub_block_rdcost[4];
} PC_TREE_STATS;
typedef struct PC_TREE {
int index;
PARTITION_TYPE partitioning;
@ -77,34 +89,21 @@ typedef struct PC_TREE {
PICK_MODE_CONTEXT none;
PICK_MODE_CONTEXT horizontal[2];
PICK_MODE_CONTEXT vertical[2];
#if CONFIG_EXT_PARTITION_TYPES
PICK_MODE_CONTEXT horizontala[3];
PICK_MODE_CONTEXT horizontalb[3];
PICK_MODE_CONTEXT verticala[3];
PICK_MODE_CONTEXT verticalb[3];
PICK_MODE_CONTEXT horizontal4[4];
PICK_MODE_CONTEXT vertical4[4];
#endif
// TODO(jingning): remove leaf_split[] when cb4x4 experiment flag is removed.
union {
struct PC_TREE *split[4];
PICK_MODE_CONTEXT *leaf_split[4];
};
#if CONFIG_SUPERTX
PICK_MODE_CONTEXT horizontal_supertx;
PICK_MODE_CONTEXT vertical_supertx;
PICK_MODE_CONTEXT split_supertx;
#if CONFIG_EXT_PARTITION_TYPES
PICK_MODE_CONTEXT horizontala_supertx;
PICK_MODE_CONTEXT horizontalb_supertx;
PICK_MODE_CONTEXT verticala_supertx;
PICK_MODE_CONTEXT verticalb_supertx;
#endif
#endif
CB_TREE_SEARCH cb_search_range;
struct PC_TREE *split[4];
PC_TREE_STATS pc_tree_stats;
} PC_TREE;
void av1_setup_pc_tree(struct AV1Common *cm, struct ThreadData *td);
void av1_free_pc_tree(struct ThreadData *td);
void av1_free_pc_tree(struct ThreadData *td, const int num_planes);
void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx,
PICK_MODE_CONTEXT *src_ctx);
#ifdef __cplusplus
} // extern "C"

View file

@ -13,7 +13,8 @@
#include <memory.h>
#include <math.h>
#include "./av1_rtcd.h"
#include "config/av1_rtcd.h"
#include "av1/encoder/corner_match.h"
#define SEARCH_SZ 9

View file

@ -13,65 +13,26 @@
#include "av1/encoder/cost.h"
#include "av1/common/entropy.h"
/* round(-log2(i/256.) * (1 << AV1_PROB_COST_SHIFT))
Begins with a bogus entry for simpler addressing. */
const uint16_t av1_prob_cost[256] = {
4096, 4096, 3584, 3284, 3072, 2907, 2772, 2659, 2560, 2473, 2395, 2325, 2260,
2201, 2147, 2096, 2048, 2003, 1961, 1921, 1883, 1847, 1813, 1780, 1748, 1718,
1689, 1661, 1635, 1609, 1584, 1559, 1536, 1513, 1491, 1470, 1449, 1429, 1409,
1390, 1371, 1353, 1335, 1318, 1301, 1284, 1268, 1252, 1236, 1221, 1206, 1192,
1177, 1163, 1149, 1136, 1123, 1110, 1097, 1084, 1072, 1059, 1047, 1036, 1024,
1013, 1001, 990, 979, 968, 958, 947, 937, 927, 917, 907, 897, 887,
878, 868, 859, 850, 841, 832, 823, 814, 806, 797, 789, 780, 772,
764, 756, 748, 740, 732, 724, 717, 709, 702, 694, 687, 680, 673,
665, 658, 651, 644, 637, 631, 624, 617, 611, 604, 598, 591, 585,
578, 572, 566, 560, 554, 547, 541, 535, 530, 524, 518, 512, 506,
501, 495, 489, 484, 478, 473, 467, 462, 456, 451, 446, 441, 435,
430, 425, 420, 415, 410, 405, 400, 395, 390, 385, 380, 375, 371,
366, 361, 356, 352, 347, 343, 338, 333, 329, 324, 320, 316, 311,
307, 302, 298, 294, 289, 285, 281, 277, 273, 268, 264, 260, 256,
252, 248, 244, 240, 236, 232, 228, 224, 220, 216, 212, 209, 205,
201, 197, 194, 190, 186, 182, 179, 175, 171, 168, 164, 161, 157,
153, 150, 146, 143, 139, 136, 132, 129, 125, 122, 119, 115, 112,
109, 105, 102, 99, 95, 92, 89, 86, 82, 79, 76, 73, 70,
66, 63, 60, 57, 54, 51, 48, 45, 42, 38, 35, 32, 29,
26, 23, 20, 18, 15, 12, 9, 6, 3
// round(-log2(i/256.) * (1 << AV1_PROB_COST_SHIFT)); i = 128~255.
const uint16_t av1_prob_cost[128] = {
512, 506, 501, 495, 489, 484, 478, 473, 467, 462, 456, 451, 446, 441, 435,
430, 425, 420, 415, 410, 405, 400, 395, 390, 385, 380, 375, 371, 366, 361,
356, 352, 347, 343, 338, 333, 329, 324, 320, 316, 311, 307, 302, 298, 294,
289, 285, 281, 277, 273, 268, 264, 260, 256, 252, 248, 244, 240, 236, 232,
228, 224, 220, 216, 212, 209, 205, 201, 197, 194, 190, 186, 182, 179, 175,
171, 168, 164, 161, 157, 153, 150, 146, 143, 139, 136, 132, 129, 125, 122,
119, 115, 112, 109, 105, 102, 99, 95, 92, 89, 86, 82, 79, 76, 73,
70, 66, 63, 60, 57, 54, 51, 48, 45, 42, 38, 35, 32, 29, 26,
23, 20, 18, 15, 12, 9, 6, 3,
};
static void cost(int *costs, aom_tree tree, const aom_prob *probs, int i,
int c) {
const aom_prob prob = probs[i / 2];
int b;
assert(prob != 0);
for (b = 0; b <= 1; ++b) {
const int cc = c + av1_cost_bit(prob, b);
const aom_tree_index ii = tree[i + b];
if (ii <= 0)
costs[-ii] = cc;
else
cost(costs, tree, probs, ii, cc);
}
}
void av1_cost_tokens(int *costs, const aom_prob *probs, aom_tree tree) {
cost(costs, tree, probs, 0, 0);
}
void av1_cost_tokens_skip(int *costs, const aom_prob *probs, aom_tree tree) {
assert(tree[0] <= 0 && tree[1] > 0);
costs[-tree[0]] = av1_cost_bit(probs[0], 0);
cost(costs, tree, probs, 2, 0);
}
void av1_cost_tokens_from_cdf(int *costs, const aom_cdf_prob *cdf,
const int *inv_map) {
int i;
aom_cdf_prob prev_cdf = 0;
for (i = 0;; ++i) {
const aom_cdf_prob p15 = AOM_ICDF(cdf[i]) - prev_cdf;
aom_cdf_prob p15 = AOM_ICDF(cdf[i]) - prev_cdf;
p15 = (p15 < EC_MIN_PROB) ? EC_MIN_PROB : p15;
prev_cdf = AOM_ICDF(cdf[i]);
if (inv_map)

View file

@ -19,17 +19,11 @@
extern "C" {
#endif
extern const uint16_t av1_prob_cost[256];
extern const uint16_t av1_prob_cost[128];
// The factor to scale from cost in bits to cost in av1_prob_cost units.
#define AV1_PROB_COST_SHIFT 9
#define av1_cost_zero(prob) (av1_prob_cost[prob])
#define av1_cost_one(prob) av1_cost_zero(256 - (prob))
#define av1_cost_bit(prob, bit) av1_cost_zero((bit) ? 256 - (prob) : (prob))
// Cost of coding an n bit literal, using 128 (i.e. 50%) probability
// for each bit.
#define av1_cost_literal(n) ((n) * (1 << AV1_PROB_COST_SHIFT))
@ -38,31 +32,11 @@ extern const uint16_t av1_prob_cost[256];
static INLINE int av1_cost_symbol(aom_cdf_prob p15) {
assert(0 < p15 && p15 < CDF_PROB_TOP);
const int shift = CDF_PROB_BITS - 1 - get_msb(p15);
return av1_cost_zero(get_prob(p15 << shift, CDF_PROB_TOP)) +
av1_cost_literal(shift);
const int prob = get_prob(p15 << shift, CDF_PROB_TOP);
assert(prob >= 128);
return av1_prob_cost[prob - 128] + av1_cost_literal(shift);
}
static INLINE unsigned int cost_branch256(const unsigned int ct[2],
aom_prob p) {
return ct[0] * av1_cost_zero(p) + ct[1] * av1_cost_one(p);
}
static INLINE int treed_cost(aom_tree tree, const aom_prob *probs, int bits,
int len) {
int cost = 0;
aom_tree_index i = 0;
do {
const int bit = (bits >> --len) & 1;
cost += av1_cost_bit(probs[i >> 1], bit);
i = tree[i + bit];
} while (len);
return cost;
}
void av1_cost_tokens(int *costs, const aom_prob *probs, aom_tree tree);
void av1_cost_tokens_skip(int *costs, const aom_prob *probs, aom_tree tree);
void av1_cost_tokens_from_cdf(int *costs, const aom_cdf_prob *cdf,
const int *inv_map);

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "encint.h"
void od_encode_checkpoint(const daala_enc_ctx *enc, od_rollback_buffer *rbuf) {
#if !CONFIG_ANS
od_ec_enc_checkpoint(&rbuf->ec, &enc->w.ec);
#else
#error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
OD_COPY(&rbuf->adapt, enc->state.adapt, 1);
}
void od_encode_rollback(daala_enc_ctx *enc, const od_rollback_buffer *rbuf) {
#if !CONFIG_ANS
od_ec_enc_rollback(&enc->w.ec, &rbuf->ec);
#else
#error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
OD_COPY(enc->state.adapt, &rbuf->adapt, 1);
}

File diff suppressed because it is too large Load diff

144
third_party/aom/av1/encoder/dwt.c vendored Normal file
View file

@ -0,0 +1,144 @@
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include "config/av1_rtcd.h"
#include "av1/encoder/dwt.h"
// Note: block length must be even for this implementation
static void analysis_53_row(int length, tran_low_t *x, tran_low_t *lowpass,
tran_low_t *highpass) {
int n;
tran_low_t r, *a, *b;
n = length >> 1;
b = highpass;
a = lowpass;
while (--n) {
*a++ = (r = *x++) * 2;
*b++ = *x - ((r + x[1] + 1) >> 1);
x++;
}
*a = (r = *x++) * 2;
*b = *x - r;
n = length >> 1;
b = highpass;
a = lowpass;
r = *highpass;
while (n--) {
*a++ += (r + (*b) + 1) >> 1;
r = *b++;
}
}
static void analysis_53_col(int length, tran_low_t *x, tran_low_t *lowpass,
tran_low_t *highpass) {
int n;
tran_low_t r, *a, *b;
n = length >> 1;
b = highpass;
a = lowpass;
while (--n) {
*a++ = (r = *x++);
*b++ = (((*x) * 2) - (r + x[1]) + 2) >> 2;
x++;
}
*a = (r = *x++);
*b = (*x - r + 1) >> 1;
n = length >> 1;
b = highpass;
a = lowpass;
r = *highpass;
while (n--) {
*a++ += (r + (*b) + 1) >> 1;
r = *b++;
}
}
static void dyadic_analyze_53_uint8_input(int levels, int width, int height,
uint8_t *x, int pitch_x,
tran_low_t *c, int pitch_c,
int dwt_scale_bits, int hbd) {
int lv, i, j, nh, nw, hh = height, hw = width;
tran_low_t buffer[2 * DWT_MAX_LENGTH];
if (hbd) {
uint16_t *x16 = CONVERT_TO_SHORTPTR(x);
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
c[i * pitch_c + j] = x16[i * pitch_x + j] << dwt_scale_bits;
}
}
} else {
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
c[i * pitch_c + j] = x[i * pitch_x + j] << dwt_scale_bits;
}
}
}
for (lv = 0; lv < levels; lv++) {
nh = hh;
hh = (hh + 1) >> 1;
nw = hw;
hw = (hw + 1) >> 1;
if ((nh < 2) || (nw < 2)) return;
for (i = 0; i < nh; i++) {
memcpy(buffer, &c[i * pitch_c], nw * sizeof(tran_low_t));
analysis_53_row(nw, buffer, &c[i * pitch_c], &c[i * pitch_c] + hw);
}
for (j = 0; j < nw; j++) {
for (i = 0; i < nh; i++) buffer[i + nh] = c[i * pitch_c + j];
analysis_53_col(nh, buffer + nh, buffer, buffer + hh);
for (i = 0; i < nh; i++) c[i * pitch_c + j] = buffer[i];
}
}
}
void av1_fdwt8x8_uint8_input_c(uint8_t *input, tran_low_t *output, int stride,
int hbd) {
dyadic_analyze_53_uint8_input(4, 8, 8, input, stride, output, 8, 2, hbd);
}
int av1_haar_ac_sad(tran_low_t *output, int bw, int bh, int stride) {
int acsad = 0;
for (int r = 0; r < bh; ++r)
for (int c = 0; c < bw; ++c) {
if (r >= bh / 2 || c >= bw / 2) acsad += abs(output[r * stride + c]);
}
return acsad;
}
uint64_t av1_dct_ac_sad(tran_low_t *output, int bw, int bh, int stride) {
uint64_t acsad = 0;
for (int r = 0; r < bh; ++r)
for (int c = 0; c < bw; ++c) {
if (r > 0 || c > 0) acsad += abs(output[r * stride + c]);
}
return acsad;
}
uint32_t av1_variance(uint8_t *input, int bw, int bh, int stride) {
int sum = 0;
uint32_t sse = 0;
for (int r = 0; r < bh; ++r)
for (int c = 0; c < bw; ++c) {
sum += input[r * stride + c];
sse += input[r * stride + c] * input[r * stride + c];
}
return sse - (uint32_t)(((int64_t)sum * sum) / (bw * bh));
}
int av1_haar_ac_sad_8x8_uint8_input(uint8_t *input, int stride, int hbd) {
tran_low_t output[64];
av1_fdwt8x8_uint8_input_c(input, output, stride, hbd);
return av1_haar_ac_sad(output, 8, 8, 8);
}

9
third_party/aom/av1/encoder/dwt.h vendored Normal file
View file

@ -0,0 +1,9 @@
#include "av1/common/common.h"
#include "av1/common/enums.h"
#define DWT_MAX_LENGTH 64
void av1_fdwt8x8(tran_low_t *input, tran_low_t *output, int stride);
void av1_fdwt8x8_uint8_input_c(uint8_t *input, tran_low_t *output, int stride,
int hbd);
int av1_haar_ac_sad_8x8_uint8_input(uint8_t *input, int stride, int hbd);

View file

@ -1,51 +0,0 @@
/*
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
/* clang-format off */
#if !defined(_encint_H)
# define _encint_H (1)
typedef struct daala_enc_ctx od_enc_ctx;
typedef struct od_params_ctx od_params_ctx;
typedef struct od_rollback_buffer od_rollback_buffer;
# include "aom_dsp/entenc.h"
# include "av1/common/odintrin.h"
# include "av1/common/pvq_state.h"
struct daala_enc_ctx{
/* Stores context-adaptive CDFs for PVQ. */
od_state state;
/* AOM entropy encoder. */
aom_writer w;
int use_activity_masking;
/* Mode of quantization matrice : FLAT (0) or HVS (1) */
int qm;
/*Normalized PVQ lambda for use where we've already performed
quantization.*/
double pvq_norm_lambda;
double pvq_norm_lambda_dc;
};
// from daalaenc.h
/**The encoder context.*/
typedef struct daala_enc_ctx daala_enc_ctx;
/** Holds important encoder information so we can roll back decisions */
struct od_rollback_buffer {
od_ec_enc ec;
od_adapt_ctx adapt;
};
void od_encode_checkpoint(const daala_enc_ctx *enc, od_rollback_buffer *rbuf);
void od_encode_rollback(daala_enc_ctx *enc, const od_rollback_buffer *rbuf);
#endif

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,8 @@
extern "C" {
#endif
#define DELTAQ_MODULATION 0 // 0: variance based, 1: wavelet AC energy based
struct macroblock;
struct yv12_buffer_config;
struct AV1_COMP;
@ -27,7 +29,7 @@ struct ThreadData;
void av1_setup_src_planes(struct macroblock *x,
const struct yv12_buffer_config *src, int mi_row,
int mi_col);
int mi_col, const int num_planes);
void av1_encode_frame(struct AV1_COMP *cpi);
@ -35,12 +37,6 @@ void av1_init_tile_data(struct AV1_COMP *cpi);
void av1_encode_tile(struct AV1_COMP *cpi, struct ThreadData *td, int tile_row,
int tile_col);
void av1_update_tx_type_count(const struct AV1Common *cm, MACROBLOCKD *xd,
#if CONFIG_TXK_SEL
int blk_row, int blk_col, int block, int plane,
#endif
BLOCK_SIZE bsize, TX_SIZE tx_size,
FRAME_COUNTS *counts);
#ifdef __cplusplus
} // extern "C"
#endif

File diff suppressed because it is too large Load diff

View file

@ -12,21 +12,23 @@
#ifndef AV1_ENCODER_ENCODEMB_H_
#define AV1_ENCODER_ENCODEMB_H_
#include "./aom_config.h"
#include "av1/common/onyxc_int.h"
#include "av1/encoder/block.h"
#include "config/aom_config.h"
#include "av1/common/onyxc_int.h"
#include "av1/common/txb_common.h"
#include "av1/encoder/block.h"
#include "av1/encoder/tokenize.h"
#ifdef __cplusplus
extern "C" {
#endif
struct optimize_ctx {
ENTROPY_CONTEXT ta[MAX_MB_PLANE][2 * MAX_MIB_SIZE];
ENTROPY_CONTEXT tl[MAX_MB_PLANE][2 * MAX_MIB_SIZE];
ENTROPY_CONTEXT ta[MAX_MB_PLANE][MAX_MIB_SIZE];
ENTROPY_CONTEXT tl[MAX_MB_PLANE][MAX_MIB_SIZE];
};
struct encode_b_args {
AV1_COMMON *cm;
const struct AV1_COMP *cpi;
MACROBLOCK *x;
struct optimize_ctx *ctx;
int8_t *skip;
@ -43,52 +45,39 @@ typedef enum AV1_XFORM_QUANT {
AV1_XFORM_QUANT_TYPES,
} AV1_XFORM_QUANT;
void av1_encode_sb(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
int mi_col);
#if CONFIG_SUPERTX
void av1_encode_sb_supertx(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize);
#endif // CONFIG_SUPERTX
void av1_encode_sb(const struct AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
int mi_row, int mi_col, RUN_TYPE dry_run);
void av1_encode_sby_pass1(AV1_COMMON *cm, MACROBLOCK *x, BLOCK_SIZE bsize);
void av1_xform_quant(const AV1_COMMON *cm, MACROBLOCK *x, int plane, int block,
int blk_row, int blk_col, BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, int ctx, AV1_XFORM_QUANT xform_quant_idx);
TX_SIZE tx_size, TX_TYPE tx_type,
AV1_XFORM_QUANT xform_quant_idx);
int av1_optimize_b(const AV1_COMMON *cm, MACROBLOCK *mb, int plane, int blk_row,
int blk_col, int block, BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, const ENTROPY_CONTEXT *a,
const ENTROPY_CONTEXT *l, int fast_mode);
int av1_optimize_b(const struct AV1_COMP *cpi, MACROBLOCK *mb, int plane,
int block, TX_SIZE tx_size, TX_TYPE tx_type,
const TXB_CTX *const txb_ctx, int fast_mode, int *rate_cost);
void av1_subtract_txb(MACROBLOCK *x, int plane, BLOCK_SIZE plane_bsize,
int blk_col, int blk_row, TX_SIZE tx_size);
void av1_subtract_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane);
#if !CONFIG_PVQ
void av1_set_txb_context(MACROBLOCK *x, int plane, int block, TX_SIZE tx_size,
ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l);
#endif
static INLINE void av1_set_txb_context(MACROBLOCK *x, int plane, int block,
TX_SIZE tx_size, ENTROPY_CONTEXT *a,
ENTROPY_CONTEXT *l) {
const uint8_t ctx = x->plane[plane].txb_entropy_ctx[block];
memset(a, ctx, tx_size_wide_unit[tx_size] * sizeof(*a));
memset(l, ctx, tx_size_high_unit[tx_size] * sizeof(*l));
}
void av1_encode_block_intra(int plane, int block, int blk_row, int blk_col,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg);
void av1_encode_intra_block_plane(AV1_COMMON *cm, MACROBLOCK *x,
void av1_encode_intra_block_plane(const struct AV1_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize, int plane,
int enable_optimize_b, int mi_row,
int mi_col);
#if CONFIG_PVQ
PVQ_SKIP_TYPE av1_pvq_encode_helper(MACROBLOCK *x, tran_low_t *const coeff,
tran_low_t *ref_coeff,
tran_low_t *const dqcoeff, uint16_t *eob,
const int16_t *quant, int plane,
TX_SIZE tx_size, TX_TYPE tx_type, int *rate,
int speed, PVQ_INFO *pvq_info);
void av1_store_pvq_enc_info(PVQ_INFO *pvq_info, int *qg, int *theta, int *k,
od_coeff *y, int nb_bands, const int *off,
int *size, int skip_rest, int skip_dir, int bs);
#endif
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -16,20 +16,9 @@
#include "av1/encoder/cost.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/subexp.h"
#include "aom_dsp/aom_dsp_common.h"
static struct av1_token mv_joint_encodings[MV_JOINTS];
static struct av1_token mv_class_encodings[MV_CLASSES];
static struct av1_token mv_fp_encodings[MV_FP_SIZE];
void av1_entropy_mv_init(void) {
av1_tokens_from_tree(mv_joint_encodings, av1_mv_joint_tree);
av1_tokens_from_tree(mv_class_encodings, av1_mv_class_tree);
av1_tokens_from_tree(mv_fp_encodings, av1_mv_fp_tree);
}
static void encode_mv_component(aom_writer *w, int comp, nmv_component *mvcomp,
MvSubpelPrecision precision) {
int offset;
@ -42,38 +31,23 @@ static void encode_mv_component(aom_writer *w, int comp, nmv_component *mvcomp,
assert(comp != 0);
// Sign
#if CONFIG_NEW_MULTISYMBOL
aom_write_bit(w, sign);
#else
aom_write(w, sign, mvcomp->sign);
#endif
// Sign
aom_write_symbol(w, sign, mvcomp->sign_cdf, 2);
// Class
aom_write_symbol(w, mv_class, mvcomp->class_cdf, MV_CLASSES);
aom_write_symbol(w, mv_class, mvcomp->classes_cdf, MV_CLASSES);
// Integer bits
if (mv_class == MV_CLASS_0) {
#if CONFIG_NEW_MULTISYMBOL
aom_write_symbol(w, d, mvcomp->class0_cdf, CLASS0_SIZE);
#else
aom_write(w, d, mvcomp->class0[0]);
#endif
} else {
int i;
const int n = mv_class + CLASS0_BITS - 1; // number of bits
#if CONFIG_NEW_MULTISYMBOL
for (i = 0; i < n; ++i)
aom_write_symbol(w, (d >> i) & 1, mvcomp->bits_cdf[(i + 1) / 2], 2);
#else
for (i = 0; i < n; ++i) aom_write(w, (d >> i) & 1, mvcomp->bits[i]);
#endif
aom_write_symbol(w, (d >> i) & 1, mvcomp->bits_cdf[i], 2);
}
// Fractional bits
#if CONFIG_INTRABC || CONFIG_AMVR
if (precision > MV_SUBPEL_NONE)
#endif // CONFIG_INTRABC || CONFIG_AMVR
{
// Fractional bits
if (precision > MV_SUBPEL_NONE) {
aom_write_symbol(
w, fr,
mv_class == MV_CLASS_0 ? mvcomp->class0_fp_cdf[d] : mvcomp->fp_cdf,
@ -82,13 +56,9 @@ static void encode_mv_component(aom_writer *w, int comp, nmv_component *mvcomp,
// High precision bit
if (precision > MV_SUBPEL_LOW_PRECISION)
#if CONFIG_NEW_MULTISYMBOL
aom_write_symbol(
w, hp, mv_class == MV_CLASS_0 ? mvcomp->class0_hp_cdf : mvcomp->hp_cdf,
2);
#else
aom_write(w, hp, mv_class == MV_CLASS_0 ? mvcomp->class0_hp : mvcomp->hp);
#endif
}
static void build_nmv_component_cost_table(int *mvcost,
@ -100,24 +70,20 @@ static void build_nmv_component_cost_table(int *mvcost,
int class0_fp_cost[CLASS0_SIZE][MV_FP_SIZE], fp_cost[MV_FP_SIZE];
int class0_hp_cost[2], hp_cost[2];
sign_cost[0] = av1_cost_zero(mvcomp->sign);
sign_cost[1] = av1_cost_one(mvcomp->sign);
av1_cost_tokens(class_cost, mvcomp->classes, av1_mv_class_tree);
av1_cost_tokens(class0_cost, mvcomp->class0, av1_mv_class0_tree);
av1_cost_tokens_from_cdf(sign_cost, mvcomp->sign_cdf, NULL);
av1_cost_tokens_from_cdf(class_cost, mvcomp->classes_cdf, NULL);
av1_cost_tokens_from_cdf(class0_cost, mvcomp->class0_cdf, NULL);
for (i = 0; i < MV_OFFSET_BITS; ++i) {
bits_cost[i][0] = av1_cost_zero(mvcomp->bits[i]);
bits_cost[i][1] = av1_cost_one(mvcomp->bits[i]);
av1_cost_tokens_from_cdf(bits_cost[i], mvcomp->bits_cdf[i], NULL);
}
for (i = 0; i < CLASS0_SIZE; ++i)
av1_cost_tokens(class0_fp_cost[i], mvcomp->class0_fp[i], av1_mv_fp_tree);
av1_cost_tokens(fp_cost, mvcomp->fp, av1_mv_fp_tree);
av1_cost_tokens_from_cdf(class0_fp_cost[i], mvcomp->class0_fp_cdf[i], NULL);
av1_cost_tokens_from_cdf(fp_cost, mvcomp->fp_cdf, NULL);
if (precision > MV_SUBPEL_LOW_PRECISION) {
class0_hp_cost[0] = av1_cost_zero(mvcomp->class0_hp);
class0_hp_cost[1] = av1_cost_one(mvcomp->class0_hp);
hp_cost[0] = av1_cost_zero(mvcomp->hp);
hp_cost[1] = av1_cost_one(mvcomp->hp);
av1_cost_tokens_from_cdf(class0_hp_cost, mvcomp->class0_hp_cdf, NULL);
av1_cost_tokens_from_cdf(hp_cost, mvcomp->hp_cdf, NULL);
}
mvcost[0] = 0;
for (v = 1; v <= MV_MAX; ++v) {
@ -134,10 +100,7 @@ static void build_nmv_component_cost_table(int *mvcost,
const int b = c + CLASS0_BITS - 1; /* number of bits */
for (i = 0; i < b; ++i) cost += bits_cost[i][((d >> i) & 1)];
}
#if CONFIG_INTRABC || CONFIG_AMVR
if (precision > MV_SUBPEL_NONE)
#endif // CONFIG_INTRABC || CONFIG_AMVR
{
if (precision > MV_SUBPEL_NONE) {
if (c == MV_CLASS_0) {
cost += class0_fp_cost[d][f];
} else {
@ -156,50 +119,14 @@ static void build_nmv_component_cost_table(int *mvcost,
}
}
#if !CONFIG_NEW_MULTISYMBOL
static void update_mv(aom_writer *w, const unsigned int ct[2], aom_prob *cur_p,
aom_prob upd_p) {
(void)upd_p;
// Just use the default maximum number of tile groups to avoid passing in the
// actual
// number
av1_cond_prob_diff_update(w, cur_p, ct, DEFAULT_MAX_NUM_TG);
}
void av1_write_nmv_probs(AV1_COMMON *cm, int usehp, aom_writer *w,
nmv_context_counts *const nmv_counts) {
int i;
int nmv_ctx = 0;
#if CONFIG_AMVR
if (cm->cur_frame_mv_precision_level) {
return;
}
#endif
for (nmv_ctx = 0; nmv_ctx < NMV_CONTEXTS; ++nmv_ctx) {
nmv_context *const mvc = &cm->fc->nmvc[nmv_ctx];
nmv_context_counts *const counts = &nmv_counts[nmv_ctx];
if (usehp) {
for (i = 0; i < 2; ++i) {
update_mv(w, counts->comps[i].class0_hp, &mvc->comps[i].class0_hp,
MV_UPDATE_PROB);
update_mv(w, counts->comps[i].hp, &mvc->comps[i].hp, MV_UPDATE_PROB);
}
}
}
}
#endif
void av1_encode_mv(AV1_COMP *cpi, aom_writer *w, const MV *mv, const MV *ref,
nmv_context *mvctx, int usehp) {
const MV diff = { mv->row - ref->row, mv->col - ref->col };
const MV_JOINT_TYPE j = av1_get_mv_joint(&diff);
#if CONFIG_AMVR
if (cpi->common.cur_frame_mv_precision_level) {
if (cpi->common.cur_frame_force_integer_mv) {
usehp = MV_SUBPEL_NONE;
}
#endif
aom_write_symbol(w, j, mvctx->joint_cdf, MV_JOINTS);
aom_write_symbol(w, j, mvctx->joints_cdf, MV_JOINTS);
if (mv_joint_vertical(j))
encode_mv_component(w, diff.row, &mvctx->comps[0], usehp);
@ -214,212 +141,81 @@ void av1_encode_mv(AV1_COMP *cpi, aom_writer *w, const MV *mv, const MV *ref,
}
}
#if CONFIG_INTRABC
void av1_encode_dv(aom_writer *w, const MV *mv, const MV *ref,
nmv_context *mvctx) {
// DV and ref DV should not have sub-pel.
assert((mv->col & 7) == 0);
assert((mv->row & 7) == 0);
assert((ref->col & 7) == 0);
assert((ref->row & 7) == 0);
const MV diff = { mv->row - ref->row, mv->col - ref->col };
const MV_JOINT_TYPE j = av1_get_mv_joint(&diff);
aom_write_symbol(w, j, mvctx->joint_cdf, MV_JOINTS);
aom_write_symbol(w, j, mvctx->joints_cdf, MV_JOINTS);
if (mv_joint_vertical(j))
encode_mv_component(w, diff.row, &mvctx->comps[0], MV_SUBPEL_NONE);
if (mv_joint_horizontal(j))
encode_mv_component(w, diff.col, &mvctx->comps[1], MV_SUBPEL_NONE);
}
#endif // CONFIG_INTRABC
void av1_build_nmv_cost_table(int *mvjoint, int *mvcost[2],
const nmv_context *ctx,
MvSubpelPrecision precision) {
av1_cost_tokens(mvjoint, ctx->joints, av1_mv_joint_tree);
av1_cost_tokens_from_cdf(mvjoint, ctx->joints_cdf, NULL);
build_nmv_component_cost_table(mvcost[0], &ctx->comps[0], precision);
build_nmv_component_cost_table(mvcost[1], &ctx->comps[1], precision);
}
static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext,
const int_mv mvs[2], const int_mv pred_mvs[2],
nmv_context_counts *nmv_counts
#if CONFIG_AMVR
,
MvSubpelPrecision precision
#endif
) {
int i;
PREDICTION_MODE mode = mbmi->mode;
int_mv av1_get_ref_mv_from_stack(int ref_idx,
const MV_REFERENCE_FRAME *ref_frame,
int ref_mv_idx,
const MB_MODE_INFO_EXT *mbmi_ext) {
const int8_t ref_frame_type = av1_ref_frame_type(ref_frame);
const CANDIDATE_MV *curr_ref_mv_stack =
mbmi_ext->ref_mv_stack[ref_frame_type];
int_mv ref_mv;
ref_mv.as_int = INVALID_MV;
if (mode == NEWMV || mode == NEW_NEWMV) {
for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0].as_mv;
const MV diff = { mvs[i].as_mv.row - ref->row,
mvs[i].as_mv.col - ref->col };
int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
int nmv_ctx =
av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
mbmi_ext->ref_mv_stack[rf_type], i, mbmi->ref_mv_idx);
nmv_context_counts *counts = &nmv_counts[nmv_ctx];
(void)pred_mvs;
#if CONFIG_AMVR
av1_inc_mv(&diff, counts, precision);
#else
av1_inc_mv(&diff, counts, 1);
#endif
}
} else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0].as_mv;
const MV diff = { mvs[1].as_mv.row - ref->row,
mvs[1].as_mv.col - ref->col };
int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
int nmv_ctx =
av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
mbmi_ext->ref_mv_stack[rf_type], 1, mbmi->ref_mv_idx);
nmv_context_counts *counts = &nmv_counts[nmv_ctx];
#if CONFIG_AMVR
av1_inc_mv(&diff, counts, precision);
#else
av1_inc_mv(&diff, counts, 1);
#endif
} else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_mv;
const MV diff = { mvs[0].as_mv.row - ref->row,
mvs[0].as_mv.col - ref->col };
int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
int nmv_ctx =
av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
mbmi_ext->ref_mv_stack[rf_type], 0, mbmi->ref_mv_idx);
nmv_context_counts *counts = &nmv_counts[nmv_ctx];
#if CONFIG_AMVR
av1_inc_mv(&diff, counts, precision);
#else
av1_inc_mv(&diff, counts, 1);
#endif
#if CONFIG_COMPOUND_SINGLEREF
} else {
assert( // mode == SR_NEAREST_NEWMV ||
mode == SR_NEAR_NEWMV || mode == SR_ZERO_NEWMV || mode == SR_NEW_NEWMV);
const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_mv;
int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
int nmv_ctx =
av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
mbmi_ext->ref_mv_stack[rf_type], 0, mbmi->ref_mv_idx);
nmv_context_counts *counts = &nmv_counts[nmv_ctx];
(void)pred_mvs;
MV diff;
if (mode == SR_NEW_NEWMV) {
diff.row = mvs[0].as_mv.row - ref->row;
diff.col = mvs[0].as_mv.col - ref->col;
av1_inc_mv(&diff, counts, 1);
}
diff.row = mvs[1].as_mv.row - ref->row;
diff.col = mvs[1].as_mv.col - ref->col;
av1_inc_mv(&diff, counts, 1);
#endif // CONFIG_COMPOUND_SINGLEREF
}
}
static void inc_mvs_sub8x8(const MODE_INFO *mi, int block, const int_mv mvs[2],
const MB_MODE_INFO_EXT *mbmi_ext,
nmv_context_counts *nmv_counts
#if CONFIG_AMVR
,
MvSubpelPrecision precision
#endif
) {
int i;
PREDICTION_MODE mode = mi->bmi[block].as_mode;
const MB_MODE_INFO *mbmi = &mi->mbmi;
if (mode == NEWMV || mode == NEW_NEWMV) {
for (i = 0; i < 1 + has_second_ref(&mi->mbmi); ++i) {
const MV *ref = &mi->bmi[block].ref_mv[i].as_mv;
const MV diff = { mvs[i].as_mv.row - ref->row,
mvs[i].as_mv.col - ref->col };
int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
int nmv_ctx =
av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
mbmi_ext->ref_mv_stack[rf_type], i, mbmi->ref_mv_idx);
nmv_context_counts *counts = &nmv_counts[nmv_ctx];
#if CONFIG_AMVR
av1_inc_mv(&diff, counts, precision);
#else
av1_inc_mv(&diff, counts, 1);
#endif
}
} else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
const MV *ref = &mi->bmi[block].ref_mv[1].as_mv;
const MV diff = { mvs[1].as_mv.row - ref->row,
mvs[1].as_mv.col - ref->col };
int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
int nmv_ctx =
av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
mbmi_ext->ref_mv_stack[rf_type], 1, mbmi->ref_mv_idx);
nmv_context_counts *counts = &nmv_counts[nmv_ctx];
#if CONFIG_AMVR
av1_inc_mv(&diff, counts, precision);
#else
av1_inc_mv(&diff, counts, 1);
#endif
} else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
const MV *ref = &mi->bmi[block].ref_mv[0].as_mv;
const MV diff = { mvs[0].as_mv.row - ref->row,
mvs[0].as_mv.col - ref->col };
int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
int nmv_ctx =
av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
mbmi_ext->ref_mv_stack[rf_type], 0, mbmi->ref_mv_idx);
nmv_context_counts *counts = &nmv_counts[nmv_ctx];
#if CONFIG_AMVR
av1_inc_mv(&diff, counts, precision);
#else
av1_inc_mv(&diff, counts, 1);
#endif
}
}
void av1_update_mv_count(ThreadData *td) {
const MACROBLOCKD *xd = &td->mb.e_mbd;
const MODE_INFO *mi = xd->mi[0];
const MB_MODE_INFO *const mbmi = &mi->mbmi;
const MB_MODE_INFO_EXT *mbmi_ext = td->mb.mbmi_ext;
#if CONFIG_CB4X4
const int unify_bsize = 1;
#else
const int unify_bsize = 0;
#endif
#if CONFIG_AMVR
MvSubpelPrecision precision = 1;
if (xd->cur_frame_mv_precision_level) {
precision = MV_SUBPEL_NONE;
}
#endif
if (mbmi->sb_type < BLOCK_8X8 && !unify_bsize) {
const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi->sb_type];
const int num_4x4_h = num_4x4_blocks_high_lookup[mbmi->sb_type];
int idx, idy;
for (idy = 0; idy < 2; idy += num_4x4_h) {
for (idx = 0; idx < 2; idx += num_4x4_w) {
const int i = idy * 2 + idx;
if (have_newmv_in_inter_mode(mi->bmi[i].as_mode))
#if CONFIG_AMVR
inc_mvs_sub8x8(mi, i, mi->bmi[i].as_mv, mbmi_ext, td->counts->mv,
precision);
#else
inc_mvs_sub8x8(mi, i, mi->bmi[i].as_mv, mbmi_ext, td->counts->mv);
#endif
}
if (ref_frame[1] > INTRA_FRAME) {
if (ref_idx == 0) {
ref_mv = curr_ref_mv_stack[ref_mv_idx].this_mv;
} else {
assert(ref_idx == 1);
ref_mv = curr_ref_mv_stack[ref_mv_idx].comp_mv;
}
} else {
if (have_newmv_in_inter_mode(mbmi->mode))
#if CONFIG_AMVR
inc_mvs(mbmi, mbmi_ext, mbmi->mv, mbmi->pred_mv, td->counts->mv,
precision);
#else
inc_mvs(mbmi, mbmi_ext, mbmi->mv, mbmi->pred_mv, td->counts->mv);
#endif
assert(ref_idx == 0);
if (ref_mv_idx < mbmi_ext->ref_mv_count[ref_frame_type]) {
ref_mv = curr_ref_mv_stack[ref_mv_idx].this_mv;
} else {
ref_mv = mbmi_ext->global_mvs[ref_frame_type];
}
}
return ref_mv;
}
int_mv av1_get_ref_mv(const MACROBLOCK *x, int ref_idx) {
const MACROBLOCKD *xd = &x->e_mbd;
const MB_MODE_INFO *mbmi = xd->mi[0];
int ref_mv_idx = mbmi->ref_mv_idx;
if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV) {
assert(has_second_ref(mbmi));
ref_mv_idx += 1;
}
return av1_get_ref_mv_from_stack(ref_idx, mbmi->ref_frame, ref_mv_idx,
x->mbmi_ext);
}
void av1_find_best_ref_mvs_from_stack(int allow_hp,
const MB_MODE_INFO_EXT *mbmi_ext,
MV_REFERENCE_FRAME ref_frame,
int_mv *nearest_mv, int_mv *near_mv,
int is_integer) {
const int ref_idx = 0;
MV_REFERENCE_FRAME ref_frames[2] = { ref_frame, NONE_FRAME };
*nearest_mv = av1_get_ref_mv_from_stack(ref_idx, ref_frames, 0, mbmi_ext);
lower_mv_precision(&nearest_mv->as_mv, allow_hp, is_integer);
*near_mv = av1_get_ref_mv_from_stack(ref_idx, ref_frames, 1, mbmi_ext);
lower_mv_precision(&near_mv->as_mv, allow_hp, is_integer);
}

View file

@ -18,13 +18,6 @@
extern "C" {
#endif
void av1_entropy_mv_init(void);
#if !CONFIG_NEW_MULTISYMBOL
void av1_write_nmv_probs(AV1_COMMON *cm, int usehp, aom_writer *w,
nmv_context_counts *const counts);
#endif
void av1_encode_mv(AV1_COMP *cpi, aom_writer *w, const MV *mv, const MV *ref,
nmv_context *mvctx, int usehp);
@ -34,10 +27,18 @@ void av1_build_nmv_cost_table(int *mvjoint, int *mvcost[2],
void av1_update_mv_count(ThreadData *td);
#if CONFIG_INTRABC
void av1_encode_dv(aom_writer *w, const MV *mv, const MV *ref,
nmv_context *mvctx);
#endif // CONFIG_INTRABC
int_mv av1_get_ref_mv(const MACROBLOCK *x, int ref_idx);
int_mv av1_get_ref_mv_from_stack(int ref_idx,
const MV_REFERENCE_FRAME *ref_frame,
int ref_mv_idx,
const MB_MODE_INFO_EXT *mbmi_ext);
void av1_find_best_ref_mvs_from_stack(int allow_hp,
const MB_MODE_INFO_EXT *mbmi_ext,
MV_REFERENCE_FRAME ref_frame,
int_mv *nearest_mv, int_mv *near_mv,
int is_integer);
#ifdef __cplusplus
} // extern "C"

File diff suppressed because it is too large Load diff

View file

@ -14,7 +14,8 @@
#include <stdio.h>
#include "./aom_config.h"
#include "config/aom_config.h"
#include "aom/aomcx.h"
#include "av1/common/alloccommon.h"
@ -22,11 +23,8 @@
#include "av1/common/thread_common.h"
#include "av1/common/onyxc_int.h"
#include "av1/common/resize.h"
#include "av1/common/timing.h"
#include "av1/encoder/aq_cyclicrefresh.h"
#if CONFIG_ANS
#include "aom_dsp/ans.h"
#include "aom_dsp/buf_ans.h"
#endif
#include "av1/encoder/av1_quantize.h"
#include "av1/encoder/context_tree.h"
#include "av1/encoder/encodemb.h"
@ -38,9 +36,6 @@
#include "av1/encoder/rd.h"
#include "av1/encoder/speed_features.h"
#include "av1/encoder/tokenize.h"
#if CONFIG_XIPHRC
#include "av1/encoder/ratectrl_xiph.h"
#endif
#if CONFIG_INTERNAL_STATS
#include "aom_dsp/ssim.h"
@ -54,19 +49,13 @@ extern "C" {
#endif
typedef struct {
int nmv_vec_cost[NMV_CONTEXTS][MV_JOINTS];
int nmv_costs[NMV_CONTEXTS][2][MV_VALS];
int nmv_costs_hp[NMV_CONTEXTS][2][MV_VALS];
// 0 = Intra, Last, GF, ARF
int8_t last_ref_lf_deltas[TOTAL_REFS_PER_FRAME];
// 0 = ZERO_MV, MV
int8_t last_mode_lf_deltas[MAX_MODE_LF_DELTAS];
int nmv_vec_cost[MV_JOINTS];
int nmv_costs[2][MV_VALS];
int nmv_costs_hp[2][MV_VALS];
FRAME_CONTEXT fc;
} CODING_CONTEXT;
#if !CONFIG_NO_FRAME_CONTEXT_SIGNALING
typedef enum {
// regular inter frame
REGULAR_FRAME = 0,
@ -76,14 +65,12 @@ typedef enum {
OVERLAY_FRAME = 2,
// golden frame
GLD_FRAME = 3,
#if CONFIG_EXT_REFS
// backward reference frame
BRF_FRAME = 4,
// extra alternate reference frame
EXT_ARF_FRAME = 5
#endif
EXT_ARF_FRAME = 5,
FRAME_CONTEXT_INDEXES
} FRAME_CONTEXT_INDEX;
#endif
typedef enum {
NORMAL = 0,
@ -101,13 +88,9 @@ typedef enum {
typedef enum {
FRAMEFLAGS_KEY = 1 << 0,
FRAMEFLAGS_GOLDEN = 1 << 1,
#if CONFIG_EXT_REFS
FRAMEFLAGS_BWDREF = 1 << 2,
// TODO(zoeliu): To determine whether a frame flag is needed for ALTREF2_FRAME
FRAMEFLAGS_ALTREF = 1 << 3,
#else // !CONFIG_EXT_REFS
FRAMEFLAGS_ALTREF = 1 << 2,
#endif // CONFIG_EXT_REFS
} FRAMETYPE_FLAGS;
typedef enum {
@ -115,26 +98,22 @@ typedef enum {
VARIANCE_AQ = 1,
COMPLEXITY_AQ = 2,
CYCLIC_REFRESH_AQ = 3,
#if !CONFIG_EXT_DELTA_Q
DELTA_AQ = 4,
#endif
AQ_MODE_COUNT // This should always be the last member of the enum
} AQ_MODE;
#if CONFIG_EXT_DELTA_Q
typedef enum {
NO_DELTA_Q = 0,
DELTA_Q_ONLY = 1,
DELTA_Q_LF = 2,
DELTAQ_MODE_COUNT // This should always be the last member of the enum
} DELTAQ_MODE;
#endif
typedef enum {
RESIZE_NONE = 0, // No frame resizing allowed.
RESIZE_FIXED = 1, // All frames are coded at the specified scale.
RESIZE_RANDOM = 2, // All frames are coded at a random scale.
RESIZE_MODES
} RESIZE_MODE;
#if CONFIG_FRAME_SUPERRES
typedef enum {
SUPERRES_NONE = 0, // No frame superres allowed
SUPERRES_FIXED = 1, // All frames are coded at the specified scale,
@ -145,13 +124,14 @@ typedef enum {
// q_index
SUPERRES_MODES
} SUPERRES_MODE;
#endif // CONFIG_FRAME_SUPERRES
typedef struct AV1EncoderConfig {
BITSTREAM_PROFILE profile;
aom_bit_depth_t bit_depth; // Codec bit-depth.
int width; // width of data passed to the compressor
int height; // height of data passed to the compressor
int forced_max_frame_width; // forced maximum width of frame (if != 0)
int forced_max_frame_height; // forced maximum height of frame (if != 0)
unsigned int input_bit_depth; // Input bit depth.
double init_framerate; // set to passed in framerate
int64_t target_bandwidth; // bandwidth to be used in bits per second
@ -159,6 +139,7 @@ typedef struct AV1EncoderConfig {
int noise_sensitivity; // pre processing blur: recommendation 0
int sharpness; // sharpening output: recommendation 0:
int speed;
int dev_sf;
// maximum allowed bitrate for any intra frame in % of bitrate target.
unsigned int rc_max_intra_bitrate_pct;
// maximum allowed bitrate for any inter frame in % of bitrate target.
@ -172,8 +153,11 @@ typedef struct AV1EncoderConfig {
// Key Framing Operations
int auto_key; // autodetect cut scenes and set the keyframes
int key_freq; // maximum distance to key frame.
int sframe_dist;
int sframe_mode;
int sframe_enabled;
int lag_in_frames; // how many frames lag before we start encoding
int fwd_kf_enabled;
// ----------------------------------------------------------------
// DATARATE CONTROL OPTIONS
@ -199,36 +183,33 @@ typedef struct AV1EncoderConfig {
int best_allowed_q;
int cq_level;
AQ_MODE aq_mode; // Adaptive Quantization mode
#if CONFIG_EXT_DELTA_Q
DELTAQ_MODE deltaq_mode;
#endif
#if CONFIG_AOM_QM
int enable_cdef;
int enable_restoration;
int disable_trellis_quant;
int using_qm;
int qm_y;
int qm_u;
int qm_v;
int qm_minlevel;
int qm_maxlevel;
#endif
#if CONFIG_DIST_8X8
int using_dist_8x8;
#endif
unsigned int num_tile_groups;
unsigned int mtu;
#if CONFIG_TEMPMV_SIGNALING
unsigned int disable_tempmv;
#endif
// Internal frame size scaling.
RESIZE_MODE resize_mode;
uint8_t resize_scale_denominator;
uint8_t resize_kf_scale_denominator;
#if CONFIG_FRAME_SUPERRES
// Frame Super-Resolution size scaling.
SUPERRES_MODE superres_mode;
uint8_t superres_scale_denominator;
uint8_t superres_kf_scale_denominator;
int superres_qthresh;
int superres_kf_qthresh;
#endif // CONFIG_FRAME_SUPERRES
// Enable feature to reduce the frame quantization every x frames.
int frame_periodic_boost;
@ -241,9 +222,7 @@ typedef struct AV1EncoderConfig {
// ----------------------------------------------------------------
int enable_auto_arf;
#if CONFIG_EXT_REFS
int enable_auto_brf; // (b)ackward (r)ef (f)rame
#endif // CONFIG_EXT_REFS
/* Bitfield defining the error resiliency features to enable.
* Can provide decodable frames after losses in previous
@ -251,12 +230,16 @@ typedef struct AV1EncoderConfig {
*/
unsigned int error_resilient_mode;
unsigned int s_frame_mode;
/* Bitfield defining the parallel decoding mode where the
* decoding in successive frames may be conducted in parallel
* just by decoding the frame headers.
*/
unsigned int frame_parallel_decoding_mode;
unsigned int limit;
int arnr_max_frames;
int arnr_strength;
@ -265,18 +248,10 @@ typedef struct AV1EncoderConfig {
int tile_columns;
int tile_rows;
#if CONFIG_MAX_TILE
int tile_width_count;
int tile_height_count;
int tile_widths[MAX_TILE_COLS];
int tile_heights[MAX_TILE_ROWS];
#endif
#if CONFIG_DEPENDENT_HORZTILES
int dependent_horz_tiles;
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
int loop_filter_across_tiles_enabled;
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
int max_threads;
@ -289,34 +264,135 @@ typedef struct AV1EncoderConfig {
aom_tune_metric tuning;
aom_tune_content content;
#if CONFIG_HIGHBITDEPTH
int use_highbitdepth;
#endif
aom_color_space_t color_space;
aom_transfer_function_t transfer_function;
aom_color_primaries_t color_primaries;
aom_transfer_characteristics_t transfer_characteristics;
aom_matrix_coefficients_t matrix_coefficients;
aom_chroma_sample_position_t chroma_sample_position;
int color_range;
int render_width;
int render_height;
aom_timing_info_type_t timing_info_type;
int timing_info_present;
aom_timing_info_t timing_info;
int decoder_model_info_present_flag;
int display_model_info_present_flag;
int buffer_removal_delay_present;
aom_dec_model_info_t buffer_model;
aom_dec_model_op_parameters_t op_params[MAX_NUM_OPERATING_POINTS + 1];
aom_op_timing_info_t op_frame_timing[MAX_NUM_OPERATING_POINTS + 1];
int film_grain_test_vector;
const char *film_grain_table_filename;
#if CONFIG_EXT_PARTITION
uint8_t cdf_update_mode;
aom_superblock_size_t superblock_size;
#endif // CONFIG_EXT_PARTITION
#if CONFIG_ANS && ANS_MAX_SYMBOLS
int ans_window_size_log2;
#endif // CONFIG_ANS && ANS_MAX_SYMBOLS
#if CONFIG_EXT_TILE
unsigned int large_scale_tile;
unsigned int single_tile_decoding;
#endif // CONFIG_EXT_TILE
int monochrome;
unsigned int full_still_picture_hdr;
int enable_dual_filter;
unsigned int motion_vector_unit_test;
const cfg_options_t *cfg;
int enable_order_hint;
int enable_jnt_comp;
int enable_ref_frame_mvs;
unsigned int allow_ref_frame_mvs;
int enable_warped_motion;
int allow_warped_motion;
int enable_superres;
unsigned int save_as_annexb;
} AV1EncoderConfig;
static INLINE int is_lossless_requested(const AV1EncoderConfig *cfg) {
return cfg->best_allowed_q == 0 && cfg->worst_allowed_q == 0;
}
typedef struct FRAME_COUNTS {
// Note: This structure should only contain 'unsigned int' fields, or
// aggregates built solely from 'unsigned int' fields/elements
#if CONFIG_ENTROPY_STATS
unsigned int kf_y_mode[KF_MODE_CONTEXTS][KF_MODE_CONTEXTS][INTRA_MODES];
unsigned int angle_delta[DIRECTIONAL_MODES][2 * MAX_ANGLE_DELTA + 1];
unsigned int y_mode[BLOCK_SIZE_GROUPS][INTRA_MODES];
unsigned int uv_mode[CFL_ALLOWED_TYPES][INTRA_MODES][UV_INTRA_MODES];
unsigned int cfl_sign[CFL_JOINT_SIGNS];
unsigned int cfl_alpha[CFL_ALPHA_CONTEXTS][CFL_ALPHABET_SIZE];
unsigned int palette_y_mode[PALATTE_BSIZE_CTXS][PALETTE_Y_MODE_CONTEXTS][2];
unsigned int palette_uv_mode[PALETTE_UV_MODE_CONTEXTS][2];
unsigned int palette_y_size[PALATTE_BSIZE_CTXS][PALETTE_SIZES];
unsigned int palette_uv_size[PALATTE_BSIZE_CTXS][PALETTE_SIZES];
unsigned int palette_y_color_index[PALETTE_SIZES]
[PALETTE_COLOR_INDEX_CONTEXTS]
[PALETTE_COLORS];
unsigned int palette_uv_color_index[PALETTE_SIZES]
[PALETTE_COLOR_INDEX_CONTEXTS]
[PALETTE_COLORS];
unsigned int partition[PARTITION_CONTEXTS][EXT_PARTITION_TYPES];
unsigned int txb_skip[TOKEN_CDF_Q_CTXS][TX_SIZES][TXB_SKIP_CONTEXTS][2];
unsigned int eob_extra[TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES]
[EOB_COEF_CONTEXTS][2];
unsigned int dc_sign[PLANE_TYPES][DC_SIGN_CONTEXTS][2];
unsigned int coeff_lps[TX_SIZES][PLANE_TYPES][BR_CDF_SIZE - 1][LEVEL_CONTEXTS]
[2];
unsigned int eob_flag[TX_SIZES][PLANE_TYPES][EOB_COEF_CONTEXTS][2];
unsigned int eob_multi16[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][5];
unsigned int eob_multi32[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][6];
unsigned int eob_multi64[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][7];
unsigned int eob_multi128[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8];
unsigned int eob_multi256[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][9];
unsigned int eob_multi512[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][10];
unsigned int eob_multi1024[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][11];
unsigned int coeff_lps_multi[TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES]
[LEVEL_CONTEXTS][BR_CDF_SIZE];
unsigned int coeff_base_multi[TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES]
[SIG_COEF_CONTEXTS][NUM_BASE_LEVELS + 2];
unsigned int coeff_base_eob_multi[TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES]
[SIG_COEF_CONTEXTS_EOB][NUM_BASE_LEVELS + 1];
unsigned int newmv_mode[NEWMV_MODE_CONTEXTS][2];
unsigned int zeromv_mode[GLOBALMV_MODE_CONTEXTS][2];
unsigned int refmv_mode[REFMV_MODE_CONTEXTS][2];
unsigned int drl_mode[DRL_MODE_CONTEXTS][2];
unsigned int inter_compound_mode[INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES];
unsigned int wedge_idx[BLOCK_SIZES_ALL][16];
unsigned int interintra[BLOCK_SIZE_GROUPS][2];
unsigned int interintra_mode[BLOCK_SIZE_GROUPS][INTERINTRA_MODES];
unsigned int wedge_interintra[BLOCK_SIZES_ALL][2];
unsigned int compound_type[BLOCK_SIZES_ALL][COMPOUND_TYPES - 1];
unsigned int motion_mode[BLOCK_SIZES_ALL][MOTION_MODES];
unsigned int obmc[BLOCK_SIZES_ALL][2];
unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
unsigned int comp_ref_type[COMP_REF_TYPE_CONTEXTS][2];
unsigned int uni_comp_ref[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1][2];
unsigned int single_ref[REF_CONTEXTS][SINGLE_REFS - 1][2];
unsigned int comp_ref[REF_CONTEXTS][FWD_REFS - 1][2];
unsigned int comp_bwdref[REF_CONTEXTS][BWD_REFS - 1][2];
unsigned int intrabc[2];
unsigned int txfm_partition[TXFM_PARTITION_CONTEXTS][2];
unsigned int intra_tx_size[MAX_TX_CATS][TX_SIZE_CONTEXTS][MAX_TX_DEPTH + 1];
unsigned int skip_mode[SKIP_MODE_CONTEXTS][2];
unsigned int skip[SKIP_CONTEXTS][2];
unsigned int compound_index[COMP_INDEX_CONTEXTS][2];
unsigned int comp_group_idx[COMP_GROUP_IDX_CONTEXTS][2];
unsigned int delta_q[DELTA_Q_PROBS][2];
unsigned int delta_lf_multi[FRAME_LF_COUNT][DELTA_LF_PROBS][2];
unsigned int delta_lf[DELTA_LF_PROBS][2];
unsigned int inter_ext_tx[EXT_TX_SETS_INTER][EXT_TX_SIZES][TX_TYPES];
unsigned int intra_ext_tx[EXT_TX_SETS_INTRA][EXT_TX_SIZES][INTRA_MODES]
[TX_TYPES];
unsigned int filter_intra_mode[FILTER_INTRA_MODES];
unsigned int filter_intra[BLOCK_SIZES_ALL][2];
unsigned int switchable_restore[RESTORE_SWITCHABLE_TYPES];
unsigned int wiener_restore[2];
unsigned int sgrproj_restore[2];
#endif // CONFIG_ENTROPY_STATS
unsigned int switchable_interp[SWITCHABLE_FILTER_CONTEXTS]
[SWITCHABLE_FILTERS];
} FRAME_COUNTS;
// TODO(jingning) All spatially adaptive variables should go to TileDataEnc.
typedef struct TileDataEnc {
TileInfo tile_info;
@ -324,42 +400,31 @@ typedef struct TileDataEnc {
int mode_map[BLOCK_SIZES_ALL][MAX_MODES];
int m_search_count;
int ex_search_count;
#if CONFIG_PVQ
PVQ_QUEUE pvq_q;
#endif
#if CONFIG_CFL
CFL_CTX cfl;
#endif
DECLARE_ALIGNED(16, FRAME_CONTEXT, tctx);
uint8_t allow_update_cdf;
} TileDataEnc;
typedef struct RD_COUNTS {
int64_t comp_pred_diff[REFERENCE_MODES];
#if CONFIG_GLOBAL_MOTION
// Stores number of 4x4 blocks using global motion per reference frame.
int global_motion_used[TOTAL_REFS_PER_FRAME];
#endif // CONFIG_GLOBAL_MOTION
int single_ref_used_flag;
int global_motion_used[REF_FRAMES];
int compound_ref_used_flag;
int skip_mode_used_flag;
} RD_COUNTS;
typedef struct ThreadData {
MACROBLOCK mb;
RD_COUNTS rd_counts;
FRAME_COUNTS *counts;
#if !CONFIG_CB4X4
PICK_MODE_CONTEXT *leaf_tree;
#endif
PC_TREE *pc_tree;
PC_TREE *pc_root[MAX_MIB_SIZE_LOG2 - MIN_MIB_SIZE_LOG2 + 1];
#if CONFIG_MOTION_VAR
int32_t *wsrc_buf;
int32_t *mask_buf;
uint8_t *above_pred_buf;
uint8_t *left_pred_buf;
#endif
PALETTE_BUFFER *palette_buffer;
int intrabc_used_this_tile;
} ThreadData;
struct EncWorkerData;
@ -370,14 +435,21 @@ typedef struct ActiveMap {
unsigned char *map;
} ActiveMap;
#define NUM_STAT_TYPES 4 // types of stats: Y, U, V and ALL
#if CONFIG_INTERNAL_STATS
// types of stats
typedef enum {
STAT_Y,
STAT_U,
STAT_V,
STAT_ALL,
NUM_STAT_TYPES // This should always be the last member of the enum
} StatType;
typedef struct IMAGE_STAT {
double stat[NUM_STAT_TYPES];
double worst;
} ImageStat;
#undef NUM_STAT_TYPES
#endif // CONFIG_INTERNAL_STATS
typedef struct {
int ref_count;
@ -392,16 +464,18 @@ typedef struct TileBufferEnc {
typedef struct AV1_COMP {
QUANTS quants;
ThreadData td;
FRAME_COUNTS counts;
MB_MODE_INFO_EXT *mbmi_ext_base;
#if CONFIG_LV_MAP
CB_COEFF_BUFFER *coeff_buffer_base;
#endif
Dequants dequants;
AV1_COMMON common;
AV1EncoderConfig oxcf;
struct lookahead_ctx *lookahead;
struct lookahead_entry *alt_ref_source;
int optimize_speed_feature;
int optimize_seg_arr[MAX_SEGMENTS];
YV12_BUFFER_CONFIG *source;
YV12_BUFFER_CONFIG *last_source; // NULL for first frame and alt_ref frames
YV12_BUFFER_CONFIG *unscaled_source;
@ -411,58 +485,42 @@ typedef struct AV1_COMP {
// For a still frame, this flag is set to 1 to skip partition search.
int partition_search_skippable_frame;
#if CONFIG_AMVR
double csm_rate_array[32];
double m_rate_array[32];
int rate_size;
int rate_index;
hash_table *previsou_hash_table;
int previsous_index;
hash_table *previous_hash_table;
int previous_index;
int cur_poc; // DebugInfo
#endif
int scaled_ref_idx[TOTAL_REFS_PER_FRAME];
#if CONFIG_EXT_REFS
int lst_fb_idxes[LAST_REF_FRAMES];
#else
int lst_fb_idx;
#endif // CONFIG_EXT_REFS
int gld_fb_idx;
#if CONFIG_EXT_REFS
int bwd_fb_idx; // BWDREF_FRAME
int alt2_fb_idx; // ALTREF2_FRAME
#endif // CONFIG_EXT_REFS
int alt_fb_idx;
#if CONFIG_EXT_REFS
int ext_fb_idx; // extra ref frame buffer index
int scaled_ref_idx[REF_FRAMES];
int ref_fb_idx[REF_FRAMES];
int refresh_fb_idx; // ref frame buffer index to refresh
#endif // CONFIG_EXT_REFS
int last_show_frame_buf_idx; // last show frame buffer index
int refresh_last_frame;
int refresh_golden_frame;
#if CONFIG_EXT_REFS
int refresh_bwd_ref_frame;
int refresh_alt2_ref_frame;
#endif // CONFIG_EXT_REFS
int refresh_alt_ref_frame;
int ext_refresh_frame_flags_pending;
int ext_refresh_last_frame;
int ext_refresh_golden_frame;
int ext_refresh_bwd_ref_frame;
int ext_refresh_alt2_ref_frame;
int ext_refresh_alt_ref_frame;
int ext_refresh_frame_context_pending;
int ext_refresh_frame_context;
int ext_use_ref_frame_mvs;
int ext_use_error_resilient;
int ext_use_s_frame;
int ext_use_primary_ref_none;
YV12_BUFFER_CONFIG last_frame_uf;
#if CONFIG_LOOP_RESTORATION
YV12_BUFFER_CONFIG last_frame_db;
YV12_BUFFER_CONFIG trial_frame_rst;
uint8_t *extra_rstbuf; // Extra buffers used in restoration search
RestorationInfo rst_search[MAX_MB_PLANE]; // Used for encoder side search
#endif // CONFIG_LOOP_RESTORATION
// Ambient reconstruction err target for force key frames
int64_t ambient_err;
@ -471,22 +529,17 @@ typedef struct AV1_COMP {
CODING_CONTEXT coding_context;
#if CONFIG_GLOBAL_MOTION
int gmtype_cost[TRANS_TYPES];
int gmparams_cost[TOTAL_REFS_PER_FRAME];
#endif // CONFIG_GLOBAL_MOTION
int gmparams_cost[REF_FRAMES];
int nmv_costs[NMV_CONTEXTS][2][MV_VALS];
int nmv_costs_hp[NMV_CONTEXTS][2][MV_VALS];
int nmv_costs[2][MV_VALS];
int nmv_costs_hp[2][MV_VALS];
int64_t last_time_stamp_seen;
int64_t last_end_time_stamp_seen;
int64_t first_time_stamp_ever;
RATE_CONTROL rc;
#if CONFIG_XIPHRC
od_rc_state od_rc;
#endif
double framerate;
// NOTE(zoeliu): Any inter frame allows maximum of REF_FRAMES inter
@ -500,6 +553,8 @@ typedef struct AV1_COMP {
int mbgraph_n_frames; // number of frames filled in the above
int static_mb_pct; // % forced skip mbs by segmentation
int ref_frame_flags;
int ext_ref_frame_flags;
RATE_FACTOR_LEVEL frame_rf_level[FRAME_BUFFERS];
SPEED_FEATURES sf;
@ -507,6 +562,7 @@ typedef struct AV1_COMP {
int mv_step_param;
int allow_comp_inter_inter;
int all_one_sided_refs;
uint8_t *segmentation_map;
@ -514,7 +570,6 @@ typedef struct AV1_COMP {
ActiveMap active_map;
fractional_mv_step_fp *find_fractional_mv_step;
av1_full_search_fn_t full_search_sad; // It is currently unused.
av1_diamond_search_fn_t diamond_search_sad;
aom_variance_fn_ptr_t fn_ptr[BLOCK_SIZES_ALL];
uint64_t time_receive_data;
@ -581,8 +636,6 @@ typedef struct AV1_COMP {
search_site_config ss_cfg;
int multi_arf_allowed;
int multi_arf_enabled;
int multi_arf_last_grp_enabled;
TileDataEnc *tile_data;
int allocated_tiles; // Keep track of memory allocated for tiles.
@ -597,6 +650,11 @@ typedef struct AV1_COMP {
int resize_buffer_underflow;
int resize_count;
// Sequence parameters have been transmitted already and locked
// or not. Once locked av1_change_config cannot change the seq
// parameters.
int seq_params_locked;
// VARIANCE_AQ segment map refresh
int vaq_refresh;
@ -604,11 +662,6 @@ typedef struct AV1_COMP {
int num_workers;
AVxWorker *workers;
struct EncWorkerData *tile_thr_data;
AV1LfSync lf_row_sync;
#if CONFIG_ANS
struct BufAnsCoder buf_ans;
#endif
#if CONFIG_EXT_REFS
int refresh_frame_mask;
int existing_fb_idx_to_show;
int is_arf_filter_off[MAX_EXT_ARFS + 1];
@ -616,22 +669,24 @@ typedef struct AV1_COMP {
int arf_map[MAX_EXT_ARFS + 1];
int arf_pos_in_gf[MAX_EXT_ARFS + 1];
int arf_pos_for_ovrly[MAX_EXT_ARFS + 1];
#endif // CONFIG_EXT_REFS
#if CONFIG_GLOBAL_MOTION
int global_motion_search_done;
#endif
#if CONFIG_LV_MAP
tran_low_t *tcoeff_buf[MAX_MB_PLANE];
#endif
#if CONFIG_EXT_REFS
int extra_arf_allowed;
int bwd_ref_allowed;
#endif // CONFIG_EXT_REFS
// A flag to indicate if intrabc is ever used in current frame.
int intrabc_used;
int dv_cost[2][MV_VALS];
// TODO(huisu@google.com): we can update dv_joint_cost per SB.
int dv_joint_cost[MV_JOINTS];
int has_lossless_segment;
#if CONFIG_BGSPRITE
int bgsprite_allowed;
#endif // CONFIG_BGSPRITE
// For frame refs short signaling:
// A mapping of each reference frame from its encoder side value to the
// decoder side value obtained following the short signaling procedure.
int ref_conv[REF_FRAMES];
AV1LfSync lf_row_sync;
AV1LrSync lr_row_sync;
AV1LrStruct lr_ctxt;
} AV1_COMP;
void av1_initialize_enc(void);
@ -650,12 +705,17 @@ int av1_receive_raw_frame(AV1_COMP *cpi, aom_enc_frame_flags_t frame_flags,
int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
size_t *size, uint8_t *dest, int64_t *time_stamp,
int64_t *time_end, int flush);
int64_t *time_end, int flush,
const aom_rational_t *timebase);
int av1_get_preview_raw_frame(AV1_COMP *cpi, YV12_BUFFER_CONFIG *dest);
int av1_get_last_show_frame(AV1_COMP *cpi, YV12_BUFFER_CONFIG *frame);
aom_codec_err_t av1_copy_new_frame_enc(AV1_COMMON *cm,
YV12_BUFFER_CONFIG *new_frame,
YV12_BUFFER_CONFIG *sd);
int av1_use_as_reference(AV1_COMP *cpi, int ref_frame_flags);
void av1_update_reference(AV1_COMP *cpi, int ref_frame_flags);
@ -675,6 +735,11 @@ int av1_set_internal_size(AV1_COMP *cpi, AOM_SCALING horiz_mode,
int av1_get_quantizer(struct AV1_COMP *cpi);
int av1_convert_sect5obus_to_annexb(uint8_t *buffer, size_t *input_size);
int64_t timebase_units_to_ticks(const aom_rational_t *timebase, int64_t n);
int64_t ticks_to_timebase_units(const aom_rational_t *timebase, int64_t n);
static INLINE int frame_is_kf_gf_arf(const AV1_COMP *cpi) {
return frame_is_intra_only(&cpi->common) || cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref);
@ -682,22 +747,7 @@ static INLINE int frame_is_kf_gf_arf(const AV1_COMP *cpi) {
static INLINE int get_ref_frame_map_idx(const AV1_COMP *cpi,
MV_REFERENCE_FRAME ref_frame) {
#if CONFIG_EXT_REFS
if (ref_frame >= LAST_FRAME && ref_frame <= LAST3_FRAME)
return cpi->lst_fb_idxes[ref_frame - 1];
#else
if (ref_frame == LAST_FRAME) return cpi->lst_fb_idx;
#endif // CONFIG_EXT_REFS
else if (ref_frame == GOLDEN_FRAME)
return cpi->gld_fb_idx;
#if CONFIG_EXT_REFS
else if (ref_frame == BWDREF_FRAME)
return cpi->bwd_fb_idx;
else if (ref_frame == ALTREF2_FRAME)
return cpi->alt2_fb_idx;
#endif // CONFIG_EXT_REFS
else
return cpi->alt_fb_idx;
return (ref_frame >= 1) ? cpi->ref_fb_idx[ref_frame - 1] : INVALID_IDX;
}
static INLINE int get_ref_frame_buf_idx(const AV1_COMP *cpi,
@ -707,16 +757,19 @@ static INLINE int get_ref_frame_buf_idx(const AV1_COMP *cpi,
return (map_idx != INVALID_IDX) ? cm->ref_frame_map[map_idx] : INVALID_IDX;
}
#if CONFIG_HASH_ME
static INLINE hash_table *get_ref_frame_hash_map(const AV1_COMP *cpi,
MV_REFERENCE_FRAME ref_frame) {
// TODO(huisu@google.com, youzhou@microsoft.com): enable hash-me for HBD.
static INLINE int av1_use_hash_me(const AV1_COMMON *const cm) {
return cm->allow_screen_content_tools;
}
static INLINE hash_table *av1_get_ref_frame_hash_map(
const AV1_COMP *cpi, MV_REFERENCE_FRAME ref_frame) {
const AV1_COMMON *const cm = &cpi->common;
const int buf_idx = get_ref_frame_buf_idx(cpi, ref_frame);
return buf_idx != INVALID_IDX
? &cm->buffer_pool->frame_bufs[buf_idx].hash_table
: NULL;
}
#endif
static INLINE YV12_BUFFER_CONFIG *get_ref_frame_buffer(
const AV1_COMP *cpi, MV_REFERENCE_FRAME ref_frame) {
@ -726,7 +779,6 @@ static INLINE YV12_BUFFER_CONFIG *get_ref_frame_buffer(
: NULL;
}
#if CONFIG_EXT_REFS || CONFIG_TEMPMV_SIGNALING
static INLINE int enc_is_ref_frame_buf(AV1_COMP *cpi, RefCntBuffer *frame_buf) {
MV_REFERENCE_FRAME ref_frame;
AV1_COMMON *const cm = &cpi->common;
@ -737,48 +789,42 @@ static INLINE int enc_is_ref_frame_buf(AV1_COMP *cpi, RefCntBuffer *frame_buf) {
}
return (ref_frame <= ALTREF_FRAME);
}
#endif // CONFIG_EXT_REFS
static INLINE unsigned int get_token_alloc(int mb_rows, int mb_cols) {
// We assume 3 planes all at full resolution. We assume up to 1 token per
// pixel, and then allow a head room of 1 EOSB token per 4x4 block per plane,
// plus EOSB_TOKEN per plane.
return mb_rows * mb_cols * (16 * 16 + 17) * 3;
// Token buffer is only used for palette tokens.
static INLINE unsigned int get_token_alloc(int mb_rows, int mb_cols,
int sb_size_log2,
const int num_planes) {
// Calculate the maximum number of max superblocks in the image.
const int shift = sb_size_log2 - 4;
const int sb_size = 1 << sb_size_log2;
const int sb_size_square = sb_size * sb_size;
const int sb_rows = ALIGN_POWER_OF_TWO(mb_rows, shift) >> shift;
const int sb_cols = ALIGN_POWER_OF_TWO(mb_cols, shift) >> shift;
// One palette token for each pixel. There can be palettes on two planes.
const int sb_palette_toks = AOMMIN(2, num_planes) * sb_size_square;
return sb_rows * sb_cols * sb_palette_toks;
}
// Get the allocated token size for a tile. It does the same calculation as in
// the frame token allocation.
static INLINE unsigned int allocated_tokens(TileInfo tile) {
#if CONFIG_CB4X4
static INLINE unsigned int allocated_tokens(TileInfo tile, int sb_size_log2,
int num_planes) {
int tile_mb_rows = (tile.mi_row_end - tile.mi_row_start + 2) >> 2;
int tile_mb_cols = (tile.mi_col_end - tile.mi_col_start + 2) >> 2;
#else
int tile_mb_rows = (tile.mi_row_end - tile.mi_row_start + 1) >> 1;
int tile_mb_cols = (tile.mi_col_end - tile.mi_col_start + 1) >> 1;
#endif
return get_token_alloc(tile_mb_rows, tile_mb_cols);
return get_token_alloc(tile_mb_rows, tile_mb_cols, sb_size_log2, num_planes);
}
#if CONFIG_TEMPMV_SIGNALING
void av1_set_temporal_mv_prediction(AV1_COMP *cpi, int allow_tempmv_prediction);
#endif
void av1_apply_encoding_flags(AV1_COMP *cpi, aom_enc_frame_flags_t flags);
#define ALT_MIN_LAG 3
static INLINE int is_altref_enabled(const AV1_COMP *const cpi) {
return cpi->oxcf.lag_in_frames > 0 && cpi->oxcf.enable_auto_arf;
return cpi->oxcf.lag_in_frames >= ALT_MIN_LAG && cpi->oxcf.enable_auto_arf;
}
// TODO(zoeliu): To set up cpi->oxcf.enable_auto_brf
#if 0 && CONFIG_EXT_REFS
static INLINE int is_bwdref_enabled(const AV1_COMP *const cpi) {
// NOTE(zoeliu): The enabling of bi-predictive frames depends on the use of
// alt_ref, and now will be off when the alt_ref interval is
// not sufficiently large.
return is_altref_enabled(cpi) && cpi->oxcf.enable_auto_brf;
}
#endif // CONFIG_EXT_REFS
static INLINE void set_ref_ptrs(const AV1_COMMON *cm, MACROBLOCKD *xd,
MV_REFERENCE_FRAME ref0,
@ -813,22 +859,14 @@ static INLINE void uref_cnt_fb(EncRefCntBuffer *ubufs, int *uidx,
ubufs[new_uidx].ref_count++;
}
// Returns 1 if a frame is unscaled and 0 otherwise.
static INLINE int av1_resize_unscaled(const AV1_COMMON *cm) {
#if CONFIG_FRAME_SUPERRES
return cm->superres_upscaled_width == cm->render_width &&
cm->superres_upscaled_height == cm->render_height;
#else
return cm->width == cm->render_width && cm->height == cm->render_height;
#endif // CONFIG_FRAME_SUPERRES
// Returns 1 if a frame is scaled and 0 otherwise.
static INLINE int av1_resize_scaled(const AV1_COMMON *cm) {
return !(cm->superres_upscaled_width == cm->render_width &&
cm->superres_upscaled_height == cm->render_height);
}
static INLINE int av1_frame_unscaled(const AV1_COMMON *cm) {
#if CONFIG_FRAME_SUPERRES
return av1_superres_unscaled(cm) && av1_resize_unscaled(cm);
#else
return av1_resize_unscaled(cm);
#endif // CONFIG_FRAME_SUPERRES
static INLINE int av1_frame_scaled(const AV1_COMMON *cm) {
return !av1_superres_scaled(cm) && av1_resize_scaled(cm);
}
#ifdef __cplusplus

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,8 @@
#ifndef ENCODETXB_H_
#define ENCODETXB_H_
#include "./aom_config.h"
#include "config/aom_config.h"
#include "av1/common/blockd.h"
#include "av1/common/onyxc_int.h"
#include "av1/common/txb_common.h"
@ -25,6 +26,7 @@ extern "C" {
typedef struct TxbInfo {
tran_low_t *qcoeff;
uint8_t *levels; // absolute values and clamped to 255.
tran_low_t *dqcoeff;
const tran_low_t *tcoeff;
const int16_t *dequant;
@ -33,7 +35,7 @@ typedef struct TxbInfo {
TX_SIZE txs_ctx;
TX_TYPE tx_type;
int bwl;
int stride;
int width;
int height;
int eob;
int seg_eob;
@ -41,51 +43,27 @@ typedef struct TxbInfo {
TXB_CTX *txb_ctx;
int64_t rdmult;
const LV_MAP_CTX_TABLE *coeff_ctx_table;
const qm_val_t *iqmatrix;
int tx_type_cost;
} TxbInfo;
typedef struct TxbCache {
int nz_count_arr[MAX_TX_SQUARE];
int nz_ctx_arr[MAX_TX_SQUARE];
int base_count_arr[NUM_BASE_LEVELS][MAX_TX_SQUARE];
int base_mag_arr[MAX_TX_SQUARE]
[2]; // [0]: max magnitude [1]: num of max magnitude
int base_ctx_arr[NUM_BASE_LEVELS][MAX_TX_SQUARE];
int br_count_arr[MAX_TX_SQUARE];
int br_mag_arr[MAX_TX_SQUARE]
[2]; // [0]: max magnitude [1]: num of max magnitude
int br_ctx_arr[MAX_TX_SQUARE];
} TxbCache;
typedef struct TxbProbs {
const aom_prob *dc_sign_prob;
const aom_prob *nz_map;
aom_prob (*coeff_base)[COEFF_BASE_CONTEXTS];
const aom_prob *coeff_lps;
const aom_prob *eob_flag;
const aom_prob *txb_skip;
#if BR_NODE
const aom_prob *coeff_br;
#endif
} TxbProbs;
void av1_alloc_txb_buf(AV1_COMP *cpi);
void av1_free_txb_buf(AV1_COMP *cpi);
int av1_cost_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCK *x, int plane,
int blk_row, int blk_col, int block, TX_SIZE tx_size,
TXB_CTX *txb_ctx);
int av1_cost_coeffs_txb(const AV1_COMMON *const cm, const MACROBLOCK *x,
const int plane, const int blk_row, const int blk_col,
const int block, const TX_SIZE tx_size,
const TXB_CTX *const txb_ctx);
void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
aom_writer *w, int blk_row, int blk_col, int block,
int plane, TX_SIZE tx_size, const tran_low_t *tcoeff,
aom_writer *w, int blk_row, int blk_col, int plane,
TX_SIZE tx_size, const tran_low_t *tcoeff,
uint16_t eob, TXB_CTX *txb_ctx);
void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x,
aom_writer *w, int plane);
void av1_write_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x, int mi_row,
int mi_col, aom_writer *w, BLOCK_SIZE bsize);
int av1_get_txb_entropy_context(const tran_low_t *qcoeff,
const SCAN_ORDER *scan_order, int eob);
void av1_update_txb_context(const AV1_COMP *cpi, ThreadData *td,
RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
const int mi_row, const int mi_col);
void av1_write_txb_probs(AV1_COMP *cpi, aom_writer *w);
int mi_row, int mi_col, uint8_t allow_update_cdf);
void av1_update_txb_context_b(int plane, int block, int blk_row, int blk_col,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
@ -98,16 +76,10 @@ void av1_update_and_record_txb_context(int plane, int block, int blk_row,
void av1_set_coeff_buffer(const AV1_COMP *const cpi, MACROBLOCK *const x,
int mi_row, int mi_col);
#if CONFIG_TXK_SEL
int64_t av1_search_txk_type(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
int block, int blk_row, int blk_col,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
const ENTROPY_CONTEXT *a, const ENTROPY_CONTEXT *l,
int use_fast_coef_costing, RD_STATS *rd_stats);
#endif
int av1_optimize_txb(const AV1_COMMON *cm, MACROBLOCK *x, int plane,
int blk_row, int blk_col, int block, TX_SIZE tx_size,
TXB_CTX *txb_ctx, int fast_mode);
void hbt_destroy();
int av1_optimize_txb_new(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
int block, TX_SIZE tx_size, TX_TYPE tx_type,
const TXB_CTX *txb_ctx, int *rate_cost, int sharpness);
#ifdef __cplusplus
}
#endif

View file

@ -18,15 +18,13 @@ static void accumulate_rd_opt(ThreadData *td, ThreadData *td_t) {
for (int i = 0; i < REFERENCE_MODES; i++)
td->rd_counts.comp_pred_diff[i] += td_t->rd_counts.comp_pred_diff[i];
#if CONFIG_GLOBAL_MOTION
for (int i = 0; i < TOTAL_REFS_PER_FRAME; i++)
for (int i = 0; i < REF_FRAMES; i++)
td->rd_counts.global_motion_used[i] +=
td_t->rd_counts.global_motion_used[i];
#endif // CONFIG_GLOBAL_MOTION
td->rd_counts.compound_ref_used_flag |=
td_t->rd_counts.compound_ref_used_flag;
td->rd_counts.single_ref_used_flag |= td_t->rd_counts.single_ref_used_flag;
td->rd_counts.skip_mode_used_flag |= td_t->rd_counts.skip_mode_used_flag;
}
static int enc_worker_hook(EncWorkerData *const thread_data, void *unused) {
@ -53,7 +51,7 @@ void av1_encode_tiles_mt(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
const int tile_cols = cm->tile_cols;
const AVxWorkerInterface *const winterface = aom_get_worker_interface();
const int num_workers = AOMMIN(cpi->oxcf.max_threads, tile_cols);
int num_workers = AOMMIN(cpi->oxcf.max_threads, tile_cols);
int i;
av1_init_tile_data(cpi);
@ -81,29 +79,19 @@ void av1_encode_tiles_mt(AV1_COMP *cpi) {
aom_memalign(32, sizeof(*thread_data->td)));
av1_zero(*thread_data->td);
// Set up pc_tree.
#if !CONFIG_CB4X4
thread_data->td->leaf_tree = NULL;
#endif
// Set up pc_tree.
thread_data->td->pc_tree = NULL;
av1_setup_pc_tree(cm, thread_data->td);
#if CONFIG_MOTION_VAR
#if CONFIG_HIGHBITDEPTH
int buf_scaler = 2;
#else
int buf_scaler = 1;
#endif
CHECK_MEM_ERROR(cm, thread_data->td->above_pred_buf,
(uint8_t *)aom_memalign(
16,
buf_scaler * MAX_MB_PLANE * MAX_SB_SQUARE *
sizeof(*thread_data->td->above_pred_buf)));
16, MAX_MB_PLANE * MAX_SB_SQUARE *
sizeof(*thread_data->td->above_pred_buf)));
CHECK_MEM_ERROR(cm, thread_data->td->left_pred_buf,
(uint8_t *)aom_memalign(
16,
buf_scaler * MAX_MB_PLANE * MAX_SB_SQUARE *
sizeof(*thread_data->td->left_pred_buf)));
16, MAX_MB_PLANE * MAX_SB_SQUARE *
sizeof(*thread_data->td->left_pred_buf)));
CHECK_MEM_ERROR(
cm, thread_data->td->wsrc_buf,
(int32_t *)aom_memalign(
@ -112,7 +100,6 @@ void av1_encode_tiles_mt(AV1_COMP *cpi) {
cm, thread_data->td->mask_buf,
(int32_t *)aom_memalign(
16, MAX_SB_SQUARE * sizeof(*thread_data->td->mask_buf)));
#endif
// Allocate frame counters in thread data.
CHECK_MEM_ERROR(cm, thread_data->td->counts,
aom_calloc(1, sizeof(*thread_data->td->counts)));
@ -133,6 +120,8 @@ void av1_encode_tiles_mt(AV1_COMP *cpi) {
winterface->sync(worker);
}
} else {
num_workers = AOMMIN(num_workers, cpi->num_workers);
}
for (i = 0; i < num_workers; i++) {
@ -148,16 +137,13 @@ void av1_encode_tiles_mt(AV1_COMP *cpi) {
if (thread_data->td != &cpi->td) {
thread_data->td->mb = cpi->td.mb;
thread_data->td->rd_counts = cpi->td.rd_counts;
#if CONFIG_MOTION_VAR
thread_data->td->mb.above_pred_buf = thread_data->td->above_pred_buf;
thread_data->td->mb.left_pred_buf = thread_data->td->left_pred_buf;
thread_data->td->mb.wsrc_buf = thread_data->td->wsrc_buf;
thread_data->td->mb.mask_buf = thread_data->td->mask_buf;
#endif
}
if (thread_data->td->counts != &cpi->common.counts) {
memcpy(thread_data->td->counts, &cpi->common.counts,
sizeof(cpi->common.counts));
if (thread_data->td->counts != &cpi->counts) {
memcpy(thread_data->td->counts, &cpi->counts, sizeof(cpi->counts));
}
if (i < num_workers - 1)
@ -187,14 +173,24 @@ void av1_encode_tiles_mt(AV1_COMP *cpi) {
for (i = 0; i < num_workers; i++) {
AVxWorker *const worker = &cpi->workers[i];
EncWorkerData *const thread_data = (EncWorkerData *)worker->data1;
cpi->intrabc_used |= thread_data->td->intrabc_used_this_tile;
// Accumulate counters.
if (i < cpi->num_workers - 1) {
av1_accumulate_frame_counts(&cm->counts, thread_data->td->counts);
av1_accumulate_frame_counts(&cpi->counts, thread_data->td->counts);
accumulate_rd_opt(&cpi->td, thread_data->td);
#if CONFIG_VAR_TX
cpi->td.mb.txb_split_count += thread_data->td->mb.txb_split_count;
#endif
}
}
}
// Accumulate frame counts. FRAME_COUNTS consist solely of 'unsigned int'
// members, so we treat it as an array, and sum over the whole length.
void av1_accumulate_frame_counts(FRAME_COUNTS *acc_counts,
const FRAME_COUNTS *counts) {
unsigned int *const acc = (unsigned int *)acc_counts;
const unsigned int *const cnt = (const unsigned int *)counts;
const unsigned int n_counts = sizeof(FRAME_COUNTS) / sizeof(unsigned int);
for (unsigned int i = 0; i < n_counts; i++) acc[i] += cnt[i];
}

View file

@ -27,6 +27,9 @@ typedef struct EncWorkerData {
void av1_encode_tiles_mt(struct AV1_COMP *cpi);
void av1_accumulate_frame_counts(struct FRAME_COUNTS *acc_counts,
const struct FRAME_COUNTS *counts);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -57,7 +57,6 @@ static void copy_and_extend_plane(const uint8_t *src, int src_pitch,
}
}
#if CONFIG_HIGHBITDEPTH
static void highbd_copy_and_extend_plane(const uint8_t *src8, int src_pitch,
uint8_t *dst8, int dst_pitch, int w,
int h, int extend_top, int extend_left,
@ -100,7 +99,6 @@ static void highbd_copy_and_extend_plane(const uint8_t *src8, int src_pitch,
dst_ptr2 += dst_pitch;
}
}
#endif // CONFIG_HIGHBITDEPTH
void av1_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
YV12_BUFFER_CONFIG *dst) {
@ -124,7 +122,6 @@ void av1_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
const int eb_uv = eb_y >> uv_height_subsampling;
const int er_uv = er_y >> uv_width_subsampling;
#if CONFIG_HIGHBITDEPTH
if (src->flags & YV12_FLAG_HIGHBITDEPTH) {
highbd_copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer,
dst->y_stride, src->y_crop_width,
@ -139,7 +136,6 @@ void av1_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv);
return;
}
#endif // CONFIG_HIGHBITDEPTH
copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer,
dst->y_stride, src->y_crop_width, src->y_crop_height,

File diff suppressed because it is too large Load diff

View file

@ -42,7 +42,6 @@ typedef struct {
} FIRSTPASS_MB_STATS;
#endif
#if CONFIG_EXT_REFS
// Length of the bi-predictive frame group (BFG)
// NOTE: Currently each BFG contains one backward ref (BWF) frame plus a certain
// number of bi-predictive frames.
@ -64,7 +63,6 @@ typedef struct {
#define MAX_SR_CODED_ERROR 40
#define MAX_RAW_ERR_VAR 2000
#define MIN_MV_IN_OUT 0.4
#endif // CONFIG_EXT_REFS
#define VLOW_MOTION_THRESHOLD 950
@ -72,6 +70,7 @@ typedef struct {
double frame;
double weight;
double intra_error;
double frame_avg_wavelet_energy;
double coded_error;
double sr_coded_error;
double pcnt_inter;
@ -91,10 +90,8 @@ typedef struct {
double new_mv_count;
double duration;
double count;
#if CONFIG_EXT_REFS || CONFIG_BGSPRITE
// standard deviation for (0, 0) motion prediction error
double raw_error_stdev;
#endif // CONFIG_EXT_REFS
} FIRSTPASS_STATS;
typedef enum {
@ -103,16 +100,12 @@ typedef enum {
GF_UPDATE = 2,
ARF_UPDATE = 3,
OVERLAY_UPDATE = 4,
#if CONFIG_EXT_REFS
BRF_UPDATE = 5, // Backward Reference Frame
LAST_BIPRED_UPDATE = 6, // Last Bi-predictive Frame
BIPRED_UPDATE = 7, // Bi-predictive Frame, but not the last one
INTNL_OVERLAY_UPDATE = 8, // Internal Overlay Frame
INTNL_ARF_UPDATE = 9, // Internal Altref Frame (candidate for ALTREF2)
FRAME_UPDATE_TYPES = 10
#else // !CONFIG_EXT_REFS
FRAME_UPDATE_TYPES = 5
#endif // CONFIG_EXT_REFS
} FRAME_UPDATE_TYPE;
#define FC_ANIMATION_THRESH 0.15
@ -129,13 +122,11 @@ typedef struct {
unsigned char arf_src_offset[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char arf_update_idx[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char arf_ref_idx[(MAX_LAG_BUFFERS * 2) + 1];
#if CONFIG_EXT_REFS
unsigned char brf_src_offset[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char bidir_pred_enabled[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char ref_fb_idx_map[(MAX_LAG_BUFFERS * 2) + 1][REF_FRAMES];
unsigned char refresh_idx[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char refresh_flag[(MAX_LAG_BUFFERS * 2) + 1];
#endif // CONFIG_EXT_REFS
int bit_allocation[(MAX_LAG_BUFFERS * 2) + 1];
} GF_GROUP;
@ -153,6 +144,7 @@ typedef struct {
double modified_error_max;
double modified_error_left;
double mb_av_energy;
double frame_avg_haar_energy;
#if CONFIG_FP_MB_STATS
uint8_t *frame_mb_stats_buf;
@ -198,7 +190,6 @@ void av1_rc_get_second_pass_params(struct AV1_COMP *cpi);
// Post encode update of the rate control parameters for 2-pass
void av1_twopass_postencode_update(struct AV1_COMP *cpi);
#if CONFIG_EXT_REFS
#if USE_GF16_MULTI_LAYER
void av1_ref_frame_map_idx_updates(struct AV1_COMP *cpi, int gf_frame_index);
#endif // USE_GF16_MULTI_LAYER
@ -213,7 +204,6 @@ static INLINE int get_number_of_extra_arfs(int interval, int arf_pending) {
else
return 0;
}
#endif // CONFIG_EXT_REFS
#ifdef __cplusplus
} // extern "C"

View file

@ -1,157 +0,0 @@
/*
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
/* clang-format off */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include "aom_dsp/bitwriter.h"
#include "av1/common/generic_code.h"
#include "av1/common/odintrin.h"
#include "pvq_encoder.h"
/** Encodes a value from 0 to N-1 (with N up to 16) based on a cdf and adapts
* the cdf accordingly.
*
* @param [in,out] w multi-symbol entropy encoder
* @param [in] val variable being encoded
* @param [in,out] cdf CDF of the variable (Q15)
* @param [in] n number of values possible
* @param [in,out] count number of symbols encoded with that cdf so far
* @param [in] rate adaptation rate shift (smaller is faster)
*/
void aom_encode_cdf_adapt_q15(aom_writer *w, int val, uint16_t *cdf, int n,
int *count, int rate) {
int i;
if (*count == 0) {
/* On the first call, we normalize the cdf to (32768 - n). This should
eventually be moved to the state init, but for now it makes it much
easier to experiment and convert symbols to the Q15 adaptation.*/
int ft;
ft = cdf[n - 1];
for (i = 0; i < n; i++) {
cdf[i] = AOM_ICDF(cdf[i]*32768/ft);
}
}
aom_write_cdf(w, val, cdf, n);
aom_cdf_adapt_q15(val, cdf, n, count, rate);
}
/** Encodes a random variable using a "generic" model, assuming that the
* distribution is one-sided (zero and up), has a single mode, and decays
* exponentially past the model.
*
* @param [in,out] w multi-symbol entropy encoder
* @param [in,out] model generic probability model
* @param [in] x variable being encoded
* @param [in,out] ExQ16 expectation of x (adapted)
* @param [in] integration integration period of ExQ16 (leaky average over
* 1<<integration samples)
*/
void generic_encode(aom_writer *w, generic_encoder *model, int x,
int *ex_q16, int integration) {
int lg_q1;
int shift;
int id;
uint16_t *cdf;
int xs;
lg_q1 = log_ex(*ex_q16);
OD_LOG((OD_LOG_ENTROPY_CODER, OD_LOG_DEBUG,
"%d %d", *ex_q16, lg_q1));
/* If expectation is too large, shift x to ensure that
all we have past xs=15 is the exponentially decaying tail
of the distribution */
shift = OD_MAXI(0, (lg_q1 - 5) >> 1);
/* Choose the cdf to use: we have two per "octave" of ExQ16 */
id = OD_MINI(GENERIC_TABLES - 1, lg_q1);
cdf = model->cdf[id];
xs = (x + (1 << shift >> 1)) >> shift;
aom_write_symbol_pvq(w, OD_MINI(15, xs), cdf, 16);
if (xs >= 15) {
int e;
unsigned decay;
/* Estimate decay based on the assumption that the distribution is close
to Laplacian for large values. We should probably have an adaptive
estimate instead. Note: The 2* is a kludge that's not fully understood
yet. */
OD_ASSERT(*ex_q16 < INT_MAX >> 1);
e = ((2**ex_q16 >> 8) + (1 << shift >> 1)) >> shift;
decay = OD_MAXI(2, OD_MINI(254, 256*e/(e + 256)));
/* Encode the tail of the distribution assuming exponential decay. */
aom_laplace_encode_special(w, xs - 15, decay);
}
if (shift != 0) {
int special;
/* Because of the rounding, there's only half the number of possibilities
for xs=0. */
special = xs == 0;
if (shift - special > 0) {
aom_write_literal(w, x - (xs << shift) + (!special << (shift - 1)),
shift - special);
}
}
generic_model_update(ex_q16, x, integration);
OD_LOG((OD_LOG_ENTROPY_CODER, OD_LOG_DEBUG,
"enc: %d %d %d %d %d %x", *ex_q16, x, shift, id, xs, enc->rng));
}
/** Estimates the cost of encoding a value with generic_encode().
*
* @param [in,out] model generic probability model
* @param [in] x variable being encoded
* @param [in,out] ExQ16 expectation of x (adapted)
* @return number of bits (approximation)
*/
double generic_encode_cost(generic_encoder *model, int x, int *ex_q16) {
int lg_q1;
int shift;
int id;
uint16_t *cdf;
int xs;
int extra;
lg_q1 = log_ex(*ex_q16);
/* If expectation is too large, shift x to ensure that
all we have past xs=15 is the exponentially decaying tail
of the distribution */
shift = OD_MAXI(0, (lg_q1 - 5) >> 1);
/* Choose the cdf to use: we have two per "octave" of ExQ16 */
id = OD_MINI(GENERIC_TABLES - 1, lg_q1);
cdf = model->cdf[id];
xs = (x + (1 << shift >> 1)) >> shift;
extra = 0;
if (shift) extra = shift - (xs == 0);
xs = OD_MINI(15, xs);
/* Shortcut: assume it's going to cost 2 bits for the Laplace coder. */
if (xs == 15) extra += 2;
return
extra - OD_LOG2((double)(cdf[xs] - (xs == 0 ? 0 : cdf[xs - 1]))/cdf[15]);
}
/*Estimates the cost of encoding a value with a given CDF.*/
double od_encode_cdf_cost(int val, uint16_t *cdf, int n) {
int total_prob;
int prev_prob;
double val_prob;
OD_ASSERT(n > 0);
total_prob = cdf[n - 1];
if (val == 0) {
prev_prob = 0;
}
else {
prev_prob = cdf[val - 1];
}
val_prob = (cdf[val] - prev_prob) / (double)total_prob;
return -OD_LOG2(val_prob);
}

View file

@ -32,12 +32,14 @@
// Border over which to compute the global motion
#define ERRORADV_BORDER 0
#define ERRORADV_MAX_THRESH 0.995
#define ERRORADV_COST_PRODUCT_THRESH 26000
static const double erroradv_tr[] = { 0.75, 0.70, 0.65 };
static const double erroradv_prod_tr[] = { 22000, 20000, 18000 };
int is_enough_erroradvantage(double best_erroradvantage, int params_cost) {
return best_erroradvantage < ERRORADV_MAX_THRESH &&
best_erroradvantage * params_cost < ERRORADV_COST_PRODUCT_THRESH;
int is_enough_erroradvantage(double best_erroradvantage, int params_cost,
int erroradv_type) {
assert(erroradv_type < GM_ERRORADV_TR_TYPES);
return best_erroradvantage < erroradv_tr[erroradv_type] &&
best_erroradvantage * params_cost < erroradv_prod_tr[erroradv_type];
}
static void convert_to_params(const double *params, int32_t *model) {
@ -76,6 +78,7 @@ static void convert_to_params(const double *params, int32_t *model) {
void convert_model_to_params(const double *params, WarpedMotionParams *model) {
convert_to_params(params, model->wmmat);
model->wmtype = get_gmtype(model);
model->invalid = 0;
}
// Adds some offset to a global motion parameter and handles
@ -110,32 +113,31 @@ static int32_t add_param_offset(int param_index, int32_t param_value,
static void force_wmtype(WarpedMotionParams *wm, TransformationType wmtype) {
switch (wmtype) {
case IDENTITY: wm->wmmat[0] = 0; wm->wmmat[1] = 0;
case IDENTITY:
wm->wmmat[0] = 0;
wm->wmmat[1] = 0;
AOM_FALLTHROUGH_INTENDED;
case TRANSLATION:
wm->wmmat[2] = 1 << WARPEDMODEL_PREC_BITS;
wm->wmmat[3] = 0;
case ROTZOOM: wm->wmmat[4] = -wm->wmmat[3]; wm->wmmat[5] = wm->wmmat[2];
AOM_FALLTHROUGH_INTENDED;
case ROTZOOM:
wm->wmmat[4] = -wm->wmmat[3];
wm->wmmat[5] = wm->wmmat[2];
AOM_FALLTHROUGH_INTENDED;
case AFFINE: wm->wmmat[6] = wm->wmmat[7] = 0; break;
case HORTRAPEZOID: wm->wmmat[6] = wm->wmmat[4] = 0; break;
case VERTRAPEZOID: wm->wmmat[7] = wm->wmmat[3] = 0; break;
case HOMOGRAPHY: break;
default: assert(0);
}
wm->wmtype = wmtype;
}
int64_t refine_integerized_param(WarpedMotionParams *wm,
TransformationType wmtype,
#if CONFIG_HIGHBITDEPTH
int use_hbd, int bd,
#endif // CONFIG_HIGHBITDEPTH
TransformationType wmtype, int use_hbd, int bd,
uint8_t *ref, int r_width, int r_height,
int r_stride, uint8_t *dst, int d_width,
int d_height, int d_stride, int n_refinements,
int64_t best_frame_error) {
static const int max_trans_model_params[TRANS_TYPES] = {
0, 2, 4, 6, 8, 8, 8
};
static const int max_trans_model_params[TRANS_TYPES] = { 0, 2, 4, 6 };
const int border = ERRORADV_BORDER;
int i = 0, p;
int n_params = max_trans_model_params[wmtype];
@ -147,35 +149,26 @@ int64_t refine_integerized_param(WarpedMotionParams *wm,
int32_t best_param;
force_wmtype(wm, wmtype);
best_error = av1_warp_error(
wm,
#if CONFIG_HIGHBITDEPTH
use_hbd, bd,
#endif // CONFIG_HIGHBITDEPTH
ref, r_width, r_height, r_stride, dst + border * d_stride + border,
border, border, d_width - 2 * border, d_height - 2 * border, d_stride, 0,
0, SCALE_SUBPEL_SHIFTS, SCALE_SUBPEL_SHIFTS, best_frame_error);
best_error = av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
dst + border * d_stride + border, border, border,
d_width - 2 * border, d_height - 2 * border,
d_stride, 0, 0, best_frame_error);
best_error = AOMMIN(best_error, best_frame_error);
step = 1 << (n_refinements - 1);
for (i = 0; i < n_refinements; i++, step >>= 1) {
for (p = 0; p < n_params; ++p) {
int step_dir = 0;
// Skip searches for parameters that are forced to be 0
if (wmtype == HORTRAPEZOID && (p == 4 || p == 6)) continue;
if (wmtype == VERTRAPEZOID && (p == 3 || p == 7)) continue;
param = param_mat + p;
curr_param = *param;
best_param = curr_param;
// look to the left
*param = add_param_offset(p, curr_param, -step);
step_error = av1_warp_error(
wm,
#if CONFIG_HIGHBITDEPTH
use_hbd, bd,
#endif // CONFIG_HIGHBITDEPTH
ref, r_width, r_height, r_stride, dst + border * d_stride + border,
border, border, d_width - 2 * border, d_height - 2 * border, d_stride,
0, 0, SCALE_SUBPEL_SHIFTS, SCALE_SUBPEL_SHIFTS, best_error);
step_error =
av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
dst + border * d_stride + border, border, border,
d_width - 2 * border, d_height - 2 * border, d_stride,
0, 0, best_error);
if (step_error < best_error) {
best_error = step_error;
best_param = *param;
@ -184,14 +177,11 @@ int64_t refine_integerized_param(WarpedMotionParams *wm,
// look to the right
*param = add_param_offset(p, curr_param, step);
step_error = av1_warp_error(
wm,
#if CONFIG_HIGHBITDEPTH
use_hbd, bd,
#endif // CONFIG_HIGHBITDEPTH
ref, r_width, r_height, r_stride, dst + border * d_stride + border,
border, border, d_width - 2 * border, d_height - 2 * border, d_stride,
0, 0, SCALE_SUBPEL_SHIFTS, SCALE_SUBPEL_SHIFTS, best_error);
step_error =
av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
dst + border * d_stride + border, border, border,
d_width - 2 * border, d_height - 2 * border, d_stride,
0, 0, best_error);
if (step_error < best_error) {
best_error = step_error;
best_param = *param;
@ -203,15 +193,11 @@ int64_t refine_integerized_param(WarpedMotionParams *wm,
// for the biggest step size
while (step_dir) {
*param = add_param_offset(p, best_param, step * step_dir);
step_error = av1_warp_error(
wm,
#if CONFIG_HIGHBITDEPTH
use_hbd, bd,
#endif // CONFIG_HIGHBITDEPTH
ref, r_width, r_height, r_stride, dst + border * d_stride + border,
border, border, d_width - 2 * border, d_height - 2 * border,
d_stride, 0, 0, SCALE_SUBPEL_SHIFTS, SCALE_SUBPEL_SHIFTS,
best_error);
step_error =
av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
dst + border * d_stride + border, border, border,
d_width - 2 * border, d_height - 2 * border,
d_stride, 0, 0, best_error);
if (step_error < best_error) {
best_error = step_error;
best_param = *param;
@ -229,9 +215,6 @@ int64_t refine_integerized_param(WarpedMotionParams *wm,
static INLINE RansacFunc get_ransac_type(TransformationType type) {
switch (type) {
case HOMOGRAPHY: return ransac_homography;
case HORTRAPEZOID: return ransac_hortrapezoid;
case VERTRAPEZOID: return ransac_vertrapezoid;
case AFFINE: return ransac_affine;
case ROTZOOM: return ransac_rotzoom;
case TRANSLATION: return ransac_translation;
@ -239,7 +222,6 @@ static INLINE RansacFunc get_ransac_type(TransformationType type) {
}
}
#if CONFIG_HIGHBITDEPTH
static unsigned char *downconvert_frame(YV12_BUFFER_CONFIG *frm,
int bit_depth) {
int i, j;
@ -257,14 +239,13 @@ static unsigned char *downconvert_frame(YV12_BUFFER_CONFIG *frm,
}
return buf_8bit;
}
#endif
int compute_global_motion_feature_based(
TransformationType type, YV12_BUFFER_CONFIG *frm, YV12_BUFFER_CONFIG *ref,
#if CONFIG_HIGHBITDEPTH
int bit_depth,
#endif
int *num_inliers_by_motion, double *params_by_motion, int num_motions) {
int compute_global_motion_feature_based(TransformationType type,
YV12_BUFFER_CONFIG *frm,
YV12_BUFFER_CONFIG *ref, int bit_depth,
int *num_inliers_by_motion,
double *params_by_motion,
int num_motions) {
int i;
int num_frm_corners, num_ref_corners;
int num_correspondences;
@ -274,7 +255,6 @@ int compute_global_motion_feature_based(
unsigned char *ref_buffer = ref->y_buffer;
RansacFunc ransac = get_ransac_type(type);
#if CONFIG_HIGHBITDEPTH
if (frm->flags & YV12_FLAG_HIGHBITDEPTH) {
// The frame buffer is 16-bit, so we need to convert to 8 bits for the
// following code. We cache the result until the frame is released.
@ -283,7 +263,6 @@ int compute_global_motion_feature_based(
if (ref->flags & YV12_FLAG_HIGHBITDEPTH) {
ref_buffer = downconvert_frame(ref, bit_depth);
}
#endif
// compute interest points in images using FAST features
num_frm_corners = fast_corner_detect(frm_buffer, frm->y_width, frm->y_height,

View file

@ -24,16 +24,14 @@ extern "C" {
void convert_model_to_params(const double *params, WarpedMotionParams *model);
int is_enough_erroradvantage(double erroradv, int params_cost);
int is_enough_erroradvantage(double best_erroradvantage, int params_cost,
int erroradv_type);
// Returns the av1_warp_error between "dst" and the result of applying the
// motion params that result from fine-tuning "wm" to "ref". Note that "wm" is
// modified in place.
int64_t refine_integerized_param(WarpedMotionParams *wm,
TransformationType wmtype,
#if CONFIG_HIGHBITDEPTH
int use_hbd, int bd,
#endif // CONFIG_HIGHBITDEPTH
TransformationType wmtype, int use_hbd, int bd,
uint8_t *ref, int r_width, int r_height,
int r_stride, uint8_t *dst, int d_width,
int d_height, int d_stride, int n_refinements,
@ -54,12 +52,12 @@ int64_t refine_integerized_param(WarpedMotionParams *wm,
number of inlier feature points for each motion. Params for which the
num_inliers entry is 0 should be ignored by the caller.
*/
int compute_global_motion_feature_based(
TransformationType type, YV12_BUFFER_CONFIG *frm, YV12_BUFFER_CONFIG *ref,
#if CONFIG_HIGHBITDEPTH
int bit_depth,
#endif
int *num_inliers_by_motion, double *params_by_motion, int num_motions);
int compute_global_motion_feature_based(TransformationType type,
YV12_BUFFER_CONFIG *frm,
YV12_BUFFER_CONFIG *ref, int bit_depth,
int *num_inliers_by_motion,
double *params_by_motion,
int num_motions);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -0,0 +1,781 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_GRAIN_TEST_VECTORS_H_
#define AV1_GRAIN_TEST_VECTORS_H_
/* Test vectors for emulation of different film grain types.
* Note that bit depth would be derived from the bitstream and
* not signaled in film grain metadata. The parameters are valid
* for any bit depth.
*/
static aom_film_grain_t film_grain_test_vectors[16] = {
/* Test 1 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{ { 16, 0 },
{ 25, 136 },
{ 33, 144 },
{ 41, 160 },
{ 48, 168 },
{ 56, 136 },
{ 67, 128 },
{ 82, 144 },
{ 97, 152 },
{ 113, 144 },
{ 128, 176 },
{ 143, 168 },
{ 158, 176 },
{ 178, 184 } },
14 /* num_points_y */,
{ { 16, 0 },
{ 20, 64 },
{ 28, 88 },
{ 60, 104 },
{ 90, 136 },
{ 105, 160 },
{ 134, 168 },
{ 168, 208 } },
8 /* num_cb_points */,
{ { 16, 0 },
{ 28, 96 },
{ 56, 80 },
{ 66, 96 },
{ 80, 104 },
{ 108, 96 },
{ 122, 112 },
{ 137, 112 },
{ 169, 176 } },
9 /* num_cr_points */,
11 /* scaling_shift */,
2 /* ar_coeff_lag */,
{ 0, 0, -58, 0, 0, 0, -76, 100, -43, 0, -51, 82 },
{ 0, 0, -49, 0, 0, 0, -36, 22, -30, 0, -38, 7, 39 },
{ 0, 0, -47, 0, 0, 0, -31, 31, -25, 0, -32, 13, -100 },
8 /* ar_coeff_shift */,
247 /* cb_mult */,
192 /* cb_luma_mult */,
18 /* cb_offset */,
229 /* cr_mult */,
192 /* cr_luma_mult */,
54 /* cr_offset */,
0 /* overlap_flag */,
1 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /* chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 2 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{ { 0, 96 }, { 255, 96 } },
2 /* num_points_y */,
{ { 0, 64 }, { 255, 64 } },
2 /* num_cb_points */,
{ { 0, 64 }, { 255, 64 } },
2 /* num_cr_points */,
11 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
4, 1, 3, 0, 1, -3, 8, -3, 7, -23, 1, -25,
0, -10, 6, -17, -4, 53, 36, 5, -5, -17, 8, 66,
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127,
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127,
},
7 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 3 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{ { 0, 192 }, { 255, 192 } },
2 /* num_points_y */,
{ { 0, 128 }, { 255, 128 } },
2 /* num_cb_points */,
{ { 0, 128 }, { 255, 128 } },
2 /* num_cr_points */,
11 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
4, 1, 3, 0, 1, -3, 8, -3, 7, -23, 1, -25,
0, -10, 6, -17, -4, 53, 36, 5, -5, -17, 8, 66,
},
{
4, -7, 2, 4, 12, -12, 5, -8, 6, 8, -19, -16, 19,
-10, -2, 17, -42, 58, -2, -13, 9, 14, -36, 67, 0,
},
{
4, -7, 2, 4, 12, -12, 5, -8, 6, 8, -19, -16, 19,
-10, -2, 17, -42, 58, -2, -13, 9, 14, -36, 67, 0,
},
7 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
1 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
1 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 4 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{
{ 16, 0 },
{ 24, 137 },
{ 53, 146 },
{ 63, 155 },
{ 78, 155 },
{ 107, 150 },
{ 122, 147 },
{ 136, 147 },
{ 166, 153 },
},
9 /* num_points_y */,
{
{ 16, 0 },
{ 20, 72 },
{ 27, 82 },
{ 33, 91 },
{ 69, 121 },
{ 95, 143 },
{ 108, 154 },
{ 134, 169 },
{ 147, 177 },
},
9 /* num_cb_points */,
{
{ 16, 0 },
{ 24, 95 },
{ 54, 93 },
{ 65, 94 },
{ 79, 98 },
{ 109, 107 },
{ 124, 119 },
{ 139, 136 },
{ 169, 170 },
},
9 /* num_cr_points */,
11 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
7, -9, 2, 4, 7, -12, 7, -18, 18, -30, -27, -42,
13, -20, 7, -18, 6, 107, 55, -2, -4, -9, -22, 113,
},
{
-3, -1, -4, 3, -6, -2, 3, 1, -4, -10, -10, -5, -5,
-3, -1, -13, -28, -25, -31, -6, -4, 14, -64, 66, 0,
},
{
0, 4, -3, 13, 0, 1, -3, 0, -3, -10, -68, -4, -2,
-5, 2, -3, -20, 62, -31, 0, -4, -1, -8, -29, 0,
},
8 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 5 */
{
1 /* apply_grain */,
0 /* update_parameters */,
{ { 0, 64 }, { 255, 64 } },
2 /* num_points_y */,
{
{ 0, 96 },
{ 32, 90 },
{ 64, 83 },
{ 96, 76 },
{ 128, 68 },
{ 159, 59 },
{ 191, 48 },
{ 223, 34 },
{ 255, 0 },
},
9 /* num_cb_points */,
{
{ 0, 0 },
{ 32, 34 },
{ 64, 48 },
{ 96, 59 },
{ 128, 68 },
{ 159, 76 },
{ 191, 83 },
{ 223, 90 },
{ 255, 96 },
},
9 /* num_cr_points */,
11 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
4, 1, 3, 0, 1, -3, 8, -3, 7, -23, 1, -25,
0, -10, 6, -17, -4, 53, 36, 5, -5, -17, 8, 66,
},
{
-2, 2, -5, 7, -6, 4, -2, -1, 1, -2, 0, -2, 2,
-3, -5, 13, -13, 6, -14, 8, -1, 18, -36, 58, 0,
},
{
-2, -1, -3, 14, -4, -1, -3, 0, -1, 7, -31, 7, 2,
0, 1, 0, -7, 50, -8, -2, 2, 2, 2, -4, 0,
},
7 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
1 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
1063 /* random_seed */
},
/* Test 6 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{
{ 0, 96 },
{ 20, 92 },
{ 39, 88 },
{ 59, 84 },
{ 78, 80 },
{ 98, 75 },
{ 118, 70 },
{ 137, 65 },
{ 157, 60 },
{ 177, 53 },
{ 196, 46 },
{ 216, 38 },
{ 235, 27 },
{ 255, 0 },
},
14 /* num_points_y */,
{ { 0, 0 } },
0 /* num_cb_points */,
{ { 0, 0 } },
0 /* num_cr_points */,
11 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
4, 1, 3, 0, 1, -3, 8, -3, 7, -23, 1, -25,
0, -10, 6, -17, -4, 53, 36, 5, -5, -17, 8, 66,
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
},
7 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
1 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
2754 /* random_seed */
},
/* Test 7 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{
{ 0, 0 },
{ 20, 27 },
{ 39, 38 },
{ 59, 46 },
{ 78, 53 },
{ 98, 60 },
{ 118, 65 },
{ 137, 70 },
{ 157, 75 },
{ 177, 80 },
{ 196, 84 },
{ 216, 88 },
{ 235, 92 },
{ 255, 96 },
},
14 /* num_points_y */,
{ { 0, 0 }, { 255, 0 } },
2 /* num_cb_points */,
{ { 0, 0 }, { 255, 0 } },
2 /* num_cr_points */,
11 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
4, 1, 3, 0, 1, -3, 8, -3, 7, -23, 1, -25,
0, -10, 6, -17, -4, 53, 36, 5, -5, -17, 8, 66,
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
},
7 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
1 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 8 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{ { 0, 96 }, { 255, 96 } },
2 /* num_points_y */,
{ { 0, 62 }, { 255, 62 } },
2 /* num_cb_points */,
{ { 0, 62 }, { 255, 62 } },
2 /* num_cr_points */,
11 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
4, 1, 3, 0, 1, -3, 8, -3, 7, -23, 1, -25,
0, -10, 6, -17, -4, 53, 36, 5, -5, -17, 8, 66,
},
{
0, -2, -2, 8, 5, -1, 1, -1, 5, 16, -33, -9, 6,
-1, -3, 10, -47, 63, 0, -15, 3, 11, -42, 75, -69,
},
{
1, -1, -1, 9, 5, 0, 1, -1, 5, 15, -32, -10, 8,
-2, -4, 11, -46, 62, 1, -16, 3, 13, -43, 75, -55,
},
7 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 9 */
{
1 /* apply_grain */,
0 /* update_parameters */,
{ { 0, 48 }, { 255, 48 } },
2 /* num_points_y */,
{ { 0, 32 }, { 255, 32 } },
2 /* num_cb_points */,
{ { 0, 32 }, { 255, 32 } },
2 /* num_cr_points */,
10 /* scaling_shift */,
2 /* ar_coeff_lag */,
{ 10, -30, -20, -39, 1, -24, 12, 103, 60, -9, -24, 113 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127 },
8 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 10 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{ { 0, 48 }, { 255, 48 } },
2 /* num_points_y */,
{ { 0, 32 }, { 255, 32 } },
2 /* num_cb_points */,
{ { 0, 32 }, { 255, 32 } },
2 /* num_cr_points */,
10 /* scaling_shift */,
2 /* ar_coeff_lag */,
{ 10, -30, -20, -39, 1, -24, 12, 103, 60, -9, -24, 113 },
{ -7, -6, -48, -22, 2, -3, -45, 73, -11, -26, -52, 76, 0 },
{ -7, -6, -48, -22, 2, -3, -45, 73, -11, -26, -52, 76, 0 },
8 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 11 */
{
1 /* apply_grain */,
0 /* update_parameters */,
{ { 0, 32 }, { 255, 32 } },
2 /* num_points_y */,
{
{ 0, 48 },
{ 32, 45 },
{ 64, 42 },
{ 96, 38 },
{ 128, 34 },
{ 159, 29 },
{ 191, 24 },
{ 223, 17 },
{ 255, 0 },
},
9 /* num_cb_points */,
{
{ 0, 0 },
{ 32, 17 },
{ 64, 24 },
{ 96, 29 },
{ 128, 34 },
{ 159, 38 },
{ 191, 42 },
{ 223, 45 },
{ 255, 48 },
},
9 /* num_cr_points */,
10 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
7, -9, 2, 4, 7, -12, 7, -18, 18, -30, -27, -42,
13, -20, 7, -18, 6, 107, 55, -2, -4, -9, -22, 113,
},
{
-3, -1, -4, 3, -6, -2, 3, 1, -4, -10, -10, -5, -5,
-3, -1, -13, -28, -25, -31, -6, -4, 14, -64, 66, 0,
},
{
0, 4, -3, 13, 0, 1, -3, 0, -3, -10, -68, -4, -2,
-5, 2, -3, -20, 62, -31, 0, -4, -1, -8, -29, 0,
},
8 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
1 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
1357 /* random_seed */
},
/* Test 12 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{
{ 16, 0 },
{ 24, 49 },
{ 39, 69 },
{ 46, 84 },
{ 53, 91 },
{ 63, 100 },
{ 78, 114 },
{ 92, 134 },
{ 164, 139 },
},
9 /* num_points_y */,
{
{ 16, 0 },
{ 20, 31 },
{ 26, 42 },
{ 33, 54 },
{ 40, 65 },
{ 47, 72 },
{ 56, 85 },
{ 84, 123 },
{ 152, 157 },
},
9 /* num_cb_points */,
{
{ 16, 0 },
{ 25, 14 },
{ 39, 33 },
{ 47, 40 },
{ 54, 47 },
{ 64, 62 },
{ 79, 76 },
{ 94, 83 },
{ 167, 101 },
},
9 /* num_cr_points */,
10 /* scaling_shift */,
2 /* ar_coeff_lag */,
{ 0, 0, -58, 0, 0, 0, -76, 100, -43, 0, -51, 82 },
{ 0, 0, -49, 0, 0, 0, -36, 22, -30, 0, -38, 7, 39 },
{ 0, 0, -47, 0, 0, 0, -31, 31, -25, 0, -32, 13, -100 },
8 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
0 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 13 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{
{ 0, 48 },
{ 20, 46 },
{ 39, 44 },
{ 59, 42 },
{ 78, 40 },
{ 98, 38 },
{ 118, 35 },
{ 137, 33 },
{ 157, 30 },
{ 177, 27 },
{ 196, 23 },
{ 216, 19 },
{ 235, 13 },
{ 255, 0 },
},
14 /* num_points_y */,
{ { 0, 0 }, { 255, 0 } },
0 /* num_cb_points */,
{ { 0, 0 }, { 255, 0 } },
0 /* num_cr_points */,
10 /* scaling_shift */,
2 /* ar_coeff_lag */,
{ 10, -30, -20, -39, 1, -24, 12, 103, 60, -9, -24, 113 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
8 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 14 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{
{ 0, 0 },
{ 20, 13 },
{ 39, 19 },
{ 59, 23 },
{ 78, 27 },
{ 98, 30 },
{ 118, 33 },
{ 137, 35 },
{ 157, 38 },
{ 177, 40 },
{ 196, 42 },
{ 216, 44 },
{ 235, 46 },
{ 255, 48 },
},
14 /* num_points_y */,
{ { 0, 0 }, { 255, 0 } },
0 /* num_cb_points */,
{ { 0, 0 }, { 255, 0 } },
0 /* num_cr_points */,
10 /* scaling_shift */,
2 /* ar_coeff_lag */,
{ 10, -30, -20, -39, 1, -24, 12, 103, 60, -9, -24, 113 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
8 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
1 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 15 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{ { 0, 96 }, { 255, 96 } },
1 /* num_points_y */,
{ { 0, 96 }, { 255, 96 } },
0 /* num_cb_points */,
{ { 0, 96 }, { 255, 96 } },
0 /* num_cr_points */,
11 /* scaling_shift */,
2 /* ar_coeff_lag */,
{ 5, -15, -10, -19, 0, -12, 6, 51, 30, -5, -12, 56 },
{ 2, 2, -24, -5, 1, 1, -18, 37, -2, 0, -15, 39, -70 },
{ 2, 3, -24, -5, -1, 0, -18, 38, -2, 0, -15, 39, -55 },
7 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
1 /*chroma_scaling_from_luma*/,
0 /* grain_scale_shift*/,
45231 /* random_seed */
},
/* Test 16 */
{
1 /* apply_grain */,
1 /* update_parameters */,
{
{ 16, 0 },
{ 58, 126 },
{ 87, 120 },
{ 97, 122 },
{ 112, 125 },
{ 126, 131 },
{ 141, 139 },
{ 199, 153 },
},
8 /* num_points_y */,
{
{ 16, 0 },
{ 59, 68 },
{ 66, 76 },
{ 73, 82 },
{ 79, 85 },
{ 86, 86 },
{ 151, 95 },
{ 192, 101 },
},
8 /* num_cb_points */,
{
{ 16, 0 },
{ 59, 64 },
{ 89, 80 },
{ 99, 86 },
{ 114, 90 },
{ 129, 93 },
{ 144, 97 },
{ 203, 85 },
},
8 /* num_cr_points */,
10 /* scaling_shift */,
3 /* ar_coeff_lag */,
{
4, 1, 3, 0, 1, -3, 8, -3, 7, -23, 1, -25,
0, -10, 6, -17, -4, 53, 36, 5, -5, -17, 8, 66,
},
{
0, -2, -2, 8, 5, -1, 1, -1, 5, 16, -33, -9, 6,
-1, -3, 10, -47, 63, 0, -15, 3, 11, -42, 75, -69,
},
{
1, -1, -1, 9, 5, 0, 1, -1, 5, 15, -32, -10, 8,
-2, -4, 11, -46, 62, 1, -16, 3, 13, -43, 75, -55,
},
7 /* ar_coeff_shift */,
128 /* cb_mult */,
192 /* cb_luma_mult */,
256 /* cb_offset */,
128 /* cr_mult */,
192 /* cr_luma_mult */,
256 /* cr_offset */,
1 /* overlap_flag */,
0 /* clip_to_restricted_range */,
8 /* bit_depth */,
0 /*chroma_scaling_from_luma*/,
2 /* grain_scale_shift*/,
45231 /* random_seed */
},
};
#endif // AV1_GRAIN_TEST_VECTORS_H_

View file

@ -22,7 +22,7 @@ static void crc_calculator_process_data(CRC_CALCULATOR *p_crc_calculator,
}
}
void crc_calculator_reset(CRC_CALCULATOR *p_crc_calculator) {
static void crc_calculator_reset(CRC_CALCULATOR *p_crc_calculator) {
p_crc_calculator->remainder = 0;
}
@ -61,9 +61,65 @@ void av1_crc_calculator_init(CRC_CALCULATOR *p_crc_calculator, uint32_t bits,
crc_calculator_init_table(p_crc_calculator);
}
uint32_t av1_get_crc_value(CRC_CALCULATOR *p_crc_calculator, uint8_t *p,
int length) {
uint32_t av1_get_crc_value(void *crc_calculator, uint8_t *p, int length) {
CRC_CALCULATOR *p_crc_calculator = (CRC_CALCULATOR *)crc_calculator;
crc_calculator_reset(p_crc_calculator);
crc_calculator_process_data(p_crc_calculator, p, length);
return crc_calculator_get_crc(p_crc_calculator);
}
/* CRC-32C (iSCSI) polynomial in reversed bit order. */
#define POLY 0x82f63b78
/* Construct table for software CRC-32C calculation. */
void av1_crc32c_calculator_init(CRC32C *p_crc32c) {
uint32_t crc;
for (int n = 0; n < 256; n++) {
crc = n;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
p_crc32c->table[0][n] = crc;
}
for (int n = 0; n < 256; n++) {
crc = p_crc32c->table[0][n];
for (int k = 1; k < 8; k++) {
crc = p_crc32c->table[0][crc & 0xff] ^ (crc >> 8);
p_crc32c->table[k][n] = crc;
}
}
}
/* Table-driven software version as a fall-back. This is about 15 times slower
than using the hardware instructions. This assumes little-endian integers,
as is the case on Intel processors that the assembler code here is for. */
uint32_t av1_get_crc32c_value_c(CRC32C *p, uint8_t *buf, size_t len) {
const uint8_t *next = (const uint8_t *)(buf);
uint64_t crc;
crc = 0 ^ 0xffffffff;
while (len && ((uintptr_t)next & 7) != 0) {
crc = p->table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
len--;
}
while (len >= 8) {
crc ^= *(uint64_t *)next;
crc = p->table[7][crc & 0xff] ^ p->table[6][(crc >> 8) & 0xff] ^
p->table[5][(crc >> 16) & 0xff] ^ p->table[4][(crc >> 24) & 0xff] ^
p->table[3][(crc >> 32) & 0xff] ^ p->table[2][(crc >> 40) & 0xff] ^
p->table[1][(crc >> 48) & 0xff] ^ p->table[0][crc >> 56];
next += 8;
len -= 8;
}
while (len) {
crc = p->table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
len--;
}
return (uint32_t)crc ^ 0xffffffff;
}

View file

@ -12,7 +12,8 @@
#ifndef AV1_ENCODER_HASH_H_
#define AV1_ENCODER_HASH_H_
#include "./aom_config.h"
#include "config/aom_config.h"
#include "aom/aom_integer.h"
#ifdef __cplusplus
@ -31,9 +32,16 @@ typedef struct _crc_calculator {
// calling av1_get_crc_value().
void av1_crc_calculator_init(CRC_CALCULATOR *p_crc_calculator, uint32_t bits,
uint32_t truncPoly);
uint32_t av1_get_crc_value(void *crc_calculator, uint8_t *p, int length);
uint32_t av1_get_crc_value(CRC_CALCULATOR *p_crc_calculator, uint8_t *p,
int length);
// CRC32C: POLY = 0x82f63b78;
typedef struct _CRC32C {
/* Table for a quadword-at-a-time software crc. */
uint32_t table[8][256];
} CRC32C;
// init table for software version crc32c
void av1_crc32c_calculator_init(CRC32C *p_crc32c);
#ifdef __cplusplus
} // extern "C"

View file

@ -1,7 +1,9 @@
#include <assert.h>
#include "config/av1_rtcd.h"
#include "av1/encoder/hash.h"
#include "av1/encoder/hash_motion.h"
#include "./av1_rtcd.h"
static const int crc_bits = 16;
static const int block_size_bits = 3;
@ -16,7 +18,7 @@ static void hash_table_clear_all(hash_table *p_hash_table) {
int max_addr = 1 << (crc_bits + block_size_bits);
for (int i = 0; i < max_addr; i++) {
if (p_hash_table->p_lookup_table[i] != NULL) {
vector_destroy(p_hash_table->p_lookup_table[i]);
aom_vector_destroy(p_hash_table->p_lookup_table[i]);
aom_free(p_hash_table->p_lookup_table[i]);
p_hash_table->p_lookup_table[i] = NULL;
}
@ -37,11 +39,30 @@ static void get_pixels_in_1D_char_array_by_block_2x2(uint8_t *y_src, int stride,
}
}
static void get_pixels_in_1D_short_array_by_block_2x2(uint16_t *y_src,
int stride,
uint16_t *p_pixels_in1D) {
uint16_t *p_pel = y_src;
int index = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
p_pixels_in1D[index++] = p_pel[j];
}
p_pel += stride;
}
}
static int is_block_2x2_row_same_value(uint8_t *p) {
if (p[0] != p[1] || p[2] != p[3]) {
return 0;
}
return 1;
}
static int is_block16_2x2_row_same_value(uint16_t *p) {
if (p[0] != p[1] || p[2] != p[3]) {
return 0;
}
return 1;
}
@ -49,7 +70,13 @@ static int is_block_2x2_col_same_value(uint8_t *p) {
if ((p[0] != p[2]) || (p[1] != p[3])) {
return 0;
}
return 1;
}
static int is_block16_2x2_col_same_value(uint16_t *p) {
if ((p[0] != p[2]) || (p[1] != p[3])) {
return 0;
}
return 1;
}
@ -63,6 +90,7 @@ static int hash_block_size_to_index(int block_size) {
case 16: return 2;
case 32: return 3;
case 64: return 4;
case 128: return 5;
default: return -1;
}
}
@ -100,11 +128,13 @@ static void hash_table_add_to_table(hash_table *p_hash_table,
if (p_hash_table->p_lookup_table[hash_value] == NULL) {
p_hash_table->p_lookup_table[hash_value] =
aom_malloc(sizeof(p_hash_table->p_lookup_table[0][0]));
vector_setup(p_hash_table->p_lookup_table[hash_value], 10,
sizeof(curr_block_hash[0]));
vector_push_back(p_hash_table->p_lookup_table[hash_value], curr_block_hash);
aom_vector_setup(p_hash_table->p_lookup_table[hash_value], 10,
sizeof(curr_block_hash[0]));
aom_vector_push_back(p_hash_table->p_lookup_table[hash_value],
curr_block_hash);
} else {
vector_push_back(p_hash_table->p_lookup_table[hash_value], curr_block_hash);
aom_vector_push_back(p_hash_table->p_lookup_table[hash_value],
curr_block_hash);
}
}
@ -119,7 +149,7 @@ int32_t av1_hash_table_count(hash_table *p_hash_table, uint32_t hash_value) {
Iterator av1_hash_get_first_iterator(hash_table *p_hash_table,
uint32_t hash_value) {
assert(av1_hash_table_count(p_hash_table, hash_value) > 0);
return vector_begin(p_hash_table->p_lookup_table[hash_value]);
return aom_vector_begin(p_hash_table->p_lookup_table[hash_value]);
}
int32_t av1_has_exact_match(hash_table *p_hash_table, uint32_t hash_value1,
@ -127,8 +157,9 @@ int32_t av1_has_exact_match(hash_table *p_hash_table, uint32_t hash_value1,
if (p_hash_table->p_lookup_table[hash_value1] == NULL) {
return 0;
}
Iterator iterator = vector_begin(p_hash_table->p_lookup_table[hash_value1]);
Iterator last = vector_end(p_hash_table->p_lookup_table[hash_value1]);
Iterator iterator =
aom_vector_begin(p_hash_table->p_lookup_table[hash_value1]);
Iterator last = aom_vector_end(p_hash_table->p_lookup_table[hash_value1]);
for (; !iterator_equals(&iterator, &last); iterator_increment(&iterator)) {
if ((*(block_hash *)iterator_get(&iterator)).hash_value2 == hash_value2) {
return 1;
@ -146,25 +177,45 @@ void av1_generate_block_2x2_hash_value(const YV12_BUFFER_CONFIG *picture,
const int y_end = picture->y_crop_height - height + 1;
const int length = width * 2;
uint8_t p[4];
if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
uint16_t p[4];
int pos = 0;
for (int y_pos = 0; y_pos < y_end; y_pos++) {
for (int x_pos = 0; x_pos < x_end; x_pos++) {
get_pixels_in_1D_short_array_by_block_2x2(
CONVERT_TO_SHORTPTR(picture->y_buffer) + y_pos * picture->y_stride +
x_pos,
picture->y_stride, p);
pic_block_same_info[0][pos] = is_block16_2x2_row_same_value(p);
pic_block_same_info[1][pos] = is_block16_2x2_col_same_value(p);
int pos = 0;
for (int y_pos = 0; y_pos < y_end; y_pos++) {
for (int x_pos = 0; x_pos < x_end; x_pos++) {
get_pixels_in_1D_char_array_by_block_2x2(
picture->y_buffer + y_pos * picture->y_stride + x_pos,
picture->y_stride, p);
pic_block_same_info[0][pos] = is_block_2x2_row_same_value(p);
pic_block_same_info[1][pos] = is_block_2x2_col_same_value(p);
pic_block_hash[0][pos] =
av1_get_crc_value(&crc_calculator1, p, length * sizeof(p[0]));
pic_block_hash[1][pos] =
av1_get_crc_value(&crc_calculator2, p, length * sizeof(p[0]));
pos++;
pic_block_hash[0][pos] = av1_get_crc_value(
&crc_calculator1, (uint8_t *)p, length * sizeof(p[0]));
pic_block_hash[1][pos] = av1_get_crc_value(
&crc_calculator2, (uint8_t *)p, length * sizeof(p[0]));
pos++;
}
pos += width - 1;
}
} else {
uint8_t p[4];
int pos = 0;
for (int y_pos = 0; y_pos < y_end; y_pos++) {
for (int x_pos = 0; x_pos < x_end; x_pos++) {
get_pixels_in_1D_char_array_by_block_2x2(
picture->y_buffer + y_pos * picture->y_stride + x_pos,
picture->y_stride, p);
pic_block_same_info[0][pos] = is_block_2x2_row_same_value(p);
pic_block_same_info[1][pos] = is_block_2x2_col_same_value(p);
pic_block_hash[0][pos] =
av1_get_crc_value(&crc_calculator1, p, length * sizeof(p[0]));
pic_block_hash[1][pos] =
av1_get_crc_value(&crc_calculator2, p, length * sizeof(p[0]));
pos++;
}
pos += width - 1;
}
pos += width - 1;
}
}
@ -222,14 +273,14 @@ void av1_generate_block_hash_value(const YV12_BUFFER_CONFIG *picture,
}
if (block_size >= 4) {
const int size_minus1 = block_size - 1;
const int size_minus_1 = block_size - 1;
pos = 0;
for (int y_pos = 0; y_pos < y_end; y_pos++) {
for (int x_pos = 0; x_pos < x_end; x_pos++) {
dst_pic_block_same_info[2][pos] =
(!dst_pic_block_same_info[0][pos] &&
!dst_pic_block_same_info[1][pos]) ||
(((x_pos & size_minus1) == 0) && ((y_pos & size_minus1) == 0));
(((x_pos & size_minus_1) == 0) && ((y_pos & size_minus_1) == 0));
pos++;
}
pos += block_size - 1;
@ -276,13 +327,25 @@ int av1_hash_is_horizontal_perfect(const YV12_BUFFER_CONFIG *picture,
const int stride = picture->y_stride;
const uint8_t *p = picture->y_buffer + y_start * stride + x_start;
for (int i = 0; i < block_size; i++) {
for (int j = 1; j < block_size; j++) {
if (p[j] != p[0]) {
return 0;
if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
const uint16_t *p16 = CONVERT_TO_SHORTPTR(p);
for (int i = 0; i < block_size; i++) {
for (int j = 1; j < block_size; j++) {
if (p16[j] != p16[0]) {
return 0;
}
}
p16 += stride;
}
} else {
for (int i = 0; i < block_size; i++) {
for (int j = 1; j < block_size; j++) {
if (p[j] != p[0]) {
return 0;
}
}
p += stride;
}
p += stride;
}
return 1;
@ -293,26 +356,38 @@ int av1_hash_is_vertical_perfect(const YV12_BUFFER_CONFIG *picture,
const int stride = picture->y_stride;
const uint8_t *p = picture->y_buffer + y_start * stride + x_start;
for (int i = 0; i < block_size; i++) {
for (int j = 1; j < block_size; j++) {
if (p[j * stride + i] != p[i]) {
return 0;
if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
const uint16_t *p16 = CONVERT_TO_SHORTPTR(p);
for (int i = 0; i < block_size; i++) {
for (int j = 1; j < block_size; j++) {
if (p16[j * stride + i] != p16[i]) {
return 0;
}
}
}
} else {
for (int i = 0; i < block_size; i++) {
for (int j = 1; j < block_size; j++) {
if (p[j * stride + i] != p[i]) {
return 0;
}
}
}
}
return 1;
}
// global buffer for hash value calculation of a block
// used only in av1_get_block_hash_value()
static uint32_t hash_value_buffer[2][2][1024]; // [first hash/second hash]
// [two buffers used ping-pong]
// [num of 2x2 blocks in 64x64]
#define AOM_BUFFER_SIZE_FOR_BLOCK_HASH (4096)
// [first hash/second hash]
// [two buffers used ping-pong]
// [num of 2x2 blocks in 128x128]
static uint32_t hash_value_buffer[2][2][AOM_BUFFER_SIZE_FOR_BLOCK_HASH];
void av1_get_block_hash_value(uint8_t *y_src, int stride, int block_size,
uint32_t *hash_value1, uint32_t *hash_value2) {
uint8_t pixel_to_hash[4];
uint32_t *hash_value1, uint32_t *hash_value2,
int use_highbitdepth) {
uint32_t to_hash[4];
const int add_value = hash_block_size_to_index(block_size) << crc_bits;
assert(add_value >= 0);
@ -320,16 +395,34 @@ void av1_get_block_hash_value(uint8_t *y_src, int stride, int block_size,
// 2x2 subblock hash values in current CU
int sub_block_in_width = (block_size >> 1);
for (int y_pos = 0; y_pos < block_size; y_pos += 2) {
for (int x_pos = 0; x_pos < block_size; x_pos += 2) {
int pos = (y_pos >> 1) * sub_block_in_width + (x_pos >> 1);
get_pixels_in_1D_char_array_by_block_2x2(y_src + y_pos * stride + x_pos,
stride, pixel_to_hash);
hash_value_buffer[0][0][pos] = av1_get_crc_value(
&crc_calculator1, pixel_to_hash, sizeof(pixel_to_hash));
hash_value_buffer[1][0][pos] = av1_get_crc_value(
&crc_calculator2, pixel_to_hash, sizeof(pixel_to_hash));
if (use_highbitdepth) {
uint16_t pixel_to_hash[4];
uint16_t *y16_src = CONVERT_TO_SHORTPTR(y_src);
for (int y_pos = 0; y_pos < block_size; y_pos += 2) {
for (int x_pos = 0; x_pos < block_size; x_pos += 2) {
int pos = (y_pos >> 1) * sub_block_in_width + (x_pos >> 1);
get_pixels_in_1D_short_array_by_block_2x2(
y16_src + y_pos * stride + x_pos, stride, pixel_to_hash);
assert(pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
hash_value_buffer[0][0][pos] = av1_get_crc_value(
&crc_calculator1, (uint8_t *)pixel_to_hash, sizeof(pixel_to_hash));
hash_value_buffer[1][0][pos] = av1_get_crc_value(
&crc_calculator2, (uint8_t *)pixel_to_hash, sizeof(pixel_to_hash));
}
}
} else {
uint8_t pixel_to_hash[4];
for (int y_pos = 0; y_pos < block_size; y_pos += 2) {
for (int x_pos = 0; x_pos < block_size; x_pos += 2) {
int pos = (y_pos >> 1) * sub_block_in_width + (x_pos >> 1);
get_pixels_in_1D_char_array_by_block_2x2(y_src + y_pos * stride + x_pos,
stride, pixel_to_hash);
assert(pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
hash_value_buffer[0][0][pos] = av1_get_crc_value(
&crc_calculator1, pixel_to_hash, sizeof(pixel_to_hash));
hash_value_buffer[1][0][pos] = av1_get_crc_value(
&crc_calculator2, pixel_to_hash, sizeof(pixel_to_hash));
}
}
}
@ -349,6 +442,10 @@ void av1_get_block_hash_value(uint8_t *y_src, int stride, int block_size,
for (int x_pos = 0; x_pos < sub_block_in_width; x_pos++) {
int srcPos = (y_pos << 1) * src_sub_block_in_width + (x_pos << 1);
assert(srcPos + 1 < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
assert(srcPos + src_sub_block_in_width + 1 <
AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
assert(dst_pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
to_hash[0] = hash_value_buffer[0][src_idx][srcPos];
to_hash[1] = hash_value_buffer[0][src_idx][srcPos + 1];
to_hash[2] =
@ -378,3 +475,5 @@ void av1_get_block_hash_value(uint8_t *y_src, int stride, int block_size,
*hash_value1 = (hash_value_buffer[0][dst_idx][0] & crc_mask) + add_value;
*hash_value2 = hash_value_buffer[1][dst_idx][0];
}
#undef AOM_BUFFER_SIZE_FOR_BLOCK_HASH

View file

@ -12,7 +12,8 @@
#ifndef AV1_ENCODER_HASH_MOTION_H_
#define AV1_ENCODER_HASH_MOTION_H_
#include "./aom_config.h"
#include "config/aom_config.h"
#include "aom/aom_integer.h"
#include "aom_scale/yv12config.h"
#include "third_party/vector/vector.h"
@ -29,7 +30,9 @@ typedef struct _block_hash {
uint32_t hash_value2;
} block_hash;
typedef struct _hash_table { Vector **p_lookup_table; } hash_table;
typedef struct _hash_table {
Vector **p_lookup_table;
} hash_table;
void av1_hash_table_init(hash_table *p_hash_table);
void av1_hash_table_destroy(hash_table *p_hash_table);
@ -63,7 +66,8 @@ int av1_hash_is_horizontal_perfect(const YV12_BUFFER_CONFIG *picture,
int av1_hash_is_vertical_perfect(const YV12_BUFFER_CONFIG *picture,
int block_size, int x_start, int y_start);
void av1_get_block_hash_value(uint8_t *y_src, int stride, int block_size,
uint32_t *hash_value1, uint32_t *hash_value2);
uint32_t *hash_value1, uint32_t *hash_value2,
int use_highbitdepth);
#ifdef __cplusplus
} // extern "C"

View file

@ -9,229 +9,74 @@
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "./av1_rtcd.h"
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
#include "config/aom_config.h"
#include "config/av1_rtcd.h"
#include "config/aom_dsp_rtcd.h"
#include "av1/common/idct.h"
#include "av1/encoder/hybrid_fwd_txfm.h"
#if CONFIG_CHROMA_2X2
static void fwd_txfm_2x2(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
tran_high_t a1 = src_diff[0];
tran_high_t b1 = src_diff[1];
tran_high_t c1 = src_diff[diff_stride];
tran_high_t d1 = src_diff[1 + diff_stride];
/* 4-point reversible, orthonormal Walsh-Hadamard in 3.5 adds, 0.5 shifts per
pixel. */
void av1_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride) {
int i;
tran_high_t a1, b1, c1, d1, e1;
const int16_t *ip_pass0 = input;
const tran_low_t *ip = NULL;
tran_low_t *op = output;
tran_high_t a2 = a1 + c1;
tran_high_t b2 = b1 + d1;
tran_high_t c2 = a1 - c1;
tran_high_t d2 = b1 - d1;
for (i = 0; i < 4; i++) {
a1 = ip_pass0[0 * stride];
b1 = ip_pass0[1 * stride];
c1 = ip_pass0[2 * stride];
d1 = ip_pass0[3 * stride];
a1 = a2 + b2;
b1 = a2 - b2;
c1 = c2 + d2;
d1 = c2 - d2;
a1 += b1;
d1 = d1 - c1;
e1 = (a1 - d1) >> 1;
b1 = e1 - b1;
c1 = e1 - c1;
a1 -= c1;
d1 += b1;
op[0] = (tran_low_t)a1;
op[4] = (tran_low_t)c1;
op[8] = (tran_low_t)d1;
op[12] = (tran_low_t)b1;
coeff[0] = (tran_low_t)(4 * a1);
coeff[1] = (tran_low_t)(4 * b1);
coeff[2] = (tran_low_t)(4 * c1);
coeff[3] = (tran_low_t)(4 * d1);
(void)txfm_param;
}
#endif
static void fwd_txfm_4x4(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
if (txfm_param->lossless) {
assert(txfm_param->tx_type == DCT_DCT);
av1_fwht4x4(src_diff, coeff, diff_stride);
return;
ip_pass0++;
op++;
}
ip = output;
op = output;
#if CONFIG_LGT || CONFIG_DAALA_DCT4
// only C version has LGTs
av1_fht4x4_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht4x4(src_diff, coeff, diff_stride, txfm_param);
#endif
}
for (i = 0; i < 4; i++) {
a1 = ip[0];
b1 = ip[1];
c1 = ip[2];
d1 = ip[3];
static void fwd_txfm_4x8(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT
av1_fht4x8_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht4x8(src_diff, coeff, diff_stride, txfm_param);
#endif
}
a1 += b1;
d1 -= c1;
e1 = (a1 - d1) >> 1;
b1 = e1 - b1;
c1 = e1 - c1;
a1 -= c1;
d1 += b1;
op[0] = (tran_low_t)(a1 * UNIT_QUANT_FACTOR);
op[1] = (tran_low_t)(c1 * UNIT_QUANT_FACTOR);
op[2] = (tran_low_t)(d1 * UNIT_QUANT_FACTOR);
op[3] = (tran_low_t)(b1 * UNIT_QUANT_FACTOR);
static void fwd_txfm_8x4(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT
av1_fht8x4_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht8x4(src_diff, coeff, diff_stride, txfm_param);
#endif
}
static void fwd_txfm_8x16(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT
av1_fht8x16_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht8x16(src_diff, coeff, diff_stride, txfm_param);
#endif
}
static void fwd_txfm_16x8(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT
av1_fht16x8_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht16x8(src_diff, coeff, diff_stride, txfm_param);
#endif
}
static void fwd_txfm_16x32(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
av1_fht16x32(src_diff, coeff, diff_stride, txfm_param);
}
static void fwd_txfm_32x16(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
av1_fht32x16(src_diff, coeff, diff_stride, txfm_param);
}
static void fwd_txfm_8x8(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT || CONFIG_DAALA_DCT8
av1_fht8x8_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht8x8(src_diff, coeff, diff_stride, txfm_param);
#endif
}
static void fwd_txfm_16x16(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_DAALA_DCT16
av1_fht16x16_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht16x16(src_diff, coeff, diff_stride, txfm_param);
#endif // CONFIG_DAALA_DCT16
}
static void fwd_txfm_32x32(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_MRC_TX
// MRC_DCT currently only has a C implementation
if (txfm_param->tx_type == MRC_DCT) {
av1_fht32x32_c(src_diff, coeff, diff_stride, txfm_param);
return;
ip += 4;
op += 4;
}
#endif // CONFIG_MRC_TX
av1_fht32x32(src_diff, coeff, diff_stride, txfm_param);
}
#if CONFIG_TX64X64
static void fwd_txfm_64x64(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_EXT_TX
if (txfm_param->tx_type == IDTX)
av1_fwd_idtx_c(src_diff, coeff, diff_stride, 64, 64, txfm_param->tx_type);
else
#endif
av1_fht64x64(src_diff, coeff, diff_stride, txfm_param);
void av1_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output,
int stride) {
av1_fwht4x4_c(input, output, stride);
}
static void fwd_txfm_32x64(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_EXT_TX
if (txfm_param->tx_type == IDTX)
av1_fwd_idtx_c(src_diff, coeff, diff_stride, 32, 64, txfm_param->tx_type);
else
#endif
av1_fht32x64(src_diff, coeff, diff_stride, txfm_param);
}
static void fwd_txfm_64x32(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_EXT_TX
if (txfm_param->tx_type == IDTX)
av1_fwd_idtx_c(src_diff, coeff, diff_stride, 64, 32, txfm_param->tx_type);
else
#endif
av1_fht64x32(src_diff, coeff, diff_stride, txfm_param);
}
#endif // CONFIG_TX64X64
#if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX)
static void fwd_txfm_16x4(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT
av1_fht16x4_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht16x4(src_diff, coeff, diff_stride, txfm_param);
#endif
}
static void fwd_txfm_4x16(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT
av1_fht4x16_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht4x16(src_diff, coeff, diff_stride, txfm_param);
#endif
}
static void fwd_txfm_32x8(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT
av1_fht32x8_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht32x8(src_diff, coeff, diff_stride, txfm_param);
#endif
}
static void fwd_txfm_8x32(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
#if CONFIG_LGT
av1_fht8x32_c(src_diff, coeff, diff_stride, txfm_param);
#else
av1_fht8x32(src_diff, coeff, diff_stride, txfm_param);
#endif
}
#endif
#if CONFIG_CHROMA_2X2
static void highbd_fwd_txfm_2x2(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
tran_high_t a1 = src_diff[0];
tran_high_t b1 = src_diff[1];
tran_high_t c1 = src_diff[diff_stride];
tran_high_t d1 = src_diff[1 + diff_stride];
tran_high_t a2 = a1 + c1;
tran_high_t b2 = b1 + d1;
tran_high_t c2 = a1 - c1;
tran_high_t d2 = b1 - d1;
a1 = a2 + b2;
b1 = a2 - b2;
c1 = c2 + d2;
d1 = c2 - d2;
coeff[0] = (tran_low_t)(4 * a1);
coeff[1] = (tran_low_t)(4 * b1);
coeff[2] = (tran_low_t)(4 * c1);
coeff[3] = (tran_low_t)(4 * d1);
(void)txfm_param;
}
#endif
static void highbd_fwd_txfm_4x4(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
int32_t *dst_coeff = (int32_t *)coeff;
@ -243,22 +88,6 @@ static void highbd_fwd_txfm_4x4(const int16_t *src_diff, tran_low_t *coeff,
return;
}
switch (tx_type) {
case DCT_DCT:
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
// fallthrough intended
av1_fwd_txfm2d_4x4(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#if CONFIG_EXT_TX
case FLIPADST_DCT:
case DCT_FLIPADST:
case FLIPADST_FLIPADST:
case ADST_FLIPADST:
case FLIPADST_ADST:
// fallthrough intended
av1_fwd_txfm2d_4x4(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
// use the c version for anything including identity for now
case V_DCT:
case H_DCT:
@ -267,11 +96,11 @@ static void highbd_fwd_txfm_4x4(const int16_t *src_diff, tran_low_t *coeff,
case V_FLIPADST:
case H_FLIPADST:
case IDTX:
// fallthrough intended
av1_fwd_txfm2d_4x4_c(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#endif // CONFIG_EXT_TX
default: assert(0);
default:
av1_fwd_txfm2d_4x4(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
}
}
@ -317,28 +146,40 @@ static void highbd_fwd_txfm_32x16(const int16_t *src_diff, tran_low_t *coeff,
txfm_param->bd);
}
static void highbd_fwd_txfm_16x4(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
int32_t *dst_coeff = (int32_t *)coeff;
av1_fwd_txfm2d_16x4_c(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
txfm_param->bd);
}
static void highbd_fwd_txfm_4x16(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
int32_t *dst_coeff = (int32_t *)coeff;
av1_fwd_txfm2d_4x16_c(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
txfm_param->bd);
}
static void highbd_fwd_txfm_32x8(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
int32_t *dst_coeff = (int32_t *)coeff;
av1_fwd_txfm2d_32x8_c(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
txfm_param->bd);
}
static void highbd_fwd_txfm_8x32(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
int32_t *dst_coeff = (int32_t *)coeff;
av1_fwd_txfm2d_8x32_c(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
txfm_param->bd);
}
static void highbd_fwd_txfm_8x8(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
int32_t *dst_coeff = (int32_t *)coeff;
const TX_TYPE tx_type = txfm_param->tx_type;
const int bd = txfm_param->bd;
switch (tx_type) {
case DCT_DCT:
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
// fallthrough intended
av1_fwd_txfm2d_8x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#if CONFIG_EXT_TX
case FLIPADST_DCT:
case DCT_FLIPADST:
case FLIPADST_FLIPADST:
case ADST_FLIPADST:
case FLIPADST_ADST:
// fallthrough intended
av1_fwd_txfm2d_8x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
// use the c version for anything including identity for now
case V_DCT:
case H_DCT:
@ -347,11 +188,11 @@ static void highbd_fwd_txfm_8x8(const int16_t *src_diff, tran_low_t *coeff,
case V_FLIPADST:
case H_FLIPADST:
case IDTX:
// fallthrough intended
av1_fwd_txfm2d_8x8_c(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#endif // CONFIG_EXT_TX
default: assert(0);
default:
av1_fwd_txfm2d_8x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
}
}
@ -361,22 +202,6 @@ static void highbd_fwd_txfm_16x16(const int16_t *src_diff, tran_low_t *coeff,
const TX_TYPE tx_type = txfm_param->tx_type;
const int bd = txfm_param->bd;
switch (tx_type) {
case DCT_DCT:
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
// fallthrough intended
av1_fwd_txfm2d_16x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#if CONFIG_EXT_TX
case FLIPADST_DCT:
case DCT_FLIPADST:
case FLIPADST_FLIPADST:
case ADST_FLIPADST:
case FLIPADST_ADST:
// fallthrough intended
av1_fwd_txfm2d_16x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
// use the c version for anything including identity for now
case V_DCT:
case H_DCT:
@ -385,11 +210,11 @@ static void highbd_fwd_txfm_16x16(const int16_t *src_diff, tran_low_t *coeff,
case V_FLIPADST:
case H_FLIPADST:
case IDTX:
// fallthrough intended
av1_fwd_txfm2d_16x16_c(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#endif // CONFIG_EXT_TX
default: assert(0);
default:
av1_fwd_txfm2d_16x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
}
}
@ -399,22 +224,6 @@ static void highbd_fwd_txfm_32x32(const int16_t *src_diff, tran_low_t *coeff,
const TX_TYPE tx_type = txfm_param->tx_type;
const int bd = txfm_param->bd;
switch (tx_type) {
case DCT_DCT:
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
// fallthrough intended
av1_fwd_txfm2d_32x32(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#if CONFIG_EXT_TX
case FLIPADST_DCT:
case DCT_FLIPADST:
case FLIPADST_FLIPADST:
case ADST_FLIPADST:
case FLIPADST_ADST:
// fallthrough intended
av1_fwd_txfm2d_32x32(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
// use the c version for anything including identity for now
case V_DCT:
case H_DCT:
@ -423,206 +232,72 @@ static void highbd_fwd_txfm_32x32(const int16_t *src_diff, tran_low_t *coeff,
case V_FLIPADST:
case H_FLIPADST:
case IDTX:
// fallthrough intended
av1_fwd_txfm2d_32x32_c(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#endif // CONFIG_EXT_TX
default: assert(0);
default:
av1_fwd_txfm2d_32x32(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
}
}
#if CONFIG_TX64X64
static void highbd_fwd_txfm_32x64(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
assert(txfm_param->tx_type == DCT_DCT);
int32_t *dst_coeff = (int32_t *)coeff;
const TX_TYPE tx_type = txfm_param->tx_type;
const int bd = txfm_param->bd;
switch (tx_type) {
case DCT_DCT:
av1_fwd_txfm2d_32x64_c(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#if CONFIG_EXT_TX
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
case FLIPADST_DCT:
case DCT_FLIPADST:
case FLIPADST_FLIPADST:
case ADST_FLIPADST:
case FLIPADST_ADST:
case V_DCT:
case H_DCT:
case V_ADST:
case H_ADST:
case V_FLIPADST:
case H_FLIPADST:
// TODO(sarahparker)
// I've deleted the 64x64 implementations that existed in lieu
// of adst, flipadst and identity for simplicity but will bring back
// in a later change. This shouldn't impact performance since
// DCT_DCT is the only extended type currently allowed for 64x64,
// as dictated by get_ext_tx_set_type in blockd.h.
av1_fwd_txfm2d_32x64_c(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
break;
case IDTX:
av1_fwd_idtx_c(src_diff, dst_coeff, diff_stride, 32, 64, tx_type);
break;
#endif // CONFIG_EXT_TX
default: assert(0); break;
}
av1_fwd_txfm2d_32x64_c(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
}
static void highbd_fwd_txfm_64x32(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
assert(txfm_param->tx_type == DCT_DCT);
int32_t *dst_coeff = (int32_t *)coeff;
const TX_TYPE tx_type = txfm_param->tx_type;
const int bd = txfm_param->bd;
switch (tx_type) {
case DCT_DCT:
av1_fwd_txfm2d_64x32_c(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#if CONFIG_EXT_TX
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
case FLIPADST_DCT:
case DCT_FLIPADST:
case FLIPADST_FLIPADST:
case ADST_FLIPADST:
case FLIPADST_ADST:
case V_DCT:
case H_DCT:
case V_ADST:
case H_ADST:
case V_FLIPADST:
case H_FLIPADST:
// TODO(sarahparker)
// I've deleted the 64x64 implementations that existed in lieu
// of adst, flipadst and identity for simplicity but will bring back
// in a later change. This shouldn't impact performance since
// DCT_DCT is the only extended type currently allowed for 64x64,
// as dictated by get_ext_tx_set_type in blockd.h.
av1_fwd_txfm2d_64x32_c(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
break;
case IDTX:
av1_fwd_idtx_c(src_diff, dst_coeff, diff_stride, 64, 32, tx_type);
break;
#endif // CONFIG_EXT_TX
default: assert(0); break;
}
av1_fwd_txfm2d_64x32_c(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
}
static void highbd_fwd_txfm_16x64(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
assert(txfm_param->tx_type == DCT_DCT);
int32_t *dst_coeff = (int32_t *)coeff;
const int bd = txfm_param->bd;
av1_fwd_txfm2d_16x64_c(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
}
static void highbd_fwd_txfm_64x16(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
assert(txfm_param->tx_type == DCT_DCT);
int32_t *dst_coeff = (int32_t *)coeff;
const int bd = txfm_param->bd;
av1_fwd_txfm2d_64x16_c(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
}
static void highbd_fwd_txfm_64x64(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
assert(txfm_param->tx_type == DCT_DCT);
int32_t *dst_coeff = (int32_t *)coeff;
const TX_TYPE tx_type = txfm_param->tx_type;
const int bd = txfm_param->bd;
switch (tx_type) {
case DCT_DCT:
av1_fwd_txfm2d_64x64(src_diff, dst_coeff, diff_stride, tx_type, bd);
break;
#if CONFIG_EXT_TX
case ADST_DCT:
case DCT_ADST:
case ADST_ADST:
case FLIPADST_DCT:
case DCT_FLIPADST:
case FLIPADST_FLIPADST:
case ADST_FLIPADST:
case FLIPADST_ADST:
case V_DCT:
case H_DCT:
case V_ADST:
case H_ADST:
case V_FLIPADST:
case H_FLIPADST:
// TODO(sarahparker)
// I've deleted the 64x64 implementations that existed in lieu
// of adst, flipadst and identity for simplicity but will bring back
// in a later change. This shouldn't impact performance since
// DCT_DCT is the only extended type currently allowed for 64x64,
// as dictated by get_ext_tx_set_type in blockd.h.
av1_fwd_txfm2d_64x64_c(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
break;
case IDTX:
av1_fwd_idtx_c(src_diff, dst_coeff, diff_stride, 64, 64, tx_type);
break;
#endif // CONFIG_EXT_TX
default: assert(0); break;
}
av1_fwd_txfm2d_64x64(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
}
#endif // CONFIG_TX64X64
void av1_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff, int diff_stride,
TxfmParam *txfm_param) {
const TX_SIZE tx_size = txfm_param->tx_size;
#if CONFIG_LGT_FROM_PRED
if (txfm_param->use_lgt) {
// if use_lgt is 1, it will override tx_type
assert(is_lgt_allowed(txfm_param->mode, tx_size));
flgt2d_from_pred_c(src_diff, coeff, diff_stride, txfm_param);
return;
}
#endif // CONFIG_LGT_FROM_PRED
switch (tx_size) {
#if CONFIG_TX64X64
case TX_64X64:
fwd_txfm_64x64(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_32X64:
fwd_txfm_32x64(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_64X32:
fwd_txfm_64x32(src_diff, coeff, diff_stride, txfm_param);
break;
#endif // CONFIG_TX64X64
case TX_32X32:
fwd_txfm_32x32(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_16X16:
fwd_txfm_16x16(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_8X8: fwd_txfm_8x8(src_diff, coeff, diff_stride, txfm_param); break;
case TX_4X8: fwd_txfm_4x8(src_diff, coeff, diff_stride, txfm_param); break;
case TX_8X4: fwd_txfm_8x4(src_diff, coeff, diff_stride, txfm_param); break;
case TX_8X16:
fwd_txfm_8x16(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_16X8:
fwd_txfm_16x8(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_16X32:
fwd_txfm_16x32(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_32X16:
fwd_txfm_32x16(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_4X4: fwd_txfm_4x4(src_diff, coeff, diff_stride, txfm_param); break;
#if CONFIG_CHROMA_2X2
case TX_2X2: fwd_txfm_2x2(src_diff, coeff, diff_stride, txfm_param); break;
#endif
#if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX)
case TX_4X16:
fwd_txfm_4x16(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_16X4:
fwd_txfm_16x4(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_8X32:
fwd_txfm_8x32(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_32X8:
fwd_txfm_32x8(src_diff, coeff, diff_stride, txfm_param);
break;
#endif
default: assert(0); break;
}
if (txfm_param->bd == 8)
av1_lowbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
else
av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
}
void av1_lowbd_fwd_txfm_c(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
}
void av1_highbd_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param) {
assert(av1_ext_tx_used[txfm_param->tx_set_type][txfm_param->tx_type]);
const TX_SIZE tx_size = txfm_param->tx_size;
switch (tx_size) {
#if CONFIG_TX64X64
case TX_64X64:
highbd_fwd_txfm_64x64(src_diff, coeff, diff_stride, txfm_param);
break;
@ -632,7 +307,12 @@ void av1_highbd_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff,
case TX_64X32:
highbd_fwd_txfm_64x32(src_diff, coeff, diff_stride, txfm_param);
break;
#endif // CONFIG_TX64X64
case TX_16X64:
highbd_fwd_txfm_16x64(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_64X16:
highbd_fwd_txfm_64x16(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_32X32:
highbd_fwd_txfm_32x32(src_diff, coeff, diff_stride, txfm_param);
break;
@ -663,11 +343,18 @@ void av1_highbd_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff,
case TX_4X4:
highbd_fwd_txfm_4x4(src_diff, coeff, diff_stride, txfm_param);
break;
#if CONFIG_CHROMA_2X2
case TX_2X2:
highbd_fwd_txfm_2x2(src_diff, coeff, diff_stride, txfm_param);
case TX_4X16:
highbd_fwd_txfm_4x16(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_16X4:
highbd_fwd_txfm_16x4(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_8X32:
highbd_fwd_txfm_8x32(src_diff, coeff, diff_stride, txfm_param);
break;
case TX_32X8:
highbd_fwd_txfm_32x8(src_diff, coeff, diff_stride, txfm_param);
break;
#endif
default: assert(0); break;
}
}

View file

@ -12,7 +12,7 @@
#ifndef AV1_ENCODER_HYBRID_FWD_TXFM_H_
#define AV1_ENCODER_HYBRID_FWD_TXFM_H_
#include "./aom_config.h"
#include "config/aom_config.h"
#ifdef __cplusplus
extern "C" {

View file

@ -23,25 +23,23 @@
#define RENAME_(x, y) AV1_K_MEANS_RENAME(x, y)
#define RENAME(x) RENAME_(x, AV1_K_MEANS_DIM)
static float RENAME(calc_dist)(const float *p1, const float *p2) {
float dist = 0;
int i;
for (i = 0; i < AV1_K_MEANS_DIM; ++i) {
const float diff = p1[i] - p2[i];
static int RENAME(calc_dist)(const int *p1, const int *p2) {
int dist = 0;
for (int i = 0; i < AV1_K_MEANS_DIM; ++i) {
const int diff = p1[i] - p2[i];
dist += diff * diff;
}
return dist;
}
void RENAME(av1_calc_indices)(const float *data, const float *centroids,
void RENAME(av1_calc_indices)(const int *data, const int *centroids,
uint8_t *indices, int n, int k) {
int i, j;
for (i = 0; i < n; ++i) {
float min_dist = RENAME(calc_dist)(data + i * AV1_K_MEANS_DIM, centroids);
for (int i = 0; i < n; ++i) {
int min_dist = RENAME(calc_dist)(data + i * AV1_K_MEANS_DIM, centroids);
indices[i] = 0;
for (j = 1; j < k; ++j) {
const float this_dist = RENAME(calc_dist)(
data + i * AV1_K_MEANS_DIM, centroids + j * AV1_K_MEANS_DIM);
for (int j = 1; j < k; ++j) {
const int this_dist = RENAME(calc_dist)(data + i * AV1_K_MEANS_DIM,
centroids + j * AV1_K_MEANS_DIM);
if (this_dist < min_dist) {
min_dist = this_dist;
indices[i] = j;
@ -50,19 +48,16 @@ void RENAME(av1_calc_indices)(const float *data, const float *centroids,
}
}
static void RENAME(calc_centroids)(const float *data, float *centroids,
static void RENAME(calc_centroids)(const int *data, int *centroids,
const uint8_t *indices, int n, int k) {
int i, j, index;
int count[PALETTE_MAX_SIZE];
int i, j;
int count[PALETTE_MAX_SIZE] = { 0 };
unsigned int rand_state = (unsigned int)data[0];
assert(n <= 32768);
memset(count, 0, sizeof(count[0]) * k);
memset(centroids, 0, sizeof(centroids[0]) * k * AV1_K_MEANS_DIM);
for (i = 0; i < n; ++i) {
index = indices[i];
const int index = indices[i];
assert(index < k);
++count[index];
for (j = 0; j < AV1_K_MEANS_DIM; ++j) {
@ -76,43 +71,35 @@ static void RENAME(calc_centroids)(const float *data, float *centroids,
data + (lcg_rand16(&rand_state) % n) * AV1_K_MEANS_DIM,
sizeof(centroids[0]) * AV1_K_MEANS_DIM);
} else {
const float norm = 1.0f / count[i];
for (j = 0; j < AV1_K_MEANS_DIM; ++j)
centroids[i * AV1_K_MEANS_DIM + j] *= norm;
for (j = 0; j < AV1_K_MEANS_DIM; ++j) {
centroids[i * AV1_K_MEANS_DIM + j] =
DIVIDE_AND_ROUND(centroids[i * AV1_K_MEANS_DIM + j], count[i]);
}
}
}
// Round to nearest integers.
for (i = 0; i < k * AV1_K_MEANS_DIM; ++i) {
centroids[i] = roundf(centroids[i]);
}
}
static float RENAME(calc_total_dist)(const float *data, const float *centroids,
const uint8_t *indices, int n, int k) {
float dist = 0;
int i;
static int64_t RENAME(calc_total_dist)(const int *data, const int *centroids,
const uint8_t *indices, int n, int k) {
int64_t dist = 0;
(void)k;
for (i = 0; i < n; ++i)
for (int i = 0; i < n; ++i) {
dist += RENAME(calc_dist)(data + i * AV1_K_MEANS_DIM,
centroids + indices[i] * AV1_K_MEANS_DIM);
}
return dist;
}
void RENAME(av1_k_means)(const float *data, float *centroids, uint8_t *indices,
void RENAME(av1_k_means)(const int *data, int *centroids, uint8_t *indices,
int n, int k, int max_itr) {
int i;
float this_dist;
float pre_centroids[2 * PALETTE_MAX_SIZE];
int pre_centroids[2 * PALETTE_MAX_SIZE];
uint8_t pre_indices[MAX_SB_SQUARE];
RENAME(av1_calc_indices)(data, centroids, indices, n, k);
this_dist = RENAME(calc_total_dist)(data, centroids, indices, n, k);
int64_t this_dist = RENAME(calc_total_dist)(data, centroids, indices, n, k);
for (i = 0; i < max_itr; ++i) {
const float pre_dist = this_dist;
for (int i = 0; i < max_itr; ++i) {
const int64_t pre_dist = this_dist;
memcpy(pre_centroids, centroids,
sizeof(pre_centroids[0]) * k * AV1_K_MEANS_DIM);
memcpy(pre_indices, indices, sizeof(pre_indices[0]) * n);
@ -132,6 +119,5 @@ void RENAME(av1_k_means)(const float *data, float *centroids, uint8_t *indices,
break;
}
}
#undef RENAME_
#undef RENAME

View file

@ -1,107 +0,0 @@
/*
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
/* clang-format off */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include "aom_dsp/bitwriter.h"
#include "av1/common/odintrin.h"
#include "av1/common/pvq.h"
#include "pvq_encoder.h"
static void aom_encode_pvq_split(aom_writer *w, od_pvq_codeword_ctx *adapt,
int count, int sum, int ctx) {
int shift;
int rest;
int fctx;
if (sum == 0) return;
shift = OD_MAXI(0, OD_ILOG(sum) - 3);
if (shift) {
rest = count & ((1 << shift) - 1);
count >>= shift;
sum >>= shift;
}
fctx = 7*ctx + sum - 1;
aom_write_symbol_pvq(w, count, adapt->pvq_split_cdf[fctx], sum + 1);
if (shift) aom_write_literal(w, rest, shift);
}
void aom_encode_band_pvq_splits(aom_writer *w, od_pvq_codeword_ctx *adapt,
const int *y, int n, int k, int level) {
int mid;
int i;
int count_right;
if (n <= 1 || k == 0) return;
if (k == 1 && n <= 16) {
int cdf_id;
int pos;
cdf_id = od_pvq_k1_ctx(n, level == 0);
for (pos = 0; !y[pos]; pos++);
OD_ASSERT(pos < n);
aom_write_symbol_pvq(w, pos, adapt->pvq_k1_cdf[cdf_id], n);
}
else {
mid = n >> 1;
count_right = k;
for (i = 0; i < mid; i++) count_right -= abs(y[i]);
aom_encode_pvq_split(w, adapt, count_right, k, od_pvq_size_ctx(n));
aom_encode_band_pvq_splits(w, adapt, y, mid, k - count_right, level + 1);
aom_encode_band_pvq_splits(w, adapt, y + mid, n - mid, count_right,
level + 1);
}
}
/** Encodes the tail of a Laplace-distributed variable, i.e. it doesn't
* do anything special for the zero case.
*
* @param [in,out] enc range encoder
* @param [in] x variable to encode (has to be positive)
* @param [in] decay decay factor of the distribution in Q8 format,
* i.e. pdf ~= decay^x
*/
void aom_laplace_encode_special(aom_writer *w, int x, unsigned decay) {
int shift;
int xs;
int sym;
const uint16_t *cdf;
shift = 0;
/* We don't want a large decay value because that would require too many
symbols. */
while (decay > 235) {
decay = (decay*decay + 128) >> 8;
shift++;
}
decay = OD_MINI(decay, 254);
decay = OD_MAXI(decay, 2);
xs = x >> shift;
cdf = EXP_CDF_TABLE[(decay + 1) >> 1];
OD_LOG((OD_LOG_PVQ, OD_LOG_DEBUG, "decay = %d", decay));
do {
sym = OD_MINI(xs, 15);
{
int i;
OD_LOG((OD_LOG_PVQ, OD_LOG_DEBUG, "%d %d %d %d %d\n", x, xs, shift,
sym, max));
for (i = 0; i < 16; i++) {
OD_LOG_PARTIAL((OD_LOG_PVQ, OD_LOG_DEBUG, "%d ", cdf[i]));
}
OD_LOG_PARTIAL((OD_LOG_PVQ, OD_LOG_DEBUG, "\n"));
}
aom_write_cdf(w, sym, cdf, 16);
xs -= 15;
} while (sym >= 15);
if (shift) aom_write_literal(w, x & ((1 << shift) - 1), shift);
}

View file

@ -11,10 +11,9 @@
#include <assert.h>
#include <stdlib.h>
#include "./aom_config.h"
#include "config/aom_config.h"
#include "av1/common/common.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/extend.h"
#include "av1/encoder/lookahead.h"
@ -42,14 +41,9 @@ void av1_lookahead_destroy(struct lookahead_ctx *ctx) {
}
}
struct lookahead_ctx *av1_lookahead_init(unsigned int width,
unsigned int height,
unsigned int subsampling_x,
unsigned int subsampling_y,
#if CONFIG_HIGHBITDEPTH
int use_highbitdepth,
#endif
unsigned int depth) {
struct lookahead_ctx *av1_lookahead_init(
unsigned int width, unsigned int height, unsigned int subsampling_x,
unsigned int subsampling_y, int use_highbitdepth, unsigned int depth) {
struct lookahead_ctx *ctx = NULL;
// Clamp the lookahead queue depth
@ -68,10 +62,7 @@ struct lookahead_ctx *av1_lookahead_init(unsigned int width,
if (!ctx->buf) goto bail;
for (i = 0; i < depth; i++)
if (aom_alloc_frame_buffer(&ctx->buf[i].img, width, height, subsampling_x,
subsampling_y,
#if CONFIG_HIGHBITDEPTH
use_highbitdepth,
#endif
subsampling_y, use_highbitdepth,
AOM_BORDER_IN_PIXELS, legacy_byte_alignment))
goto bail;
}
@ -84,10 +75,7 @@ bail:
#define USE_PARTIAL_COPY 0
int av1_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int64_t ts_start, int64_t ts_end,
#if CONFIG_HIGHBITDEPTH
int use_highbitdepth,
#endif
int64_t ts_start, int64_t ts_end, int use_highbitdepth,
aom_enc_frame_flags_t flags) {
struct lookahead_entry *buf;
#if USE_PARTIAL_COPY
@ -160,10 +148,7 @@ int av1_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
YV12_BUFFER_CONFIG new_img;
memset(&new_img, 0, sizeof(new_img));
if (aom_alloc_frame_buffer(&new_img, width, height, subsampling_x,
subsampling_y,
#if CONFIG_HIGHBITDEPTH
use_highbitdepth,
#endif
subsampling_y, use_highbitdepth,
AOM_BORDER_IN_PIXELS, 0))
return 1;
aom_free_frame_buffer(&buf->img);

View file

@ -44,14 +44,9 @@ struct lookahead_ctx {
* The lookahead stage is a queue of frame buffers on which some analysis
* may be done when buffers are enqueued.
*/
struct lookahead_ctx *av1_lookahead_init(unsigned int width,
unsigned int height,
unsigned int subsampling_x,
unsigned int subsampling_y,
#if CONFIG_HIGHBITDEPTH
int use_highbitdepth,
#endif
unsigned int depth);
struct lookahead_ctx *av1_lookahead_init(
unsigned int width, unsigned int height, unsigned int subsampling_x,
unsigned int subsampling_y, int use_highbitdepth, unsigned int depth);
/**\brief Destroys the lookahead stage
*/
@ -73,10 +68,7 @@ void av1_lookahead_destroy(struct lookahead_ctx *ctx);
* \param[in] active_map Map that specifies which macroblock is active
*/
int av1_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int64_t ts_start, int64_t ts_end,
#if CONFIG_HIGHBITDEPTH
int use_highbitdepth,
#endif
int64_t ts_start, int64_t ts_end, int use_highbitdepth,
aom_enc_frame_flags_t flags);
/**\brief Get the next source buffer to encode

View file

@ -11,8 +11,8 @@
#include <limits.h>
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"
#include "config/aom_dsp_rtcd.h"
#include "aom_dsp/aom_dsp_common.h"
#include "aom_mem/aom_mem.h"
@ -47,32 +47,28 @@ static unsigned int do_16x16_motion_iteration(AV1_COMP *cpi, const MV *ref_mv,
av1_hex_search(x, &ref_full, step_param, x->errorperbit, 0,
cond_cost_list(cpi, cost_list), &v_fn_ptr, 0, ref_mv);
// Try sub-pixel MC
// if (bestsme > error_thresh && bestsme < INT_MAX)
#if CONFIG_AMVR
if (cpi->common.cur_frame_mv_precision_level == 1) {
// Try sub-pixel MC
// if (bestsme > error_thresh && bestsme < INT_MAX)
if (cpi->common.cur_frame_force_integer_mv == 1) {
x->best_mv.as_mv.row *= 8;
x->best_mv.as_mv.col *= 8;
} else {
#else
{
#endif
int distortion;
unsigned int sse;
cpi->find_fractional_mv_step(x, ref_mv, cpi->common.allow_high_precision_mv,
x->errorperbit, &v_fn_ptr, 0,
mv_sf->subpel_iters_per_step,
cond_cost_list(cpi, cost_list), NULL, NULL,
&distortion, &sse, NULL, NULL, 0, 0, 0, 0, 0);
cpi->find_fractional_mv_step(
x, &cpi->common, mb_row, mb_col, ref_mv,
cpi->common.allow_high_precision_mv, x->errorperbit, &v_fn_ptr, 0,
mv_sf->subpel_iters_per_step, cond_cost_list(cpi, cost_list), NULL,
NULL, &distortion, &sse, NULL, NULL, 0, 0, 0, 0, 0);
}
if (has_second_ref(&xd->mi[0]->mbmi))
xd->mi[0]->mbmi.mode = NEW_NEWMV;
if (has_second_ref(xd->mi[0]))
xd->mi[0]->mode = NEW_NEWMV;
else
xd->mi[0]->mbmi.mode = NEWMV;
xd->mi[0]->mode = NEWMV;
xd->mi[0]->mbmi.mv[0] = x->best_mv;
xd->mi[0]->mbmi.ref_frame[1] = NONE_FRAME;
xd->mi[0]->mv[0] = x->best_mv;
xd->mi[0]->ref_frame[1] = NONE_FRAME;
av1_build_inter_predictors_sby(&cpi->common, xd, mb_row, mb_col, NULL,
BLOCK_16X16);
@ -108,7 +104,7 @@ static int do_16x16_motion_search(AV1_COMP *cpi, const MV *ref_mv, int mb_row,
// If the current best reference mv is not centered on 0,0 then do a 0,0
// based search as well.
if (ref_mv->row != 0 || ref_mv->col != 0) {
MV zero_ref_mv = { 0, 0 };
MV zero_ref_mv = kZeroMv;
tmp_err = do_16x16_motion_iteration(cpi, &zero_ref_mv, mb_row, mb_col);
if (tmp_err < err) {
@ -144,14 +140,14 @@ static int find_best_16x16_intra(AV1_COMP *cpi, PREDICTION_MODE *pbest_mode) {
// calculate SATD for each intra prediction mode;
// we're intentionally not doing 4x4, we just want a rough estimate
for (mode = DC_PRED; mode <= TM_PRED; mode++) {
for (mode = DC_PRED; mode <= PAETH_PRED; mode++) {
unsigned int err;
xd->mi[0]->mbmi.mode = mode;
av1_predict_intra_block(cm, xd, 16, 16, BLOCK_16X16, mode,
x->plane[0].src.buf, x->plane[0].src.stride,
xd->plane[0].dst.buf, xd->plane[0].dst.stride, 0, 0,
0);
xd->mi[0]->mode = mode;
av1_predict_intra_block(cm, xd, 16, 16, TX_16X16, mode, 0, 0,
FILTER_INTRA_MODES, x->plane[0].src.buf,
x->plane[0].src.stride, xd->plane[0].dst.buf,
xd->plane[0].dst.stride, 0, 0, 0);
err = aom_sad16x16(x->plane[0].src.buf, x->plane[0].src.stride,
xd->plane[0].dst.buf, xd->plane[0].dst.stride);
@ -231,8 +227,8 @@ static void update_mbgraph_frame_stats(AV1_COMP *cpi,
int mb_col, mb_row, offset = 0;
int mb_y_offset = 0, arf_y_offset = 0, gld_y_offset = 0;
MV gld_top_mv = { 0, 0 };
MODE_INFO mi_local;
MV gld_top_mv = kZeroMv;
MB_MODE_INFO mi_local;
av1_zero(mi_local);
// Set up limit values for motion vectors to prevent them extending outside
@ -244,9 +240,9 @@ static void update_mbgraph_frame_stats(AV1_COMP *cpi,
xd->plane[0].pre[0].stride = buf->y_stride;
xd->plane[1].dst.stride = buf->uv_stride;
xd->mi[0] = &mi_local;
mi_local.mbmi.sb_type = BLOCK_16X16;
mi_local.mbmi.ref_frame[0] = LAST_FRAME;
mi_local.mbmi.ref_frame[1] = NONE_FRAME;
mi_local.sb_type = BLOCK_16X16;
mi_local.ref_frame[0] = LAST_FRAME;
mi_local.ref_frame[1] = NONE_FRAME;
for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
MV gld_left_mv = gld_top_mv;

View file

@ -23,10 +23,12 @@ typedef struct {
int_mv mv;
PREDICTION_MODE mode;
} m;
} ref[TOTAL_REFS_PER_FRAME];
} ref[REF_FRAMES];
} MBGRAPH_MB_STATS;
typedef struct { MBGRAPH_MB_STATS *mb_stats; } MBGRAPH_FRAME_STATS;
typedef struct {
MBGRAPH_MB_STATS *mb_stats;
} MBGRAPH_FRAME_STATS;
struct AV1_COMP;

File diff suppressed because it is too large Load diff

View file

@ -69,10 +69,9 @@ struct SPEED_FEATURES;
int av1_init_search_range(int size);
int av1_refining_search_sad(struct macroblock *x, struct mv *ref_mv,
int sad_per_bit, int distance,
const aom_variance_fn_ptr_t *fn_ptr,
const struct mv *center_mv);
int av1_refining_search_sad(struct macroblock *x, MV *ref_mv, int sad_per_bit,
int distance, const aom_variance_fn_ptr_t *fn_ptr,
const MV *center_mv);
// Runs sequence of diamond searches in smaller steps for RD.
int av1_full_pixel_diamond(const struct AV1_COMP *cpi, MACROBLOCK *x,
@ -81,24 +80,20 @@ int av1_full_pixel_diamond(const struct AV1_COMP *cpi, MACROBLOCK *x,
const aom_variance_fn_ptr_t *fn_ptr,
const MV *ref_mv, MV *dst_mv);
// Perform integral projection based motion estimation.
unsigned int av1_int_pro_motion_estimation(const struct AV1_COMP *cpi,
MACROBLOCK *x, BLOCK_SIZE bsize,
int mi_row, int mi_col);
int av1_hex_search(MACROBLOCK *x, MV *start_mv, int search_param,
int sad_per_bit, int do_init_search, int *cost_list,
const aom_variance_fn_ptr_t *vfp, int use_mvcost,
const MV *center_mv);
typedef int(fractional_mv_step_fp)(
MACROBLOCK *x, const MV *ref_mv, int allow_hp, int error_per_bit,
MACROBLOCK *x, const AV1_COMMON *const cm, int mi_row, int mi_col,
const MV *ref_mv, int allow_hp, int error_per_bit,
const aom_variance_fn_ptr_t *vfp,
int forced_stop, // 0 - full, 1 - qtr only, 2 - half only
int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
int *distortion, unsigned int *sse1, const uint8_t *second_pred,
const uint8_t *mask, int mask_stride, int invert_mask, int w, int h,
int use_upsampled_ref);
int use_accurate_subpel_search);
extern fractional_mv_step_fp av1_find_best_sub_pixel_tree;
extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned;
@ -123,52 +118,33 @@ int av1_refining_search_8p_c(MACROBLOCK *x, int error_per_bit, int search_range,
int invert_mask, const MV *center_mv,
const uint8_t *second_pred);
struct AV1_COMP;
#if CONFIG_HASH_ME
int av1_full_pixel_search(const struct AV1_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize, MV *mvp_full, int step_param,
int error_per_bit, int *cost_list, const MV *ref_mv,
int var_max, int rd, int x_pos, int y_pos, int intra);
#else
int av1_full_pixel_search(const struct AV1_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize, MV *mvp_full, int step_param,
int error_per_bit, int *cost_list, const MV *ref_mv,
int var_max, int rd);
#endif
#if CONFIG_MOTION_VAR
int av1_obmc_full_pixel_diamond(const struct AV1_COMP *cpi, MACROBLOCK *x,
MV *mvp_full, int step_param, int sadpb,
int further_steps, int do_refine,
const aom_variance_fn_ptr_t *fn_ptr,
const MV *ref_mv, MV *dst_mv, int is_second);
int av1_find_best_obmc_sub_pixel_tree_up(
MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
int error_per_bit, const aom_variance_fn_ptr_t *vfp, int forced_stop,
int iters_per_step, int *mvjcost, int *mvcost[2], int *distortion,
unsigned int *sse1, int is_second, int use_upsampled_ref);
#endif // CONFIG_MOTION_VAR
MACROBLOCK *x, const AV1_COMMON *const cm, int mi_row, int mi_col,
MV *bestmv, const MV *ref_mv, int allow_hp, int error_per_bit,
const aom_variance_fn_ptr_t *vfp, int forced_stop, int iters_per_step,
int *mvjcost, int *mvcost[2], int *distortion, unsigned int *sse1,
int is_second, int use_accurate_subpel_search);
unsigned int av1_compute_motion_cost(const struct AV1_COMP *cpi,
MACROBLOCK *const x, BLOCK_SIZE bsize,
int mi_row, int mi_col, const MV *this_mv);
unsigned int av1_refine_warped_mv(const struct AV1_COMP *cpi,
MACROBLOCK *const x, BLOCK_SIZE bsize,
int mi_row, int mi_col, int *pts0,
int *pts_inref0, int total_samples);
#ifdef __cplusplus
} // extern "C"
#endif
#if CONFIG_WARPED_MOTION
unsigned int av1_compute_motion_cost(const struct AV1_COMP *cpi,
MACROBLOCK *const x, BLOCK_SIZE bsize,
int mi_row, int mi_col, const MV *this_mv);
#if WARPED_MOTION_SORT_SAMPLES
unsigned int av1_refine_warped_mv(const struct AV1_COMP *cpi,
MACROBLOCK *const x, BLOCK_SIZE bsize,
int mi_row, int mi_col, int *pts0,
int *pts_inref0, int *pts_mv0,
int total_samples);
#else
unsigned int av1_refine_warped_mv(const struct AV1_COMP *cpi,
MACROBLOCK *const x, BLOCK_SIZE bsize,
int mi_row, int mi_col, int *pts,
int *pts_inref);
#endif // WARPED_MOTION_SORT_SAMPLES
#endif // CONFIG_WARPED_MOTION
#endif // AV1_ENCODER_MCOMP_H_

View file

@ -9,7 +9,8 @@
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "./av1_rtcd.h"
#include "config/av1_rtcd.h"
#include "aom_dsp/mips/macros_msa.h"
#define BLOCK_ERROR_BLOCKSIZE_MSA(BSize) \

View file

@ -1,436 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <assert.h>
#include "av1/common/enums.h"
#include "av1/encoder/mips/msa/fdct_msa.h"
#include "aom_dsp/mips/fwd_txfm_msa.h"
static void fadst16_cols_step1_msa(const int16_t *input, int32_t stride,
const int32_t *const0, int16_t *int_buf) {
v8i16 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15;
v8i16 tp0, tp1, tp2, tp3, g0, g1, g2, g3, g8, g9, g10, g11, h0, h1, h2, h3;
v4i32 k0, k1, k2, k3;
/* load input data */
r0 = LD_SH(input);
r15 = LD_SH(input + 15 * stride);
r7 = LD_SH(input + 7 * stride);
r8 = LD_SH(input + 8 * stride);
SLLI_4V(r0, r15, r7, r8, 2);
/* stage 1 */
LD_SW2(const0, 4, k0, k1);
LD_SW2(const0 + 8, 4, k2, k3);
MADD_BF(r15, r0, r7, r8, k0, k1, k2, k3, g0, g1, g2, g3);
r3 = LD_SH(input + 3 * stride);
r4 = LD_SH(input + 4 * stride);
r11 = LD_SH(input + 11 * stride);
r12 = LD_SH(input + 12 * stride);
SLLI_4V(r3, r4, r11, r12, 2);
LD_SW2(const0 + 4 * 4, 4, k0, k1);
LD_SW2(const0 + 4 * 6, 4, k2, k3);
MADD_BF(r11, r4, r3, r12, k0, k1, k2, k3, g8, g9, g10, g11);
/* stage 2 */
BUTTERFLY_4(g0, g2, g10, g8, tp0, tp2, tp3, tp1);
ST_SH2(tp0, tp2, int_buf, 8);
ST_SH2(tp1, tp3, int_buf + 4 * 8, 8);
LD_SW2(const0 + 4 * 8, 4, k0, k1);
k2 = LD_SW(const0 + 4 * 10);
MADD_BF(g1, g3, g9, g11, k0, k1, k2, k0, h0, h1, h2, h3);
ST_SH2(h0, h1, int_buf + 8 * 8, 8);
ST_SH2(h3, h2, int_buf + 12 * 8, 8);
r9 = LD_SH(input + 9 * stride);
r6 = LD_SH(input + 6 * stride);
r1 = LD_SH(input + stride);
r14 = LD_SH(input + 14 * stride);
SLLI_4V(r9, r6, r1, r14, 2);
LD_SW2(const0 + 4 * 11, 4, k0, k1);
LD_SW2(const0 + 4 * 13, 4, k2, k3);
MADD_BF(r9, r6, r1, r14, k0, k1, k2, k3, g0, g1, g2, g3);
ST_SH2(g1, g3, int_buf + 3 * 8, 4 * 8);
r13 = LD_SH(input + 13 * stride);
r2 = LD_SH(input + 2 * stride);
r5 = LD_SH(input + 5 * stride);
r10 = LD_SH(input + 10 * stride);
SLLI_4V(r13, r2, r5, r10, 2);
LD_SW2(const0 + 4 * 15, 4, k0, k1);
LD_SW2(const0 + 4 * 17, 4, k2, k3);
MADD_BF(r13, r2, r5, r10, k0, k1, k2, k3, h0, h1, h2, h3);
ST_SH2(h1, h3, int_buf + 11 * 8, 4 * 8);
BUTTERFLY_4(h0, h2, g2, g0, tp0, tp1, tp2, tp3);
ST_SH4(tp0, tp1, tp2, tp3, int_buf + 2 * 8, 4 * 8);
}
static void fadst16_step2_msa_helper(int16_t *int_buf, const int32_t *const0,
int16_t *out, int16_t *out_ptr) {
v8i16 tp0, tp1, tp2, tp3, g5, g7, g13, g15;
v8i16 h0, h1, h2, h3, h4, h5, h6, h7, h10, h11;
v8i16 out0, out1, out2, out3, out4, out5, out6, out7;
v8i16 out8, out9, out10, out11, out12, out13, out14, out15;
v4i32 k0, k1, k2, k3;
LD_SH2(int_buf + 3 * 8, 4 * 8, g13, g15);
LD_SH2(int_buf + 11 * 8, 4 * 8, g5, g7);
LD_SW2(const0 + 4 * 19, 4, k0, k1);
k2 = LD_SW(const0 + 4 * 21);
MADD_BF(g7, g5, g15, g13, k0, k1, k2, k0, h4, h5, h6, h7);
tp0 = LD_SH(int_buf + 4 * 8);
tp1 = LD_SH(int_buf + 5 * 8);
tp3 = LD_SH(int_buf + 10 * 8);
tp2 = LD_SH(int_buf + 14 * 8);
LD_SW2(const0 + 4 * 22, 4, k0, k1);
k2 = LD_SW(const0 + 4 * 24);
MADD_BF(tp0, tp1, tp2, tp3, k0, k1, k2, k0, out4, out6, out5, out7);
out4 = -out4;
ST_SH(out4, (out + 3 * 16));
ST_SH(out5, (out_ptr + 4 * 16));
h1 = LD_SH(int_buf + 9 * 8);
h3 = LD_SH(int_buf + 12 * 8);
MADD_BF(h1, h3, h5, h7, k0, k1, k2, k0, out12, out14, out13, out15);
out13 = -out13;
ST_SH(out12, (out + 2 * 16));
ST_SH(out13, (out_ptr + 5 * 16));
tp0 = LD_SH(int_buf);
tp1 = LD_SH(int_buf + 8);
tp2 = LD_SH(int_buf + 2 * 8);
tp3 = LD_SH(int_buf + 6 * 8);
BUTTERFLY_4(tp0, tp1, tp3, tp2, out0, out1, h11, h10);
out1 = -out1;
ST_SH(out0, (out));
ST_SH(out1, (out_ptr + 7 * 16));
h0 = LD_SH(int_buf + 8 * 8);
h2 = LD_SH(int_buf + 13 * 8);
BUTTERFLY_4(h0, h2, h6, h4, out8, out9, out11, out10);
out8 = -out8;
ST_SH(out8, (out + 16));
ST_SH(out9, (out_ptr + 6 * 16));
/* stage 4 */
LD_SW2(const0 + 4 * 25, 4, k0, k1);
LD_SW2(const0 + 4 * 27, 4, k2, k3);
MADD_SHORT(h10, h11, k1, k2, out2, out3);
ST_SH(out2, (out + 7 * 16));
ST_SH(out3, (out_ptr));
MADD_SHORT(out6, out7, k0, k3, out6, out7);
ST_SH(out6, (out + 4 * 16));
ST_SH(out7, (out_ptr + 3 * 16));
MADD_SHORT(out10, out11, k0, k3, out10, out11);
ST_SH(out10, (out + 6 * 16));
ST_SH(out11, (out_ptr + 16));
MADD_SHORT(out14, out15, k1, k2, out14, out15);
ST_SH(out14, (out + 5 * 16));
ST_SH(out15, (out_ptr + 2 * 16));
}
static void fadst16_cols_step2_msa(int16_t *int_buf, const int32_t *const0,
int16_t *out) {
fadst16_step2_msa_helper(int_buf, const0, out, out + 128);
}
static void fadst16_transpose_postproc_msa(int16_t *input, int16_t *out) {
v8i16 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15;
v8i16 l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15;
/* load input data */
LD_SH8(input, 16, l0, l1, l2, l3, l4, l5, l6, l7);
TRANSPOSE8x8_SH_SH(l0, l1, l2, l3, l4, l5, l6, l7, r0, r1, r2, r3, r4, r5, r6,
r7);
FDCT_POSTPROC_2V_NEG_H(r0, r1);
FDCT_POSTPROC_2V_NEG_H(r2, r3);
FDCT_POSTPROC_2V_NEG_H(r4, r5);
FDCT_POSTPROC_2V_NEG_H(r6, r7);
ST_SH8(r0, r1, r2, r3, r4, r5, r6, r7, out, 8);
out += 64;
LD_SH8(input + 8, 16, l8, l9, l10, l11, l12, l13, l14, l15);
TRANSPOSE8x8_SH_SH(l8, l9, l10, l11, l12, l13, l14, l15, r8, r9, r10, r11,
r12, r13, r14, r15);
FDCT_POSTPROC_2V_NEG_H(r8, r9);
FDCT_POSTPROC_2V_NEG_H(r10, r11);
FDCT_POSTPROC_2V_NEG_H(r12, r13);
FDCT_POSTPROC_2V_NEG_H(r14, r15);
ST_SH8(r8, r9, r10, r11, r12, r13, r14, r15, out, 8);
out += 64;
/* load input data */
input += 128;
LD_SH8(input, 16, l0, l1, l2, l3, l4, l5, l6, l7);
TRANSPOSE8x8_SH_SH(l0, l1, l2, l3, l4, l5, l6, l7, r0, r1, r2, r3, r4, r5, r6,
r7);
FDCT_POSTPROC_2V_NEG_H(r0, r1);
FDCT_POSTPROC_2V_NEG_H(r2, r3);
FDCT_POSTPROC_2V_NEG_H(r4, r5);
FDCT_POSTPROC_2V_NEG_H(r6, r7);
ST_SH8(r0, r1, r2, r3, r4, r5, r6, r7, out, 8);
out += 64;
LD_SH8(input + 8, 16, l8, l9, l10, l11, l12, l13, l14, l15);
TRANSPOSE8x8_SH_SH(l8, l9, l10, l11, l12, l13, l14, l15, r8, r9, r10, r11,
r12, r13, r14, r15);
FDCT_POSTPROC_2V_NEG_H(r8, r9);
FDCT_POSTPROC_2V_NEG_H(r10, r11);
FDCT_POSTPROC_2V_NEG_H(r12, r13);
FDCT_POSTPROC_2V_NEG_H(r14, r15);
ST_SH8(r8, r9, r10, r11, r12, r13, r14, r15, out, 8);
}
static void fadst16_rows_step1_msa(int16_t *input, const int32_t *const0,
int16_t *int_buf) {
v8i16 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15;
v8i16 tp0, tp1, tp2, tp3, g0, g1, g2, g3, g8, g9, g10, g11, h0, h1, h2, h3;
v4i32 k0, k1, k2, k3;
/* load input data */
r0 = LD_SH(input);
r7 = LD_SH(input + 7 * 8);
r8 = LD_SH(input + 8 * 8);
r15 = LD_SH(input + 15 * 8);
/* stage 1 */
LD_SW2(const0, 4, k0, k1);
LD_SW2(const0 + 4 * 2, 4, k2, k3);
MADD_BF(r15, r0, r7, r8, k0, k1, k2, k3, g0, g1, g2, g3);
r3 = LD_SH(input + 3 * 8);
r4 = LD_SH(input + 4 * 8);
r11 = LD_SH(input + 11 * 8);
r12 = LD_SH(input + 12 * 8);
LD_SW2(const0 + 4 * 4, 4, k0, k1);
LD_SW2(const0 + 4 * 6, 4, k2, k3);
MADD_BF(r11, r4, r3, r12, k0, k1, k2, k3, g8, g9, g10, g11);
/* stage 2 */
BUTTERFLY_4(g0, g2, g10, g8, tp0, tp2, tp3, tp1);
ST_SH2(tp0, tp1, int_buf, 4 * 8);
ST_SH2(tp2, tp3, int_buf + 8, 4 * 8);
LD_SW2(const0 + 4 * 8, 4, k0, k1);
k2 = LD_SW(const0 + 4 * 10);
MADD_BF(g1, g3, g9, g11, k0, k1, k2, k0, h0, h1, h2, h3);
ST_SH2(h0, h3, int_buf + 8 * 8, 4 * 8);
ST_SH2(h1, h2, int_buf + 9 * 8, 4 * 8);
r1 = LD_SH(input + 8);
r6 = LD_SH(input + 6 * 8);
r9 = LD_SH(input + 9 * 8);
r14 = LD_SH(input + 14 * 8);
LD_SW2(const0 + 4 * 11, 4, k0, k1);
LD_SW2(const0 + 4 * 13, 4, k2, k3);
MADD_BF(r9, r6, r1, r14, k0, k1, k2, k3, g0, g1, g2, g3);
ST_SH2(g1, g3, int_buf + 3 * 8, 4 * 8);
r2 = LD_SH(input + 2 * 8);
r5 = LD_SH(input + 5 * 8);
r10 = LD_SH(input + 10 * 8);
r13 = LD_SH(input + 13 * 8);
LD_SW2(const0 + 4 * 15, 4, k0, k1);
LD_SW2(const0 + 4 * 17, 4, k2, k3);
MADD_BF(r13, r2, r5, r10, k0, k1, k2, k3, h0, h1, h2, h3);
ST_SH2(h1, h3, int_buf + 11 * 8, 4 * 8);
BUTTERFLY_4(h0, h2, g2, g0, tp0, tp1, tp2, tp3);
ST_SH4(tp0, tp1, tp2, tp3, int_buf + 2 * 8, 4 * 8);
}
static void fadst16_rows_step2_msa(int16_t *int_buf, const int32_t *const0,
int16_t *out) {
fadst16_step2_msa_helper(int_buf, const0, out, out + 8);
}
static void fadst16_transpose_msa(int16_t *input, int16_t *out) {
v8i16 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15;
v8i16 l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15;
/* load input data */
LD_SH16(input, 8, l0, l8, l1, l9, l2, l10, l3, l11, l4, l12, l5, l13, l6, l14,
l7, l15);
TRANSPOSE8x8_SH_SH(l0, l1, l2, l3, l4, l5, l6, l7, r0, r1, r2, r3, r4, r5, r6,
r7);
TRANSPOSE8x8_SH_SH(l8, l9, l10, l11, l12, l13, l14, l15, r8, r9, r10, r11,
r12, r13, r14, r15);
ST_SH8(r0, r8, r1, r9, r2, r10, r3, r11, out, 8);
ST_SH8(r4, r12, r5, r13, r6, r14, r7, r15, (out + 64), 8);
out += 16 * 8;
/* load input data */
input += 128;
LD_SH16(input, 8, l0, l8, l1, l9, l2, l10, l3, l11, l4, l12, l5, l13, l6, l14,
l7, l15);
TRANSPOSE8x8_SH_SH(l0, l1, l2, l3, l4, l5, l6, l7, r0, r1, r2, r3, r4, r5, r6,
r7);
TRANSPOSE8x8_SH_SH(l8, l9, l10, l11, l12, l13, l14, l15, r8, r9, r10, r11,
r12, r13, r14, r15);
ST_SH8(r0, r8, r1, r9, r2, r10, r3, r11, out, 8);
ST_SH8(r4, r12, r5, r13, r6, r14, r7, r15, (out + 64), 8);
}
static void postproc_fdct16x8_1d_row(int16_t *intermediate, int16_t *output) {
int16_t *temp = intermediate;
int16_t *out = output;
v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
v8i16 in0, in1, in2, in3, in4, in5, in6, in7, in8, in9, in10, in11;
v8i16 in12, in13, in14, in15;
LD_SH8(temp, 16, in0, in1, in2, in3, in4, in5, in6, in7);
temp = intermediate + 8;
LD_SH8(temp, 16, in8, in9, in10, in11, in12, in13, in14, in15);
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
in4, in5, in6, in7);
TRANSPOSE8x8_SH_SH(in8, in9, in10, in11, in12, in13, in14, in15, in8, in9,
in10, in11, in12, in13, in14, in15);
FDCT_POSTPROC_2V_NEG_H(in0, in1);
FDCT_POSTPROC_2V_NEG_H(in2, in3);
FDCT_POSTPROC_2V_NEG_H(in4, in5);
FDCT_POSTPROC_2V_NEG_H(in6, in7);
FDCT_POSTPROC_2V_NEG_H(in8, in9);
FDCT_POSTPROC_2V_NEG_H(in10, in11);
FDCT_POSTPROC_2V_NEG_H(in12, in13);
FDCT_POSTPROC_2V_NEG_H(in14, in15);
BUTTERFLY_16(in0, in1, in2, in3, in4, in5, in6, in7, in8, in9, in10, in11,
in12, in13, in14, in15, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6,
tmp7, in8, in9, in10, in11, in12, in13, in14, in15);
temp = intermediate;
ST_SH8(in8, in9, in10, in11, in12, in13, in14, in15, temp, 16);
FDCT8x16_EVEN(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp0, tmp1,
tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);
temp = intermediate;
LD_SH8(temp, 16, in8, in9, in10, in11, in12, in13, in14, in15);
FDCT8x16_ODD(in8, in9, in10, in11, in12, in13, in14, in15, in0, in1, in2, in3,
in4, in5, in6, in7);
TRANSPOSE8x8_SH_SH(tmp0, in0, tmp1, in1, tmp2, in2, tmp3, in3, tmp0, in0,
tmp1, in1, tmp2, in2, tmp3, in3);
ST_SH8(tmp0, in0, tmp1, in1, tmp2, in2, tmp3, in3, out, 16);
TRANSPOSE8x8_SH_SH(tmp4, in4, tmp5, in5, tmp6, in6, tmp7, in7, tmp4, in4,
tmp5, in5, tmp6, in6, tmp7, in7);
out = output + 8;
ST_SH8(tmp4, in4, tmp5, in5, tmp6, in6, tmp7, in7, out, 16);
}
void av1_fht16x16_msa(const int16_t *input, int16_t *output, int32_t stride,
int32_t tx_type) {
DECLARE_ALIGNED(32, int16_t, tmp[256]);
DECLARE_ALIGNED(32, int16_t, trans_buf[256]);
DECLARE_ALIGNED(32, int16_t, tmp_buf[128]);
int32_t i;
int16_t *ptmpbuf = &tmp_buf[0];
int16_t *trans = &trans_buf[0];
const int32_t const_arr[29 * 4] = {
52707308, 52707308, 52707308, 52707308, -1072430300,
-1072430300, -1072430300, -1072430300, 795618043, 795618043,
795618043, 795618043, -721080468, -721080468, -721080468,
-721080468, 459094491, 459094491, 459094491, 459094491,
-970646691, -970646691, -970646691, -970646691, 1010963856,
1010963856, 1010963856, 1010963856, -361743294, -361743294,
-361743294, -361743294, 209469125, 209469125, 209469125,
209469125, -1053094788, -1053094788, -1053094788, -1053094788,
1053160324, 1053160324, 1053160324, 1053160324, 639644520,
639644520, 639644520, 639644520, -862444000, -862444000,
-862444000, -862444000, 1062144356, 1062144356, 1062144356,
1062144356, -157532337, -157532337, -157532337, -157532337,
260914709, 260914709, 260914709, 260914709, -1041559667,
-1041559667, -1041559667, -1041559667, 920985831, 920985831,
920985831, 920985831, -551995675, -551995675, -551995675,
-551995675, 596522295, 596522295, 596522295, 596522295,
892853362, 892853362, 892853362, 892853362, -892787826,
-892787826, -892787826, -892787826, 410925857, 410925857,
410925857, 410925857, -992012162, -992012162, -992012162,
-992012162, 992077698, 992077698, 992077698, 992077698,
759246145, 759246145, 759246145, 759246145, -759180609,
-759180609, -759180609, -759180609, -759222975, -759222975,
-759222975, -759222975, 759288511, 759288511, 759288511,
759288511
};
switch (tx_type) {
case DCT_DCT:
/* column transform */
for (i = 0; i < 2; ++i) {
fdct8x16_1d_column(input + 8 * i, tmp + 8 * i, stride);
}
/* row transform */
for (i = 0; i < 2; ++i) {
fdct16x8_1d_row(tmp + (128 * i), output + (128 * i));
}
break;
case ADST_DCT:
/* column transform */
for (i = 0; i < 2; ++i) {
fadst16_cols_step1_msa(input + (i << 3), stride, const_arr, ptmpbuf);
fadst16_cols_step2_msa(ptmpbuf, const_arr, tmp + (i << 3));
}
/* row transform */
for (i = 0; i < 2; ++i) {
postproc_fdct16x8_1d_row(tmp + (128 * i), output + (128 * i));
}
break;
case DCT_ADST:
/* column transform */
for (i = 0; i < 2; ++i) {
fdct8x16_1d_column(input + 8 * i, tmp + 8 * i, stride);
}
fadst16_transpose_postproc_msa(tmp, trans);
/* row transform */
for (i = 0; i < 2; ++i) {
fadst16_rows_step1_msa(trans + (i << 7), const_arr, ptmpbuf);
fadst16_rows_step2_msa(ptmpbuf, const_arr, tmp + (i << 7));
}
fadst16_transpose_msa(tmp, output);
break;
case ADST_ADST:
/* column transform */
for (i = 0; i < 2; ++i) {
fadst16_cols_step1_msa(input + (i << 3), stride, const_arr, ptmpbuf);
fadst16_cols_step2_msa(ptmpbuf, const_arr, tmp + (i << 3));
}
fadst16_transpose_postproc_msa(tmp, trans);
/* row transform */
for (i = 0; i < 2; ++i) {
fadst16_rows_step1_msa(trans + (i << 7), const_arr, ptmpbuf);
fadst16_rows_step2_msa(ptmpbuf, const_arr, tmp + (i << 7));
}
fadst16_transpose_msa(tmp, output);
break;
default: assert(0); break;
}
}

View file

@ -12,7 +12,6 @@
#include <assert.h>
#include "av1/common/enums.h"
#include "av1/encoder/mips/msa/fdct_msa.h"
void av1_fwht4x4_msa(const int16_t *input, int16_t *output,
int32_t src_stride) {
@ -45,54 +44,3 @@ void av1_fwht4x4_msa(const int16_t *input, int16_t *output,
ST4x2_UB(in1, output + 8, 4);
ST4x2_UB(in2, output + 12, 4);
}
void av1_fht4x4_msa(const int16_t *input, int16_t *output, int32_t stride,
int32_t tx_type) {
v8i16 in0, in1, in2, in3;
LD_SH4(input, stride, in0, in1, in2, in3);
/* fdct4 pre-process */
{
v8i16 temp, mask;
v16i8 zero = { 0 };
v16i8 one = __msa_ldi_b(1);
mask = (v8i16)__msa_sldi_b(zero, one, 15);
SLLI_4V(in0, in1, in2, in3, 4);
temp = __msa_ceqi_h(in0, 0);
temp = (v8i16)__msa_xori_b((v16u8)temp, 255);
temp = mask & temp;
in0 += temp;
}
switch (tx_type) {
case DCT_DCT:
AOM_FDCT4(in0, in1, in2, in3, in0, in1, in2, in3);
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
AOM_FDCT4(in0, in1, in2, in3, in0, in1, in2, in3);
break;
case ADST_DCT:
AOM_FADST4(in0, in1, in2, in3, in0, in1, in2, in3);
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
AOM_FDCT4(in0, in1, in2, in3, in0, in1, in2, in3);
break;
case DCT_ADST:
AOM_FDCT4(in0, in1, in2, in3, in0, in1, in2, in3);
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
AOM_FADST4(in0, in1, in2, in3, in0, in1, in2, in3);
break;
case ADST_ADST:
AOM_FADST4(in0, in1, in2, in3, in0, in1, in2, in3);
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
AOM_FADST4(in0, in1, in2, in3, in0, in1, in2, in3);
break;
default: assert(0); break;
}
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
ADD4(in0, 1, in1, 1, in2, 1, in3, 1, in0, in1, in2, in3);
SRA_4V(in0, in1, in2, in3, 2);
PCKEV_D2_SH(in1, in0, in3, in2, in0, in2);
ST_SH2(in0, in2, output, 8);
}

View file

@ -1,65 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <assert.h>
#include "av1/common/enums.h"
#include "av1/encoder/mips/msa/fdct_msa.h"
void av1_fht8x8_msa(const int16_t *input, int16_t *output, int32_t stride,
int32_t tx_type) {
v8i16 in0, in1, in2, in3, in4, in5, in6, in7;
LD_SH8(input, stride, in0, in1, in2, in3, in4, in5, in6, in7);
SLLI_4V(in0, in1, in2, in3, 2);
SLLI_4V(in4, in5, in6, in7, 2);
switch (tx_type) {
case DCT_DCT:
AOM_FDCT8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3, in4,
in5, in6, in7);
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2,
in3, in4, in5, in6, in7);
AOM_FDCT8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3, in4,
in5, in6, in7);
break;
case ADST_DCT:
AOM_ADST8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3, in4,
in5, in6, in7);
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2,
in3, in4, in5, in6, in7);
AOM_FDCT8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3, in4,
in5, in6, in7);
break;
case DCT_ADST:
AOM_FDCT8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3, in4,
in5, in6, in7);
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2,
in3, in4, in5, in6, in7);
AOM_ADST8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3, in4,
in5, in6, in7);
break;
case ADST_ADST:
AOM_ADST8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3, in4,
in5, in6, in7);
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2,
in3, in4, in5, in6, in7);
AOM_ADST8(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3, in4,
in5, in6, in7);
break;
default: assert(0); break;
}
TRANSPOSE8x8_SH_SH(in0, in1, in2, in3, in4, in5, in6, in7, in0, in1, in2, in3,
in4, in5, in6, in7);
SRLI_AVE_S_4V_H(in0, in1, in2, in3, in4, in5, in6, in7);
ST_SH8(in0, in1, in2, in3, in4, in5, in6, in7, output, 8);
}

View file

@ -1,117 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_ENCODER_MIPS_MSA_AV1_FDCT_MSA_H_
#define AV1_ENCODER_MIPS_MSA_AV1_FDCT_MSA_H_
#include "aom_dsp/mips/fwd_txfm_msa.h"
#include "aom_dsp/mips/txfm_macros_msa.h"
#include "aom_ports/mem.h"
#define AOM_ADST8(in0, in1, in2, in3, in4, in5, in6, in7, out0, out1, out2, \
out3, out4, out5, out6, out7) \
{ \
v8i16 cnst0_m, cnst1_m, cnst2_m, cnst3_m, cnst4_m; \
v8i16 vec0_m, vec1_m, vec2_m, vec3_m, s0_m, s1_m; \
v8i16 coeff0_m = { cospi_2_64, cospi_6_64, cospi_10_64, cospi_14_64, \
cospi_18_64, cospi_22_64, cospi_26_64, cospi_30_64 }; \
v8i16 coeff1_m = { cospi_8_64, -cospi_8_64, cospi_16_64, -cospi_16_64, \
cospi_24_64, -cospi_24_64, 0, 0 }; \
\
SPLATI_H2_SH(coeff0_m, 0, 7, cnst0_m, cnst1_m); \
cnst2_m = -cnst0_m; \
ILVEV_H2_SH(cnst0_m, cnst1_m, cnst1_m, cnst2_m, cnst0_m, cnst1_m); \
SPLATI_H2_SH(coeff0_m, 4, 3, cnst2_m, cnst3_m); \
cnst4_m = -cnst2_m; \
ILVEV_H2_SH(cnst2_m, cnst3_m, cnst3_m, cnst4_m, cnst2_m, cnst3_m); \
\
ILVRL_H2_SH(in0, in7, vec1_m, vec0_m); \
ILVRL_H2_SH(in4, in3, vec3_m, vec2_m); \
DOT_ADD_SUB_SRARI_PCK(vec0_m, vec1_m, vec2_m, vec3_m, cnst0_m, cnst1_m, \
cnst2_m, cnst3_m, in7, in0, in4, in3); \
\
SPLATI_H2_SH(coeff0_m, 2, 5, cnst0_m, cnst1_m); \
cnst2_m = -cnst0_m; \
ILVEV_H2_SH(cnst0_m, cnst1_m, cnst1_m, cnst2_m, cnst0_m, cnst1_m); \
SPLATI_H2_SH(coeff0_m, 6, 1, cnst2_m, cnst3_m); \
cnst4_m = -cnst2_m; \
ILVEV_H2_SH(cnst2_m, cnst3_m, cnst3_m, cnst4_m, cnst2_m, cnst3_m); \
\
ILVRL_H2_SH(in2, in5, vec1_m, vec0_m); \
ILVRL_H2_SH(in6, in1, vec3_m, vec2_m); \
\
DOT_ADD_SUB_SRARI_PCK(vec0_m, vec1_m, vec2_m, vec3_m, cnst0_m, cnst1_m, \
cnst2_m, cnst3_m, in5, in2, in6, in1); \
BUTTERFLY_4(in7, in0, in2, in5, s1_m, s0_m, in2, in5); \
out7 = -s0_m; \
out0 = s1_m; \
\
SPLATI_H4_SH(coeff1_m, 0, 4, 1, 5, cnst0_m, cnst1_m, cnst2_m, cnst3_m); \
\
ILVEV_H2_SH(cnst3_m, cnst0_m, cnst1_m, cnst2_m, cnst3_m, cnst2_m); \
cnst0_m = __msa_ilvev_h(cnst1_m, cnst0_m); \
cnst1_m = cnst0_m; \
\
ILVRL_H2_SH(in4, in3, vec1_m, vec0_m); \
ILVRL_H2_SH(in6, in1, vec3_m, vec2_m); \
DOT_ADD_SUB_SRARI_PCK(vec0_m, vec1_m, vec2_m, vec3_m, cnst0_m, cnst2_m, \
cnst3_m, cnst1_m, out1, out6, s0_m, s1_m); \
\
SPLATI_H2_SH(coeff1_m, 2, 3, cnst0_m, cnst1_m); \
cnst1_m = __msa_ilvev_h(cnst1_m, cnst0_m); \
\
ILVRL_H2_SH(in2, in5, vec1_m, vec0_m); \
ILVRL_H2_SH(s0_m, s1_m, vec3_m, vec2_m); \
out3 = DOT_SHIFT_RIGHT_PCK_H(vec0_m, vec1_m, cnst0_m); \
out4 = DOT_SHIFT_RIGHT_PCK_H(vec0_m, vec1_m, cnst1_m); \
out2 = DOT_SHIFT_RIGHT_PCK_H(vec2_m, vec3_m, cnst0_m); \
out5 = DOT_SHIFT_RIGHT_PCK_H(vec2_m, vec3_m, cnst1_m); \
\
out1 = -out1; \
out3 = -out3; \
out5 = -out5; \
}
#define AOM_FADST4(in0, in1, in2, in3, out0, out1, out2, out3) \
{ \
v4i32 s0_m, s1_m, s2_m, s3_m, constant_m; \
v4i32 in0_r_m, in1_r_m, in2_r_m, in3_r_m; \
\
UNPCK_R_SH_SW(in0, in0_r_m); \
UNPCK_R_SH_SW(in1, in1_r_m); \
UNPCK_R_SH_SW(in2, in2_r_m); \
UNPCK_R_SH_SW(in3, in3_r_m); \
\
constant_m = __msa_fill_w(sinpi_4_9); \
MUL2(in0_r_m, constant_m, in3_r_m, constant_m, s1_m, s0_m); \
\
constant_m = __msa_fill_w(sinpi_1_9); \
s0_m += in0_r_m * constant_m; \
s1_m -= in1_r_m * constant_m; \
\
constant_m = __msa_fill_w(sinpi_2_9); \
s0_m += in1_r_m * constant_m; \
s1_m += in3_r_m * constant_m; \
\
s2_m = in0_r_m + in1_r_m - in3_r_m; \
\
constant_m = __msa_fill_w(sinpi_3_9); \
MUL2(in2_r_m, constant_m, s2_m, constant_m, s3_m, in1_r_m); \
\
in0_r_m = s0_m + s3_m; \
s2_m = s1_m - s3_m; \
s3_m = s1_m - s0_m + s3_m; \
\
SRARI_W4_SW(in0_r_m, in1_r_m, s2_m, s3_m, DCT_CONST_BITS); \
PCKEV_H4_SH(in0_r_m, in0_r_m, in1_r_m, in1_r_m, s2_m, s2_m, s3_m, s3_m, \
out0, out1, out2, out3); \
}
#endif // AV1_ENCODER_MIPS_MSA_AV1_FDCT_MSA_H_

View file

@ -9,7 +9,8 @@
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "./av1_rtcd.h"
#include "config/av1_rtcd.h"
#include "aom_dsp/mips/macros_msa.h"
static void temporal_filter_apply_8size_msa(uint8_t *frm1_ptr, uint32_t stride,

57
third_party/aom/av1/encoder/ml.c vendored Normal file
View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <assert.h>
#include "av1/encoder/ml.h"
void av1_nn_predict(const float *features, const NN_CONFIG *nn_config,
float *output) {
int num_input_nodes = nn_config->num_inputs;
int buf_index = 0;
float buf[2][NN_MAX_NODES_PER_LAYER];
const float *input_nodes = features;
// Propagate hidden layers.
const int num_layers = nn_config->num_hidden_layers;
assert(num_layers <= NN_MAX_HIDDEN_LAYERS);
for (int layer = 0; layer < num_layers; ++layer) {
const float *weights = nn_config->weights[layer];
const float *bias = nn_config->bias[layer];
float *output_nodes = buf[buf_index];
const int num_output_nodes = nn_config->num_hidden_nodes[layer];
assert(num_output_nodes < NN_MAX_NODES_PER_LAYER);
for (int node = 0; node < num_output_nodes; ++node) {
float val = 0.0f;
for (int i = 0; i < num_input_nodes; ++i)
val += weights[i] * input_nodes[i];
val += bias[node];
// ReLU as activation function.
val = val > 0.0f ? val : 0.0f; // Could use AOMMAX().
output_nodes[node] = val;
weights += num_input_nodes;
}
num_input_nodes = num_output_nodes;
input_nodes = output_nodes;
buf_index = 1 - buf_index;
}
// Final output layer.
const float *weights = nn_config->weights[num_layers];
for (int node = 0; node < nn_config->num_outputs; ++node) {
const float *bias = nn_config->bias[num_layers];
float val = 0.0f;
for (int i = 0; i < num_input_nodes; ++i)
val += weights[i] * input_nodes[i];
output[node] = val + bias[node];
weights += num_input_nodes;
}
}

44
third_party/aom/av1/encoder/ml.h vendored Normal file
View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_ENCODER_ML_H_
#define AV1_ENCODER_ML_H_
#ifdef __cplusplus
extern "C" {
#endif
#define NN_MAX_HIDDEN_LAYERS 10
#define NN_MAX_NODES_PER_LAYER 128
typedef struct {
int num_inputs; // Number of input nodes, i.e. features.
int num_outputs; // Number of output nodes.
int num_hidden_layers; // Number of hidden layers, maximum 10.
// Number of nodes for each hidden layer.
int num_hidden_nodes[NN_MAX_HIDDEN_LAYERS];
// Weight parameters, indexed by layer.
const float *weights[NN_MAX_HIDDEN_LAYERS + 1];
// Bias parameters, indexed by layer.
const float *bias[NN_MAX_HIDDEN_LAYERS + 1];
} NN_CONFIG;
// Calculate prediction based on the given input features and neural net config.
// Assume there are no more than NN_MAX_NODES_PER_LAYER nodes in each hidden
// layer.
void av1_nn_predict(const float *features, const NN_CONFIG *nn_config,
float *output);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AV1_ENCODER_RD_H_

View file

@ -23,16 +23,14 @@
#include "av1/encoder/k_means_template.h"
#undef AV1_K_MEANS_DIM
static int float_comparer(const void *a, const void *b) {
const float fa = *(const float *)a;
const float fb = *(const float *)b;
return (fa > fb) - (fa < fb);
static int int_comparer(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int av1_remove_duplicates(float *centroids, int num_centroids) {
int av1_remove_duplicates(int *centroids, int num_centroids) {
int num_unique; // number of unique centroids
int i;
qsort(centroids, num_centroids, sizeof(*centroids), float_comparer);
qsort(centroids, num_centroids, sizeof(*centroids), int_comparer);
// Remove duplicates.
num_unique = 1;
for (i = 1; i < num_centroids; ++i) {
@ -43,7 +41,6 @@ int av1_remove_duplicates(float *centroids, int num_centroids) {
return num_unique;
}
#if CONFIG_PALETTE_DELTA_ENCODING
static int delta_encode_cost(const int *colors, int num, int bit_depth,
int min_val) {
if (num <= 0) return 0;
@ -116,15 +113,11 @@ int av1_get_palette_delta_bits_v(const PALETTE_MODE_INFO *const pmi,
}
return AOMMAX(av1_ceil_log2(max_d + 1), *min_bits);
}
#endif // CONFIG_PALETTE_DELTA_ENCODING
int av1_palette_color_cost_y(const PALETTE_MODE_INFO *const pmi,
#if CONFIG_PALETTE_DELTA_ENCODING
uint16_t *color_cache, int n_cache,
#endif // CONFIG_PALETTE_DELTA_ENCODING
int bit_depth) {
const int n = pmi->palette_size[0];
#if CONFIG_PALETTE_DELTA_ENCODING
int out_cache_colors[PALETTE_MAX_SIZE];
uint8_t cache_color_found[2 * PALETTE_MAX_SIZE];
const int n_out_cache =
@ -132,19 +125,13 @@ int av1_palette_color_cost_y(const PALETTE_MODE_INFO *const pmi,
cache_color_found, out_cache_colors);
const int total_bits =
n_cache + delta_encode_cost(out_cache_colors, n_out_cache, bit_depth, 1);
return total_bits * av1_cost_bit(128, 0);
#else
return bit_depth * n * av1_cost_bit(128, 0);
#endif // CONFIG_PALETTE_DELTA_ENCODING
return av1_cost_literal(total_bits);
}
int av1_palette_color_cost_uv(const PALETTE_MODE_INFO *const pmi,
#if CONFIG_PALETTE_DELTA_ENCODING
uint16_t *color_cache, int n_cache,
#endif // CONFIG_PALETTE_DELTA_ENCODING
int bit_depth) {
const int n = pmi->palette_size[1];
#if CONFIG_PALETTE_DELTA_ENCODING
int total_bits = 0;
// U channel palette color cost.
int out_cache_colors[PALETTE_MAX_SIZE];
@ -163,8 +150,5 @@ int av1_palette_color_cost_uv(const PALETTE_MODE_INFO *const pmi,
2 + bit_depth + (bits_v + 1) * (n - 1) - zero_count;
const int bits_using_raw = bit_depth * n;
total_bits += 1 + AOMMIN(bits_using_delta, bits_using_raw);
return total_bits * av1_cost_bit(128, 0);
#else
return 2 * bit_depth * n * av1_cost_bit(128, 0);
#endif // CONFIG_PALETTE_DELTA_ENCODING
return av1_cost_literal(total_bits);
}

View file

@ -20,22 +20,22 @@ extern "C" {
#define AV1_K_MEANS_RENAME(func, dim) func##_dim##dim
void AV1_K_MEANS_RENAME(av1_calc_indices, 1)(const float *data,
const float *centroids,
void AV1_K_MEANS_RENAME(av1_calc_indices, 1)(const int *data,
const int *centroids,
uint8_t *indices, int n, int k);
void AV1_K_MEANS_RENAME(av1_calc_indices, 2)(const float *data,
const float *centroids,
void AV1_K_MEANS_RENAME(av1_calc_indices, 2)(const int *data,
const int *centroids,
uint8_t *indices, int n, int k);
void AV1_K_MEANS_RENAME(av1_k_means, 1)(const float *data, float *centroids,
void AV1_K_MEANS_RENAME(av1_k_means, 1)(const int *data, int *centroids,
uint8_t *indices, int n, int k,
int max_itr);
void AV1_K_MEANS_RENAME(av1_k_means, 2)(const float *data, float *centroids,
void AV1_K_MEANS_RENAME(av1_k_means, 2)(const int *data, int *centroids,
uint8_t *indices, int n, int k,
int max_itr);
// Given 'n' 'data' points and 'k' 'centroids' each of dimension 'dim',
// calculate the centroid 'indices' for the data points.
static INLINE void av1_calc_indices(const float *data, const float *centroids,
static INLINE void av1_calc_indices(const int *data, const int *centroids,
uint8_t *indices, int n, int k, int dim) {
if (dim == 1) {
AV1_K_MEANS_RENAME(av1_calc_indices, 1)(data, centroids, indices, n, k);
@ -50,7 +50,7 @@ static INLINE void av1_calc_indices(const float *data, const float *centroids,
// dimension 'dim', runs up to 'max_itr' iterations of k-means algorithm to get
// updated 'centroids' and the centroid 'indices' for elements in 'data'.
// Note: the output centroids are rounded off to nearest integers.
static INLINE void av1_k_means(const float *data, float *centroids,
static INLINE void av1_k_means(const int *data, int *centroids,
uint8_t *indices, int n, int k, int dim,
int max_itr) {
if (dim == 1) {
@ -66,9 +66,8 @@ static INLINE void av1_k_means(const float *data, float *centroids,
// puts these unique centroids in first 'k' indices of 'centroids' array.
// Ideally, the centroids should be rounded to integers before calling this
// method.
int av1_remove_duplicates(float *centroids, int num_centroids);
int av1_remove_duplicates(int *centroids, int num_centroids);
#if CONFIG_PALETTE_DELTA_ENCODING
// Given a color cache and a set of base colors, find if each cache color is
// present in the base colors, record the binary results in "cache_color_found".
// Record the colors that are not in the color cache in "out_cache_colors".
@ -80,20 +79,14 @@ int av1_index_color_cache(const uint16_t *color_cache, int n_cache,
// assign zero_count with the number of deltas being 0.
int av1_get_palette_delta_bits_v(const PALETTE_MODE_INFO *const pmi,
int bit_depth, int *zero_count, int *min_bits);
#endif // CONFIG_PALETTE_DELTA_ENCODING
// Return the rate cost for transmitting luma palette color values.
int av1_palette_color_cost_y(const PALETTE_MODE_INFO *const pmi,
#if CONFIG_PALETTE_DELTA_ENCODING
uint16_t *color_cache, int n_cache,
#endif // CONFIG_PALETTE_DELTA_ENCODING
int bit_depth);
uint16_t *color_cache, int n_cache, int bit_depth);
// Return the rate cost for transmitting chroma palette color values.
int av1_palette_color_cost_uv(const PALETTE_MODE_INFO *const pmi,
#if CONFIG_PALETTE_DELTA_ENCODING
uint16_t *color_cache, int n_cache,
#endif // CONFIG_PALETTE_DELTA_ENCODING
int bit_depth);
#ifdef __cplusplus

View file

@ -12,7 +12,8 @@
#include <math.h>
#include <string.h>
#include "./aom_scale_rtcd.h"
#include "config/aom_scale_rtcd.h"
#include "aom/aom_integer.h"
#include "av1/common/cdef.h"
#include "av1/common/onyxc_int.h"
@ -23,7 +24,7 @@
#define REDUCED_TOTAL_STRENGTHS (REDUCED_PRI_STRENGTHS * CDEF_SEC_STRENGTHS)
#define TOTAL_STRENGTHS (CDEF_PRI_STRENGTHS * CDEF_SEC_STRENGTHS)
static int priconv[REDUCED_PRI_STRENGTHS] = { 0, 1, 2, 3, 4, 7, 12, 25 };
static int priconv[REDUCED_PRI_STRENGTHS] = { 0, 1, 2, 3, 5, 7, 10, 13 };
/* Search for the best strength to add as an option, knowing we
already selected nb_strengths options. */
@ -68,16 +69,11 @@ static uint64_t search_one_dual(int *lev0, int *lev1, int nb_strengths,
uint64_t (**mse)[TOTAL_STRENGTHS], int sb_count,
int fast) {
uint64_t tot_mse[TOTAL_STRENGTHS][TOTAL_STRENGTHS];
#if !CONFIG_CDEF_SINGLEPASS
const int total_strengths = fast ? REDUCED_TOTAL_STRENGTHS : TOTAL_STRENGTHS;
#endif
int i, j;
uint64_t best_tot_mse = (uint64_t)1 << 63;
int best_id0 = 0;
int best_id1 = 0;
#if CONFIG_CDEF_SINGLEPASS
const int total_strengths = fast ? REDUCED_TOTAL_STRENGTHS : TOTAL_STRENGTHS;
#endif
memset(tot_mse, 0, sizeof(tot_mse));
for (i = 0; i < sb_count; i++) {
int gi;
@ -204,10 +200,9 @@ static INLINE uint64_t dist_8x8_16bit(uint16_t *dst, int dstride, uint16_t *src,
svar = sum_s2 - ((sum_s * sum_s + 32) >> 6);
dvar = sum_d2 - ((sum_d * sum_d + 32) >> 6);
return (uint64_t)floor(
.5 +
(sum_d2 + sum_s2 - 2 * sum_sd) * .5 *
(svar + dvar + (400 << 2 * coeff_shift)) /
(sqrt((20000 << 4 * coeff_shift) + svar * (double)dvar)));
.5 + (sum_d2 + sum_s2 - 2 * sum_sd) * .5 *
(svar + dvar + (400 << 2 * coeff_shift)) /
(sqrt((20000 << 4 * coeff_shift) + svar * (double)dvar)));
}
static INLINE uint64_t mse_8x8_16bit(uint16_t *dst, int dstride, uint16_t *src,
@ -290,7 +285,7 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
int fbr, fbc;
uint16_t *src[3];
uint16_t *ref_coeff[3];
cdef_list dlist[MI_SIZE_64X64 * MI_SIZE_64X64];
static cdef_list dlist[MI_SIZE_128X128 * MI_SIZE_128X128];
int dir[CDEF_NBLOCKS][CDEF_NBLOCKS] = { { 0 } };
int var[CDEF_NBLOCKS][CDEF_NBLOCKS] = { { 0 } };
int stride[3];
@ -310,32 +305,27 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
int *sb_index = aom_malloc(nvfb * nhfb * sizeof(*sb_index));
int *selected_strength = aom_malloc(nvfb * nhfb * sizeof(*sb_index));
uint64_t(*mse[2])[TOTAL_STRENGTHS];
#if CONFIG_CDEF_SINGLEPASS
int pri_damping = 3 + (cm->base_qindex >> 6);
#else
int pri_damping = 6;
#endif
int sec_damping = 3 + (cm->base_qindex >> 6);
int i;
int nb_strengths;
int nb_strength_bits;
int quantizer;
double lambda;
int nplanes = 3;
const int num_planes = av1_num_planes(cm);
const int total_strengths = fast ? REDUCED_TOTAL_STRENGTHS : TOTAL_STRENGTHS;
DECLARE_ALIGNED(32, uint16_t, inbuf[CDEF_INBUF_SIZE]);
uint16_t *in;
DECLARE_ALIGNED(32, uint16_t, tmp_dst[CDEF_BLOCKSIZE * CDEF_BLOCKSIZE]);
int chroma_cdef = xd->plane[1].subsampling_x == xd->plane[1].subsampling_y &&
xd->plane[2].subsampling_x == xd->plane[2].subsampling_y;
DECLARE_ALIGNED(32, uint16_t, tmp_dst[1 << (MAX_SB_SIZE_LOG2 * 2)]);
quantizer =
av1_ac_quant(cm->base_qindex, 0, cm->bit_depth) >> (cm->bit_depth - 8);
av1_ac_quant_Q3(cm->base_qindex, 0, cm->bit_depth) >> (cm->bit_depth - 8);
lambda = .12 * quantizer * quantizer / 256.;
av1_setup_dst_planes(xd->plane, cm->sb_size, frame, 0, 0);
av1_setup_dst_planes(xd->plane, cm->seq_params.sb_size, frame, 0, 0, 0,
num_planes);
mse[0] = aom_malloc(sizeof(**mse) * nvfb * nhfb);
mse[1] = aom_malloc(sizeof(**mse) * nvfb * nhfb);
for (pli = 0; pli < nplanes; pli++) {
for (pli = 0; pli < num_planes; pli++) {
uint8_t *ref_buffer;
int ref_stride;
switch (pli) {
@ -371,20 +361,16 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
for (r = 0; r < frame_height; ++r) {
for (c = 0; c < frame_width; ++c) {
#if CONFIG_HIGHBITDEPTH
if (cm->use_highbitdepth) {
src[pli][r * stride[pli] + c] = CONVERT_TO_SHORTPTR(
xd->plane[pli].dst.buf)[r * xd->plane[pli].dst.stride + c];
ref_coeff[pli][r * stride[pli] + c] =
CONVERT_TO_SHORTPTR(ref_buffer)[r * ref_stride + c];
} else {
#endif
src[pli][r * stride[pli] + c] =
xd->plane[pli].dst.buf[r * xd->plane[pli].dst.stride + c];
ref_coeff[pli][r * stride[pli] + c] = ref_buffer[r * ref_stride + c];
#if CONFIG_HIGHBITDEPTH
}
#endif
}
}
}
@ -397,13 +383,33 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
int dirinit = 0;
nhb = AOMMIN(MI_SIZE_64X64, cm->mi_cols - MI_SIZE_64X64 * fbc);
nvb = AOMMIN(MI_SIZE_64X64, cm->mi_rows - MI_SIZE_64X64 * fbr);
cm->mi_grid_visible[MI_SIZE_64X64 * fbr * cm->mi_stride +
MI_SIZE_64X64 * fbc]
->mbmi.cdef_strength = -1;
int hb_step = 1;
int vb_step = 1;
BLOCK_SIZE bs = BLOCK_64X64;
MB_MODE_INFO *const mbmi =
cm->mi_grid_visible[MI_SIZE_64X64 * fbr * cm->mi_stride +
MI_SIZE_64X64 * fbc];
if (((fbc & 1) &&
(mbmi->sb_type == BLOCK_128X128 || mbmi->sb_type == BLOCK_128X64)) ||
((fbr & 1) &&
(mbmi->sb_type == BLOCK_128X128 || mbmi->sb_type == BLOCK_64X128)))
continue;
if (mbmi->sb_type == BLOCK_128X128 || mbmi->sb_type == BLOCK_128X64 ||
mbmi->sb_type == BLOCK_64X128)
bs = mbmi->sb_type;
if (bs == BLOCK_128X128 || bs == BLOCK_128X64) {
nhb = AOMMIN(MI_SIZE_128X128, cm->mi_cols - MI_SIZE_64X64 * fbc);
hb_step = 2;
}
if (bs == BLOCK_128X128 || bs == BLOCK_64X128) {
nvb = AOMMIN(MI_SIZE_128X128, cm->mi_rows - MI_SIZE_64X64 * fbr);
vb_step = 2;
}
// No filtering if the entire filter block is skipped
if (sb_all_skip(cm, fbr * MI_SIZE_64X64, fbc * MI_SIZE_64X64)) continue;
cdef_count = sb_compute_cdef_list(cm, fbr * MI_SIZE_64X64,
fbc * MI_SIZE_64X64, dlist, 1);
for (pli = 0; pli < nplanes; pli++) {
fbc * MI_SIZE_64X64, dlist, bs);
for (pli = 0; pli < num_planes; pli++) {
for (i = 0; i < CDEF_INBUF_SIZE; i++) inbuf[i] = CDEF_VERY_LARGE;
for (gi = 0; gi < total_strengths; gi++) {
int threshold;
@ -411,7 +417,6 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
int sec_strength;
threshold = gi / CDEF_SEC_STRENGTHS;
if (fast) threshold = priconv[threshold];
if (pli > 0 && !chroma_cdef) threshold = 0;
/* We avoid filtering the pixels for which some of the pixels to
average
are outside the frame. We could change the filter instead, but it
@ -419,11 +424,10 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
int yoff = CDEF_VBORDER * (fbr != 0);
int xoff = CDEF_HBORDER * (fbc != 0);
int ysize = (nvb << mi_high_l2[pli]) +
CDEF_VBORDER * (fbr != nvfb - 1) + yoff;
CDEF_VBORDER * (fbr + vb_step < nvfb) + yoff;
int xsize = (nhb << mi_wide_l2[pli]) +
CDEF_HBORDER * (fbc != nhfb - 1) + xoff;
CDEF_HBORDER * (fbc + hb_step < nhfb) + xoff;
sec_strength = gi % CDEF_SEC_STRENGTHS;
#if CONFIG_CDEF_SINGLEPASS
copy_sb16_16(&in[(-yoff * CDEF_BSTRIDE - xoff)], CDEF_BSTRIDE,
src[pli],
(fbr * MI_SIZE_64X64 << mi_high_l2[pli]) - yoff,
@ -433,19 +437,6 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
dir, &dirinit, var, pli, dlist, cdef_count, threshold,
sec_strength + (sec_strength == 3), pri_damping,
sec_damping, coeff_shift);
#else
if (sec_strength == 0)
copy_sb16_16(&in[(-yoff * CDEF_BSTRIDE - xoff)], CDEF_BSTRIDE,
src[pli],
(fbr * MI_SIZE_64X64 << mi_high_l2[pli]) - yoff,
(fbc * MI_SIZE_64X64 << mi_wide_l2[pli]) - xoff,
stride[pli], ysize, xsize);
cdef_filter_fb(sec_strength ? NULL : (uint8_t *)in, CDEF_BSTRIDE,
tmp_dst, in, xdec[pli], ydec[pli], dir, &dirinit, var,
pli, dlist, cdef_count, threshold,
sec_strength + (sec_strength == 3), sec_damping,
pri_damping, coeff_shift, sec_strength != 0, 1);
#endif
curr_mse = compute_cdef_dist(
ref_coeff[pli] +
(fbr * MI_SIZE_64X64 << mi_high_l2[pli]) * stride[pli] +
@ -470,7 +461,7 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
int best_lev0[CDEF_MAX_STRENGTHS];
int best_lev1[CDEF_MAX_STRENGTHS] = { 0 };
nb_strengths = 1 << i;
if (nplanes >= 3)
if (num_planes >= 3)
tot_mse = joint_strength_search_dual(best_lev0, best_lev1, nb_strengths,
mse, sb_count, fast);
else
@ -500,14 +491,14 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
best_gi = 0;
for (gi = 0; gi < cm->nb_cdef_strengths; gi++) {
uint64_t curr = mse[0][i][cm->cdef_strengths[gi]];
if (nplanes >= 3) curr += mse[1][i][cm->cdef_uv_strengths[gi]];
if (num_planes >= 3) curr += mse[1][i][cm->cdef_uv_strengths[gi]];
if (curr < best_mse) {
best_gi = gi;
best_mse = curr;
}
}
selected_strength[i] = best_gi;
cm->mi_grid_visible[sb_index[i]]->mbmi.cdef_strength = best_gi;
cm->mi_grid_visible[sb_index[i]]->cdef_strength = best_gi;
}
if (fast) {
@ -526,7 +517,7 @@ void av1_cdef_search(YV12_BUFFER_CONFIG *frame, const YV12_BUFFER_CONFIG *ref,
cm->cdef_sec_damping = sec_damping;
aom_free(mse[0]);
aom_free(mse[1]);
for (pli = 0; pli < nplanes; pli++) {
for (pli = 0; pli < num_planes; pli++) {
aom_free(src[pli]);
aom_free(ref_coeff[pli]);
}

View file

@ -12,7 +12,7 @@
#include <assert.h>
#include <limits.h>
#include "./aom_scale_rtcd.h"
#include "config/aom_scale_rtcd.h"
#include "aom_dsp/aom_dsp_common.h"
#include "aom_dsp/psnr.h"
@ -27,74 +27,6 @@
#include "av1/encoder/encoder.h"
#include "av1/encoder/picklpf.h"
#if CONFIG_LPF_SB
#if CONFIG_HIGHBITDEPTH
static int compute_sb_y_sse_highbd(const YV12_BUFFER_CONFIG *src,
const YV12_BUFFER_CONFIG *frame,
AV1_COMMON *const cm, int mi_row,
int mi_col) {
int sse = 0;
const int mi_row_start = AOMMAX(0, mi_row - FILT_BOUNDARY_MI_OFFSET);
const int mi_col_start = AOMMAX(0, mi_col - FILT_BOUNDARY_MI_OFFSET);
const int mi_row_range = mi_row - FILT_BOUNDARY_MI_OFFSET + MAX_MIB_SIZE;
const int mi_col_range = mi_col - FILT_BOUNDARY_MI_OFFSET + MAX_MIB_SIZE;
const int mi_row_end = AOMMIN(mi_row_range, cm->mi_rows);
const int mi_col_end = AOMMIN(mi_col_range, cm->mi_cols);
const int row = mi_row_start * MI_SIZE;
const int col = mi_col_start * MI_SIZE;
const uint16_t *src_y =
CONVERT_TO_SHORTPTR(src->y_buffer) + row * src->y_stride + col;
const uint16_t *frame_y =
CONVERT_TO_SHORTPTR(frame->y_buffer) + row * frame->y_stride + col;
const int row_end = (mi_row_end - mi_row_start) * MI_SIZE;
const int col_end = (mi_col_end - mi_col_start) * MI_SIZE;
int x, y;
for (y = 0; y < row_end; ++y) {
for (x = 0; x < col_end; ++x) {
const int diff = src_y[x] - frame_y[x];
sse += diff * diff;
}
src_y += src->y_stride;
frame_y += frame->y_stride;
}
return sse;
}
#endif
static int compute_sb_y_sse(const YV12_BUFFER_CONFIG *src,
const YV12_BUFFER_CONFIG *frame,
AV1_COMMON *const cm, int mi_row, int mi_col) {
int sse = 0;
const int mi_row_start = AOMMAX(0, mi_row - FILT_BOUNDARY_MI_OFFSET);
const int mi_col_start = AOMMAX(0, mi_col - FILT_BOUNDARY_MI_OFFSET);
const int mi_row_range = mi_row - FILT_BOUNDARY_MI_OFFSET + MAX_MIB_SIZE;
const int mi_col_range = mi_col - FILT_BOUNDARY_MI_OFFSET + MAX_MIB_SIZE;
const int mi_row_end = AOMMIN(mi_row_range, cm->mi_rows);
const int mi_col_end = AOMMIN(mi_col_range, cm->mi_cols);
const int row = mi_row_start * MI_SIZE;
const int col = mi_col_start * MI_SIZE;
const uint8_t *src_y = src->y_buffer + row * src->y_stride + col;
const uint8_t *frame_y = frame->y_buffer + row * frame->y_stride + col;
const int row_end = (mi_row_end - mi_row_start) * MI_SIZE;
const int col_end = (mi_col_end - mi_col_start) * MI_SIZE;
int x, y;
for (y = 0; y < row_end; ++y) {
for (x = 0; x < col_end; ++x) {
const int diff = src_y[x] - frame_y[x];
sse += diff * diff;
}
src_y += src->y_stride;
frame_y += frame->y_stride;
}
return sse;
}
#endif // CONFIG_LPF_SB
#if !CONFIG_LPF_SB
static void yv12_copy_plane(const YV12_BUFFER_CONFIG *src_bc,
YV12_BUFFER_CONFIG *dst_bc, int plane) {
switch (plane) {
@ -104,7 +36,6 @@ static void yv12_copy_plane(const YV12_BUFFER_CONFIG *src_bc,
default: assert(plane >= 0 && plane <= 2); break;
}
}
#endif // CONFIG_LPF_SB
int av1_get_max_filter_level(const AV1_COMP *cpi) {
if (cpi->oxcf.pass == 2) {
@ -115,195 +46,58 @@ int av1_get_max_filter_level(const AV1_COMP *cpi) {
}
}
#if CONFIG_LPF_SB
// TODO(chengchen): reduce memory usage by copy superblock instead of frame
static int try_filter_superblock(const YV12_BUFFER_CONFIG *sd,
AV1_COMP *const cpi, int filt_level,
int partial_frame, int mi_row, int mi_col) {
AV1_COMMON *const cm = &cpi->common;
int filt_err;
#if CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_CB4X4
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filt_level, 1,
partial_frame, mi_row, mi_col);
#else
if (cpi->num_workers > 1)
av1_loop_filter_frame_mt(cm->frame_to_show, cm, cpi->td.mb.e_mbd.plane,
filt_level, 1, partial_frame, cpi->workers,
cpi->num_workers, &cpi->lf_row_sync);
else
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filt_level,
1, partial_frame);
#endif
#if CONFIG_HIGHBITDEPTH
if (cm->use_highbitdepth) {
filt_err =
compute_sb_y_sse_highbd(sd, cm->frame_to_show, cm, mi_row, mi_col);
} else {
filt_err = compute_sb_y_sse(sd, cm->frame_to_show, cm, mi_row, mi_col);
}
#else
filt_err = compute_sb_y_sse(sd, cm->frame_to_show, cm, mi_row, mi_col);
#endif // CONFIG_HIGHBITDEPTH
// TODO(chengchen): Copy the superblock only
// Re-instate the unfiltered frame
aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
return filt_err;
}
static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
int partial_frame, double *best_cost_ret,
int mi_row, int mi_col, int last_lvl) {
assert(partial_frame == 1);
assert(last_lvl >= 0);
const AV1_COMMON *const cm = &cpi->common;
MACROBLOCK *x = &cpi->td.mb;
int min_filter_level = AOMMAX(0, last_lvl - MAX_LPF_OFFSET);
int max_filter_level =
AOMMIN(av1_get_max_filter_level(cpi), last_lvl + MAX_LPF_OFFSET);
// search a larger range for the start superblock
if (mi_row == 0 && mi_col == 0) {
min_filter_level = 0;
max_filter_level = av1_get_max_filter_level(cpi);
}
// TODO(chengchen): Copy for superblock only
// Make a copy of the unfiltered / processed recon buffer
aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
int estimate_err =
try_filter_superblock(sd, cpi, last_lvl, partial_frame, mi_row, mi_col);
int best_err = estimate_err;
int filt_best = last_lvl;
int i;
for (i = min_filter_level; i <= max_filter_level; i += LPF_STEP) {
if (i == last_lvl) continue;
int filt_err =
try_filter_superblock(sd, cpi, i, partial_frame, mi_row, mi_col);
if (filt_err < best_err) {
best_err = filt_err;
filt_best = i;
}
}
// If previous sb filter level has similar filtering performance as current
// best filter level, use previous level such that we can only send one bit
// to indicate current filter level is the same as the previous.
int threshold = 400;
// ratio = the filtering area / a superblock size
int ratio = 1;
if (mi_row + MAX_MIB_SIZE > cm->mi_rows) {
ratio *= (cm->mi_rows - mi_row);
} else {
if (mi_row == 0) {
ratio *= (MAX_MIB_SIZE - FILT_BOUNDARY_MI_OFFSET);
} else {
ratio *= MAX_MIB_SIZE;
}
}
if (mi_col + MAX_MIB_SIZE > cm->mi_cols) {
ratio *= (cm->mi_cols - mi_col);
} else {
if (mi_col == 0) {
ratio *= (MAX_MIB_SIZE - FILT_BOUNDARY_MI_OFFSET);
} else {
ratio *= MAX_MIB_SIZE;
}
}
threshold = threshold * ratio / (MAX_MIB_SIZE * MAX_MIB_SIZE);
const int diff = abs(estimate_err - best_err);
const int percent_thresh = (int)((double)estimate_err * 0.01);
threshold = AOMMAX(threshold, percent_thresh);
if (diff < threshold) {
best_err = estimate_err;
filt_best = last_lvl;
}
// Compute rdcost to determine whether to reuse previous filter lvl
if (filt_best != last_lvl) {
}
if (best_cost_ret) *best_cost_ret = RDCOST_DBL(x->rdmult, 0, best_err);
return filt_best;
}
#else // CONFIG_LPF_SB
static int64_t try_filter_frame(const YV12_BUFFER_CONFIG *sd,
AV1_COMP *const cpi, int filt_level,
int partial_frame
#if CONFIG_LOOPFILTER_LEVEL
,
int plane, int dir
#endif
) {
int partial_frame, int plane, int dir) {
AV1_COMMON *const cm = &cpi->common;
int64_t filt_err;
#if CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_CB4X4
#if CONFIG_LOOPFILTER_LEVEL
assert(plane >= 0 && plane <= 2);
int filter_level[2] = { filt_level, filt_level };
if (plane == 0 && dir == 0) filter_level[1] = cm->lf.filter_level[1];
if (plane == 0 && dir == 1) filter_level[0] = cm->lf.filter_level[0];
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd,
filter_level[0], filter_level[1], plane, partial_frame);
#else
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filt_level, 1,
partial_frame);
#endif // CONFIG_LOOPFILTER_LEVEL
// set base filters for use of get_filter_level when in DELTA_Q_LF mode
switch (plane) {
case 0:
cm->lf.filter_level[0] = filter_level[0];
cm->lf.filter_level[1] = filter_level[1];
break;
case 1: cm->lf.filter_level_u = filter_level[0]; break;
case 2: cm->lf.filter_level_v = filter_level[0]; break;
}
// TODO(any): please enable multi-thread and remove the flag when loop
// filter mask is compatible with multi-thread.
#if LOOP_FILTER_BITMASK
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, plane,
plane + 1, partial_frame);
#else
if (cpi->num_workers > 1)
av1_loop_filter_frame_mt(cm->frame_to_show, cm, cpi->td.mb.e_mbd.plane,
filt_level, 1, partial_frame, cpi->workers,
av1_loop_filter_frame_mt(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, plane,
plane + 1, partial_frame, cpi->workers,
cpi->num_workers, &cpi->lf_row_sync);
else
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filt_level,
1, partial_frame);
av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, plane,
plane + 1, partial_frame);
#endif
int highbd = 0;
#if CONFIG_HIGHBITDEPTH
highbd = cm->use_highbitdepth;
#endif // CONFIG_HIGHBITDEPTH
#if CONFIG_LOOPFILTER_LEVEL
filt_err = aom_get_sse_plane(sd, cm->frame_to_show, plane, highbd);
// Re-instate the unfiltered frame
yv12_copy_plane(&cpi->last_frame_uf, cm->frame_to_show, plane);
#else
filt_err = aom_get_sse_plane(sd, cm->frame_to_show, 0, highbd);
// Re-instate the unfiltered frame
yv12_copy_plane(&cpi->last_frame_uf, cm->frame_to_show, 0);
#endif // CONFIG_LOOPFILTER_LEVEL
return filt_err;
}
static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
int partial_frame, double *best_cost_ret
#if CONFIG_LOOPFILTER_LEVEL
,
int plane, int dir
#endif
) {
int partial_frame,
const int *last_frame_filter_level,
double *best_cost_ret, int plane, int dir) {
const AV1_COMMON *const cm = &cpi->common;
const struct loopfilter *const lf = &cm->lf;
const int min_filter_level = 0;
const int max_filter_level = av1_get_max_filter_level(cpi);
int filt_direction = 0;
@ -311,39 +105,24 @@ static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
int filt_best;
MACROBLOCK *x = &cpi->td.mb;
// Start the search at the previous frame filter level unless it is now out of
// range.
#if CONFIG_LOOPFILTER_LEVEL
// Start the search at the previous frame filter level unless it is now out of
// range.
int lvl;
switch (plane) {
case 0: lvl = (dir == 1) ? lf->filter_level[1] : lf->filter_level[0]; break;
case 1: lvl = lf->filter_level_u; break;
case 2: lvl = lf->filter_level_v; break;
case 0: lvl = last_frame_filter_level[dir]; break;
case 1: lvl = last_frame_filter_level[2]; break;
case 2: lvl = last_frame_filter_level[3]; break;
default: assert(plane >= 0 && plane <= 2); return 0;
}
int filt_mid = clamp(lvl, min_filter_level, max_filter_level);
#else
int filt_mid = clamp(lf->filter_level, min_filter_level, max_filter_level);
#endif // CONFIG_LOOPFILTER_LEVEL
int filter_step = filt_mid < 16 ? 4 : filt_mid / 4;
// Sum squared error at each filter level
int64_t ss_err[MAX_LOOP_FILTER + 1];
// Set each entry to -1
memset(ss_err, 0xFF, sizeof(ss_err));
#if CONFIG_LOOPFILTER_LEVEL
yv12_copy_plane(cm->frame_to_show, &cpi->last_frame_uf, plane);
#else
// Make a copy of the unfiltered / processed recon buffer
aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
#endif // CONFIG_LOOPFILTER_LEVEL
#if CONFIG_LOOPFILTER_LEVEL
best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame, plane, dir);
#else
best_err = try_filter_frame(sd, cpi, filt_mid, partial_frame);
#endif // CONFIG_LOOPFILTER_LEVEL
filt_best = filt_mid;
ss_err[filt_mid] = best_err;
@ -363,12 +142,8 @@ static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
if (filt_direction <= 0 && filt_low != filt_mid) {
// Get Low filter error score
if (ss_err[filt_low] < 0) {
#if CONFIG_LOOPFILTER_LEVEL
ss_err[filt_low] =
try_filter_frame(sd, cpi, filt_low, partial_frame, plane, dir);
#else
ss_err[filt_low] = try_filter_frame(sd, cpi, filt_low, partial_frame);
#endif // CONFIG_LOOPFILTER_LEVEL
}
// If value is close to the best so far then bias towards a lower loop
// filter value.
@ -384,12 +159,8 @@ static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
// Now look at filt_high
if (filt_direction >= 0 && filt_high != filt_mid) {
if (ss_err[filt_high] < 0) {
#if CONFIG_LOOPFILTER_LEVEL
ss_err[filt_high] =
try_filter_frame(sd, cpi, filt_high, partial_frame, plane, dir);
#else
ss_err[filt_high] = try_filter_frame(sd, cpi, filt_high, partial_frame);
#endif // CONFIG_LOOPFILTER_LEVEL
}
// If value is significantly better than previous best, bias added against
// raising filter value
@ -415,33 +186,36 @@ static int search_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
if (best_cost_ret) *best_cost_ret = RDCOST_DBL(x->rdmult, 0, best_err);
return filt_best;
}
#endif // CONFIG_LPF_SB
void av1_pick_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
LPF_PICK_METHOD method) {
AV1_COMMON *const cm = &cpi->common;
const int num_planes = av1_num_planes(cm);
struct loopfilter *const lf = &cm->lf;
(void)sd;
lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 : cpi->oxcf.sharpness;
lf->sharpness_level = 0;
if (method == LPF_PICK_MINIMAL_LPF) {
#if CONFIG_LOOPFILTER_LEVEL
lf->filter_level[0] = 0;
lf->filter_level[1] = 0;
#else
lf->filter_level = 0;
#endif
} else if (method >= LPF_PICK_FROM_Q) {
const int min_filter_level = 0;
const int max_filter_level = av1_get_max_filter_level(cpi);
const int q = av1_ac_quant(cm->base_qindex, 0, cm->bit_depth);
// These values were determined by linear fitting the result of the
// searched level, filt_guess = q * 0.316206 + 3.87252
#if CONFIG_HIGHBITDEPTH
const int q = av1_ac_quant_Q3(cm->base_qindex, 0, cm->bit_depth);
// These values were determined by linear fitting the result of the
// searched level for 8 bit depth:
// Keyframes: filt_guess = q * 0.06699 - 1.60817
// Other frames: filt_guess = q * 0.02295 + 2.48225
//
// And high bit depth separately:
// filt_guess = q * 0.316206 + 3.87252
int filt_guess;
switch (cm->bit_depth) {
case AOM_BITS_8:
filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 1015158, 18);
filt_guess = (cm->frame_type == KEY_FRAME)
? ROUND_POWER_OF_TWO(q * 17563 - 421574, 18)
: ROUND_POWER_OF_TWO(q * 6017 + 650707, 18);
break;
case AOM_BITS_10:
filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 4060632, 20);
@ -455,58 +229,36 @@ void av1_pick_filter_level(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
"or AOM_BITS_12");
return;
}
#else
int filt_guess = ROUND_POWER_OF_TWO(q * 20723 + 1015158, 18);
#endif // CONFIG_HIGHBITDEPTH
if (cm->frame_type == KEY_FRAME) filt_guess -= 4;
#if CONFIG_LOOPFILTER_LEVEL
if (cm->bit_depth != AOM_BITS_8 && cm->frame_type == KEY_FRAME)
filt_guess -= 4;
// TODO(chengchen): retrain the model for Y, U, V filter levels
lf->filter_level[0] = clamp(filt_guess, min_filter_level, max_filter_level);
lf->filter_level[1] = clamp(filt_guess, min_filter_level, max_filter_level);
#else
lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level);
#endif
lf->filter_level_u = clamp(filt_guess, min_filter_level, max_filter_level);
lf->filter_level_v = clamp(filt_guess, min_filter_level, max_filter_level);
} else {
#if CONFIG_LPF_SB
int mi_row, mi_col;
// TODO(chengchen): init last_lvl using previous frame's info?
int last_lvl = 0;
// TODO(chengchen): if the frame size makes the last superblock very small,
// consider merge it to the previous superblock to save bits.
// Example, if frame size 1080x720, then in the last row of superblock,
// there're (FILT_BOUNDAR_OFFSET + 16) pixels.
for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MAX_MIB_SIZE) {
for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MAX_MIB_SIZE) {
int lvl =
search_filter_level(sd, cpi, 1, NULL, mi_row, mi_col, last_lvl);
const int last_frame_filter_level[4] = { lf->filter_level[0],
lf->filter_level[1],
lf->filter_level_u,
lf->filter_level_v };
av1_loop_filter_sb_level_init(cm, mi_row, mi_col, lvl);
lf->filter_level[0] = lf->filter_level[1] =
search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE,
last_frame_filter_level, NULL, 0, 2);
lf->filter_level[0] =
search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE,
last_frame_filter_level, NULL, 0, 0);
lf->filter_level[1] =
search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE,
last_frame_filter_level, NULL, 0, 1);
// For the superblock at row start, its previous filter level should be
// the one above it, not the one at the end of last row
if (mi_col + MAX_MIB_SIZE >= cm->mi_cols) {
last_lvl = cm->mi_grid_visible[mi_row * cm->mi_stride]->mbmi.filt_lvl;
} else {
last_lvl = lvl;
}
}
if (num_planes > 1) {
lf->filter_level_u =
search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE,
last_frame_filter_level, NULL, 1, 0);
lf->filter_level_v =
search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE,
last_frame_filter_level, NULL, 2, 0);
}
#else // CONFIG_LPF_SB
#if CONFIG_LOOPFILTER_LEVEL
lf->filter_level[0] = lf->filter_level[1] = search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 2);
lf->filter_level[0] = search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 0);
lf->filter_level[1] = search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 0, 1);
lf->filter_level_u = search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 1, 0);
lf->filter_level_v = search_filter_level(
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL, 2, 0);
#else
lf->filter_level =
search_filter_level(sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, NULL);
#endif // CONFIG_LOOPFILTER_LEVEL
#endif // CONFIG_LPF_SB
}
}

File diff suppressed because it is too large Load diff

View file

@ -20,8 +20,7 @@ extern "C" {
struct yv12_buffer_config;
struct AV1_COMP;
void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi,
LPF_PICK_METHOD method);
void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *sd, AV1_COMP *cpi);
#ifdef __cplusplus
} // extern "C"

229
third_party/aom/av1/encoder/pustats.h vendored Normal file
View file

@ -0,0 +1,229 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_ENCODER_PUSTATS_H_
#define AV1_ENCODER_PUSTATS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "av1/encoder/ml.h"
#define NUM_FEATURES 20
#define NUM_HIDDEN_LAYERS 2
#define HIDDEN_LAYERS_0_NODES 10
#define HIDDEN_LAYERS_1_NODES 10
#define LOGITS_NODES 1
static const float
av1_pustats_rate_hiddenlayer_0_kernel[NUM_FEATURES *
HIDDEN_LAYERS_0_NODES] = {
13.8498f, 19.6630f, 13.3036f, 5.2448f, -18.0270f, 21.6671f,
-0.2135f, -0.0060f, 0.1211f, -0.3549f, -0.3550f, 0.0190f,
0.0167f, -0.1192f, 0.2003f, 8.6663f, 32.0264f, 9.9558f,
9.0935f, -110.4994f, 51.8056f, 64.8041f, 58.5392f, 53.0189f,
-61.6300f, 4.7540f, -0.0140f, 0.0185f, -15.8050f, 0.0790f,
0.0707f, 0.0784f, 0.0766f, -0.3030f, 0.0392f, 49.3312f,
63.3326f, 61.4025f, 54.2723f, -62.2769f, -147.1736f, -84.9432f,
-82.5422f, -70.4857f, 46.7622f, -1.0285f, -0.4809f, 0.0068f,
1.0888f, -0.0515f, -0.0384f, -0.0232f, -0.0396f, 0.2429f,
0.2040f, -144.4016f, -88.0868f, -80.3134f, -70.6685f, 66.8528f,
-53.8097f, -45.4011f, -52.8680f, -58.7226f, 99.7830f, 2.3728f,
0.0229f, 0.0002f, -0.3288f, -0.0563f, -0.0550f, -0.0552f,
-0.0563f, 0.2214f, 0.0139f, -60.8965f, -45.5251f, -50.4188f,
-51.5623f, 85.7369f, 77.3415f, 47.4930f, 53.8120f, 58.2311f,
-45.9650f, -2.4938f, 0.1639f, -0.5270f, -75.4622f, -0.0026f,
0.0031f, 0.0047f, 0.0015f, 0.0092f, 0.0654f, 75.6402f,
54.7447f, 54.8156f, 52.6834f, -9.1246f, -34.0108f, -35.6423f,
-34.2911f, -38.5444f, 72.1123f, 10.9750f, -0.1595f, 0.1983f,
22.5724f, -0.0556f, -0.0618f, -0.0571f, -0.0608f, 0.2439f,
-0.0805f, -32.5107f, -28.9688f, -33.7284f, -48.1365f, 61.5297f,
39.2492f, -35.1928f, -11.5000f, 7.7038f, -94.2469f, 13.5586f,
0.7541f, 0.0105f, 4.4041f, 0.1799f, 0.1339f, 0.1567f,
-0.6668f, -0.7384f, 0.2185f, 17.1700f, -26.4601f, -1.8970f,
38.9635f, -30.1916f, 31.8139f, 14.6157f, 10.0565f, 3.3340f,
-40.6985f, -2.1186f, 0.0116f, 0.0962f, 0.7115f, -1.4071f,
-1.3701f, -1.4728f, -1.3404f, -1.7286f, 5.5632f, 28.4998f,
5.4087f, 16.2668f, 11.8693f, -39.4153f, 106.3281f, 38.3075f,
39.4933f, 47.3805f, -15.0514f, -21.2421f, -0.2358f, -0.0024f,
0.3505f, -0.0429f, -0.0377f, -0.0322f, -0.0344f, 0.2020f,
0.1417f, 99.6711f, 35.3896f, 43.1117f, 59.8879f, -17.8250f,
-16.6976f, 18.5100f, 6.3383f, 25.3020f, -55.8824f, 25.1027f,
-0.9926f, -0.0738f, -1.4892f, 0.0269f, -0.0051f, -5.8168f,
-0.0579f, -0.1500f, 0.7224f, 8.3066f, -3.8805f, -12.1482f,
14.3492f, -20.8118f,
};
static const float av1_pustats_rate_hiddenlayer_0_bias[HIDDEN_LAYERS_0_NODES] =
{
17.6566f, 62.2217f, -107.2644f, -56.2255f, 68.2252f,
-37.5662f, 9.587f, 18.5206f, 69.6873f, 4.3903f,
};
static const float
av1_pustats_rate_hiddenlayer_1_kernel[HIDDEN_LAYERS_0_NODES *
HIDDEN_LAYERS_1_NODES] = {
-0.0494f, 0.3505f, -0.0461f, -1.3451f, 0.0198f, -0.0746f, -0.2217f,
-0.9525f, 0.0633f, -0.0737f, -0.3568f, 1.8569f, -0.0189f, -1.8269f,
0.6281f, -1.3266f, -0.9202f, 2.8978f, -0.6437f, -0.8709f, -1.5066f,
-1.0582f, -1.9509f, -0.0417f, -0.1315f, -0.3368f, 0.0014f, -0.5734f,
-1.4640f, -1.6042f, 3.3911f, -1.6815f, -1.9026f, -4.8702f, -0.1012f,
-1.4517f, -3.2156f, 0.8448f, 0.2331f, -0.1593f, 2.6627f, -0.8451f,
-1.7382f, 0.9303f, 2.3003f, -0.0659f, 0.5772f, 0.4253f, 0.2083f,
0.3649f, -0.9198f, -0.2183f, -0.5381f, -1.0831f, 2.0359f, 0.0040f,
-0.0871f, -0.1715f, 2.2453f, 0.5099f, -0.5900f, -0.6313f, -1.3028f,
-1.7257f, 1.4130f, -0.7189f, -0.4336f, 1.9266f, 1.7495f, -0.3321f,
0.2827f, 0.4015f, -0.5044f, -1.0420f, -0.1258f, -0.0342f, -0.1190f,
-3.1263f, 0.7485f, -0.3161f, -0.2224f, 2.5533f, -0.2121f, -1.3389f,
0.5556f, -0.9407f, -0.7456f, 1.4137f, -0.0353f, -0.0521f, 2.4382f,
0.1493f, -11.5631f, -1.6178f, 3.5538f, -3.6538f, -0.5972f, -3.0038f,
-2.1640f, 0.5754f,
};
static const float av1_pustats_rate_hiddenlayer_1_bias[HIDDEN_LAYERS_1_NODES] =
{
69.1995f, 41.7369f, -1.4885f, -35.785f, 26.1678f,
58.4472f, 36.2223f, 66.327f, 50.8867f, 2.8306f,
};
static const float
av1_pustats_rate_logits_kernel[HIDDEN_LAYERS_1_NODES * LOGITS_NODES] = {
1.811f, 0.9009f, 0.0694f, -0.9985f, -0.039f,
0.2076f, 0.5643f, 0.5408f, 0.6071f, 0.277f,
};
static const float av1_pustats_rate_logits_bias[LOGITS_NODES] = {
39.5529f,
};
static const NN_CONFIG av1_pustats_rate_nnconfig = {
NUM_FEATURES, // num_inputs
LOGITS_NODES, // num_outputs
NUM_HIDDEN_LAYERS, // num_hidden_layers
{ HIDDEN_LAYERS_0_NODES, HIDDEN_LAYERS_1_NODES }, // num_hidden_nodes
{
av1_pustats_rate_hiddenlayer_0_kernel,
av1_pustats_rate_hiddenlayer_1_kernel,
av1_pustats_rate_logits_kernel,
},
{
av1_pustats_rate_hiddenlayer_0_bias,
av1_pustats_rate_hiddenlayer_1_bias,
av1_pustats_rate_logits_bias,
},
};
static const float
av1_pustats_dist_hiddenlayer_0_kernel[NUM_FEATURES *
HIDDEN_LAYERS_0_NODES] = {
-39.0787f, -212.9998f, -174.2088f, -264.1454f, 292.7151f, -60.8750f,
-5.9915f, 0.0712f, -60.2312f, -0.2020f, -0.2135f, -0.1663f,
-0.0711f, 0.2267f, 0.9152f, -36.1294f, -159.9320f, -222.9809f,
-270.2556f, 300.7162f, 159.9224f, -172.5735f, -7.6852f, 54.3985f,
110.6721f, 19.2907f, -15.1039f, -0.0457f, 0.3289f, 0.4529f,
-8.2222f, 1.3213f, -0.8378f, -0.2605f, 3.9600f, 17.3407f,
113.1116f, 34.6326f, 11.6688f, 109.3541f, 240.8123f, 45.0615f,
80.7443f, 39.2500f, -21.0931f, -27.1989f, -0.4264f, -0.1345f,
1.6269f, -0.0716f, 0.0989f, -0.1382f, 0.0248f, 0.0913f,
4.3903f, 244.1014f, 32.2567f, 58.6171f, 62.2273f, -2.8647f,
-227.5659f, 16.0031f, -70.5256f, 23.8071f, 290.7356f, 13.6094f,
-2.1842f, 0.0104f, -2.8760f, 0.3708f, 0.8501f, -3.2964f,
-0.2088f, -0.4474f, 1.2248f, 40.5180f, -130.7891f, -188.1583f,
-174.0906f, 205.9622f, 0.3425f, 0.2531f, 0.2822f, 0.0488f,
0.1416f, -0.0433f, -0.1195f, -0.0413f, -0.0708f, -0.0787f,
-0.0889f, -0.4022f, -0.5055f, -0.4715f, 0.2315f, 0.1021f,
-0.3676f, -0.3499f, -0.0715f, 0.1913f, 205.7521f, 125.2265f,
92.0640f, 77.5566f, -164.4280f, -19.3715f, -0.1346f, -0.4060f,
0.5042f, -0.2395f, -0.1329f, -0.1397f, 0.2175f, 0.2895f,
5.5019f, 198.9799f, 114.0018f, 94.9015f, 86.8434f, -183.4237f,
121.5626f, 94.8945f, 65.0803f, 93.6487f, -346.5279f, -47.6168f,
0.0633f, 0.0135f, -0.0692f, -0.1015f, -0.1146f, -0.1341f,
-0.1175f, 0.4186f, 0.1505f, 130.7402f, 107.8443f, 62.8497f,
65.3501f, -312.7407f, 282.8321f, 98.1531f, 75.6648f, 25.8733f,
-176.9298f, -37.2695f, -0.3760f, 0.0017f, 0.1030f, -0.1483f,
0.0787f, -0.0962f, 0.4109f, -0.2292f, 9.1681f, 274.3607f,
60.9538f, 75.9405f, 68.3776f, -167.3098f, -335.1045f, -69.2583f,
-76.3441f, -16.5793f, 218.5244f, 28.2405f, 0.9169f, -0.0026f,
-0.8077f, -1.5756f, -0.0804f, 0.1404f, 1.2656f, 0.0272f,
-0.2529f, -340.8659f, -112.7778f, -58.3890f, -4.1224f, 108.1709f,
-180.7382f, -93.7114f, -77.8686f, -131.8134f, 353.3893f, 4.8233f,
0.0205f, 0.0000f, -1.1654f, -0.0161f, -0.0255f, -0.0358f,
-0.0412f, 0.1103f, 0.1041f, -188.9934f, -110.1792f, -88.6301f,
-93.7226f, 336.9746f,
};
static const float av1_pustats_dist_hiddenlayer_0_bias[HIDDEN_LAYERS_0_NODES] =
{ -175.6918f, 43.4519f, 154.196f, -81.1015f, -0.0758f,
136.5695f, 110.8713f, 142.029f, -153.0901f, -145.2688f };
static const float
av1_pustats_dist_hiddenlayer_1_kernel[HIDDEN_LAYERS_0_NODES *
HIDDEN_LAYERS_1_NODES] = {
-0.1727f, -0.2859f, -0.3757f, -0.4260f, -0.5441f, -0.0666f, -0.3792f,
-0.1335f, -0.1521f, -0.0821f, -3.1590f, 0.2711f, 0.5889f, 0.0878f,
0.4693f, 0.7773f, -9.2989f, 0.0414f, 0.4485f, 22.8958f, -3.7024f,
-2.4672f, -43.2908f, 0.0956f, 0.4431f, 2.3429f, 1.7183f, 0.3985f,
-0.2275f, -3.1583f, -0.3485f, 0.3280f, 0.3763f, 0.2069f, 0.4231f,
0.7366f, -6.9527f, 0.0713f, 0.1359f, 16.6500f, -1.7655f, -0.1651f,
0.1280f, -0.2678f, -0.2120f, 1.6243f, 1.8773f, -0.7543f, -0.3292f,
-0.7627f, -0.2001f, -0.1125f, -0.8100f, -0.1866f, 0.0567f, -0.4002f,
3.2429f, 0.6427f, -0.3759f, -11.6518f, -2.2893f, 0.7708f, -1.8637f,
1.7148f, 0.3124f, -0.7129f, -0.4927f, 0.1964f, -0.2570f, -25.0783f,
2.5061f, 0.1457f, -1.1239f, 0.0570f, -0.2526f, -0.0669f, 0.6791f,
1.1531f, -0.7246f, -0.3180f, -0.0015f, -0.0061f, -0.1626f, -0.0181f,
0.1271f, -0.0140f, -0.6027f, 0.0736f, -0.0157f, 1.2420f, -6.4055f,
0.2128f, -0.0386f, 0.3446f, 0.1840f, -0.7208f, -1.6979f, -0.0442f,
0.3230f, -1.9745f,
};
static const float av1_pustats_dist_hiddenlayer_1_bias[HIDDEN_LAYERS_1_NODES] =
{ 0.f, 70.3414f, 9.6036f, -118.1096f, 49.2507f,
95.1849f, 81.8015f, 167.0967f, -337.7945f, 169.8344f };
static const float
av1_pustats_dist_logits_kernel[HIDDEN_LAYERS_1_NODES * LOGITS_NODES] = {
-0.3627f, 1.2272f, 0.2201f, -1.7406f, -0.6885f,
0.8487f, -0.2761f, 0.7731f, -5.2096f, -0.7351f,
};
static const float av1_pustats_dist_logits_bias[LOGITS_NODES] = {
48.2331f,
};
static const NN_CONFIG av1_pustats_dist_nnconfig = {
NUM_FEATURES, // num_inputs
LOGITS_NODES, // num_outputs
NUM_HIDDEN_LAYERS, // num_hidden_layers
{ HIDDEN_LAYERS_0_NODES, HIDDEN_LAYERS_1_NODES }, // num_hidden_nodes
{
av1_pustats_dist_hiddenlayer_0_kernel,
av1_pustats_dist_hiddenlayer_1_kernel,
av1_pustats_dist_logits_kernel,
},
{
av1_pustats_dist_hiddenlayer_0_bias,
av1_pustats_dist_hiddenlayer_1_bias,
av1_pustats_dist_logits_bias,
},
};
#undef NUM_FEATURES
#undef NUM_HIDDEN_LAYERS
#undef HIDDEN_LAYERS_0_NODES
#undef HIDDEN_LAYERS_1_NODES
#undef LOGITS_NODES
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AV1_ENCODER_PUSTATS_H_

View file

@ -1,988 +0,0 @@
/*
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
/* clang-format off */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "aom_dsp/entcode.h"
#include "aom_dsp/entenc.h"
#include "av1/common/blockd.h"
#include "av1/common/odintrin.h"
#include "av1/common/partition.h"
#include "av1/common/pvq_state.h"
#include "av1/encoder/encodemb.h"
#include "av1/encoder/pvq_encoder.h"
#include "aom_ports/system_state.h"
/*Shift to ensure that the upper bound (i.e. for the max blocksize) of the
dot-product of the 1st band of chroma with the luma ref doesn't overflow.*/
#define OD_CFL_FLIP_SHIFT (OD_LIMIT_BSIZE_MAX + 0)
void aom_write_symbol_pvq(aom_writer *w, int symb, aom_cdf_prob *cdf,
int nsymbs) {
if (cdf[0] == 0)
aom_cdf_init_q15_1D(cdf, nsymbs, CDF_SIZE(nsymbs));
aom_write_symbol(w, symb, cdf, nsymbs);
}
static void aom_encode_pvq_codeword(aom_writer *w, od_pvq_codeword_ctx *adapt,
const od_coeff *in, int n, int k) {
int i;
aom_encode_band_pvq_splits(w, adapt, in, n, k, 0);
for (i = 0; i < n; i++) if (in[i]) aom_write_bit(w, in[i] < 0);
}
/* Computes 1/sqrt(i) using a table for small values. */
static double od_rsqrt_table(int i) {
static double table[16] = {
1.000000, 0.707107, 0.577350, 0.500000,
0.447214, 0.408248, 0.377964, 0.353553,
0.333333, 0.316228, 0.301511, 0.288675,
0.277350, 0.267261, 0.258199, 0.250000};
if (i <= 16) return table[i-1];
else return 1./sqrt(i);
}
/*Computes 1/sqrt(start+2*i+1) using a lookup table containing the results
where 0 <= i < table_size.*/
static double od_custom_rsqrt_dynamic_table(const double* table,
const int table_size, const double start, const int i) {
if (i < table_size) return table[i];
else return od_rsqrt_table((int)(start + 2*i + 1));
}
/*Fills tables used in od_custom_rsqrt_dynamic_table for a given start.*/
static void od_fill_dynamic_rsqrt_table(double *table, const int table_size,
const double start) {
int i;
for (i = 0; i < table_size; i++)
table[i] = od_rsqrt_table((int)(start + 2*i + 1));
}
/** Find the codepoint on the given PSphere closest to the desired
* vector. Double-precision PVQ search just to make sure our tests
* aren't limited by numerical accuracy.
*
* @param [in] xcoeff input vector to quantize (x in the math doc)
* @param [in] n number of dimensions
* @param [in] k number of pulses
* @param [out] ypulse optimal codevector found (y in the math doc)
* @param [out] g2 multiplier for the distortion (typically squared
* gain units)
* @param [in] pvq_norm_lambda enc->pvq_norm_lambda for quantized RDO
* @param [in] prev_k number of pulses already in ypulse that we should
* reuse for the search (or 0 for a new search)
* @return cosine distance between x and y (between 0 and 1)
*/
double pvq_search_rdo_double_c(const od_val16 *xcoeff, int n, int k,
od_coeff *ypulse, double g2, double pvq_norm_lambda, int prev_k) {
int i, j;
double xy;
double yy;
/* TODO - This blows our 8kB stack space budget and should be fixed when
converting PVQ to fixed point. */
double x[MAXN];
double xx;
double lambda;
double norm_1;
int rdo_pulses;
double delta_rate;
xx = xy = yy = 0;
for (j = 0; j < n; j++) {
x[j] = fabs((float)xcoeff[j]);
xx += x[j]*x[j];
}
norm_1 = 1./sqrt(1e-30 + xx);
lambda = pvq_norm_lambda/(1e-30 + g2);
i = 0;
if (prev_k > 0 && prev_k <= k) {
/* We reuse pulses from a previous search so we don't have to search them
again. */
for (j = 0; j < n; j++) {
ypulse[j] = abs(ypulse[j]);
xy += x[j]*ypulse[j];
yy += ypulse[j]*ypulse[j];
i += ypulse[j];
}
}
else if (k > 2) {
double l1_norm;
double l1_inv;
l1_norm = 0;
for (j = 0; j < n; j++) l1_norm += x[j];
l1_inv = 1./OD_MAXF(l1_norm, 1e-100);
for (j = 0; j < n; j++) {
double tmp;
tmp = k*x[j]*l1_inv;
ypulse[j] = OD_MAXI(0, (int)floor(tmp));
xy += x[j]*ypulse[j];
yy += ypulse[j]*ypulse[j];
i += ypulse[j];
}
}
else OD_CLEAR(ypulse, n);
/* Only use RDO on the last few pulses. This not only saves CPU, but using
RDO on all pulses actually makes the results worse for reasons I don't
fully understand. */
rdo_pulses = 1 + k/4;
/* Rough assumption for now, the last position costs about 3 bits more than
the first. */
delta_rate = 3./n;
/* Search one pulse at a time */
for (; i < k - rdo_pulses; i++) {
int pos;
double best_xy;
double best_yy;
pos = 0;
best_xy = -10;
best_yy = 1;
for (j = 0; j < n; j++) {
double tmp_xy;
double tmp_yy;
tmp_xy = xy + x[j];
tmp_yy = yy + 2*ypulse[j] + 1;
tmp_xy *= tmp_xy;
if (j == 0 || tmp_xy*best_yy > best_xy*tmp_yy) {
best_xy = tmp_xy;
best_yy = tmp_yy;
pos = j;
}
}
xy = xy + x[pos];
yy = yy + 2*ypulse[pos] + 1;
ypulse[pos]++;
}
/* Search last pulses with RDO. Distortion is D = (x-y)^2 = x^2 - 2*x*y + y^2
and since x^2 and y^2 are constant, we just maximize x*y, plus a
lambda*rate term. Note that since x and y aren't normalized here,
we need to divide by sqrt(x^2)*sqrt(y^2). */
for (; i < k; i++) {
double rsqrt_table[4];
int rsqrt_table_size = 4;
int pos;
double best_cost;
pos = 0;
best_cost = -1e5;
/*Fill the small rsqrt lookup table with inputs relative to yy.
Specifically, the table of n values is filled with
rsqrt(yy + 1), rsqrt(yy + 2 + 1) .. rsqrt(yy + 2*(n-1) + 1).*/
od_fill_dynamic_rsqrt_table(rsqrt_table, rsqrt_table_size, yy);
for (j = 0; j < n; j++) {
double tmp_xy;
double tmp_yy;
tmp_xy = xy + x[j];
/*Calculate rsqrt(yy + 2*ypulse[j] + 1) using an optimized method.*/
tmp_yy = od_custom_rsqrt_dynamic_table(rsqrt_table, rsqrt_table_size,
yy, ypulse[j]);
tmp_xy = 2*tmp_xy*norm_1*tmp_yy - lambda*j*delta_rate;
if (j == 0 || tmp_xy > best_cost) {
best_cost = tmp_xy;
pos = j;
}
}
xy = xy + x[pos];
yy = yy + 2*ypulse[pos] + 1;
ypulse[pos]++;
}
for (i = 0; i < n; i++) {
if (xcoeff[i] < 0) ypulse[i] = -ypulse[i];
}
return xy/(1e-100 + sqrt(xx*yy));
}
/** Encodes the gain so that the return value increases with the
* distance |x-ref|, so that we can encode a zero when x=ref. The
* value x=0 is not covered because it is only allowed in the noref
* case.
*
* @param [in] x quantized gain to encode
* @param [in] ref quantized gain of the reference
* @return interleave-encoded quantized gain value
*/
static int neg_interleave(int x, int ref) {
if (x < ref) return -2*(x - ref) - 1;
else if (x < 2*ref) return 2*(x - ref);
else return x-1;
}
int od_vector_is_null(const od_coeff *x, int len) {
int i;
for (i = 0; i < len; i++) if (x[i]) return 0;
return 1;
}
static double od_pvq_rate(int qg, int icgr, int theta, int ts,
const od_adapt_ctx *adapt, const od_coeff *y0, int k, int n, int speed) {
double rate;
if (k == 0) rate = 0;
else if (speed > 0) {
int i;
int sum;
double f;
/* Compute "center of mass" of the pulse vector. */
sum = 0;
for (i = 0; i < n - (theta != -1); i++) sum += i*abs(y0[i]);
f = sum/(double)(k*n);
/* Estimates the number of bits it will cost to encode K pulses in
N dimensions based on hand-tuned fit for bitrate vs K, N and
"center of mass". */
rate = (1 + .4*f)*n*OD_LOG2(1 + OD_MAXF(0, log(n*2*(1*f + .025))*k/n)) + 3;
}
else {
aom_writer w;
od_pvq_codeword_ctx cd;
int tell;
#if !CONFIG_ANS
od_ec_enc_init(&w.ec, 1000);
#else
# error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
OD_COPY(&cd, &adapt->pvq.pvq_codeword_ctx, 1);
#if !CONFIG_ANS
tell = od_ec_enc_tell_frac(&w.ec);
#else
# error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
aom_encode_pvq_codeword(&w, &cd, y0, n - (theta != -1), k);
#if !CONFIG_ANS
rate = (od_ec_enc_tell_frac(&w.ec)-tell)/8.;
od_ec_enc_clear(&w.ec);
#else
# error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
}
if (qg > 0 && theta >= 0) {
/* Approximate cost of entropy-coding theta */
rate += .9*OD_LOG2(ts);
if (qg == icgr) rate -= .5;
}
return rate;
}
#define MAX_PVQ_ITEMS (20)
/* This stores the information about a PVQ search candidate, so we can sort
based on K. */
typedef struct {
int gain;
int k;
od_val32 qtheta;
int theta;
int ts;
od_val32 qcg;
} pvq_search_item;
int items_compare(pvq_search_item *a, pvq_search_item *b) {
/* Break ties in K with gain to ensure a stable sort.
Otherwise, the order depends on qsort implementation. */
return a->k == b->k ? a->gain - b->gain : a->k - b->k;
}
/** Perform PVQ quantization with prediction, trying several
* possible gains and angles. See draft-valin-videocodec-pvq and
* http://jmvalin.ca/slides/pvq.pdf for more details.
*
* @param [out] out coefficients after quantization
* @param [in] x0 coefficients before quantization
* @param [in] r0 reference, aka predicted coefficients
* @param [in] n number of dimensions
* @param [in] q0 quantization step size
* @param [out] y pulse vector (i.e. selected PVQ codevector)
* @param [out] itheta angle between input and reference (-1 if noref)
* @param [out] vk total number of pulses
* @param [in] beta per-band activity masking beta param
* @param [out] skip_diff distortion cost of skipping this block
* (accumulated)
* @param [in] is_keyframe whether we're encoding a keyframe
* @param [in] pli plane index
* @param [in] adapt probability adaptation context
* @param [in] qm QM with magnitude compensation
* @param [in] qm_inv Inverse of QM with magnitude compensation
* @param [in] pvq_norm_lambda enc->pvq_norm_lambda for quantized RDO
* @param [in] speed Make search faster by making approximations
* @return gain index of the quatized gain
*/
static int pvq_theta(od_coeff *out, const od_coeff *x0, const od_coeff *r0,
int n, int q0, od_coeff *y, int *itheta, int *vk,
od_val16 beta, double *skip_diff, int is_keyframe, int pli,
const od_adapt_ctx *adapt, const int16_t *qm, const int16_t *qm_inv,
double pvq_norm_lambda, int speed) {
od_val32 g;
od_val32 gr;
od_coeff y_tmp[MAXN + 3];
int i;
/* Number of pulses. */
int k;
/* Companded gain of x and reference, normalized to q. */
od_val32 cg;
od_val32 cgr;
int icgr;
int qg;
/* Best RDO cost (D + lamdba*R) so far. */
double best_cost;
double dist0;
/* Distortion (D) that corresponds to the best RDO cost. */
double best_dist;
double dist;
/* Sign of Householder reflection. */
int s;
/* Dimension on which Householder reflects. */
int m;
od_val32 theta;
double corr;
int best_k;
od_val32 best_qtheta;
od_val32 gain_offset;
int noref;
double skip_dist;
int cfl_enabled;
int skip;
double gain_weight;
od_val16 x16[MAXN];
od_val16 r16[MAXN];
int xshift;
int rshift;
/* Give more weight to gain error when calculating the total distortion. */
gain_weight = 1.0;
OD_ASSERT(n > 1);
corr = 0;
#if !defined(OD_FLOAT_PVQ)
/* Shift needed to make x fit in 16 bits even after rotation.
This shift value is not normative (it can be changed without breaking
the bitstream) */
xshift = OD_MAXI(0, od_vector_log_mag(x0, n) - 15);
/* Shift needed to make the reference fit in 15 bits, so that the Householder
vector can fit in 16 bits.
This shift value *is* normative, and has to match the decoder. */
rshift = OD_MAXI(0, od_vector_log_mag(r0, n) - 14);
#else
xshift = 0;
rshift = 0;
#endif
for (i = 0; i < n; i++) {
#if defined(OD_FLOAT_PVQ)
/*This is slightly different from the original float PVQ code,
where the qm was applied in the accumulation in od_pvq_compute_gain and
the vectors were od_coeffs, not od_val16 (i.e. double).*/
x16[i] = x0[i]*(double)qm[i]*OD_QM_SCALE_1;
r16[i] = r0[i]*(double)qm[i]*OD_QM_SCALE_1;
#else
x16[i] = OD_SHR_ROUND(x0[i]*qm[i], OD_QM_SHIFT + xshift);
r16[i] = OD_SHR_ROUND(r0[i]*qm[i], OD_QM_SHIFT + rshift);
#endif
corr += OD_MULT16_16(x16[i], r16[i]);
}
cfl_enabled = is_keyframe && pli != 0 && !OD_DISABLE_CFL;
cg = od_pvq_compute_gain(x16, n, q0, &g, beta, xshift);
cgr = od_pvq_compute_gain(r16, n, q0, &gr, beta, rshift);
if (cfl_enabled) cgr = OD_CGAIN_SCALE;
/* gain_offset is meant to make sure one of the quantized gains has
exactly the same gain as the reference. */
#if defined(OD_FLOAT_PVQ)
icgr = (int)floor(.5 + cgr);
#else
icgr = OD_SHR_ROUND(cgr, OD_CGAIN_SHIFT);
#endif
gain_offset = cgr - OD_SHL(icgr, OD_CGAIN_SHIFT);
/* Start search with null case: gain=0, no pulse. */
qg = 0;
dist = gain_weight*cg*cg*OD_CGAIN_SCALE_2;
best_dist = dist;
best_cost = dist + pvq_norm_lambda*od_pvq_rate(0, 0, -1, 0, adapt, NULL, 0,
n, speed);
noref = 1;
best_k = 0;
*itheta = -1;
OD_CLEAR(y, n);
best_qtheta = 0;
m = 0;
s = 1;
corr = corr/(1e-100 + g*(double)gr/OD_SHL(1, xshift + rshift));
corr = OD_MAXF(OD_MINF(corr, 1.), -1.);
if (is_keyframe) skip_dist = gain_weight*cg*cg*OD_CGAIN_SCALE_2;
else {
skip_dist = gain_weight*(cg - cgr)*(cg - cgr)
+ cgr*(double)cg*(2 - 2*corr);
skip_dist *= OD_CGAIN_SCALE_2;
}
if (!is_keyframe) {
/* noref, gain=0 isn't allowed, but skip is allowed. */
od_val32 scgr;
scgr = OD_MAXF(0,gain_offset);
if (icgr == 0) {
best_dist = gain_weight*(cg - scgr)*(cg - scgr)
+ scgr*(double)cg*(2 - 2*corr);
best_dist *= OD_CGAIN_SCALE_2;
}
best_cost = best_dist + pvq_norm_lambda*od_pvq_rate(0, icgr, 0, 0, adapt,
NULL, 0, n, speed);
best_qtheta = 0;
*itheta = 0;
noref = 0;
}
dist0 = best_dist;
if (n <= OD_MAX_PVQ_SIZE && !od_vector_is_null(r0, n) && corr > 0) {
od_val16 xr[MAXN];
int gain_bound;
int prev_k;
pvq_search_item items[MAX_PVQ_ITEMS];
int idx;
int nitems;
double cos_dist;
idx = 0;
gain_bound = OD_SHR(cg - gain_offset, OD_CGAIN_SHIFT);
/* Perform theta search only if prediction is useful. */
theta = OD_ROUND32(OD_THETA_SCALE*acos(corr));
m = od_compute_householder(r16, n, gr, &s, rshift);
od_apply_householder(xr, x16, r16, n);
prev_k = 0;
for (i = m; i < n - 1; i++) xr[i] = xr[i + 1];
/* Compute all candidate PVQ searches within a reasonable range of gain
and theta. */
for (i = OD_MAXI(1, gain_bound - 1); i <= gain_bound + 1; i++) {
int j;
od_val32 qcg;
int ts;
int theta_lower;
int theta_upper;
/* Quantized companded gain */
qcg = OD_SHL(i, OD_CGAIN_SHIFT) + gain_offset;
/* Set angular resolution (in ra) to match the encoded gain */
ts = od_pvq_compute_max_theta(qcg, beta);
theta_lower = OD_MAXI(0, (int)floor(.5 +
theta*OD_THETA_SCALE_1*2/M_PI*ts) - 2);
theta_upper = OD_MINI(ts - 1, (int)ceil(theta*OD_THETA_SCALE_1*2/M_PI*ts));
/* Include the angles within a reasonable range. */
for (j = theta_lower; j <= theta_upper; j++) {
od_val32 qtheta;
qtheta = od_pvq_compute_theta(j, ts);
k = od_pvq_compute_k(qcg, j, 0, n, beta);
items[idx].gain = i;
items[idx].theta = j;
items[idx].k = k;
items[idx].qcg = qcg;
items[idx].qtheta = qtheta;
items[idx].ts = ts;
idx++;
OD_ASSERT(idx < MAX_PVQ_ITEMS);
}
}
nitems = idx;
cos_dist = 0;
/* Sort PVQ search candidates in ascending order of pulses K so that
we can reuse all the previously searched pulses across searches. */
qsort(items, nitems, sizeof(items[0]),
(int (*)(const void *, const void *))items_compare);
/* Search for the best gain/theta in order. */
for (idx = 0; idx < nitems; idx++) {
int j;
od_val32 qcg;
int ts;
double cost;
double dist_theta;
double sin_prod;
od_val32 qtheta;
/* Quantized companded gain */
qcg = items[idx].qcg;
i = items[idx].gain;
j = items[idx].theta;
/* Set angular resolution (in ra) to match the encoded gain */
ts = items[idx].ts;
/* Search for the best angle within a reasonable range. */
qtheta = items[idx].qtheta;
k = items[idx].k;
/* Compute the minimal possible distortion by not taking the PVQ
cos_dist into account. */
dist_theta = 2 - 2.*od_pvq_cos(theta - qtheta)*OD_TRIG_SCALE_1;
dist = gain_weight*(qcg - cg)*(qcg - cg) + qcg*(double)cg*dist_theta;
dist *= OD_CGAIN_SCALE_2;
/* If we have no hope of beating skip (including a 1-bit worst-case
penalty), stop now. */
if (dist > dist0 + 1.0*pvq_norm_lambda && k != 0) continue;
sin_prod = od_pvq_sin(theta)*OD_TRIG_SCALE_1*od_pvq_sin(qtheta)*
OD_TRIG_SCALE_1;
/* PVQ search, using a gain of qcg*cg*sin(theta)*sin(qtheta) since
that's the factor by which cos_dist is multiplied to get the
distortion metric. */
if (k == 0) {
cos_dist = 0;
OD_CLEAR(y_tmp, n-1);
}
else if (k != prev_k) {
cos_dist = pvq_search_rdo_double(xr, n - 1, k, y_tmp,
qcg*(double)cg*sin_prod*OD_CGAIN_SCALE_2, pvq_norm_lambda, prev_k);
}
prev_k = k;
/* See Jmspeex' Journal of Dubious Theoretical Results. */
dist_theta = 2 - 2.*od_pvq_cos(theta - qtheta)*OD_TRIG_SCALE_1
+ sin_prod*(2 - 2*cos_dist);
dist = gain_weight*(qcg - cg)*(qcg - cg) + qcg*(double)cg*dist_theta;
dist *= OD_CGAIN_SCALE_2;
/* Do approximate RDO. */
cost = dist + pvq_norm_lambda*od_pvq_rate(i, icgr, j, ts, adapt, y_tmp,
k, n, speed);
if (cost < best_cost) {
best_cost = cost;
best_dist = dist;
qg = i;
best_k = k;
best_qtheta = qtheta;
*itheta = j;
noref = 0;
OD_COPY(y, y_tmp, n - 1);
}
}
}
/* Don't bother with no-reference version if there's a reasonable
correlation. */
if (n <= OD_MAX_PVQ_SIZE && (corr < .5
|| cg < (od_val32)(OD_SHL(2, OD_CGAIN_SHIFT)))) {
int gain_bound;
int prev_k;
gain_bound = OD_SHR(cg, OD_CGAIN_SHIFT);
prev_k = 0;
/* Search for the best gain (haven't determined reasonable range yet). */
for (i = OD_MAXI(1, gain_bound); i <= gain_bound + 1; i++) {
double cos_dist;
double cost;
od_val32 qcg;
qcg = OD_SHL(i, OD_CGAIN_SHIFT);
k = od_pvq_compute_k(qcg, -1, 1, n, beta);
/* Compute the minimal possible distortion by not taking the PVQ
cos_dist into account. */
dist = gain_weight*(qcg - cg)*(qcg - cg);
dist *= OD_CGAIN_SCALE_2;
if (dist > dist0 && k != 0) continue;
cos_dist = pvq_search_rdo_double(x16, n, k, y_tmp,
qcg*(double)cg*OD_CGAIN_SCALE_2, pvq_norm_lambda, prev_k);
prev_k = k;
/* See Jmspeex' Journal of Dubious Theoretical Results. */
dist = gain_weight*(qcg - cg)*(qcg - cg)
+ qcg*(double)cg*(2 - 2*cos_dist);
dist *= OD_CGAIN_SCALE_2;
/* Do approximate RDO. */
cost = dist + pvq_norm_lambda*od_pvq_rate(i, 0, -1, 0, adapt, y_tmp, k,
n, speed);
if (cost <= best_cost) {
best_cost = cost;
best_dist = dist;
qg = i;
noref = 1;
best_k = k;
*itheta = -1;
OD_COPY(y, y_tmp, n);
}
}
}
k = best_k;
theta = best_qtheta;
skip = 0;
if (noref) {
if (qg == 0) skip = OD_PVQ_SKIP_ZERO;
}
else {
if (!is_keyframe && qg == 0) {
skip = (icgr ? OD_PVQ_SKIP_ZERO : OD_PVQ_SKIP_COPY);
}
if (qg == icgr && *itheta == 0 && !cfl_enabled) skip = OD_PVQ_SKIP_COPY;
}
/* Synthesize like the decoder would. */
if (skip) {
if (skip == OD_PVQ_SKIP_COPY) OD_COPY(out, r0, n);
else OD_CLEAR(out, n);
}
else {
if (noref) gain_offset = 0;
g = od_gain_expand(OD_SHL(qg, OD_CGAIN_SHIFT) + gain_offset, q0, beta);
od_pvq_synthesis_partial(out, y, r16, n, noref, g, theta, m, s,
qm_inv);
}
*vk = k;
*skip_diff += skip_dist - best_dist;
/* Encode gain differently depending on whether we use prediction or not.
Special encoding on inter frames where qg=0 is allowed for noref=0
but not noref=1.*/
if (is_keyframe) return noref ? qg : neg_interleave(qg, icgr);
else return noref ? qg - 1 : neg_interleave(qg + 1, icgr + 1);
}
/** Encodes a single vector of integers (eg, a partition within a
* coefficient block) using PVQ
*
* @param [in,out] w multi-symbol entropy encoder
* @param [in] qg quantized gain
* @param [in] theta quantized post-prediction theta
* @param [in] in coefficient vector to code
* @param [in] n number of coefficients in partition
* @param [in] k number of pulses in partition
* @param [in,out] model entropy encoder state
* @param [in,out] adapt adaptation context
* @param [in,out] exg ExQ16 expectation of gain value
* @param [in,out] ext ExQ16 expectation of theta value
* @param [in] cdf_ctx selects which cdf context to use
* @param [in] is_keyframe whether we're encoding a keyframe
* @param [in] code_skip whether the "skip rest" flag is allowed
* @param [in] skip_rest when set, we skip all higher bands
* @param [in] encode_flip whether we need to encode the CfL flip flag now
* @param [in] flip value of the CfL flip flag
*/
void pvq_encode_partition(aom_writer *w,
int qg,
int theta,
const od_coeff *in,
int n,
int k,
generic_encoder model[3],
od_adapt_ctx *adapt,
int *exg,
int *ext,
int cdf_ctx,
int is_keyframe,
int code_skip,
int skip_rest,
int encode_flip,
int flip) {
int noref;
int id;
noref = (theta == -1);
id = (qg > 0) + 2*OD_MINI(theta + 1,3) + 8*code_skip*skip_rest;
if (is_keyframe) {
OD_ASSERT(id != 8);
if (id >= 8) id--;
}
else {
OD_ASSERT(id != 10);
if (id >= 10) id--;
}
/* Jointly code gain, theta and noref for small values. Then we handle
larger gain and theta values. For noref, theta = -1. */
aom_write_symbol_pvq(w, id, &adapt->pvq.pvq_gaintheta_cdf[cdf_ctx][0],
8 + 7*code_skip);
if (encode_flip) {
/* We could eventually do some smarter entropy coding here, but it would
have to be good enough to overcome the overhead of the entropy coder.
An early attempt using a "toogle" flag with simple adaptation wasn't
worth the trouble. */
aom_write_bit(w, flip);
}
if (qg > 0) {
int tmp;
tmp = *exg;
generic_encode(w, &model[!noref], qg - 1, &tmp, 2);
OD_IIR_DIADIC(*exg, qg << 16, 2);
}
if (theta > 1) {
int tmp;
tmp = *ext;
generic_encode(w, &model[2], theta - 2, &tmp, 2);
OD_IIR_DIADIC(*ext, theta << 16, 2);
}
aom_encode_pvq_codeword(w, &adapt->pvq.pvq_codeword_ctx, in,
n - (theta != -1), k);
}
/** Quantizes a scalar with rate-distortion optimization (RDO)
* @param [in] x unquantized value
* @param [in] q quantization step size
* @param [in] delta0 rate increase for encoding a 1 instead of a 0
* @param [in] pvq_norm_lambda enc->pvq_norm_lambda for quantized RDO
* @retval quantized value
*/
int od_rdo_quant(od_coeff x, int q, double delta0, double pvq_norm_lambda) {
int n;
/* Optimal quantization threshold is 1/2 + lambda*delta_rate/2. See
Jmspeex' Journal of Dubious Theoretical Results for details. */
n = OD_DIV_R0(abs(x), q);
if ((double)abs(x)/q < (double)n/2 + pvq_norm_lambda*delta0/(2*n)) {
return 0;
}
else {
return OD_DIV_R0(x, q);
}
}
/** Encode a coefficient block (excepting DC) using PVQ
*
* @param [in,out] enc daala encoder context
* @param [in] ref 'reference' (prediction) vector
* @param [in] in coefficient block to quantize and encode
* @param [out] out quantized coefficient block
* @param [in] q0 scale/quantizer
* @param [in] pli plane index
* @param [in] bs log of the block size minus two
* @param [in] beta per-band activity masking beta param
* @param [in] is_keyframe whether we're encoding a keyframe
* @param [in] qm QM with magnitude compensation
* @param [in] qm_inv Inverse of QM with magnitude compensation
* @param [in] speed Make search faster by making approximations
* @param [in] pvq_info If null, conisdered as RDO search mode
* @return Returns block skip info indicating whether DC/AC are coded.
* bit0: DC is coded, bit1: AC is coded (1 means coded)
*
*/
PVQ_SKIP_TYPE od_pvq_encode(daala_enc_ctx *enc,
od_coeff *ref,
const od_coeff *in,
od_coeff *out,
int q_dc,
int q_ac,
int pli,
int bs,
const od_val16 *beta,
int is_keyframe,
const int16_t *qm,
const int16_t *qm_inv,
int speed,
PVQ_INFO *pvq_info){
int theta[PVQ_MAX_PARTITIONS];
int qg[PVQ_MAX_PARTITIONS];
int k[PVQ_MAX_PARTITIONS];
od_coeff y[OD_TXSIZE_MAX*OD_TXSIZE_MAX];
int *exg;
int *ext;
int nb_bands;
int i;
const int *off;
int size[PVQ_MAX_PARTITIONS];
generic_encoder *model;
double skip_diff;
int tell;
uint16_t *skip_cdf;
od_rollback_buffer buf;
int dc_quant;
int flip;
int cfl_encoded;
int skip_rest;
int skip_dir;
int skip_theta_value;
const unsigned char *pvq_qm;
double dc_rate;
int use_masking;
PVQ_SKIP_TYPE ac_dc_coded;
aom_clear_system_state();
use_masking = enc->use_activity_masking;
if (use_masking)
pvq_qm = &enc->state.pvq_qm_q4[pli][0];
else
pvq_qm = 0;
exg = &enc->state.adapt->pvq.pvq_exg[pli][bs][0];
ext = enc->state.adapt->pvq.pvq_ext + bs*PVQ_MAX_PARTITIONS;
skip_cdf = enc->state.adapt->skip_cdf[2*bs + (pli != 0)];
model = enc->state.adapt->pvq.pvq_param_model;
nb_bands = OD_BAND_OFFSETS[bs][0];
off = &OD_BAND_OFFSETS[bs][1];
if (use_masking)
dc_quant = OD_MAXI(1, q_dc * pvq_qm[od_qm_get_index(bs, 0)] >> 4);
else
dc_quant = OD_MAXI(1, q_dc);
tell = 0;
for (i = 0; i < nb_bands; i++) size[i] = off[i+1] - off[i];
skip_diff = 0;
flip = 0;
/*If we are coding a chroma block of a keyframe, we are doing CfL.*/
if (pli != 0 && is_keyframe) {
od_val32 xy;
xy = 0;
/*Compute the dot-product of the first band of chroma with the luma ref.*/
for (i = off[0]; i < off[1]; i++) {
#if defined(OD_FLOAT_PVQ)
xy += ref[i]*(double)qm[i]*OD_QM_SCALE_1*
(double)in[i]*(double)qm[i]*OD_QM_SCALE_1;
#else
od_val32 rq;
od_val32 inq;
rq = ref[i]*qm[i];
inq = in[i]*qm[i];
xy += OD_SHR(rq*(int64_t)inq, OD_SHL(OD_QM_SHIFT + OD_CFL_FLIP_SHIFT,
1));
#endif
}
/*If cos(theta) < 0, then |theta| > pi/2 and we should negate the ref.*/
if (xy < 0) {
flip = 1;
for(i = off[0]; i < off[nb_bands]; i++) ref[i] = -ref[i];
}
}
for (i = 0; i < nb_bands; i++) {
int q;
if (use_masking)
q = OD_MAXI(1, q_ac * pvq_qm[od_qm_get_index(bs, i + 1)] >> 4);
else
q = OD_MAXI(1, q_ac);
qg[i] = pvq_theta(out + off[i], in + off[i], ref + off[i], size[i],
q, y + off[i], &theta[i], &k[i], beta[i], &skip_diff, is_keyframe,
pli, enc->state.adapt, qm + off[i], qm_inv + off[i],
enc->pvq_norm_lambda, speed);
}
od_encode_checkpoint(enc, &buf);
if (is_keyframe) out[0] = 0;
else {
int n;
n = OD_DIV_R0(abs(in[0] - ref[0]), dc_quant);
if (n == 0) {
out[0] = 0;
} else {
int tell2;
od_rollback_buffer dc_buf;
dc_rate = -OD_LOG2((double)(OD_ICDF(skip_cdf[3]) - OD_ICDF(skip_cdf[2]))/
(double)(OD_ICDF(skip_cdf[2]) - OD_ICDF(skip_cdf[1])));
dc_rate += 1;
#if !CONFIG_ANS
tell2 = od_ec_enc_tell_frac(&enc->w.ec);
#else
#error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
od_encode_checkpoint(enc, &dc_buf);
generic_encode(&enc->w, &enc->state.adapt->model_dc[pli],
n - 1, &enc->state.adapt->ex_dc[pli][bs][0], 2);
#if !CONFIG_ANS
tell2 = od_ec_enc_tell_frac(&enc->w.ec) - tell2;
#else
#error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
dc_rate += tell2/8.0;
od_encode_rollback(enc, &dc_buf);
out[0] = od_rdo_quant(in[0] - ref[0], dc_quant, dc_rate,
enc->pvq_norm_lambda);
}
}
#if !CONFIG_ANS
tell = od_ec_enc_tell_frac(&enc->w.ec);
#else
#error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
/* Code as if we're not skipping. */
aom_write_symbol(&enc->w, 2 + (out[0] != 0), skip_cdf, 4);
ac_dc_coded = AC_CODED + (out[0] != 0);
cfl_encoded = 0;
skip_rest = 1;
skip_theta_value = is_keyframe ? -1 : 0;
for (i = 1; i < nb_bands; i++) {
if (theta[i] != skip_theta_value || qg[i]) skip_rest = 0;
}
skip_dir = 0;
if (nb_bands > 1) {
for (i = 0; i < 3; i++) {
int j;
int tmp;
tmp = 1;
// ToDo(yaowu): figure out better stop condition without gcc warning.
for (j = i + 1; j < nb_bands && j < PVQ_MAX_PARTITIONS; j += 3) {
if (theta[j] != skip_theta_value || qg[j]) tmp = 0;
}
skip_dir |= tmp << i;
}
}
if (theta[0] == skip_theta_value && qg[0] == 0 && skip_rest) nb_bands = 0;
/* NOTE: There was no other better place to put this function. */
if (pvq_info)
av1_store_pvq_enc_info(pvq_info, qg, theta, k, y, nb_bands, off, size,
skip_rest, skip_dir, bs);
for (i = 0; i < nb_bands; i++) {
int encode_flip;
/* Encode CFL flip bit just after the first time it's used. */
encode_flip = pli != 0 && is_keyframe && theta[i] != -1 && !cfl_encoded;
if (i == 0 || (!skip_rest && !(skip_dir & (1 << ((i - 1)%3))))) {
pvq_encode_partition(&enc->w, qg[i], theta[i], y + off[i],
size[i], k[i], model, enc->state.adapt, exg + i, ext + i,
(pli != 0)*OD_TXSIZES*PVQ_MAX_PARTITIONS + bs*PVQ_MAX_PARTITIONS + i,
is_keyframe, i == 0 && (i < nb_bands - 1), skip_rest, encode_flip, flip);
}
if (i == 0 && !skip_rest && bs > 0) {
aom_write_symbol(&enc->w, skip_dir,
&enc->state.adapt->pvq.pvq_skip_dir_cdf[(pli != 0) + 2*(bs - 1)][0], 7);
}
if (encode_flip) cfl_encoded = 1;
}
#if !CONFIG_ANS
tell = od_ec_enc_tell_frac(&enc->w.ec) - tell;
#else
#error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
/* Account for the rate of skipping the AC, based on the same DC decision
we made when trying to not skip AC. */
{
double skip_rate;
if (out[0] != 0) {
skip_rate = -OD_LOG2((OD_ICDF(skip_cdf[1]) - OD_ICDF(skip_cdf[0]))/
(double)OD_ICDF(skip_cdf[3]));
}
else {
skip_rate = -OD_LOG2(OD_ICDF(skip_cdf[0])/
(double)OD_ICDF(skip_cdf[3]));
}
tell -= (int)floor(.5+8*skip_rate);
}
if (nb_bands == 0 || skip_diff <= enc->pvq_norm_lambda/8*tell) {
if (is_keyframe) out[0] = 0;
else {
int n;
n = OD_DIV_R0(abs(in[0] - ref[0]), dc_quant);
if (n == 0) {
out[0] = 0;
} else {
int tell2;
od_rollback_buffer dc_buf;
dc_rate = -OD_LOG2((double)(OD_ICDF(skip_cdf[1]) - OD_ICDF(skip_cdf[0]))/
(double)OD_ICDF(skip_cdf[0]));
dc_rate += 1;
#if !CONFIG_ANS
tell2 = od_ec_enc_tell_frac(&enc->w.ec);
#else
#error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
od_encode_checkpoint(enc, &dc_buf);
generic_encode(&enc->w, &enc->state.adapt->model_dc[pli],
n - 1, &enc->state.adapt->ex_dc[pli][bs][0], 2);
#if !CONFIG_ANS
tell2 = od_ec_enc_tell_frac(&enc->w.ec) - tell2;
#else
#error "CONFIG_PVQ currently requires !CONFIG_ANS."
#endif
dc_rate += tell2/8.0;
od_encode_rollback(enc, &dc_buf);
out[0] = od_rdo_quant(in[0] - ref[0], dc_quant, dc_rate,
enc->pvq_norm_lambda);
}
}
/* We decide to skip, roll back everything as it was before. */
od_encode_rollback(enc, &buf);
aom_write_symbol(&enc->w, out[0] != 0, skip_cdf, 4);
ac_dc_coded = (out[0] != 0);
if (is_keyframe) for (i = 1; i < 1 << (2*bs + 4); i++) out[i] = 0;
else for (i = 1; i < 1 << (2*bs + 4); i++) out[i] = ref[i];
}
if (pvq_info)
pvq_info->ac_dc_coded = ac_dc_coded;
return ac_dc_coded;
}

View file

@ -1,53 +0,0 @@
/*
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
/* clang-format off */
#if !defined(_pvq_encoder_H)
# define _pvq_encoder_H (1)
# include "aom_dsp/bitwriter.h"
# include "aom_dsp/entenc.h"
# include "av1/common/blockd.h"
# include "av1/common/pvq.h"
# include "av1/encoder/encint.h"
void aom_write_symbol_pvq(aom_writer *w, int symb, aom_cdf_prob *cdf,
int nsymbs);
void aom_encode_band_pvq_splits(aom_writer *w, od_pvq_codeword_ctx *adapt,
const int *y, int n, int k, int level);
void aom_laplace_encode_special(aom_writer *w, int x, unsigned decay);
void pvq_encode_partition(aom_writer *w,
int qg,
int theta,
const od_coeff *in,
int n,
int k,
generic_encoder model[3],
od_adapt_ctx *adapt,
int *exg,
int *ext,
int cdf_ctx,
int is_keyframe,
int code_skip,
int skip_rest,
int encode_flip,
int flip);
PVQ_SKIP_TYPE od_pvq_encode(daala_enc_ctx *enc, od_coeff *ref,
const od_coeff *in, od_coeff *out, int q_dc, int q_ac, int pli, int bs,
const od_val16 *beta, int is_keyframe,
const int16_t *qm, const int16_t *qm_inv, int speed,
PVQ_INFO *pvq_info);
#endif

View file

@ -80,60 +80,6 @@ static void project_points_double_affine(double *mat, double *points,
}
}
static void project_points_double_hortrapezoid(double *mat, double *points,
double *proj, const int n,
const int stride_points,
const int stride_proj) {
int i;
double x, y, Z, Z_inv;
for (i = 0; i < n; ++i) {
x = *(points++), y = *(points++);
Z_inv = mat[7] * y + 1;
assert(fabs(Z_inv) > 0.000001);
Z = 1. / Z_inv;
*(proj++) = (mat[2] * x + mat[3] * y + mat[0]) * Z;
*(proj++) = (mat[5] * y + mat[1]) * Z;
points += stride_points - 2;
proj += stride_proj - 2;
}
}
static void project_points_double_vertrapezoid(double *mat, double *points,
double *proj, const int n,
const int stride_points,
const int stride_proj) {
int i;
double x, y, Z, Z_inv;
for (i = 0; i < n; ++i) {
x = *(points++), y = *(points++);
Z_inv = mat[6] * x + 1;
assert(fabs(Z_inv) > 0.000001);
Z = 1. / Z_inv;
*(proj++) = (mat[2] * x + mat[0]) * Z;
*(proj++) = (mat[4] * x + mat[5] * y + mat[1]) * Z;
points += stride_points - 2;
proj += stride_proj - 2;
}
}
static void project_points_double_homography(double *mat, double *points,
double *proj, const int n,
const int stride_points,
const int stride_proj) {
int i;
double x, y, Z, Z_inv;
for (i = 0; i < n; ++i) {
x = *(points++), y = *(points++);
Z_inv = mat[6] * x + mat[7] * y + 1;
assert(fabs(Z_inv) > 0.000001);
Z = 1. / Z_inv;
*(proj++) = (mat[2] * x + mat[3] * y + mat[0]) * Z;
*(proj++) = (mat[4] * x + mat[5] * y + mat[1]) * Z;
points += stride_points - 2;
proj += stride_proj - 2;
}
}
static void normalize_homography(double *pts, int n, double *T) {
double *p = pts;
double mean[2] = { 0, 0 };
@ -193,22 +139,6 @@ static void denormalize_homography(double *params, double *T1, double *T2) {
multiply_mat(iT2, params2, params, 3, 3, 3);
}
static void denormalize_homography_reorder(double *params, double *T1,
double *T2) {
double params_denorm[MAX_PARAMDIM];
memcpy(params_denorm, params, sizeof(*params) * 8);
params_denorm[8] = 1.0;
denormalize_homography(params_denorm, T1, T2);
params[0] = params_denorm[2];
params[1] = params_denorm[5];
params[2] = params_denorm[0];
params[3] = params_denorm[1];
params[4] = params_denorm[3];
params[5] = params_denorm[4];
params[6] = params_denorm[6];
params[7] = params_denorm[7];
}
static void denormalize_affine_reorder(double *params, double *T1, double *T2) {
double params_denorm[MAX_PARAMDIM];
params_denorm[0] = params[0];
@ -377,217 +307,6 @@ static int find_affine(int np, double *pts1, double *pts2, double *mat) {
return 0;
}
static int find_vertrapezoid(int np, double *pts1, double *pts2, double *mat) {
const int np3 = np * 3;
double *a = (double *)aom_malloc(sizeof(*a) * np3 * 14);
double *U = a + np3 * 7;
double S[7], V[7 * 7], H[9];
int i, mini;
double sx, sy, dx, dy;
double T1[9], T2[9];
normalize_homography(pts1, np, T1);
normalize_homography(pts2, np, T2);
for (i = 0; i < np; ++i) {
dx = *(pts2++);
dy = *(pts2++);
sx = *(pts1++);
sy = *(pts1++);
a[i * 3 * 7 + 0] = a[i * 3 * 7 + 1] = 0;
a[i * 3 * 7 + 2] = -sx;
a[i * 3 * 7 + 3] = -sy;
a[i * 3 * 7 + 4] = -1;
a[i * 3 * 7 + 5] = dy * sx;
a[i * 3 * 7 + 6] = dy;
a[(i * 3 + 1) * 7 + 0] = sx;
a[(i * 3 + 1) * 7 + 1] = 1;
a[(i * 3 + 1) * 7 + 2] = a[(i * 3 + 1) * 7 + 3] = a[(i * 3 + 1) * 7 + 4] =
0;
a[(i * 3 + 1) * 7 + 5] = -dx * sx;
a[(i * 3 + 1) * 7 + 6] = -dx;
a[(i * 3 + 2) * 7 + 0] = -dy * sx;
a[(i * 3 + 2) * 7 + 1] = -dy;
a[(i * 3 + 2) * 7 + 2] = dx * sx;
a[(i * 3 + 2) * 7 + 3] = dx * sy;
a[(i * 3 + 2) * 7 + 4] = dx;
a[(i * 3 + 2) * 7 + 5] = a[(i * 3 + 2) * 7 + 6] = 0;
}
if (SVD(U, S, V, a, np3, 7)) {
aom_free(a);
return 1;
} else {
double minS = 1e12;
mini = -1;
for (i = 0; i < 7; ++i) {
if (S[i] < minS) {
minS = S[i];
mini = i;
}
}
}
H[1] = H[7] = 0;
for (i = 0; i < 1; i++) H[i] = V[i * 7 + mini];
for (; i < 6; i++) H[i + 1] = V[i * 7 + mini];
for (; i < 7; i++) H[i + 2] = V[i * 7 + mini];
denormalize_homography_reorder(H, T1, T2);
aom_free(a);
if (H[8] == 0.0) {
return 1;
} else {
// normalize
double f = 1.0 / H[8];
for (i = 0; i < 8; i++) mat[i] = f * H[i];
}
return 0;
}
static int find_hortrapezoid(int np, double *pts1, double *pts2, double *mat) {
const int np3 = np * 3;
double *a = (double *)aom_malloc(sizeof(*a) * np3 * 14);
double *U = a + np3 * 7;
double S[7], V[7 * 7], H[9];
int i, mini;
double sx, sy, dx, dy;
double T1[9], T2[9];
normalize_homography(pts1, np, T1);
normalize_homography(pts2, np, T2);
for (i = 0; i < np; ++i) {
dx = *(pts2++);
dy = *(pts2++);
sx = *(pts1++);
sy = *(pts1++);
a[i * 3 * 7 + 0] = a[i * 3 * 7 + 1] = a[i * 3 * 7 + 2] = 0;
a[i * 3 * 7 + 3] = -sy;
a[i * 3 * 7 + 4] = -1;
a[i * 3 * 7 + 5] = dy * sy;
a[i * 3 * 7 + 6] = dy;
a[(i * 3 + 1) * 7 + 0] = sx;
a[(i * 3 + 1) * 7 + 1] = sy;
a[(i * 3 + 1) * 7 + 2] = 1;
a[(i * 3 + 1) * 7 + 3] = a[(i * 3 + 1) * 7 + 4] = 0;
a[(i * 3 + 1) * 7 + 5] = -dx * sy;
a[(i * 3 + 1) * 7 + 6] = -dx;
a[(i * 3 + 2) * 7 + 0] = -dy * sx;
a[(i * 3 + 2) * 7 + 1] = -dy * sy;
a[(i * 3 + 2) * 7 + 2] = -dy;
a[(i * 3 + 2) * 7 + 3] = dx * sy;
a[(i * 3 + 2) * 7 + 4] = dx;
a[(i * 3 + 2) * 7 + 5] = a[(i * 3 + 2) * 7 + 6] = 0;
}
if (SVD(U, S, V, a, np3, 7)) {
aom_free(a);
return 1;
} else {
double minS = 1e12;
mini = -1;
for (i = 0; i < 7; ++i) {
if (S[i] < minS) {
minS = S[i];
mini = i;
}
}
}
H[3] = H[6] = 0;
for (i = 0; i < 3; i++) H[i] = V[i * 7 + mini];
for (; i < 5; i++) H[i + 1] = V[i * 7 + mini];
for (; i < 7; i++) H[i + 2] = V[i * 7 + mini];
denormalize_homography_reorder(H, T1, T2);
aom_free(a);
if (H[8] == 0.0) {
return 1;
} else {
// normalize
double f = 1.0 / H[8];
for (i = 0; i < 8; i++) mat[i] = f * H[i];
}
return 0;
}
static int find_homography(int np, double *pts1, double *pts2, double *mat) {
// Implemented from Peter Kovesi's normalized implementation
const int np3 = np * 3;
double *a = (double *)aom_malloc(sizeof(*a) * np3 * 18);
double *U = a + np3 * 9;
double S[9], V[9 * 9], H[9];
int i, mini;
double sx, sy, dx, dy;
double T1[9], T2[9];
normalize_homography(pts1, np, T1);
normalize_homography(pts2, np, T2);
for (i = 0; i < np; ++i) {
dx = *(pts2++);
dy = *(pts2++);
sx = *(pts1++);
sy = *(pts1++);
a[i * 3 * 9 + 0] = a[i * 3 * 9 + 1] = a[i * 3 * 9 + 2] = 0;
a[i * 3 * 9 + 3] = -sx;
a[i * 3 * 9 + 4] = -sy;
a[i * 3 * 9 + 5] = -1;
a[i * 3 * 9 + 6] = dy * sx;
a[i * 3 * 9 + 7] = dy * sy;
a[i * 3 * 9 + 8] = dy;
a[(i * 3 + 1) * 9 + 0] = sx;
a[(i * 3 + 1) * 9 + 1] = sy;
a[(i * 3 + 1) * 9 + 2] = 1;
a[(i * 3 + 1) * 9 + 3] = a[(i * 3 + 1) * 9 + 4] = a[(i * 3 + 1) * 9 + 5] =
0;
a[(i * 3 + 1) * 9 + 6] = -dx * sx;
a[(i * 3 + 1) * 9 + 7] = -dx * sy;
a[(i * 3 + 1) * 9 + 8] = -dx;
a[(i * 3 + 2) * 9 + 0] = -dy * sx;
a[(i * 3 + 2) * 9 + 1] = -dy * sy;
a[(i * 3 + 2) * 9 + 2] = -dy;
a[(i * 3 + 2) * 9 + 3] = dx * sx;
a[(i * 3 + 2) * 9 + 4] = dx * sy;
a[(i * 3 + 2) * 9 + 5] = dx;
a[(i * 3 + 2) * 9 + 6] = a[(i * 3 + 2) * 9 + 7] = a[(i * 3 + 2) * 9 + 8] =
0;
}
if (SVD(U, S, V, a, np3, 9)) {
aom_free(a);
return 1;
} else {
double minS = 1e12;
mini = -1;
for (i = 0; i < 9; ++i) {
if (S[i] < minS) {
minS = S[i];
mini = i;
}
}
}
for (i = 0; i < 9; i++) H[i] = V[i * 9 + mini];
denormalize_homography_reorder(H, T1, T2);
aom_free(a);
if (H[8] == 0.0) {
return 1;
} else {
// normalize
double f = 1.0 / H[8];
for (i = 0; i < 8; i++) mat[i] = f * H[i];
}
return 0;
}
static int get_rand_indices(int npoints, int minpts, int *indices,
unsigned int *seed) {
int i, j;
@ -860,11 +579,6 @@ static int is_degenerate_affine(double *p) {
return is_collinear3(p, p + 2, p + 4);
}
static int is_degenerate_homography(double *p) {
return is_collinear3(p, p + 2, p + 4) || is_collinear3(p, p + 2, p + 6) ||
is_collinear3(p, p + 4, p + 6) || is_collinear3(p + 2, p + 4, p + 6);
}
int ransac_translation(int *matched_points, int npoints,
int *num_inliers_by_motion, double *params_by_motion,
int num_desired_motions) {
@ -887,30 +601,3 @@ int ransac_affine(int *matched_points, int npoints, int *num_inliers_by_motion,
params_by_motion, num_desired_motions, 3, is_degenerate_affine,
find_affine, project_points_double_affine);
}
int ransac_homography(int *matched_points, int npoints,
int *num_inliers_by_motion, double *params_by_motion,
int num_desired_motions) {
return ransac(matched_points, npoints, num_inliers_by_motion,
params_by_motion, num_desired_motions, 4,
is_degenerate_homography, find_homography,
project_points_double_homography);
}
int ransac_hortrapezoid(int *matched_points, int npoints,
int *num_inliers_by_motion, double *params_by_motion,
int num_desired_motions) {
return ransac(matched_points, npoints, num_inliers_by_motion,
params_by_motion, num_desired_motions, 4,
is_degenerate_homography, find_hortrapezoid,
project_points_double_hortrapezoid);
}
int ransac_vertrapezoid(int *matched_points, int npoints,
int *num_inliers_by_motion, double *params_by_motion,
int num_desired_motions) {
return ransac(matched_points, npoints, num_inliers_by_motion,
params_by_motion, num_desired_motions, 4,
is_degenerate_homography, find_vertrapezoid,
project_points_double_vertrapezoid);
}

View file

@ -25,17 +25,8 @@ typedef int (*RansacFunc)(int *matched_points, int npoints,
/* Each of these functions fits a motion model from a set of
corresponding points in 2 frames using RANSAC. */
int ransac_homography(int *matched_points, int npoints,
int *num_inliers_by_motion, double *params_by_motion,
int num_motions);
int ransac_affine(int *matched_points, int npoints, int *num_inliers_by_motion,
double *params_by_motion, int num_motions);
int ransac_hortrapezoid(int *matched_points, int npoints,
int *num_inliers_by_motion, double *params_by_motion,
int num_motions);
int ransac_vertrapezoid(int *matched_points, int npoints,
int *num_inliers_by_motion, double *params_by_motion,
int num_motions);
int ransac_rotzoom(int *matched_points, int npoints, int *num_inliers_by_motion,
double *params_by_motion, int num_motions);
int ransac_translation(int *matched_points, int npoints,

View file

@ -44,7 +44,6 @@
#define MAX_BPB_FACTOR 50
#define FRAME_OVERHEAD_BITS 200
#if CONFIG_HIGHBITDEPTH
#define ASSIGN_MINQ_TABLE(bit_depth, name) \
do { \
switch (bit_depth) { \
@ -58,13 +57,6 @@
name = NULL; \
} \
} while (0)
#else
#define ASSIGN_MINQ_TABLE(bit_depth, name) \
do { \
(void)bit_depth; \
name = name##_8; \
} while (0)
#endif
// Tables relating active max Q to active min Q
static int kf_low_motion_minq_8[QINDEX_RANGE];
@ -74,7 +66,6 @@ static int arfgf_high_motion_minq_8[QINDEX_RANGE];
static int inter_minq_8[QINDEX_RANGE];
static int rtc_minq_8[QINDEX_RANGE];
#if CONFIG_HIGHBITDEPTH
static int kf_low_motion_minq_10[QINDEX_RANGE];
static int kf_high_motion_minq_10[QINDEX_RANGE];
static int arfgf_low_motion_minq_10[QINDEX_RANGE];
@ -87,7 +78,6 @@ static int arfgf_low_motion_minq_12[QINDEX_RANGE];
static int arfgf_high_motion_minq_12[QINDEX_RANGE];
static int inter_minq_12[QINDEX_RANGE];
static int rtc_minq_12[QINDEX_RANGE];
#endif
static int gf_high = 2000;
static int gf_low = 400;
@ -97,7 +87,6 @@ static int kf_low = 400;
// How many times less pixels there are to encode given the current scaling.
// Temporary replacement for rcf_mult and rate_thresh_mult.
static double resize_rate_factor(const AV1_COMP *cpi, int width, int height) {
(void)cpi;
return (double)(cpi->oxcf.width * cpi->oxcf.height) / (width * height);
}
@ -140,33 +129,27 @@ void av1_rc_init_minq_luts(void) {
init_minq_luts(kf_low_motion_minq_8, kf_high_motion_minq_8,
arfgf_low_motion_minq_8, arfgf_high_motion_minq_8,
inter_minq_8, rtc_minq_8, AOM_BITS_8);
#if CONFIG_HIGHBITDEPTH
init_minq_luts(kf_low_motion_minq_10, kf_high_motion_minq_10,
arfgf_low_motion_minq_10, arfgf_high_motion_minq_10,
inter_minq_10, rtc_minq_10, AOM_BITS_10);
init_minq_luts(kf_low_motion_minq_12, kf_high_motion_minq_12,
arfgf_low_motion_minq_12, arfgf_high_motion_minq_12,
inter_minq_12, rtc_minq_12, AOM_BITS_12);
#endif
}
// These functions use formulaic calculations to make playing with the
// quantizer tables easier. If necessary they can be replaced by lookup
// tables if and when things settle down in the experimental bitstream
double av1_convert_qindex_to_q(int qindex, aom_bit_depth_t bit_depth) {
// Convert the index to a real Q value (scaled down to match old Q values)
#if CONFIG_HIGHBITDEPTH
// Convert the index to a real Q value (scaled down to match old Q values)
switch (bit_depth) {
case AOM_BITS_8: return av1_ac_quant(qindex, 0, bit_depth) / 4.0;
case AOM_BITS_10: return av1_ac_quant(qindex, 0, bit_depth) / 16.0;
case AOM_BITS_12: return av1_ac_quant(qindex, 0, bit_depth) / 64.0;
case AOM_BITS_8: return av1_ac_quant_Q3(qindex, 0, bit_depth) / 4.0;
case AOM_BITS_10: return av1_ac_quant_Q3(qindex, 0, bit_depth) / 16.0;
case AOM_BITS_12: return av1_ac_quant_Q3(qindex, 0, bit_depth) / 64.0;
default:
assert(0 && "bit_depth should be AOM_BITS_8, AOM_BITS_10 or AOM_BITS_12");
return -1.0;
}
#else
return av1_ac_quant(qindex, 0, bit_depth) / 4.0;
#endif
}
int av1_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,
@ -196,12 +179,8 @@ int av1_rc_clamp_pframe_target_size(const AV1_COMP *const cpi, int target) {
const AV1EncoderConfig *oxcf = &cpi->oxcf;
const int min_frame_target =
AOMMAX(rc->min_frame_bandwidth, rc->avg_frame_bandwidth >> 5);
// Clip the frame target to the minimum setup value.
#if CONFIG_EXT_REFS
// Clip the frame target to the minimum setup value.
if (cpi->rc.is_src_frame_alt_ref) {
#else
if (cpi->refresh_golden_frame && rc->is_src_frame_alt_ref) {
#endif // CONFIG_EXT_REFS
// If there is an active ARF at this location use the minimum
// bits on this frame even if it is a constructed arf.
// The active maximum quantizer insures that an appropriate
@ -239,14 +218,10 @@ static void update_buffer_level(AV1_COMP *cpi, int encoded_frame_size) {
const AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
// Non-viewable frames are a special case and are treated as pure overhead.
#if CONFIG_EXT_REFS
// Non-viewable frames are a special case and are treated as pure overhead.
// TODO(zoeliu): To further explore whether we should treat BWDREF_FRAME
// differently, since it is a no-show frame.
if (!cm->show_frame && !rc->is_bwd_ref_frame)
#else
if (!cm->show_frame)
#endif // CONFIG_EXT_REFS
rc->bits_off_target -= encoded_frame_size;
else
rc->bits_off_target += rc->avg_frame_bandwidth - encoded_frame_size;
@ -590,11 +565,9 @@ static int calc_active_worst_quality_one_pass_vbr(const AV1_COMP *cpi) {
active_worst_quality =
curr_frame == 0 ? rc->worst_quality : rc->last_q[KEY_FRAME] * 2;
} else {
if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
#if CONFIG_EXT_REFS
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS
cpi->refresh_alt_ref_frame)) {
if (!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt2_ref_frame ||
cpi->refresh_alt_ref_frame)) {
active_worst_quality = curr_frame == 1 ? rc->last_q[KEY_FRAME] * 5 / 4
: rc->last_q[INTER_FRAME];
} else {
@ -931,26 +904,9 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const AV1_COMP *cpi, int width,
}
int av1_frame_type_qdelta(const AV1_COMP *cpi, int rf_level, int q) {
static const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
1.00, // INTER_NORMAL
#if CONFIG_EXT_REFS
0.80, // INTER_LOW
1.50, // INTER_HIGH
1.25, // GF_ARF_LOW
#else
1.00, // INTER_HIGH
1.50, // GF_ARF_LOW
#endif // CONFIG_EXT_REFS
2.00, // GF_ARF_STD
2.00, // KF_STD
static const FRAME_TYPE frame_type[RATE_FACTOR_LEVELS] = {
INTER_FRAME, INTER_FRAME, INTER_FRAME, INTER_FRAME, INTER_FRAME, KEY_FRAME
};
static const FRAME_TYPE frame_type[RATE_FACTOR_LEVELS] =
#if CONFIG_EXT_REFS
{ INTER_FRAME, INTER_FRAME, INTER_FRAME,
INTER_FRAME, INTER_FRAME, KEY_FRAME };
#else
{ INTER_FRAME, INTER_FRAME, INTER_FRAME, INTER_FRAME, KEY_FRAME };
#endif // CONFIG_EXT_REFS
const AV1_COMMON *const cm = &cpi->common;
int qdelta =
av1_compute_qdelta_by_rate(&cpi->rc, frame_type[rf_level], q,
@ -1020,11 +976,9 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
active_best_quality +=
av1_compute_qdelta(rc, q_val, q_val * q_adj_factor, cm->bit_depth);
}
} else if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
#if CONFIG_EXT_REFS
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS
cpi->refresh_alt_ref_frame)) {
} else if (!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt2_ref_frame ||
cpi->refresh_alt_ref_frame)) {
// Use the lower of active_worst_quality and recent
// average Q as basis for GF/ARF best Q limit unless last frame was
// a key frame.
@ -1044,11 +998,7 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
active_best_quality = active_best_quality * 15 / 16;
} else if (oxcf->rc_mode == AOM_Q) {
#if CONFIG_EXT_REFS
if (!cpi->refresh_alt_ref_frame && !cpi->refresh_alt2_ref_frame) {
#else
if (!cpi->refresh_alt_ref_frame) {
#endif // CONFIG_EXT_REFS
active_best_quality = cq_level;
} else {
active_best_quality = get_gf_active_quality(rc, q, cm->bit_depth);
@ -1080,11 +1030,9 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
if ((cpi->oxcf.rc_mode != AOM_Q) &&
(cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD)) {
if (frame_is_intra_only(cm) ||
(!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
#if CONFIG_EXT_REFS
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS
cpi->refresh_alt_ref_frame))) {
(!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt2_ref_frame ||
cpi->refresh_alt_ref_frame))) {
active_best_quality -=
(cpi->twopass.extend_minq + cpi->twopass.extend_minq_fast);
active_worst_quality += (cpi->twopass.extend_maxq / 2);
@ -1106,7 +1054,7 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
}
// Modify active_best_quality for downscaled normal frames.
if (!av1_frame_unscaled(cm) && !frame_is_kf_gf_arf(cpi)) {
if (av1_frame_scaled(cm) && !frame_is_kf_gf_arf(cpi)) {
int qdelta = av1_compute_qdelta_by_rate(
rc, cm->frame_type, active_best_quality, 2.0, cm->bit_depth);
active_best_quality =
@ -1193,7 +1141,7 @@ static void rc_set_frame_target(AV1_COMP *cpi, int target, int width,
rc->this_frame_target = target;
// Modify frame size target when down-scaled.
if (!av1_frame_unscaled(cm))
if (av1_frame_scaled(cm))
rc->this_frame_target =
(int)(rc->this_frame_target * resize_rate_factor(cpi, width, height));
@ -1217,21 +1165,13 @@ static void update_alt_ref_frame_stats(AV1_COMP *cpi) {
static void update_golden_frame_stats(AV1_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
#if CONFIG_EXT_REFS
// Update the Golden frame usage counts.
// NOTE(weitinglin): If we use show_existing_frame for an OVERLAY frame,
// only the virtual indices for the reference frame will be
// updated and cpi->refresh_golden_frame will still be zero.
if (cpi->refresh_golden_frame || rc->is_src_frame_alt_ref) {
#else // !CONFIG_EXT_REFS
// Update the Golden frame usage counts.
if (cpi->refresh_golden_frame) {
#endif // CONFIG_EXT_REFS
#if CONFIG_EXT_REFS
// We will not use internal overlay frames to replace the golden frame
if (!rc->is_src_frame_ext_arf)
#endif // CONFIG_EXT_REFS
// this frame refreshes means next frames don't unless specified by user
rc->frames_since_golden = 0;
@ -1248,11 +1188,7 @@ static void update_golden_frame_stats(AV1_COMP *cpi) {
// Decrement count down till next gf
if (rc->frames_till_gf_update_due > 0) rc->frames_till_gf_update_due--;
#if CONFIG_EXT_REFS
} else if (!cpi->refresh_alt_ref_frame && !cpi->refresh_alt2_ref_frame) {
#else
} else if (!cpi->refresh_alt_ref_frame) {
#endif // CONFIG_EXT_REFS
// Decrement count down till next gf
if (rc->frames_till_gf_update_due > 0) rc->frames_till_gf_update_due--;
@ -1282,10 +1218,7 @@ void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
ROUND_POWER_OF_TWO(3 * rc->avg_frame_qindex[KEY_FRAME] + qindex, 2);
} else {
if (!rc->is_src_frame_alt_ref &&
!(cpi->refresh_golden_frame ||
#if CONFIG_EXT_REFS
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS
!(cpi->refresh_golden_frame || cpi->refresh_alt2_ref_frame ||
cpi->refresh_alt_ref_frame)) {
rc->last_q[INTER_FRAME] = qindex;
rc->avg_frame_qindex[INTER_FRAME] =
@ -1307,10 +1240,7 @@ void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
// This is used to help set quality in forced key frames to reduce popping
if ((qindex < rc->last_boosted_qindex) || (cm->frame_type == KEY_FRAME) ||
(!rc->constrained_gf_group &&
(cpi->refresh_alt_ref_frame ||
#if CONFIG_EXT_REFS
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS
(cpi->refresh_alt_ref_frame || cpi->refresh_alt2_ref_frame ||
(cpi->refresh_golden_frame && !rc->is_src_frame_alt_ref)))) {
rc->last_boosted_qindex = qindex;
}
@ -1320,7 +1250,7 @@ void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
// Rolling monitors of whether we are over or underspending used to help
// regulate min and Max Q in two pass.
if (!av1_frame_unscaled(cm))
if (av1_frame_scaled(cm))
rc->this_frame_target =
(int)(rc->this_frame_target /
resize_rate_factor(cpi, cm->width, cm->height));
@ -1337,14 +1267,10 @@ void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
// Actual bits spent
rc->total_actual_bits += rc->projected_frame_size;
#if CONFIG_EXT_REFS
// TODO(zoeliu): To investigate whether we should treat BWDREF_FRAME
// differently here for rc->avg_frame_bandwidth.
rc->total_target_bits +=
(cm->show_frame || rc->is_bwd_ref_frame) ? rc->avg_frame_bandwidth : 0;
#else
rc->total_target_bits += cm->show_frame ? rc->avg_frame_bandwidth : 0;
#endif // CONFIG_EXT_REFS
rc->total_target_vs_actual = rc->total_actual_bits - rc->total_target_bits;
@ -1358,13 +1284,9 @@ void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
if (cm->frame_type == KEY_FRAME) rc->frames_since_key = 0;
#if CONFIG_EXT_REFS
// TODO(zoeliu): To investigate whether we should treat BWDREF_FRAME
// differently here for rc->avg_frame_bandwidth.
if (cm->show_frame || rc->is_bwd_ref_frame) {
#else
if (cm->show_frame) {
#endif // CONFIG_EXT_REFS
rc->frames_since_key++;
rc->frames_to_key--;
}
@ -1417,6 +1339,10 @@ void av1_rc_get_one_pass_vbr_params(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
int target;
int altref_enabled = is_altref_enabled(cpi);
int sframe_dist = cpi->oxcf.sframe_dist;
int sframe_mode = cpi->oxcf.sframe_mode;
int sframe_enabled = cpi->oxcf.sframe_enabled;
// TODO(yaowu): replace the "auto_key && 0" below with proper decision logic.
if (!cpi->refresh_alt_ref_frame &&
(cm->current_video_frame == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY) ||
@ -1429,6 +1355,37 @@ void av1_rc_get_one_pass_vbr_params(AV1_COMP *cpi) {
rc->source_alt_ref_active = 0;
} else {
cm->frame_type = INTER_FRAME;
if (sframe_enabled) {
if (altref_enabled) {
if (sframe_mode == 1) {
// sframe_mode == 1: insert sframe if it matches altref frame.
if (cm->current_video_frame % sframe_dist == 0 &&
cm->frame_type != KEY_FRAME && cm->current_video_frame != 0 &&
cpi->refresh_alt_ref_frame) {
cm->frame_type = S_FRAME;
}
} else {
// sframe_mode != 1: if sframe will be inserted at the next available
// altref frame
if (cm->current_video_frame % sframe_dist == 0 &&
cm->frame_type != KEY_FRAME && cm->current_video_frame != 0) {
rc->sframe_due = 1;
}
if (rc->sframe_due && cpi->refresh_alt_ref_frame) {
cm->frame_type = S_FRAME;
rc->sframe_due = 0;
}
}
} else {
if (cm->current_video_frame % sframe_dist == 0 &&
cm->frame_type != KEY_FRAME && cm->current_video_frame != 0) {
cm->frame_type = S_FRAME;
}
}
}
}
if (rc->frames_till_gf_update_due == 0) {
rc->baseline_gf_interval = (rc->min_gf_interval + rc->max_gf_interval) / 2;
@ -1444,6 +1401,10 @@ void av1_rc_get_one_pass_vbr_params(AV1_COMP *cpi) {
rc->source_alt_ref_pending = USE_ALTREF_FOR_ONE_PASS;
rc->gfu_boost = DEFAULT_GF_BOOST;
}
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
av1_cyclic_refresh_update_parameters(cpi);
if (cm->frame_type == KEY_FRAME)
target = calc_iframe_target_size_one_pass_vbr(cpi);
else

View file

@ -28,7 +28,6 @@ extern "C" {
#define MAX_GF_INTERVAL 16
#define FIXED_GF_INTERVAL 8 // Used in some testing modes only
#if CONFIG_EXT_REFS
typedef enum {
INTER_NORMAL = 0,
INTER_LOW = 1,
@ -38,23 +37,20 @@ typedef enum {
KF_STD = 5,
RATE_FACTOR_LEVELS = 6
} RATE_FACTOR_LEVEL;
#else
typedef enum {
INTER_NORMAL = 0,
INTER_HIGH = 1,
GF_ARF_LOW = 2,
GF_ARF_STD = 3,
KF_STD = 4,
RATE_FACTOR_LEVELS = 5
} RATE_FACTOR_LEVEL;
#endif // CONFIG_EXT_REFS
static const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
1.00, // INTER_NORMAL
0.80, // INTER_LOW
1.50, // INTER_HIGH
1.25, // GF_ARF_LOW
2.00, // GF_ARF_STD
2.00, // KF_STD
};
typedef struct {
int resize_width;
int resize_height;
#if CONFIG_FRAME_SUPERRES
uint8_t superres_denom;
#endif // CONFIG_FRAME_SUPERRES
} size_params_type;
typedef struct {
@ -88,8 +84,8 @@ typedef struct {
int source_alt_ref_pending;
int source_alt_ref_active;
int is_src_frame_alt_ref;
int sframe_due;
#if CONFIG_EXT_REFS
// Length of the bi-predictive frame group interval
int bipred_group_interval;
@ -99,7 +95,6 @@ typedef struct {
int is_last_bipred_frame;
int is_bipred_frame;
int is_src_frame_ext_arf;
#endif // CONFIG_EXT_REFS
int avg_frame_bandwidth; // Average frame size target for clip
int min_frame_bandwidth; // Minimum allocation used for any frame

File diff suppressed because it is too large Load diff

View file

@ -1,200 +0,0 @@
/*
* Copyright (c) 2001-2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#if !defined(_ratectrl_xiph_H)
#define _ratectrl_xiph_H (1)
#include "av1/encoder/ratectrl.h"
#include "aom/internal/aom_codec_internal.h"
/*Frame types.*/
#define OD_I_FRAME (0)
#define OD_P_FRAME (1)
#define OD_GOLDEN_P_FRAME (2)
#define OD_ALTREF_P_FRAME (3)
#define OD_FRAME_NSUBTYPES (OD_ALTREF_P_FRAME + 1)
/* Periodic boost (in between golden frames) strength - lower is more */
#define OD_PERIODIC_BOOST_DIV (10)
/* Constants for frame QP modulation <- tweak these
* Adjusts how the rate control system decides the quantizers per frame
* (sub)type */
#define OD_MQP_I (0.98)
#define OD_MQP_P (1.06)
#define OD_MQP_GP (0.99)
#define OD_MQP_AP (0.92)
#define OD_DQP_I (-2)
#define OD_DQP_P (0)
#define OD_DQP_GP (-2)
#define OD_DQP_AP (-2)
/*Fractional_coded_quantizer ~=
log2(quantizer / (1 << OD_COEFF_SHIFT))*6.307 + 6.235*/
/*Base/scale factor for linear quantizer to fractional coded quantizer
conversion (6.307 * 2^12) */
#define OD_LOG_QUANTIZER_BASE_Q12 (0x0064EB)
/*Inverse of above scale factor.*/
#define OD_LOG_QUANTIZER_EXP_Q12 (0x000289)
/*Offset for linear quantizer to fractional coded quantizer
conversion (6.235 * 2^45) */
#define OD_LOG_QUANTIZER_OFFSET_Q45 (0x0000C7851EB851ECLL)
#define OD_RC_2PASS_MAGIC (0x53015641) /* [A, V, 1, S] in little endian */
#define OD_RC_2PASS_SUMMARY_SZ (4 + 1 + (4 + 4 + 8) * OD_FRAME_NSUBTYPES)
#define OD_RC_2PASS_PACKET_SZ (1 + 4)
#define OD_RC_2PASS_MIN (OD_RC_2PASS_PACKET_SZ + OD_RC_2PASS_SUMMARY_SZ)
#define OD_RC_2PASS_VERSION (1)
/*A 2nd order low-pass Bessel follower.
We use this for rate control because it has fast reaction time, but is
critically damped.*/
typedef struct od_iir_bessel2 {
int32_t c[2];
int64_t g;
int32_t x[2];
int32_t y[2];
} od_iir_bessel2;
/* The 2-pass metrics associated with a single frame. */
typedef struct od_frame_metrics {
/*The log base 2 of the scale factor for this frame in Q24 format.*/
int64_t log_scale;
/*The frame type from pass 1.*/
unsigned frame_type : 1;
} od_frame_metrics;
/*Rate control setup and working state information.*/
typedef struct od_rc_state {
/* Image format */
int frame_width;
int frame_height;
int bit_depth;
/* Framerate */
double framerate;
/* Keyframe rate */
int keyframe_rate;
/* Golden frame period */
int goldenframe_rate;
/* Altref frame period */
int altref_rate;
/*The target bit-rate in bits per second.*/
int64_t target_bitrate;
/* Quality level for non-bitrate-targeting */
int quality;
/* Copied from oxcf->frame_periodic_boost */
int periodic_boosts;
/* Max Q */
int maxq;
/* Min Q */
int minq;
/* Quantizer to use for the first pass */
int firstpass_quant;
/* 2-pass metrics */
od_frame_metrics cur_metrics;
/* 2-pass state */
int64_t scale_sum[OD_FRAME_NSUBTYPES];
int nframes[OD_FRAME_NSUBTYPES];
/* 2-pass bytestream reader/writer context */
uint8_t *twopass_buffer;
int twopass_buffer_bytes;
/* Pass 1 stats packet storage */
uint8_t firstpass_buffer[OD_RC_2PASS_SUMMARY_SZ];
/* Every state packet from the first pass in a single buffer */
uint8_t *twopass_allframes_buf;
size_t twopass_allframes_buf_size;
/* Actual returned quantizer */
int target_quantizer;
/*The full-precision, unmodulated quantizer upon which
our modulated quantizers are based.*/
int base_quantizer;
/* Increments by 1 for each frame. */
int64_t cur_frame;
/* End of input flag */
int end_of_input;
/* Closed GOP flag */
int closed_gop;
/*The number of frames over which to distribute the reservoir usage.*/
int reservoir_frame_delay;
/*Will we drop frames to meet bitrate target?*/
unsigned char drop_frames;
/*Do we respect the maximum reservoir fullness?*/
unsigned char cap_overflow;
/*Can the reservoir go negative?*/
unsigned char cap_underflow;
/*Two-pass mode state.
0 => 1-pass encoding.
1 => 1st pass of 2-pass encoding.
2 => 2nd pass of 2-pass encoding.*/
int twopass_state;
/*The log of the number of pixels in a frame in Q57 format.*/
int64_t log_npixels;
/*The target average bits per frame.*/
int64_t bits_per_frame;
/*The current bit reservoir fullness (bits available to be used).*/
int64_t reservoir_fullness;
/*The target buffer fullness.
This is where we'd like to be by the last keyframe the appears in the next
buf_delay frames.*/
int64_t reservoir_target;
/*The maximum buffer fullness (total size of the buffer).*/
int64_t reservoir_max;
/*The log of estimated scale factor for the rate model in Q57 format.*/
int64_t log_scale[OD_FRAME_NSUBTYPES];
/*The exponent used in the rate model in Q8 format.*/
unsigned exp[OD_FRAME_NSUBTYPES];
/*The log of an estimated scale factor used to obtain the real framerate, for
VFR sources or, e.g., 12 fps content doubled to 24 fps, etc.*/
int64_t log_drop_scale[OD_FRAME_NSUBTYPES];
/*The total drop count from the previous frame.*/
uint32_t prev_drop_count[OD_FRAME_NSUBTYPES];
/*Second-order lowpass filters to track scale and VFR/drops.*/
od_iir_bessel2 scalefilter[OD_FRAME_NSUBTYPES];
od_iir_bessel2 vfrfilter[OD_FRAME_NSUBTYPES];
int frame_count[OD_FRAME_NSUBTYPES];
int inter_p_delay;
int inter_delay_target;
/*The total accumulated estimation bias.*/
int64_t rate_bias;
} od_rc_state;
int od_enc_rc_init(od_rc_state *rc, int64_t bitrate, int delay_ms);
int od_enc_rc_select_quantizers_and_lambdas(od_rc_state *rc,
int is_golden_frame,
int is_altref_frame, int frame_type,
int *bottom_idx, int *top_idx);
/* Returns 1 if the frame should be dropped */
int od_enc_rc_update_state(od_rc_state *rc, int64_t bits, int is_golden_frame,
int is_altref_frame, int frame_type, int droppable);
int od_frame_type(od_rc_state *rc, int64_t coding_frame_count, int *is_golden,
int *is_altref, int64_t *ip_count);
int od_enc_rc_resize(od_rc_state *rc);
int od_enc_rc_2pass_out(od_rc_state *rc, struct aom_codec_pkt_list *pkt_list,
int summary);
int od_enc_rc_2pass_in(od_rc_state *rc);
#endif

File diff suppressed because it is too large Load diff

View file

@ -14,9 +14,6 @@
#include <limits.h>
#if CONFIG_ANS
#include "aom_dsp/ans.h"
#endif // CONFIG_ANS
#include "av1/common/blockd.h"
#include "av1/encoder/block.h"
@ -30,9 +27,9 @@ extern "C" {
#define RDDIV_BITS 7
#define RD_EPB_SHIFT 6
#define RDCOST(RM, R, D) \
(ROUND_POWER_OF_TWO(((int64_t)R) * (RM), AV1_PROB_COST_SHIFT) + \
(D << RDDIV_BITS))
#define RDCOST(RM, R, D) \
(ROUND_POWER_OF_TWO(((int64_t)(R)) * (RM), AV1_PROB_COST_SHIFT) + \
((D) * (1 << RDDIV_BITS)))
#define RDCOST_DBL(RM, R, D) \
(((((double)(R)) * (RM)) / (double)(1 << AV1_PROB_COST_SHIFT)) + \
@ -50,102 +47,43 @@ extern "C" {
// const MODE_DEFINITION av1_mode_order[MAX_MODES] used in the rd code.
typedef enum {
THR_NEARESTMV,
#if CONFIG_EXT_REFS
THR_NEARESTL2,
THR_NEARESTL3,
THR_NEARESTB,
THR_NEARESTA2,
#endif // CONFIG_EXT_REFS
THR_NEARESTA,
THR_NEARESTG,
THR_DC,
THR_NEWMV,
#if CONFIG_EXT_REFS
THR_NEWL2,
THR_NEWL3,
THR_NEWB,
THR_NEWA2,
#endif // CONFIG_EXT_REFS
THR_NEWA,
THR_NEWG,
THR_NEARMV,
#if CONFIG_EXT_REFS
THR_NEARL2,
THR_NEARL3,
THR_NEARB,
THR_NEARA2,
#endif // CONFIG_EXT_REFS
THR_NEARA,
THR_NEARG,
THR_ZEROMV,
#if CONFIG_EXT_REFS
THR_ZEROL2,
THR_ZEROL3,
THR_ZEROB,
THR_ZEROA2,
#endif // CONFIG_EXT_REFS
THR_ZEROA,
THR_ZEROG,
#if CONFIG_COMPOUND_SINGLEREF
THR_SR_NEAREST_NEARMV,
#if CONFIG_EXT_REFS
THR_SR_NEAREST_NEARL2,
THR_SR_NEAREST_NEARL3,
THR_SR_NEAREST_NEARB,
#endif // CONFIG_EXT_REFS
THR_SR_NEAREST_NEARG,
THR_SR_NEAREST_NEARA,
/*
THR_SR_NEAREST_NEWMV,
#if CONFIG_EXT_REFS
THR_SR_NEAREST_NEWL2,
THR_SR_NEAREST_NEWL3,
THR_SR_NEAREST_NEWB,
#endif // CONFIG_EXT_REFS
THR_SR_NEAREST_NEWG,
THR_SR_NEAREST_NEWA,*/
THR_SR_NEAR_NEWMV,
#if CONFIG_EXT_REFS
THR_SR_NEAR_NEWL2,
THR_SR_NEAR_NEWL3,
THR_SR_NEAR_NEWB,
#endif // CONFIG_EXT_REFS
THR_SR_NEAR_NEWG,
THR_SR_NEAR_NEWA,
THR_SR_ZERO_NEWMV,
#if CONFIG_EXT_REFS
THR_SR_ZERO_NEWL2,
THR_SR_ZERO_NEWL3,
THR_SR_ZERO_NEWB,
#endif // CONFIG_EXT_REFS
THR_SR_ZERO_NEWG,
THR_SR_ZERO_NEWA,
THR_SR_NEW_NEWMV,
#if CONFIG_EXT_REFS
THR_SR_NEW_NEWL2,
THR_SR_NEW_NEWL3,
THR_SR_NEW_NEWB,
#endif // CONFIG_EXT_REFS
THR_SR_NEW_NEWG,
THR_SR_NEW_NEWA,
#endif // CONFIG_COMPOUND_SINGLEREF
THR_GLOBALMV,
THR_GLOBALL2,
THR_GLOBALL3,
THR_GLOBALB,
THR_GLOBALA2,
THR_GLOBALA,
THR_GLOBALG,
THR_COMP_NEAREST_NEARESTLA,
#if CONFIG_EXT_REFS
THR_COMP_NEAREST_NEARESTL2A,
THR_COMP_NEAREST_NEARESTL3A,
#endif // CONFIG_EXT_REFS
THR_COMP_NEAREST_NEARESTGA,
#if CONFIG_EXT_REFS
THR_COMP_NEAREST_NEARESTLB,
THR_COMP_NEAREST_NEARESTL2B,
THR_COMP_NEAREST_NEARESTL3B,
@ -154,21 +92,16 @@ typedef enum {
THR_COMP_NEAREST_NEARESTL2A2,
THR_COMP_NEAREST_NEARESTL3A2,
THR_COMP_NEAREST_NEARESTGA2,
#if CONFIG_EXT_COMP_REFS
THR_COMP_NEAREST_NEARESTLL2,
THR_COMP_NEAREST_NEARESTLL3,
THR_COMP_NEAREST_NEARESTLG,
THR_COMP_NEAREST_NEARESTBA,
#endif // CONFIG_EXT_COMP_REFS
#endif // CONFIG_EXT_REFS
THR_TM,
THR_PAETH,
THR_SMOOTH,
#if CONFIG_SMOOTH_HV
THR_SMOOTH_V,
THR_SMOOTH_H,
#endif // CONFIG_SMOOTH_HV
THR_COMP_NEAR_NEARLA,
THR_COMP_NEW_NEARESTLA,
@ -176,16 +109,15 @@ typedef enum {
THR_COMP_NEW_NEARLA,
THR_COMP_NEAR_NEWLA,
THR_COMP_NEW_NEWLA,
THR_COMP_ZERO_ZEROLA,
THR_COMP_GLOBAL_GLOBALLA,
#if CONFIG_EXT_REFS
THR_COMP_NEAR_NEARL2A,
THR_COMP_NEW_NEARESTL2A,
THR_COMP_NEAREST_NEWL2A,
THR_COMP_NEW_NEARL2A,
THR_COMP_NEAR_NEWL2A,
THR_COMP_NEW_NEWL2A,
THR_COMP_ZERO_ZEROL2A,
THR_COMP_GLOBAL_GLOBALL2A,
THR_COMP_NEAR_NEARL3A,
THR_COMP_NEW_NEARESTL3A,
@ -193,8 +125,7 @@ typedef enum {
THR_COMP_NEW_NEARL3A,
THR_COMP_NEAR_NEWL3A,
THR_COMP_NEW_NEWL3A,
THR_COMP_ZERO_ZEROL3A,
#endif // CONFIG_EXT_REFS
THR_COMP_GLOBAL_GLOBALL3A,
THR_COMP_NEAR_NEARGA,
THR_COMP_NEW_NEARESTGA,
@ -202,16 +133,15 @@ typedef enum {
THR_COMP_NEW_NEARGA,
THR_COMP_NEAR_NEWGA,
THR_COMP_NEW_NEWGA,
THR_COMP_ZERO_ZEROGA,
THR_COMP_GLOBAL_GLOBALGA,
#if CONFIG_EXT_REFS
THR_COMP_NEAR_NEARLB,
THR_COMP_NEW_NEARESTLB,
THR_COMP_NEAREST_NEWLB,
THR_COMP_NEW_NEARLB,
THR_COMP_NEAR_NEWLB,
THR_COMP_NEW_NEWLB,
THR_COMP_ZERO_ZEROLB,
THR_COMP_GLOBAL_GLOBALLB,
THR_COMP_NEAR_NEARL2B,
THR_COMP_NEW_NEARESTL2B,
@ -219,7 +149,7 @@ typedef enum {
THR_COMP_NEW_NEARL2B,
THR_COMP_NEAR_NEWL2B,
THR_COMP_NEW_NEWL2B,
THR_COMP_ZERO_ZEROL2B,
THR_COMP_GLOBAL_GLOBALL2B,
THR_COMP_NEAR_NEARL3B,
THR_COMP_NEW_NEARESTL3B,
@ -227,7 +157,7 @@ typedef enum {
THR_COMP_NEW_NEARL3B,
THR_COMP_NEAR_NEWL3B,
THR_COMP_NEW_NEWL3B,
THR_COMP_ZERO_ZEROL3B,
THR_COMP_GLOBAL_GLOBALL3B,
THR_COMP_NEAR_NEARGB,
THR_COMP_NEW_NEARESTGB,
@ -235,7 +165,7 @@ typedef enum {
THR_COMP_NEW_NEARGB,
THR_COMP_NEAR_NEWGB,
THR_COMP_NEW_NEWGB,
THR_COMP_ZERO_ZEROGB,
THR_COMP_GLOBAL_GLOBALGB,
THR_COMP_NEAR_NEARLA2,
THR_COMP_NEW_NEARESTLA2,
@ -243,7 +173,7 @@ typedef enum {
THR_COMP_NEW_NEARLA2,
THR_COMP_NEAR_NEWLA2,
THR_COMP_NEW_NEWLA2,
THR_COMP_ZERO_ZEROLA2,
THR_COMP_GLOBAL_GLOBALLA2,
THR_COMP_NEAR_NEARL2A2,
THR_COMP_NEW_NEARESTL2A2,
@ -251,7 +181,7 @@ typedef enum {
THR_COMP_NEW_NEARL2A2,
THR_COMP_NEAR_NEWL2A2,
THR_COMP_NEW_NEWL2A2,
THR_COMP_ZERO_ZEROL2A2,
THR_COMP_GLOBAL_GLOBALL2A2,
THR_COMP_NEAR_NEARL3A2,
THR_COMP_NEW_NEARESTL3A2,
@ -259,7 +189,7 @@ typedef enum {
THR_COMP_NEW_NEARL3A2,
THR_COMP_NEAR_NEWL3A2,
THR_COMP_NEW_NEWL3A2,
THR_COMP_ZERO_ZEROL3A2,
THR_COMP_GLOBAL_GLOBALL3A2,
THR_COMP_NEAR_NEARGA2,
THR_COMP_NEW_NEARESTGA2,
@ -267,16 +197,24 @@ typedef enum {
THR_COMP_NEW_NEARGA2,
THR_COMP_NEAR_NEWGA2,
THR_COMP_NEW_NEWGA2,
THR_COMP_ZERO_ZEROGA2,
THR_COMP_GLOBAL_GLOBALGA2,
THR_H_PRED,
THR_V_PRED,
THR_D135_PRED,
THR_D203_PRED,
THR_D157_PRED,
THR_D67_PRED,
THR_D113_PRED,
THR_D45_PRED,
#if CONFIG_EXT_COMP_REFS
THR_COMP_NEAR_NEARLL2,
THR_COMP_NEW_NEARESTLL2,
THR_COMP_NEAREST_NEWLL2,
THR_COMP_NEW_NEARLL2,
THR_COMP_NEAR_NEWLL2,
THR_COMP_NEW_NEWLL2,
THR_COMP_ZERO_ZEROLL2,
THR_COMP_GLOBAL_GLOBALLL2,
THR_COMP_NEAR_NEARLL3,
THR_COMP_NEW_NEARESTLL3,
@ -284,7 +222,7 @@ typedef enum {
THR_COMP_NEW_NEARLL3,
THR_COMP_NEAR_NEWLL3,
THR_COMP_NEW_NEWLL3,
THR_COMP_ZERO_ZEROLL3,
THR_COMP_GLOBAL_GLOBALLL3,
THR_COMP_NEAR_NEARLG,
THR_COMP_NEW_NEARESTLG,
@ -292,7 +230,7 @@ typedef enum {
THR_COMP_NEW_NEARLG,
THR_COMP_NEAR_NEWLG,
THR_COMP_NEW_NEWLG,
THR_COMP_ZERO_ZEROLG,
THR_COMP_GLOBAL_GLOBALLG,
THR_COMP_NEAR_NEARBA,
THR_COMP_NEW_NEARESTBA,
@ -300,79 +238,25 @@ typedef enum {
THR_COMP_NEW_NEARBA,
THR_COMP_NEAR_NEWBA,
THR_COMP_NEW_NEWBA,
THR_COMP_ZERO_ZEROBA,
#endif // CONFIG_EXT_COMP_REFS
#endif // CONFIG_EXT_REFS
THR_COMP_GLOBAL_GLOBALBA,
THR_H_PRED,
THR_V_PRED,
THR_D135_PRED,
THR_D207_PRED,
THR_D153_PRED,
THR_D63_PRED,
THR_D117_PRED,
THR_D45_PRED,
THR_COMP_INTERINTRA_ZEROL,
THR_COMP_INTERINTRA_NEARESTL,
THR_COMP_INTERINTRA_NEARL,
THR_COMP_INTERINTRA_NEWL,
#if CONFIG_EXT_REFS
THR_COMP_INTERINTRA_ZEROL2,
THR_COMP_INTERINTRA_NEARESTL2,
THR_COMP_INTERINTRA_NEARL2,
THR_COMP_INTERINTRA_NEWL2,
THR_COMP_INTERINTRA_ZEROL3,
THR_COMP_INTERINTRA_NEARESTL3,
THR_COMP_INTERINTRA_NEARL3,
THR_COMP_INTERINTRA_NEWL3,
#endif // CONFIG_EXT_REFS
THR_COMP_INTERINTRA_ZEROG,
THR_COMP_INTERINTRA_NEARESTG,
THR_COMP_INTERINTRA_NEARG,
THR_COMP_INTERINTRA_NEWG,
#if CONFIG_EXT_REFS
THR_COMP_INTERINTRA_ZEROB,
THR_COMP_INTERINTRA_NEARESTB,
THR_COMP_INTERINTRA_NEARB,
THR_COMP_INTERINTRA_NEWB,
THR_COMP_INTERINTRA_ZEROA2,
THR_COMP_INTERINTRA_NEARESTA2,
THR_COMP_INTERINTRA_NEARA2,
THR_COMP_INTERINTRA_NEWA2,
#endif // CONFIG_EXT_REFS
THR_COMP_INTERINTRA_ZEROA,
THR_COMP_INTERINTRA_NEARESTA,
THR_COMP_INTERINTRA_NEARA,
THR_COMP_INTERINTRA_NEWA,
MAX_MODES
} THR_MODES;
typedef enum {
THR_LAST,
#if CONFIG_EXT_REFS
THR_LAST2,
THR_LAST3,
THR_BWDR,
THR_ALTR2,
#endif // CONFIG_EXT_REFS
THR_GOLD,
THR_ALTR,
THR_COMP_LA,
#if CONFIG_EXT_REFS
THR_COMP_L2A,
THR_COMP_L3A,
#endif // CONFIG_EXT_REFS
THR_COMP_GA,
#if CONFIG_EXT_REFS
THR_COMP_LB,
THR_COMP_L2B,
THR_COMP_L3B,
@ -382,7 +266,6 @@ typedef enum {
THR_COMP_L2A2,
THR_COMP_L3A2,
THR_COMP_GA2,
#endif // CONFIG_EXT_REFS
THR_INTRA,
@ -399,7 +282,7 @@ typedef struct RD_OPT {
int threshes[MAX_SEGMENTS][BLOCK_SIZES_ALL][MAX_MODES];
int64_t prediction_type_threshes[TOTAL_REFS_PER_FRAME][REFERENCE_MODES];
int64_t prediction_type_threshes[REF_FRAMES][REFERENCE_MODES];
int RDMULT;
} RD_OPT;
@ -417,16 +300,16 @@ static INLINE void av1_init_rd_stats(RD_STATS *rd_stats) {
rd_stats->invalid_rate = 0;
rd_stats->ref_rdcost = INT64_MAX;
#if CONFIG_RD_DEBUG
// This may run into problems when monochrome video is
// encoded, as there will only be 1 plane
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
rd_stats->txb_coeff_cost[plane] = 0;
#if CONFIG_VAR_TX
{
int r, c;
for (r = 0; r < TXB_COEFF_COST_MAP_SIZE; ++r)
for (c = 0; c < TXB_COEFF_COST_MAP_SIZE; ++c)
rd_stats->txb_coeff_cost_map[plane][r][c] = 0;
}
#endif
}
#endif
}
@ -444,16 +327,16 @@ static INLINE void av1_invalid_rd_stats(RD_STATS *rd_stats) {
rd_stats->invalid_rate = 1;
rd_stats->ref_rdcost = INT64_MAX;
#if CONFIG_RD_DEBUG
// This may run into problems when monochrome video is
// encoded, as there will only be 1 plane
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
rd_stats->txb_coeff_cost[plane] = INT_MAX;
#if CONFIG_VAR_TX
{
int r, c;
for (r = 0; r < TXB_COEFF_COST_MAP_SIZE; ++r)
for (c = 0; c < TXB_COEFF_COST_MAP_SIZE; ++c)
rd_stats->txb_coeff_cost_map[plane][r][c] = INT_MAX;
}
#endif
}
#endif
}
@ -464,14 +347,17 @@ static INLINE void av1_merge_rd_stats(RD_STATS *rd_stats_dst,
int plane;
#endif
rd_stats_dst->rate += rd_stats_src->rate;
if (!rd_stats_dst->zero_rate)
rd_stats_dst->zero_rate = rd_stats_src->zero_rate;
rd_stats_dst->dist += rd_stats_src->dist;
rd_stats_dst->sse += rd_stats_src->sse;
rd_stats_dst->skip &= rd_stats_src->skip;
rd_stats_dst->invalid_rate &= rd_stats_src->invalid_rate;
#if CONFIG_RD_DEBUG
// This may run into problems when monochrome video is
// encoded, as there will only be 1 plane
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
rd_stats_dst->txb_coeff_cost[plane] += rd_stats_src->txb_coeff_cost[plane];
#if CONFIG_VAR_TX
{
// TODO(angiebird): optimize this part
int r, c;
@ -484,21 +370,10 @@ static INLINE void av1_merge_rd_stats(RD_STATS *rd_stats_dst,
}
assert(ref_txb_coeff_cost == rd_stats_dst->txb_coeff_cost[plane]);
}
#endif
}
#endif
}
static INLINE int av1_get_coeff_token_cost(int token, int eob_val, int is_first,
const int *head_cost_table,
const int *tail_cost_table) {
if (eob_val == LAST_EOB) return av1_cost_zero(128);
const int comb_symb = 2 * AOMMIN(token, TWO_TOKEN) - eob_val + is_first;
int cost = head_cost_table[comb_symb];
if (token > ONE_TOKEN) cost += tail_cost_table[token - TWO_TOKEN];
return cost;
}
struct TileInfo;
struct TileDataEnc;
struct AV1_COMP;
@ -528,13 +403,12 @@ YV12_BUFFER_CONFIG *av1_get_scaled_ref_frame(const struct AV1_COMP *cpi,
void av1_init_me_luts(void);
void av1_set_mvcost(MACROBLOCK *x, MV_REFERENCE_FRAME ref_frame, int ref,
int ref_mv_idx);
void av1_set_mvcost(MACROBLOCK *x, int ref, int ref_mv_idx);
void av1_get_entropy_contexts(BLOCK_SIZE bsize, TX_SIZE tx_size,
void av1_get_entropy_contexts(BLOCK_SIZE bsize,
const struct macroblockd_plane *pd,
ENTROPY_CONTEXT t_above[2 * MAX_MIB_SIZE],
ENTROPY_CONTEXT t_left[2 * MAX_MIB_SIZE]);
ENTROPY_CONTEXT t_above[MAX_MIB_SIZE],
ENTROPY_CONTEXT t_left[MAX_MIB_SIZE]);
void av1_set_rd_speed_thresholds(struct AV1_COMP *cpi);
@ -562,7 +436,8 @@ void av1_setup_pred_block(const MACROBLOCKD *xd,
struct buf_2d dst[MAX_MB_PLANE],
const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
const struct scale_factors *scale,
const struct scale_factors *scale_uv);
const struct scale_factors *scale_uv,
const int num_planes);
int av1_get_intra_cost_penalty(int qindex, int qdelta,
aom_bit_depth_t bit_depth);
@ -570,12 +445,8 @@ int av1_get_intra_cost_penalty(int qindex, int qdelta,
void av1_fill_mode_rates(AV1_COMMON *const cm, MACROBLOCK *x,
FRAME_CONTEXT *fc);
#if CONFIG_LV_MAP
void av1_fill_coeff_costs(MACROBLOCK *x, FRAME_CONTEXT *fc);
#endif
void av1_fill_token_costs_from_cdf(av1_coeff_cost *cost,
coeff_cdf_model (*cdf)[PLANE_TYPES]);
void av1_fill_coeff_costs(MACROBLOCK *x, FRAME_CONTEXT *fc,
const int num_planes);
#ifdef __cplusplus
} // extern "C"

File diff suppressed because it is too large Load diff

View file

@ -13,16 +13,20 @@
#define AV1_ENCODER_RDOPT_H_
#include "av1/common/blockd.h"
#include "av1/common/txb_common.h"
#include "av1/encoder/block.h"
#include "av1/encoder/context_tree.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/encodetxb.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_REF_MV_SERCH 3
struct TileInfo;
struct AV1_COMP;
struct macroblock;
struct RD_STATS;
@ -35,7 +39,6 @@ static INLINE void av1_update_txb_coeff_cost(RD_STATS *rd_stats, int plane,
(void)tx_size;
rd_stats->txb_coeff_cost[plane] += txb_coeff_cost;
#if CONFIG_VAR_TX
{
const int txb_h = tx_size_high_unit[tx_size];
const int txb_w = tx_size_wide_unit[tx_size];
@ -48,113 +51,86 @@ static INLINE void av1_update_txb_coeff_cost(RD_STATS *rd_stats, int plane,
}
assert(blk_row < TXB_COEFF_COST_MAP_SIZE);
assert(blk_col < TXB_COEFF_COST_MAP_SIZE);
#endif
}
#endif
typedef enum OUTPUT_STATUS {
OUTPUT_HAS_PREDICTED_PIXELS,
OUTPUT_HAS_DECODED_PIXELS
} OUTPUT_STATUS;
// Returns the number of colors in 'src'.
int av1_count_colors(const uint8_t *src, int stride, int rows, int cols);
#if CONFIG_HIGHBITDEPTH
int av1_count_colors(const uint8_t *src, int stride, int rows, int cols,
int *val_count);
// Same as av1_count_colors(), but for high-bitdepth mode.
int av1_count_colors_highbd(const uint8_t *src8, int stride, int rows, int cols,
int bit_depth);
#endif // CONFIG_HIGHBITDEPTH
void av1_dist_block(const AV1_COMP *cpi, MACROBLOCK *x, int plane,
BLOCK_SIZE plane_bsize, int block, int blk_row, int blk_col,
TX_SIZE tx_size, int64_t *out_dist, int64_t *out_sse,
OUTPUT_STATUS output_status);
int bit_depth, int *val_count);
#if CONFIG_DIST_8X8
int64_t av1_dist_8x8(const AV1_COMP *const cpi, const MACROBLOCK *x,
int64_t av1_dist_8x8(const struct AV1_COMP *const cpi, const MACROBLOCK *x,
const uint8_t *src, int src_stride, const uint8_t *dst,
int dst_stride, const BLOCK_SIZE tx_bsize, int bsw,
int bsh, int visible_w, int visible_h, int qindex);
#endif
#if !CONFIG_PVQ || CONFIG_VAR_TX
int av1_cost_coeffs(const AV1_COMP *const cpi, MACROBLOCK *x, int plane,
int blk_row, int blk_col, int block, TX_SIZE tx_size,
const SCAN_ORDER *scan_order, const ENTROPY_CONTEXT *a,
const ENTROPY_CONTEXT *l, int use_fast_coef_costing);
#endif
void av1_rd_pick_intra_mode_sb(const struct AV1_COMP *cpi, struct macroblock *x,
struct RD_STATS *rd_cost, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx, int64_t best_rd);
static INLINE int av1_cost_skip_txb(MACROBLOCK *x, const TXB_CTX *const txb_ctx,
int plane, TX_SIZE tx_size) {
const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
const PLANE_TYPE plane_type = get_plane_type(plane);
const LV_MAP_COEFF_COST *const coeff_costs =
&x->coeff_costs[txs_ctx][plane_type];
return coeff_costs->txb_skip_cost[txb_ctx->txb_skip_ctx][1];
}
unsigned int av1_get_sby_perpixel_variance(const AV1_COMP *cpi,
static INLINE int av1_cost_coeffs(const AV1_COMMON *const cm, MACROBLOCK *x,
int plane, int blk_row, int blk_col,
int block, TX_SIZE tx_size,
const TXB_CTX *const txb_ctx,
int use_fast_coef_costing) {
#if TXCOEFF_COST_TIMER
struct aom_usec_timer timer;
aom_usec_timer_start(&timer);
#endif
(void)use_fast_coef_costing;
const int cost = av1_cost_coeffs_txb(cm, x, plane, blk_row, blk_col, block,
tx_size, txb_ctx);
#if TXCOEFF_COST_TIMER
AV1_COMMON *tmp_cm = (AV1_COMMON *)&cpi->common;
aom_usec_timer_mark(&timer);
const int64_t elapsed_time = aom_usec_timer_elapsed(&timer);
tmp_cm->txcoeff_cost_timer += elapsed_time;
++tmp_cm->txcoeff_cost_count;
#endif
return cost;
}
void av1_rd_pick_intra_mode_sb(const struct AV1_COMP *cpi, struct macroblock *x,
int mi_row, int mi_col, struct RD_STATS *rd_cost,
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
int64_t best_rd);
unsigned int av1_get_sby_perpixel_variance(const struct AV1_COMP *cpi,
const struct buf_2d *ref,
BLOCK_SIZE bs);
#if CONFIG_HIGHBITDEPTH
unsigned int av1_high_get_sby_perpixel_variance(const AV1_COMP *cpi,
unsigned int av1_high_get_sby_perpixel_variance(const struct AV1_COMP *cpi,
const struct buf_2d *ref,
BLOCK_SIZE bs, int bd);
#endif
void av1_rd_pick_inter_mode_sb(const struct AV1_COMP *cpi,
struct TileDataEnc *tile_data,
struct macroblock *x, int mi_row, int mi_col,
struct RD_STATS *rd_cost,
#if CONFIG_SUPERTX
int *returnrate_nocoef,
#endif // CONFIG_SUPERTX
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
int64_t best_rd_so_far);
struct RD_STATS *rd_cost, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far);
void av1_rd_pick_inter_mode_sb_seg_skip(
const struct AV1_COMP *cpi, struct TileDataEnc *tile_data,
struct macroblock *x, int mi_row, int mi_col, struct RD_STATS *rd_cost,
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far);
int av1_internal_image_edge(const struct AV1_COMP *cpi);
int av1_active_h_edge(const struct AV1_COMP *cpi, int mi_row, int mi_step);
int av1_active_v_edge(const struct AV1_COMP *cpi, int mi_col, int mi_step);
int av1_active_edge_sb(const struct AV1_COMP *cpi, int mi_row, int mi_col);
#if CONFIG_MOTION_VAR && CONFIG_NCOBMC
void av1_check_ncobmc_rd(const struct AV1_COMP *cpi, struct macroblock *x,
int mi_row, int mi_col);
#endif // CONFIG_MOTION_VAR && CONFIG_NCOBMC
#if CONFIG_SUPERTX
#if CONFIG_VAR_TX
void av1_tx_block_rd_b(const AV1_COMP *cpi, MACROBLOCK *x, TX_SIZE tx_size,
int blk_row, int blk_col, int plane, int block,
int plane_bsize, const ENTROPY_CONTEXT *a,
const ENTROPY_CONTEXT *l, RD_STATS *rd_stats);
#if CONFIG_COLLECT_INTER_MODE_RD_STATS
#define INTER_MODE_RD_TEST 0
void av1_inter_mode_data_init();
void av1_inter_mode_data_fit(int rdmult);
void av1_inter_mode_data_show(const AV1_COMMON *cm);
#endif
void av1_txfm_rd_in_plane_supertx(MACROBLOCK *x, const AV1_COMP *cpi, int *rate,
int64_t *distortion, int *skippable,
int64_t *sse, int64_t ref_best_rd, int plane,
BLOCK_SIZE bsize, TX_SIZE tx_size,
int use_fast_coef_casting);
#endif // CONFIG_SUPERTX
#ifdef __cplusplus
} // extern "C"
#endif
int av1_tx_type_cost(const AV1_COMMON *cm, const MACROBLOCK *x,
const MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
TX_SIZE tx_size, TX_TYPE tx_type);
int64_t get_prediction_rd_cost(const struct AV1_COMP *cpi, struct macroblock *x,
int mi_row, int mi_col, int *skip_blk,
MB_MODE_INFO *backup_mbmi);
#if CONFIG_NCOBMC_ADAPT_WEIGHT
void av1_check_ncobmc_adapt_weight_rd(const struct AV1_COMP *cpi,
struct macroblock *x, int mi_row,
int mi_col);
int get_ncobmc_mode(const AV1_COMP *const cpi, MACROBLOCK *const x,
MACROBLOCKD *xd, int mi_row, int mi_col, int bsize);
#endif
#endif // AV1_ENCODER_RDOPT_H_

View file

@ -18,26 +18,21 @@
#include "av1/encoder/cost.h"
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
void av1_enable_segmentation(struct segmentation *seg) {
seg->enabled = 1;
seg->update_map = 1;
seg->update_data = 1;
seg->temporal_update = 0;
}
void av1_disable_segmentation(struct segmentation *seg) {
seg->enabled = 0;
seg->update_map = 0;
seg->update_data = 0;
seg->temporal_update = 0;
}
void av1_set_segment_data(struct segmentation *seg, int8_t *feature_data,
unsigned char abs_delta) {
seg->abs_delta = abs_delta;
memcpy(seg->feature_data, feature_data, sizeof(seg->feature_data));
}
void av1_disable_segfeature(struct segmentation *seg, int segment_id,
SEG_LVL_FEATURES feature_id) {
seg->feature_mask[segment_id] &= ~(1 << feature_id);
@ -48,76 +43,8 @@ void av1_clear_segdata(struct segmentation *seg, int segment_id,
seg->feature_data[segment_id][feature_id] = 0;
}
// Based on set of segment counts calculate a probability tree
static void calc_segtree_probs(unsigned *segcounts,
aom_prob *segment_tree_probs,
const aom_prob *cur_tree_probs,
const int probwt) {
// Work out probabilities of each segment
const unsigned cc[4] = { segcounts[0] + segcounts[1],
segcounts[2] + segcounts[3],
segcounts[4] + segcounts[5],
segcounts[6] + segcounts[7] };
const unsigned ccc[2] = { cc[0] + cc[1], cc[2] + cc[3] };
int i;
segment_tree_probs[0] = get_binary_prob(ccc[0], ccc[1]);
segment_tree_probs[1] = get_binary_prob(cc[0], cc[1]);
segment_tree_probs[2] = get_binary_prob(cc[2], cc[3]);
segment_tree_probs[3] = get_binary_prob(segcounts[0], segcounts[1]);
segment_tree_probs[4] = get_binary_prob(segcounts[2], segcounts[3]);
segment_tree_probs[5] = get_binary_prob(segcounts[4], segcounts[5]);
segment_tree_probs[6] = get_binary_prob(segcounts[6], segcounts[7]);
for (i = 0; i < 7; i++) {
const unsigned *ct =
i == 0 ? ccc : i < 3 ? cc + (i & 2) : segcounts + (i - 3) * 2;
av1_prob_diff_update_savings_search(ct, cur_tree_probs[i],
&segment_tree_probs[i],
DIFF_UPDATE_PROB, probwt);
}
}
// Based on set of segment counts and probabilities calculate a cost estimate
static int cost_segmap(unsigned *segcounts, aom_prob *probs) {
const int c01 = segcounts[0] + segcounts[1];
const int c23 = segcounts[2] + segcounts[3];
const int c45 = segcounts[4] + segcounts[5];
const int c67 = segcounts[6] + segcounts[7];
const int c0123 = c01 + c23;
const int c4567 = c45 + c67;
// Cost the top node of the tree
int cost = c0123 * av1_cost_zero(probs[0]) + c4567 * av1_cost_one(probs[0]);
// Cost subsequent levels
if (c0123 > 0) {
cost += c01 * av1_cost_zero(probs[1]) + c23 * av1_cost_one(probs[1]);
if (c01 > 0)
cost += segcounts[0] * av1_cost_zero(probs[3]) +
segcounts[1] * av1_cost_one(probs[3]);
if (c23 > 0)
cost += segcounts[2] * av1_cost_zero(probs[4]) +
segcounts[3] * av1_cost_one(probs[4]);
}
if (c4567 > 0) {
cost += c45 * av1_cost_zero(probs[2]) + c67 * av1_cost_one(probs[2]);
if (c45 > 0)
cost += segcounts[4] * av1_cost_zero(probs[5]) +
segcounts[5] * av1_cost_one(probs[5]);
if (c67 > 0)
cost += segcounts[6] * av1_cost_zero(probs[6]) +
segcounts[7] * av1_cost_one(probs[6]);
}
return cost;
}
static void count_segs(const AV1_COMMON *cm, MACROBLOCKD *xd,
const TileInfo *tile, MODE_INFO **mi,
const TileInfo *tile, MB_MODE_INFO **mi,
unsigned *no_pred_segcounts,
unsigned (*temporal_predictor_count)[2],
unsigned *t_unpred_seg_counts, int bw, int bh,
@ -127,29 +54,27 @@ static void count_segs(const AV1_COMMON *cm, MACROBLOCKD *xd,
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
xd->mi = mi;
segment_id = xd->mi[0]->mbmi.segment_id;
segment_id = xd->mi[0]->segment_id;
set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw,
#if CONFIG_DEPENDENT_HORZTILES
cm->dependent_horz_tiles,
#endif // CONFIG_DEPENDENT_HORZTILES
cm->mi_rows, cm->mi_cols);
set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, cm->mi_rows, cm->mi_cols);
// Count the number of hits on each segment with no prediction
no_pred_segcounts[segment_id]++;
// Temporal prediction not allowed on key frames
if (cm->frame_type != KEY_FRAME) {
const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
const BLOCK_SIZE bsize = xd->mi[0]->sb_type;
// Test to see if the segment id matches the predicted value.
const int pred_segment_id =
get_segment_id(cm, cm->last_frame_seg_map, bsize, mi_row, mi_col);
cm->last_frame_seg_map
? get_segment_id(cm, cm->last_frame_seg_map, bsize, mi_row, mi_col)
: 0;
const int pred_flag = pred_segment_id == segment_id;
const int pred_context = av1_get_pred_context_seg_id(xd);
// Store the prediction status for this mb and update counts
// as appropriate
xd->mi[0]->mbmi.seg_id_predicted = pred_flag;
xd->mi[0]->seg_id_predicted = pred_flag;
temporal_predictor_count[pred_context][pred_flag]++;
// Update the "unpredicted" segment count
@ -158,21 +83,15 @@ static void count_segs(const AV1_COMMON *cm, MACROBLOCKD *xd,
}
static void count_segs_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
const TileInfo *tile, MODE_INFO **mi,
const TileInfo *tile, MB_MODE_INFO **mi,
unsigned *no_pred_segcounts,
unsigned (*temporal_predictor_count)[2],
unsigned *t_unpred_seg_counts, int mi_row, int mi_col,
BLOCK_SIZE bsize) {
const int mis = cm->mi_stride;
const int bs = mi_size_wide[bsize], hbs = bs / 2;
#if CONFIG_EXT_PARTITION_TYPES
PARTITION_TYPE partition;
#if CONFIG_EXT_PARTITION_TYPES_AB
const int qbs = bs / 4;
#endif // CONFIG_EXT_PARTITION_TYPES_AB
#else
int bw, bh;
#endif // CONFIG_EXT_PARTITION_TYPES
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
@ -181,7 +100,6 @@ static void count_segs_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
no_pred_segcounts, temporal_predictor_count, t_unpred_seg_counts, \
(cs_bw), (cs_bh), mi_row + (cs_rowoff), mi_col + (cs_coloff));
#if CONFIG_EXT_PARTITION_TYPES
if (bsize == BLOCK_8X8)
partition = PARTITION_NONE;
else
@ -196,55 +114,43 @@ static void count_segs_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
CSEGS(hbs, bs, 0, 0);
CSEGS(hbs, bs, 0, hbs);
break;
#if CONFIG_EXT_PARTITION_TYPES_AB
case PARTITION_HORZ_A:
CSEGS(hbs, hbs, 0, 0);
CSEGS(hbs, hbs, 0, hbs);
CSEGS(bs, hbs, hbs, 0);
break;
case PARTITION_HORZ_B:
CSEGS(bs, hbs, 0, 0);
CSEGS(hbs, hbs, hbs, 0);
CSEGS(hbs, hbs, hbs, hbs);
break;
case PARTITION_VERT_A:
CSEGS(hbs, hbs, 0, 0);
CSEGS(hbs, hbs, hbs, 0);
CSEGS(hbs, bs, 0, hbs);
break;
case PARTITION_VERT_B:
CSEGS(hbs, bs, 0, 0);
CSEGS(hbs, hbs, 0, hbs);
CSEGS(hbs, hbs, hbs, hbs);
break;
case PARTITION_HORZ_4:
CSEGS(bs, qbs, 0, 0);
CSEGS(bs, qbs, qbs, 0);
CSEGS(bs, hbs, hbs, 0);
break;
case PARTITION_HORZ_B:
CSEGS(bs, hbs, 0, 0);
CSEGS(bs, qbs, hbs, 0);
CSEGS(bs, qbs, 2 * qbs, 0);
if (mi_row + 3 * qbs < cm->mi_rows) CSEGS(bs, qbs, 3 * qbs, 0);
break;
case PARTITION_VERT_A:
case PARTITION_VERT_4:
CSEGS(qbs, bs, 0, 0);
CSEGS(qbs, bs, 0, qbs);
CSEGS(hbs, bs, 0, hbs);
break;
case PARTITION_VERT_B:
CSEGS(hbs, bs, 0, 0);
CSEGS(qbs, bs, 0, hbs);
CSEGS(qbs, bs, 0, 2 * qbs);
if (mi_col + 3 * qbs < cm->mi_cols) CSEGS(qbs, bs, 0, 3 * qbs);
break;
#else
case PARTITION_HORZ_A:
CSEGS(hbs, hbs, 0, 0);
CSEGS(hbs, hbs, 0, hbs);
CSEGS(bs, hbs, hbs, 0);
break;
case PARTITION_HORZ_B:
CSEGS(bs, hbs, 0, 0);
CSEGS(hbs, hbs, hbs, 0);
CSEGS(hbs, hbs, hbs, hbs);
break;
case PARTITION_VERT_A:
CSEGS(hbs, hbs, 0, 0);
CSEGS(hbs, hbs, hbs, 0);
CSEGS(hbs, bs, 0, hbs);
break;
case PARTITION_VERT_B:
CSEGS(hbs, bs, 0, 0);
CSEGS(hbs, hbs, 0, hbs);
CSEGS(hbs, hbs, hbs, hbs);
break;
#endif
case PARTITION_SPLIT: {
const BLOCK_SIZE subsize = subsize_lookup[PARTITION_SPLIT][bsize];
int n;
assert(num_8x8_blocks_wide_lookup[mi[0]->mbmi.sb_type] < bs &&
num_8x8_blocks_high_lookup[mi[0]->mbmi.sb_type] < bs);
case PARTITION_SPLIT: {
const BLOCK_SIZE subsize = get_partition_subsize(bsize, PARTITION_SPLIT);
int n;
for (n = 0; n < 4; n++) {
const int mi_dc = hbs * (n & 1);
@ -257,34 +163,6 @@ static void count_segs_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
} break;
default: assert(0);
}
#else
bw = mi_size_wide[mi[0]->mbmi.sb_type];
bh = mi_size_high[mi[0]->mbmi.sb_type];
if (bw == bs && bh == bs) {
CSEGS(bs, bs, 0, 0);
} else if (bw == bs && bh < bs) {
CSEGS(bs, hbs, 0, 0);
CSEGS(bs, hbs, hbs, 0);
} else if (bw < bs && bh == bs) {
CSEGS(hbs, bs, 0, 0);
CSEGS(hbs, bs, 0, hbs);
} else {
const BLOCK_SIZE subsize = subsize_lookup[PARTITION_SPLIT][bsize];
int n;
assert(bw < bs && bh < bs);
for (n = 0; n < 4; n++) {
const int mi_dc = hbs * (n & 1);
const int mi_dr = hbs * (n >> 1);
count_segs_sb(cm, xd, tile, &mi[mi_dr * mis + mi_dc], no_pred_segcounts,
temporal_predictor_count, t_unpred_seg_counts,
mi_row + mi_dr, mi_col + mi_dc, subsize);
}
}
#endif // CONFIG_EXT_PARTITION_TYPES
#undef CSEGS
}
@ -292,83 +170,58 @@ static void count_segs_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
void av1_choose_segmap_coding_method(AV1_COMMON *cm, MACROBLOCKD *xd) {
struct segmentation *seg = &cm->seg;
struct segmentation_probs *segp = &cm->fc->seg;
int no_pred_cost;
int t_pred_cost = INT_MAX;
int tile_col, tile_row, mi_row, mi_col;
const int probwt = cm->num_tg;
unsigned(*temporal_predictor_count)[2] = cm->counts.seg.pred;
unsigned *no_pred_segcounts = cm->counts.seg.tree_total;
unsigned *t_unpred_seg_counts = cm->counts.seg.tree_mispred;
aom_prob no_pred_tree[SEG_TREE_PROBS];
aom_prob t_pred_tree[SEG_TREE_PROBS];
#if !CONFIG_NEW_MULTISYMBOL
aom_prob t_nopred_prob[PREDICTION_PROBS];
#endif
unsigned temporal_predictor_count[SEG_TEMPORAL_PRED_CTXS][2] = { { 0 } };
unsigned no_pred_segcounts[MAX_SEGMENTS] = { 0 };
unsigned t_unpred_seg_counts[MAX_SEGMENTS] = { 0 };
(void)xd;
// We are about to recompute all the segment counts, so zero the accumulators.
av1_zero(cm->counts.seg);
// First of all generate stats regarding how well the last segment map
// predicts this one
for (tile_row = 0; tile_row < cm->tile_rows; tile_row++) {
TileInfo tile_info;
av1_tile_set_row(&tile_info, cm, tile_row);
for (tile_col = 0; tile_col < cm->tile_cols; tile_col++) {
MODE_INFO **mi_ptr;
MB_MODE_INFO **mi_ptr;
av1_tile_set_col(&tile_info, cm, tile_col);
#if CONFIG_DEPENDENT_HORZTILES
av1_tile_set_tg_boundary(&tile_info, cm, tile_row, tile_col);
#endif
mi_ptr = cm->mi_grid_visible + tile_info.mi_row_start * cm->mi_stride +
tile_info.mi_col_start;
for (mi_row = tile_info.mi_row_start; mi_row < tile_info.mi_row_end;
mi_row += cm->mib_size, mi_ptr += cm->mib_size * cm->mi_stride) {
MODE_INFO **mi = mi_ptr;
mi_row += cm->seq_params.mib_size,
mi_ptr += cm->seq_params.mib_size * cm->mi_stride) {
MB_MODE_INFO **mi = mi_ptr;
for (mi_col = tile_info.mi_col_start; mi_col < tile_info.mi_col_end;
mi_col += cm->mib_size, mi += cm->mib_size) {
mi_col += cm->seq_params.mib_size, mi += cm->seq_params.mib_size) {
count_segs_sb(cm, xd, &tile_info, mi, no_pred_segcounts,
temporal_predictor_count, t_unpred_seg_counts, mi_row,
mi_col, cm->sb_size);
mi_col, cm->seq_params.sb_size);
}
}
}
}
// Work out probability tree for coding segments without prediction
// and the cost.
calc_segtree_probs(no_pred_segcounts, no_pred_tree, segp->tree_probs, probwt);
no_pred_cost = cost_segmap(no_pred_segcounts, no_pred_tree);
int seg_id_cost[MAX_SEGMENTS];
av1_cost_tokens_from_cdf(seg_id_cost, segp->tree_cdf, NULL);
no_pred_cost = 0;
for (int i = 0; i < MAX_SEGMENTS; ++i)
no_pred_cost += no_pred_segcounts[i] * seg_id_cost[i];
// Key frames cannot use temporal prediction
if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
// Work out probability tree for coding those segments not
// predicted using the temporal method and the cost.
calc_segtree_probs(t_unpred_seg_counts, t_pred_tree, segp->tree_probs,
probwt);
t_pred_cost = cost_segmap(t_unpred_seg_counts, t_pred_tree);
#if !CONFIG_NEW_MULTISYMBOL
// Add in the cost of the signaling for each prediction context.
int i;
for (i = 0; i < PREDICTION_PROBS; i++) {
const int count0 = temporal_predictor_count[i][0];
const int count1 = temporal_predictor_count[i][1];
t_nopred_prob[i] = get_binary_prob(count0, count1);
av1_prob_diff_update_savings_search(
temporal_predictor_count[i], segp->pred_probs[i], &t_nopred_prob[i],
DIFF_UPDATE_PROB, probwt);
// Add in the predictor signaling cost
t_pred_cost += count0 * av1_cost_zero(t_nopred_prob[i]) +
count1 * av1_cost_one(t_nopred_prob[i]);
// Frames without past dependency cannot use temporal prediction
if (cm->primary_ref_frame != PRIMARY_REF_NONE) {
int pred_flag_cost[SEG_TEMPORAL_PRED_CTXS][2];
for (int i = 0; i < SEG_TEMPORAL_PRED_CTXS; ++i)
av1_cost_tokens_from_cdf(pred_flag_cost[i], segp->pred_cdf[i], NULL);
t_pred_cost = 0;
// Cost for signaling the prediction flag.
for (int i = 0; i < SEG_TEMPORAL_PRED_CTXS; ++i) {
for (int j = 0; j < 2; ++j)
t_pred_cost += temporal_predictor_count[i][j] * pred_flag_cost[i][j];
}
#endif
// Cost for signaling the unpredicted segment id.
for (int i = 0; i < MAX_SEGMENTS; ++i)
t_pred_cost += t_unpred_seg_counts[i] * seg_id_cost[i];
}
// Now choose which coding method to use.

View file

@ -27,19 +27,6 @@ void av1_disable_segfeature(struct segmentation *seg, int segment_id,
void av1_clear_segdata(struct segmentation *seg, int segment_id,
SEG_LVL_FEATURES feature_id);
// The values given for each segment can be either deltas (from the default
// value chosen for the frame) or absolute values.
//
// Valid range for abs values is (0-127 for MB_LVL_ALT_Q), (0-63 for
// SEGMENT_ALT_LF)
// Valid range for delta values are (+/-127 for MB_LVL_ALT_Q), (+/-63 for
// SEGMENT_ALT_LF)
//
// abs_delta = SEGMENT_DELTADATA (deltas) abs_delta = SEGMENT_ABSDATA (use
// the absolute values given).
void av1_set_segment_data(struct segmentation *seg, int8_t *feature_data,
unsigned char abs_delta);
void av1_choose_segmap_coding_method(AV1_COMMON *cm, MACROBLOCKD *xd);
void av1_reset_segment_features(AV1_COMMON *cm);

View file

@ -17,6 +17,12 @@
#include "aom_dsp/aom_dsp_common.h"
// Setting this to 1 will disable trellis optimization completely.
// Setting this to 2 will disable trellis optimization within the
// transform search. Trellis optimization will still be applied
// in the final encode.
#define DISABLE_TRELLISQ_SEARCH 0
#define MAX_MESH_SPEED 5 // Max speed setting for mesh motion method
static MESH_PATTERN
good_quality_mesh_patterns[MAX_MESH_SPEED + 1][MAX_MESH_STEP] = {
@ -28,23 +34,21 @@ static MESH_PATTERN
{ { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
};
static unsigned char good_quality_max_mesh_pct[MAX_MESH_SPEED + 1] = {
50, 25, 15, 5, 1, 1
50, 50, 25, 15, 5, 1
};
#if CONFIG_INTRABC
// TODO(aconverse@google.com): These settings are pretty relaxed, tune them for
// TODO(huisu@google.com): These settings are pretty relaxed, tune them for
// each speed setting
static MESH_PATTERN intrabc_mesh_patterns[MAX_MESH_SPEED + 1][MAX_MESH_STEP] = {
{ { 256, 1 }, { 256, 1 }, { 0, 0 }, { 0, 0 } },
{ { 256, 1 }, { 256, 1 }, { 0, 0 }, { 0, 0 } },
{ { 64, 1 }, { 64, 1 }, { 0, 0 }, { 0, 0 } },
{ { 64, 1 }, { 64, 1 }, { 0, 0 }, { 0, 0 } },
{ { 64, 4 }, { 16, 1 }, { 0, 0 }, { 0, 0 } },
{ { 64, 4 }, { 16, 1 }, { 0, 0 }, { 0, 0 } },
{ { 64, 4 }, { 16, 1 }, { 0, 0 }, { 0, 0 } },
};
static uint8_t intrabc_max_mesh_pct[MAX_MESH_SPEED + 1] = { 100, 100, 100,
25, 25, 10 };
#endif
// Intra only frames, golden frames (except alt ref overlays) and
// alt ref frames tend to be coded at a higher than ambient quality
@ -74,22 +78,18 @@ static BLOCK_SIZE set_partition_min_limit(AV1_COMMON *const cm) {
}
}
// Do we have an internal image edge (e.g. formatting bars).
static int has_internal_image_edge(const AV1_COMP *cpi) {
return (cpi->oxcf.pass == 2) &&
((cpi->twopass.this_frame_stats.inactive_zone_rows > 0) ||
(cpi->twopass.this_frame_stats.inactive_zone_cols > 0));
}
static void set_good_speed_feature_framesize_dependent(AV1_COMP *cpi,
SPEED_FEATURES *sf,
int speed) {
AV1_COMMON *const cm = &cpi->common;
if (speed >= 1) {
if (AOMMIN(cm->width, cm->height) >= 720) {
sf->disable_split_mask =
cm->show_frame ? DISABLE_ALL_SPLIT : DISABLE_ALL_INTER_SPLIT;
sf->partition_search_breakout_dist_thr = (1 << 23);
} else {
sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
sf->partition_search_breakout_dist_thr = (1 << 21);
}
}
if (speed >= 2) {
if (AOMMIN(cm->width, cm->height) >= 720) {
sf->disable_split_mask =
@ -121,11 +121,11 @@ static void set_good_speed_feature_framesize_dependent(AV1_COMP *cpi,
}
// If this is a two pass clip that fits the criteria for animated or
// graphics content then reset disable_split_mask for speeds 1-4.
// graphics content then reset disable_split_mask for speeds 2+.
// Also if the image edge is internal to the coded area.
if ((speed >= 1) && (cpi->oxcf.pass == 2) &&
if ((speed >= 2) && (cpi->oxcf.pass == 2) &&
((cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION) ||
(av1_internal_image_edge(cpi)))) {
(has_internal_image_edge(cpi)))) {
sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
}
@ -145,85 +145,83 @@ static void set_good_speed_features_framesize_independent(AV1_COMP *cpi,
AV1_COMMON *const cm = &cpi->common;
const int boosted = frame_is_boosted(cpi);
// Speed 0 for all speed features that give neutral coding performance change.
sf->reduce_inter_modes = 1;
sf->prune_ext_partition_types_search_level = 1;
sf->ml_prune_ab_partition = 1;
sf->adaptive_txb_search_level = 1;
sf->jnt_comp_skip_mv_search = 1;
sf->model_based_prune_tx_search_level = 1;
sf->model_based_post_interp_filter_breakout = 1;
sf->inter_mode_rd_model_estimation = 1;
if (speed >= 1) {
sf->tx_type_search.fast_intra_tx_type_search = 1;
sf->tx_type_search.fast_inter_tx_type_search = 1;
sf->gm_erroradv_type = GM_ERRORADV_TR_1;
sf->selective_ref_frame = 1;
sf->inter_tx_size_search_init_depth_rect = 1;
sf->inter_tx_size_search_init_depth_sqr = 1;
sf->intra_tx_size_search_init_depth_rect = 1;
sf->intra_tx_size_search_init_depth_sqr = 1;
sf->tx_size_search_lgr_block = 1;
sf->two_pass_partition_search = 1;
sf->mode_pruning_based_on_two_pass_partition_search = 1;
sf->prune_ext_partition_types_search_level = 2;
sf->use_fast_interpolation_filter_search = 1;
sf->skip_repeat_interpolation_filter_search = 1;
sf->tx_type_search.skip_tx_search = 1;
sf->tx_type_search.ml_tx_split_thresh = 40;
sf->model_based_prune_tx_search_level = 0;
sf->model_based_post_interp_filter_breakout = 0;
// TODO(angiebird): Re-evaluate the impact of inter_mode_rd_model_estimation
// on speed 1
sf->inter_mode_rd_model_estimation = 0;
sf->adaptive_txb_search_level = 2;
sf->use_intra_txb_hash = 1;
sf->optimize_b_precheck = 1;
sf->dual_sgr_penalty_level = 1;
}
if (speed >= 2) {
if ((cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION) ||
av1_internal_image_edge(cpi)) {
sf->use_square_partition_only = !frame_is_boosted(cpi);
} else {
sf->use_square_partition_only = !frame_is_intra_only(cm);
}
sf->gm_erroradv_type = GM_ERRORADV_TR_2;
sf->less_rectangular_check = 1;
sf->selective_ref_frame = 2;
sf->fast_cdef_search = 1;
sf->use_rd_breakout = 1;
sf->adaptive_motion_search = 1;
sf->mv.auto_mv_step_size = 1;
sf->adaptive_rd_thresh = 1;
sf->mv.auto_mv_step_size = 1;
sf->mv.subpel_iters_per_step = 1;
sf->mode_skip_start = 10;
sf->adaptive_pred_interp_filter = 1;
sf->disable_filter_search_var_thresh = 100;
sf->comp_inter_joint_search_thresh = BLOCK_SIZES_ALL;
sf->recode_loop = ALLOW_RECODE_KFARFGF;
#if CONFIG_TX64X64
sf->intra_y_mode_mask[TX_64X64] = INTRA_DC_H_V;
#if CONFIG_CFL
sf->intra_uv_mode_mask[TX_64X64] = UV_INTRA_DC_H_V_CFL;
#else
sf->intra_uv_mode_mask[TX_64X64] = INTRA_DC_H_V;
#endif // CONFIG_CFL
#endif // CONFIG_TX64X64
sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
#if CONFIG_CFL
sf->intra_uv_mode_mask[TX_32X32] = UV_INTRA_DC_H_V_CFL;
#else
sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
#endif
sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
#if CONFIG_CFL
sf->intra_uv_mode_mask[TX_16X16] = UV_INTRA_DC_H_V_CFL;
#else
sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
#endif
sf->tx_size_search_breakout = 1;
sf->partition_search_breakout_rate_thr = 80;
sf->tx_type_search.prune_mode = PRUNE_ONE;
// Use transform domain distortion.
// Note var-tx expt always uses pixel domain distortion.
sf->use_transform_domain_distortion = 1;
sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
sf->allow_partition_search_skip = 1;
sf->disable_wedge_search_var_thresh = 100;
sf->fast_wedge_sign_estimate = 1;
}
if (speed >= 3) {
sf->tx_size_search_method =
frame_is_boosted(cpi) ? USE_FULL_RD : USE_LARGESTALL;
sf->mode_search_skip_flags =
(cm->frame_type == KEY_FRAME)
? 0
: FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER |
FLAG_SKIP_COMP_BESTINTRA | FLAG_SKIP_INTRA_LOWVAR;
sf->disable_filter_search_var_thresh = 100;
sf->comp_inter_joint_search_thresh = BLOCK_SIZES_ALL;
sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
sf->allow_partition_search_skip = 1;
sf->use_upsampled_references = 0;
sf->tx_size_search_method = boosted ? USE_FULL_RD : USE_LARGESTALL;
sf->less_rectangular_check = 1;
sf->mode_skip_start = 10;
sf->adaptive_pred_interp_filter = 1;
// adaptive_motion_search breaks encoder multi-thread tests.
// The values in x->pred_mv[] differ for single and multi-thread cases.
// See aomedia:1778.
// sf->adaptive_motion_search = 1;
sf->recode_loop = ALLOW_RECODE_KFARFGF;
sf->use_transform_domain_distortion = 1;
sf->use_accurate_subpel_search = 0;
sf->adaptive_rd_thresh = 2;
#if CONFIG_EXT_TX
sf->tx_type_search.prune_mode = PRUNE_TWO;
#endif
#if CONFIG_GLOBAL_MOTION
sf->tx_type_search.prune_mode = PRUNE_2D_FAST;
sf->gm_search_type = GM_DISABLE_SEARCH;
#endif // CONFIG_GLOBAL_MOTION
}
if (speed >= 4) {
sf->use_square_partition_only = !frame_is_intra_only(cm);
sf->tx_type_search.fast_intra_tx_type_search = 1;
sf->tx_type_search.fast_inter_tx_type_search = 1;
sf->use_square_partition_only = !boosted;
sf->tx_size_search_method =
frame_is_intra_only(cm) ? USE_FULL_RD : USE_LARGESTALL;
sf->mv.subpel_search_method = SUBPEL_TREE_PRUNED;
@ -232,52 +230,44 @@ static void set_good_speed_features_framesize_independent(AV1_COMP *cpi,
sf->cb_partition_search = !boosted;
sf->cb_pred_filter_search = 1;
sf->alt_ref_search_fp = 1;
sf->recode_loop = ALLOW_RECODE_KFMAXBW;
sf->adaptive_rd_thresh = 3;
sf->mode_skip_start = 6;
#if CONFIG_TX64X64
sf->intra_y_mode_mask[TX_64X64] = INTRA_DC;
#if CONFIG_CFL
sf->intra_uv_mode_mask[TX_64X64] = UV_INTRA_DC_CFL;
#else
sf->intra_uv_mode_mask[TX_64X64] = INTRA_DC;
#endif // CONFIG_CFL
#endif // CONFIG_TX64X64
sf->intra_y_mode_mask[TX_32X32] = INTRA_DC;
#if CONFIG_CFL
sf->intra_uv_mode_mask[TX_32X32] = UV_INTRA_DC_CFL;
#else
sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC;
#endif // CONFIG_CFL
sf->adaptive_interp_filter_search = 1;
}
if (speed >= 5) {
sf->recode_loop = ALLOW_RECODE_KFMAXBW;
sf->intra_y_mode_mask[TX_64X64] = INTRA_DC_H_V;
sf->intra_uv_mode_mask[TX_64X64] = UV_INTRA_DC_H_V_CFL;
sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
sf->intra_uv_mode_mask[TX_32X32] = UV_INTRA_DC_H_V_CFL;
sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
sf->intra_uv_mode_mask[TX_16X16] = UV_INTRA_DC_H_V_CFL;
sf->use_square_partition_only = 1;
sf->tx_size_search_method = USE_LARGESTALL;
sf->mv.search_method = BIGDIA;
sf->mv.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
sf->adaptive_rd_thresh = 4;
if (cm->frame_type != KEY_FRAME)
sf->mode_search_skip_flags |= FLAG_EARLY_TERMINATE;
sf->mode_search_skip_flags =
(cm->frame_type == KEY_FRAME)
? 0
: FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER |
FLAG_SKIP_COMP_BESTINTRA | FLAG_SKIP_INTRA_LOWVAR |
FLAG_EARLY_TERMINATE;
sf->disable_filter_search_var_thresh = 200;
sf->use_fast_coef_updates = ONE_LOOP_REDUCED;
sf->use_fast_coef_costing = 1;
sf->partition_search_breakout_rate_thr = 300;
sf->use_transform_domain_distortion = 2;
}
if (speed >= 6) {
int i;
sf->optimize_coefficients = 0;
sf->optimize_coefficients = NO_TRELLIS_OPT;
sf->mv.search_method = HEX;
sf->disable_filter_search_var_thresh = 500;
for (i = 0; i < TX_SIZES; ++i) {
sf->intra_y_mode_mask[i] = INTRA_DC;
#if CONFIG_CFL
sf->intra_uv_mode_mask[i] = UV_INTRA_DC_CFL;
#else
sf->intra_uv_mode_mask[i] = INTRA_DC;
#endif // CONFIG_CFL
}
sf->partition_search_breakout_rate_thr = 500;
sf->mv.reduce_first_step_size = 1;
@ -288,9 +278,7 @@ static void set_good_speed_features_framesize_independent(AV1_COMP *cpi,
const int frames_since_key = is_keyframe ? 0 : cpi->rc.frames_since_key;
sf->default_max_partition_size = BLOCK_32X32;
sf->default_min_partition_size = BLOCK_8X8;
#if CONFIG_TX64X64
sf->intra_y_mode_mask[TX_64X64] = INTRA_DC;
#endif // CONFIG_TX64X64
sf->intra_y_mode_mask[TX_32X32] = INTRA_DC;
sf->frame_parameter_update = 0;
sf->mv.search_method = FAST_HEX;
@ -298,13 +286,10 @@ static void set_good_speed_features_framesize_independent(AV1_COMP *cpi,
sf->inter_mode_mask[BLOCK_32X64] = INTER_NEAREST;
sf->inter_mode_mask[BLOCK_64X32] = INTER_NEAREST;
sf->inter_mode_mask[BLOCK_64X64] = INTER_NEAREST;
#if CONFIG_EXT_PARTITION
sf->inter_mode_mask[BLOCK_64X128] = INTER_NEAREST;
sf->inter_mode_mask[BLOCK_128X64] = INTER_NEAREST;
sf->inter_mode_mask[BLOCK_128X128] = INTER_NEAREST;
#endif // CONFIG_EXT_PARTITION
sf->partition_search_type = REFERENCE_PARTITION;
sf->default_min_partition_size = BLOCK_8X8;
sf->reuse_inter_pred_sby = 1;
sf->force_frame_boost =
is_keyframe ||
@ -324,31 +309,9 @@ static void set_good_speed_features_framesize_independent(AV1_COMP *cpi,
void av1_set_speed_features_framesize_dependent(AV1_COMP *cpi) {
SPEED_FEATURES *const sf = &cpi->sf;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
AV1_COMMON *const cm = &cpi->common;
RD_OPT *const rd = &cpi->rd;
int i;
// Limit memory usage for high resolutions
#if CONFIG_EXT_REFS
// TODO(zoeliu): Temporary solution to resolve the insufficient RAM issue for
// ext-refs. Need to work with @yunqingwang to have a more
// effective solution.
if (AOMMIN(cm->width, cm->height) > 720) {
// Turn off the use of upsampled references for HD resolution
sf->use_upsampled_references = 0;
} else if ((AOMMIN(cm->width, cm->height) > 540) &&
(oxcf->profile != PROFILE_0)) {
sf->use_upsampled_references = 0;
}
#else
if (AOMMIN(cm->width, cm->height) > 1080) {
sf->use_upsampled_references = 0;
} else if ((AOMMIN(cm->width, cm->height) > 720) &&
(oxcf->profile != PROFILE_0)) {
sf->use_upsampled_references = 0;
}
#endif // CONFIG_EXT_REFS
if (oxcf->mode == GOOD) {
set_good_speed_feature_framesize_dependent(cpi, sf, oxcf->speed);
}
@ -371,6 +334,52 @@ void av1_set_speed_features_framesize_dependent(AV1_COMP *cpi) {
cpi->find_fractional_mv_step = av1_return_min_sub_pixel_mv;
}
static void set_dev_sf(AV1_COMP *cpi, SPEED_FEATURES *sf, int speed) {
AV1_COMMON *const cm = &cpi->common;
if (speed & TXFM_CODING_SF) {
sf->inter_tx_size_search_init_depth_rect = 1;
sf->inter_tx_size_search_init_depth_sqr = 1;
sf->intra_tx_size_search_init_depth_rect = 1;
sf->intra_tx_size_search_init_depth_sqr = 1;
sf->tx_size_search_method = USE_FAST_RD;
sf->tx_type_search.fast_intra_tx_type_search = 1;
sf->tx_type_search.fast_inter_tx_type_search = 1;
}
if (speed & INTER_PRED_SF) {
sf->selective_ref_frame = 2;
// sf->adaptive_motion_search = 1;
sf->mv.auto_mv_step_size = 1;
sf->adaptive_rd_thresh = 1;
sf->mv.subpel_iters_per_step = 1;
sf->adaptive_pred_interp_filter = 1;
}
if (speed & INTRA_PRED_SF) {
sf->max_intra_bsize = BLOCK_32X32;
}
if (speed & PARTITION_SF) {
if ((cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION) ||
has_internal_image_edge(cpi)) {
sf->use_square_partition_only = !frame_is_boosted(cpi);
} else {
sf->use_square_partition_only = !frame_is_intra_only(cm);
}
sf->less_rectangular_check = 1;
sf->prune_ext_partition_types_search_level = 2;
}
if (speed & LOOP_FILTER_SF) {
sf->fast_cdef_search = 1;
}
if (speed & RD_SKIP_SF) {
sf->use_rd_breakout = 1;
}
}
void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
SPEED_FEATURES *const sf = &cpi->sf;
@ -378,7 +387,6 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
int i;
(void)cm;
// best quality defaults
sf->frame_parameter_update = 1;
sf->mv.search_method = NSTEP;
@ -386,7 +394,19 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
sf->mv.subpel_search_method = SUBPEL_TREE;
sf->mv.subpel_iters_per_step = 2;
sf->mv.subpel_force_stop = 0;
sf->optimize_coefficients = !is_lossless_requested(&cpi->oxcf);
#if DISABLE_TRELLISQ_SEARCH == 2
sf->optimize_coefficients = !is_lossless_requested(&cpi->oxcf)
? FINAL_PASS_TRELLIS_OPT
: NO_TRELLIS_OPT;
#elif DISABLE_TRELLISQ_SEARCH == 1
sf->optimize_coefficients = NO_TRELLIS_OPT;
#else
if (is_lossless_requested(&cpi->oxcf))
sf->optimize_coefficients = NO_TRELLIS_OPT;
else
sf->optimize_coefficients = FULL_TRELLIS_OPT;
#endif // DISABLE_TRELLISQ_SEARCH
sf->gm_erroradv_type = GM_ERRORADV_TR_0;
sf->mv.reduce_first_step_size = 0;
sf->coeff_prob_appx_step = 1;
sf->mv.auto_mv_step_size = 0;
@ -394,6 +414,15 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
sf->comp_inter_joint_search_thresh = BLOCK_4X4;
sf->adaptive_rd_thresh = 0;
sf->tx_size_search_method = USE_FULL_RD;
sf->inter_tx_size_search_init_depth_sqr = 0;
sf->inter_tx_size_search_init_depth_rect = 0;
sf->intra_tx_size_search_init_depth_rect = 0;
sf->intra_tx_size_search_init_depth_sqr = 0;
sf->tx_size_search_lgr_block = 0;
sf->model_based_prune_tx_search_level = 0;
sf->model_based_post_interp_filter_breakout = 0;
sf->reduce_inter_modes = 0;
sf->selective_ref_gm = 1;
sf->adaptive_motion_search = 0;
sf->adaptive_pred_interp_filter = 0;
sf->adaptive_mode_search = 0;
@ -401,10 +430,13 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
sf->cb_partition_search = 0;
sf->alt_ref_search_fp = 0;
sf->partition_search_type = SEARCH_PARTITION;
sf->tx_type_search.prune_mode = NO_PRUNE;
sf->tx_type_search.prune_mode = PRUNE_2D_ACCURATE;
sf->tx_type_search.ml_tx_split_thresh = 30;
sf->tx_type_search.use_skip_flag_prediction = 1;
sf->tx_type_search.fast_intra_tx_type_search = 0;
sf->tx_type_search.fast_inter_tx_type_search = 0;
sf->tx_type_search.skip_tx_search = 0;
sf->selective_ref_frame = 0;
sf->less_rectangular_check = 0;
sf->use_square_partition_only = 0;
sf->auto_min_max_partition_size = NOT_IN_USE;
@ -420,17 +452,25 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
sf->disable_filter_search_var_thresh = 0;
sf->adaptive_interp_filter_search = 0;
sf->allow_partition_search_skip = 0;
sf->use_upsampled_references = 1;
sf->use_accurate_subpel_search = 1;
sf->disable_wedge_search_var_thresh = 0;
sf->fast_wedge_sign_estimate = 0;
sf->drop_ref = 0;
sf->skip_intra_in_interframe = 1;
sf->txb_split_cap = 1;
sf->adaptive_txb_search_level = 0;
sf->two_pass_partition_search = 0;
sf->mode_pruning_based_on_two_pass_partition_search = 0;
sf->use_intra_txb_hash = 0;
sf->use_inter_txb_hash = 1;
sf->use_mb_rd_hash = 1;
sf->optimize_b_precheck = 0;
sf->jnt_comp_fast_tx_search = 0;
sf->jnt_comp_skip_mv_search = 0;
for (i = 0; i < TX_SIZES; i++) {
sf->intra_y_mode_mask[i] = INTRA_ALL;
#if CONFIG_CFL
sf->intra_uv_mode_mask[i] = UV_INTRA_ALL;
#else
sf->intra_uv_mode_mask[i] = INTRA_ALL;
#endif // CONFIG_CFL
}
sf->use_rd_breakout = 0;
sf->lpf_pick = LPF_PICK_FROM_FULL_IMAGE;
@ -448,22 +488,28 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
// Recode loop tolerance %.
sf->recode_tolerance = 25;
sf->default_interp_filter = SWITCHABLE;
sf->tx_size_search_breakout = 0;
sf->partition_search_breakout_dist_thr = 0;
sf->partition_search_breakout_rate_thr = 0;
sf->simple_model_rd_from_var = 0;
sf->prune_ext_partition_types_search_level = 0;
sf->ml_prune_ab_partition = 0;
sf->fast_cdef_search = 0;
// Set this at the appropriate speed levels
sf->use_transform_domain_distortion = 0;
#if CONFIG_GLOBAL_MOTION
sf->gm_search_type = GM_FULL_SEARCH;
#endif // CONFIG_GLOBAL_MOTION
sf->use_fast_interpolation_filter_search = 0;
sf->skip_repeat_interpolation_filter_search = 0;
sf->use_hash_based_trellis = 0;
if (oxcf->mode == GOOD
#if CONFIG_XIPHRC
|| oxcf->pass == 1
#endif
)
// Set decoder side speed feature to use less dual sgr modes
sf->dual_sgr_penalty_level = 0;
sf->inter_mode_rd_model_estimation = 0;
set_dev_sf(cpi, sf, oxcf->dev_sf);
if (oxcf->mode == GOOD)
set_good_speed_features_framesize_independent(cpi, sf, oxcf->speed);
// sf->partition_search_breakout_dist_thr is set assuming max 64x64
@ -472,7 +518,6 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
sf->partition_search_breakout_dist_thr <<= 2 * (MAX_SB_SIZE_LOG2 - 6);
}
cpi->full_search_sad = av1_full_search_sad;
cpi->diamond_search_sad = av1_diamond_search_sad;
sf->allow_exhaustive_searches = 1;
@ -490,7 +535,6 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
sf->mesh_patterns[i].interval =
good_quality_mesh_patterns[speed][i].interval;
}
#if CONFIG_INTRABC
if ((frame_is_intra_only(cm) && cm->allow_screen_content_tools) &&
(cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION ||
cpi->oxcf.content == AOM_CONTENT_SCREEN)) {
@ -500,18 +544,15 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
}
sf->max_exaustive_pct = intrabc_max_mesh_pct[speed];
}
#endif // CONFIG_INTRABC
#if !CONFIG_XIPHRC
// Slow quant, dct and trellis not worthwhile for first pass
// so make sure they are always turned off.
if (oxcf->pass == 1) sf->optimize_coefficients = 0;
#endif
if (oxcf->pass == 1) sf->optimize_coefficients = NO_TRELLIS_OPT;
// No recode for 1 pass.
if (oxcf->pass == 0) {
sf->recode_loop = DISALLOW_RECODE;
sf->optimize_coefficients = 0;
sf->optimize_coefficients = NO_TRELLIS_OPT;
}
if (sf->mv.subpel_search_method == SUBPEL_TREE) {
@ -524,12 +565,11 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
cpi->find_fractional_mv_step = av1_find_best_sub_pixel_tree_pruned_evenmore;
}
#if !CONFIG_AOM_QM
x->optimize = sf->optimize_coefficients == 1 && oxcf->pass != 1;
#else
cpi->optimize_speed_feature =
oxcf->pass != 1 ? sf->optimize_coefficients : NO_TRELLIS_OPT;
// FIXME: trellis not very efficient for quantisation matrices
x->optimize = 0;
#endif
if (cm->using_qmatrix) cpi->optimize_speed_feature = NO_TRELLIS_OPT;
if (oxcf->disable_trellis_quant) cpi->optimize_speed_feature = NO_TRELLIS_OPT;
x->min_partition_size = sf->default_min_partition_size;
x->max_partition_size = sf->default_max_partition_size;
@ -543,4 +583,8 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) {
cpi->find_fractional_mv_step = av1_return_max_sub_pixel_mv;
else if (cpi->oxcf.motion_vector_unit_test == 2)
cpi->find_fractional_mv_step = av1_return_min_sub_pixel_mv;
#if CONFIG_DIST_8X8
if (sf->use_transform_domain_distortion > 0) cpi->oxcf.using_dist_8x8 = 0;
#endif // CONFIG_DIST_8X8
}

View file

@ -20,64 +20,51 @@ extern "C" {
enum {
INTRA_ALL = (1 << DC_PRED) | (1 << V_PRED) | (1 << H_PRED) | (1 << D45_PRED) |
(1 << D135_PRED) | (1 << D117_PRED) | (1 << D153_PRED) |
(1 << D207_PRED) | (1 << D63_PRED) | (1 << SMOOTH_PRED) |
#if CONFIG_SMOOTH_HV
(1 << SMOOTH_V_PRED) | (1 << SMOOTH_H_PRED) |
#endif // CONFIG_SMOOTH_HV
(1 << TM_PRED),
#if CONFIG_CFL
UV_INTRA_ALL = (1 << UV_DC_PRED) | (1 << UV_V_PRED) | (1 << UV_H_PRED) |
(1 << UV_D45_PRED) | (1 << UV_D135_PRED) |
(1 << UV_D117_PRED) | (1 << UV_D153_PRED) |
(1 << UV_D207_PRED) | (1 << UV_D63_PRED) |
(1 << UV_SMOOTH_PRED) |
#if CONFIG_SMOOTH_HV
(1 << UV_SMOOTH_V_PRED) | (1 << UV_SMOOTH_H_PRED) |
#endif // CONFIG_SMOOTH_HV
(1 << UV_TM_PRED) | (1 << UV_CFL_PRED),
(1 << D135_PRED) | (1 << D113_PRED) | (1 << D157_PRED) |
(1 << D203_PRED) | (1 << D67_PRED) | (1 << SMOOTH_PRED) |
(1 << SMOOTH_V_PRED) | (1 << SMOOTH_H_PRED) | (1 << PAETH_PRED),
UV_INTRA_ALL =
(1 << UV_DC_PRED) | (1 << UV_V_PRED) | (1 << UV_H_PRED) |
(1 << UV_D45_PRED) | (1 << UV_D135_PRED) | (1 << UV_D113_PRED) |
(1 << UV_D157_PRED) | (1 << UV_D203_PRED) | (1 << UV_D67_PRED) |
(1 << UV_SMOOTH_PRED) | (1 << UV_SMOOTH_V_PRED) |
(1 << UV_SMOOTH_H_PRED) | (1 << UV_PAETH_PRED) | (1 << UV_CFL_PRED),
UV_INTRA_DC = (1 << UV_DC_PRED),
UV_INTRA_DC_CFL = (1 << UV_DC_PRED) | (1 << UV_CFL_PRED),
UV_INTRA_DC_TM = (1 << UV_DC_PRED) | (1 << UV_TM_PRED),
UV_INTRA_DC_TM_CFL =
(1 << UV_DC_PRED) | (1 << UV_TM_PRED) | (1 << UV_CFL_PRED),
UV_INTRA_DC_TM = (1 << UV_DC_PRED) | (1 << UV_PAETH_PRED),
UV_INTRA_DC_PAETH_CFL =
(1 << UV_DC_PRED) | (1 << UV_PAETH_PRED) | (1 << UV_CFL_PRED),
UV_INTRA_DC_H_V = (1 << UV_DC_PRED) | (1 << UV_V_PRED) | (1 << UV_H_PRED),
UV_INTRA_DC_H_V_CFL = (1 << UV_DC_PRED) | (1 << UV_V_PRED) |
(1 << UV_H_PRED) | (1 << UV_CFL_PRED),
UV_INTRA_DC_TM_H_V = (1 << UV_DC_PRED) | (1 << UV_TM_PRED) |
(1 << UV_V_PRED) | (1 << UV_H_PRED),
UV_INTRA_DC_TM_H_V_CFL = (1 << UV_DC_PRED) | (1 << UV_TM_PRED) |
(1 << UV_V_PRED) | (1 << UV_H_PRED) |
(1 << UV_CFL_PRED),
#endif // CONFIG_CFL
UV_INTRA_DC_PAETH_H_V = (1 << UV_DC_PRED) | (1 << UV_PAETH_PRED) |
(1 << UV_V_PRED) | (1 << UV_H_PRED),
UV_INTRA_DC_PAETH_H_V_CFL = (1 << UV_DC_PRED) | (1 << UV_PAETH_PRED) |
(1 << UV_V_PRED) | (1 << UV_H_PRED) |
(1 << UV_CFL_PRED),
INTRA_DC = (1 << DC_PRED),
INTRA_DC_TM = (1 << DC_PRED) | (1 << TM_PRED),
INTRA_DC_TM = (1 << DC_PRED) | (1 << PAETH_PRED),
INTRA_DC_H_V = (1 << DC_PRED) | (1 << V_PRED) | (1 << H_PRED),
INTRA_DC_TM_H_V =
(1 << DC_PRED) | (1 << TM_PRED) | (1 << V_PRED) | (1 << H_PRED)
INTRA_DC_PAETH_H_V =
(1 << DC_PRED) | (1 << PAETH_PRED) | (1 << V_PRED) | (1 << H_PRED)
};
enum {
#if CONFIG_COMPOUND_SINGLEREF
// TODO(zoeliu): To further consider following single ref comp modes:
// SR_NEAREST_NEARMV, SR_NEAREST_NEWMV, SR_NEAR_NEWMV,
// SR_ZERO_NEWMV, and SR_NEW_NEWMV.
#endif // CONFIG_COMPOUND_SINGLEREF
INTER_ALL = (1 << NEARESTMV) | (1 << NEARMV) | (1 << ZEROMV) | (1 << NEWMV) |
(1 << NEAREST_NEARESTMV) | (1 << NEAR_NEARMV) | (1 << NEW_NEWMV) |
(1 << NEAREST_NEWMV) | (1 << NEAR_NEWMV) | (1 << NEW_NEARMV) |
(1 << NEW_NEARESTMV) | (1 << ZERO_ZEROMV),
INTER_ALL = (1 << NEARESTMV) | (1 << NEARMV) | (1 << GLOBALMV) |
(1 << NEWMV) | (1 << NEAREST_NEARESTMV) | (1 << NEAR_NEARMV) |
(1 << NEW_NEWMV) | (1 << NEAREST_NEWMV) | (1 << NEAR_NEWMV) |
(1 << NEW_NEARMV) | (1 << NEW_NEARESTMV) | (1 << GLOBAL_GLOBALMV),
INTER_NEAREST = (1 << NEARESTMV) | (1 << NEAREST_NEARESTMV) |
(1 << NEW_NEARESTMV) | (1 << NEAREST_NEWMV),
INTER_NEAREST_NEW = (1 << NEARESTMV) | (1 << NEWMV) |
(1 << NEAREST_NEARESTMV) | (1 << NEW_NEWMV) |
(1 << NEW_NEARESTMV) | (1 << NEAREST_NEWMV) |
(1 << NEW_NEARMV) | (1 << NEAR_NEWMV),
INTER_NEAREST_ZERO = (1 << NEARESTMV) | (1 << ZEROMV) |
(1 << NEAREST_NEARESTMV) | (1 << ZERO_ZEROMV) |
INTER_NEAREST_ZERO = (1 << NEARESTMV) | (1 << GLOBALMV) |
(1 << NEAREST_NEARESTMV) | (1 << GLOBAL_GLOBALMV) |
(1 << NEAREST_NEWMV) | (1 << NEW_NEARESTMV),
INTER_NEAREST_NEW_ZERO = (1 << NEARESTMV) | (1 << ZEROMV) | (1 << NEWMV) |
(1 << NEAREST_NEARESTMV) | (1 << ZERO_ZEROMV) |
INTER_NEAREST_NEW_ZERO = (1 << NEARESTMV) | (1 << GLOBALMV) | (1 << NEWMV) |
(1 << NEAREST_NEARESTMV) | (1 << GLOBAL_GLOBALMV) |
(1 << NEW_NEWMV) | (1 << NEW_NEARESTMV) |
(1 << NEAREST_NEWMV) | (1 << NEW_NEARMV) |
(1 << NEAR_NEWMV),
@ -86,8 +73,8 @@ enum {
(1 << NEW_NEARESTMV) | (1 << NEAREST_NEWMV) |
(1 << NEW_NEARMV) | (1 << NEAR_NEWMV) |
(1 << NEAR_NEARMV),
INTER_NEAREST_NEAR_ZERO = (1 << NEARESTMV) | (1 << NEARMV) | (1 << ZEROMV) |
(1 << NEAREST_NEARESTMV) | (1 << ZERO_ZEROMV) |
INTER_NEAREST_NEAR_ZERO = (1 << NEARESTMV) | (1 << NEARMV) | (1 << GLOBALMV) |
(1 << NEAREST_NEARESTMV) | (1 << GLOBAL_GLOBALMV) |
(1 << NEAREST_NEWMV) | (1 << NEW_NEARESTMV) |
(1 << NEW_NEARMV) | (1 << NEAR_NEWMV) |
(1 << NEAR_NEARMV),
@ -105,6 +92,17 @@ enum {
(1 << THR_ALTR) | (1 << THR_GOLD)
};
typedef enum {
TXFM_CODING_SF = 1,
INTER_PRED_SF = 2,
INTRA_PRED_SF = 4,
PARTITION_SF = 8,
LOOP_FILTER_SF = 16,
RD_SKIP_SF = 32,
RESERVE_2_SF = 64,
RESERVE_3_SF = 128,
} DEV_SPEED_FEATURES;
typedef enum {
DIAMOND = 0,
NSTEP = 1,
@ -141,8 +139,8 @@ typedef enum {
typedef enum {
USE_FULL_RD = 0,
USE_FAST_RD,
USE_LARGESTALL,
USE_TX_8X8
} TX_SIZE_SEARCH_METHOD;
typedef enum {
@ -190,10 +188,13 @@ typedef enum {
NO_PRUNE = 0,
// eliminates one tx type in vertical and horizontal direction
PRUNE_ONE = 1,
#if CONFIG_EXT_TX
// eliminates two tx types in each direction
PRUNE_TWO = 2,
#endif
// adaptively prunes the least perspective tx types out of all 16
// (tuned to provide negligible quality loss)
PRUNE_2D_ACCURATE = 3,
// similar, but applies much more aggressive pruning to get better speed-up
PRUNE_2D_FAST = 4,
} TX_TYPE_PRUNE_MODE;
typedef struct {
@ -204,6 +205,13 @@ typedef struct {
// Use a skip flag prediction model to detect blocks with skip = 1 early
// and avoid doing full TX type search for such blocks.
int use_skip_flag_prediction;
// Threshold used by the ML based method to predict TX block split decisions.
int ml_tx_split_thresh;
// skip remaining transform type search when we found the rdcost of skip is
// better than applying transform
int skip_tx_search;
} TX_TYPE_SEARCH;
typedef enum {
@ -261,13 +269,29 @@ typedef struct MESH_PATTERN {
int interval;
} MESH_PATTERN;
#if CONFIG_GLOBAL_MOTION
typedef enum {
GM_FULL_SEARCH,
GM_REDUCED_REF_SEARCH,
GM_DISABLE_SEARCH
} GM_SEARCH_TYPE;
#endif // CONFIG_GLOBAL_MOTION
typedef enum {
GM_ERRORADV_TR_0,
GM_ERRORADV_TR_1,
GM_ERRORADV_TR_2,
GM_ERRORADV_TR_TYPES,
} GM_ERRORADV_TYPE;
typedef enum {
NO_TRELLIS_OPT, // No trellis optimization
FULL_TRELLIS_OPT, // Trellis optimization in all stages
FINAL_PASS_TRELLIS_OPT // Trellis optimization in only the final encode pass
} TRELLIS_OPT_TYPE;
typedef enum {
FULL_TXFM_RD,
LOW_TXFM_RD,
} TXFM_RD_MODEL;
typedef struct SPEED_FEATURES {
MV_SPEED_FEATURES mv;
@ -277,8 +301,11 @@ typedef struct SPEED_FEATURES {
RECODE_LOOP_TYPE recode_loop;
// Trellis (dynamic programming) optimization of quantized values (+1, 0).
int optimize_coefficients;
// Trellis (dynamic programming) optimization of quantized values
TRELLIS_OPT_TYPE optimize_coefficients;
// Global motion warp error threshold
GM_ERRORADV_TYPE gm_erroradv_type;
// Always set to 0. If on it enables 0 cost background transmission
// (except for the initial transmission of the segmentation). The feature is
@ -287,6 +314,14 @@ typedef struct SPEED_FEATURES {
// adds overhead.
int static_segmentation;
// Limit the inter mode tested in the RD loop
int reduce_inter_modes;
// Do not compute the global motion parameters for a LAST2_FRAME or
// LAST3_FRAME if the GOLDEN_FRAME is closer and it has a non identity
// global model.
int selective_ref_gm;
// If 1 we iterate finding a best reference for 2 ref frames together - via
// a log search that iterates 4 times (check around mv for last for best
// error of combined predictor then check around mv for alt). If 0 we
@ -309,6 +344,17 @@ typedef struct SPEED_FEATURES {
// for intra and model coefs for the rest.
TX_SIZE_SEARCH_METHOD tx_size_search_method;
// Init search depth for square and rectangular transform partitions.
// Values:
// 0 - search full tree, 1: search 1 level, 2: search the highest level only
int inter_tx_size_search_init_depth_sqr;
int inter_tx_size_search_init_depth_rect;
int intra_tx_size_search_init_depth_sqr;
int intra_tx_size_search_init_depth_rect;
// If any dimension of a coding block size above 64, always search the
// largest transform only, since the largest transform block size is 64x64.
int tx_size_search_lgr_block;
// After looking at the first set of modes (set by index here), skip
// checking modes for reference frames that don't match the reference frame
// of the best so far.
@ -318,9 +364,51 @@ typedef struct SPEED_FEATURES {
TX_TYPE_SEARCH tx_type_search;
// Skip split transform block partition when the collocated bigger block
// is selected as all zero coefficients.
int txb_split_cap;
// Shortcut the transform block partition and type search when the target
// rdcost is relatively lower.
// Values are 0 (not used) , or 1 - 2 with progressively increasing
// aggressiveness
int adaptive_txb_search_level;
// Prune level for tx_size_type search for inter based on rd model
// 0: no pruning
// 1-2: progressively increasing aggressiveness of pruning
int model_based_prune_tx_search_level;
// Model based breakout after interpolation filter search
// 0: no breakout
// 1: use model based rd breakout
int model_based_post_interp_filter_breakout;
// Used if partition_search_type = FIXED_SIZE_PARTITION
BLOCK_SIZE always_this_block_size;
// Drop less likely to be picked reference frames in the RD search.
// Has three levels for now: 0, 1 and 2, where higher levels prune more
// aggressively than lower ones. (0 means no pruning).
int selective_ref_frame;
// Prune extended partition types search
// Can take values 0 - 2, 0 referring to no pruning, and 1 - 2 increasing
// aggressiveness of pruning in order.
int prune_ext_partition_types_search_level;
// Use a ML model to prune horz_a, horz_b, vert_a and vert_b partitions.
int ml_prune_ab_partition;
int fast_cdef_search;
// 2-pass coding block partition search
int two_pass_partition_search;
// Use the mode decisions made in the initial partition search to prune mode
// candidates, e.g. ref frames.
int mode_pruning_based_on_two_pass_partition_search;
// Skip rectangular partition test when partition type none gives better
// rd than partition type split.
int less_rectangular_check;
@ -427,7 +515,7 @@ typedef struct SPEED_FEATURES {
// by only looking at counts from 1/2 the bands.
FAST_COEFF_UPDATE use_fast_coef_updates;
// A binary mask indicating if NEARESTMV, NEARMV, ZEROMV, NEWMV
// A binary mask indicating if NEARESTMV, NEARMV, GLOBALMV, NEWMV
// modes are used in order from LSB to MSB for each BLOCK_SIZE.
int inter_mode_mask[BLOCK_SIZES_ALL];
@ -456,10 +544,6 @@ typedef struct SPEED_FEATURES {
// default interp filter choice
InterpFilter default_interp_filter;
// Early termination in transform size search, which only applies while
// tx_size_search_method is USE_FULL_RD.
int tx_size_search_breakout;
// adaptive interp_filter search to allow skip of certain filter types.
int adaptive_interp_filter_search;
@ -476,16 +560,67 @@ typedef struct SPEED_FEATURES {
// Fast approximation of av1_model_rd_from_var_lapndz
int simple_model_rd_from_var;
// Do sub-pixel search in up-sampled reference frames
int use_upsampled_references;
// If true, sub-pixel search uses the exact convolve function used for final
// encoding and decoding; otherwise, it uses bilinear interpolation.
int use_accurate_subpel_search;
// Whether to compute distortion in the image domain (slower but
// more accurate), or in the transform domain (faster but less acurate).
// 0: use image domain
// 1: use transform domain in tx_type search, and use image domain for
// RD_STATS
// 2: use transform domain
int use_transform_domain_distortion;
#if CONFIG_GLOBAL_MOTION
GM_SEARCH_TYPE gm_search_type;
#endif // CONFIG_GLOBAL_MOTION
// Do limited interpolation filter search for dual filters, since best choice
// usually includes EIGHTTAP_REGULAR.
int use_fast_interpolation_filter_search;
// Save results of interpolation_filter_search for a block
// Check mv and ref_frames before search, if they are same with previous
// saved results, it can be skipped.
int skip_repeat_interpolation_filter_search;
// Use a hash table to store previously computed optimized qcoeffs from
// expensive calls to optimize_txb.
int use_hash_based_trellis;
// flag to drop some ref frames in compound motion search
int drop_ref;
// flag to allow skipping intra mode for inter frame prediction
int skip_intra_in_interframe;
// Use hash table to store intra(keyframe only) txb transform search results
// to avoid repeated search on the same residue signal.
int use_intra_txb_hash;
// Use hash table to store inter txb transform search results
// to avoid repeated search on the same residue signal.
int use_inter_txb_hash;
// Use hash table to store macroblock RD search results
// to avoid repeated search on the same residue signal.
int use_mb_rd_hash;
// Calculate RD cost before doing optimize_b, and skip if the cost is large.
int optimize_b_precheck;
// Use model rd instead of transform search in jnt_comp
int jnt_comp_fast_tx_search;
// Skip mv search in jnt_comp
int jnt_comp_skip_mv_search;
// Decoder side speed feature to add penalty for use of dual-sgr filters.
// Takes values 0 - 10, 0 indicating no penalty and each additional level
// adding a penalty of 1%
int dual_sgr_penalty_level;
// Dynamically estimate final rd from prediction error and mode cost
int inter_mode_rd_model_estimation;
} SPEED_FEATURES;
struct AV1_COMP;

View file

@ -1,164 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "aom_dsp/bitwriter.h"
#include "av1/common/common.h"
#include "av1/common/entropy.h"
#include "av1/encoder/cost.h"
#include "av1/encoder/subexp.h"
static const uint8_t update_bits[255] = {
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 0,
};
#define MIN_DELP_BITS 5
static int recenter_nonneg(int v, int m) {
if (v > (m << 1))
return v;
else if (v >= m)
return ((v - m) << 1);
else
return ((m - v) << 1) - 1;
}
static int remap_prob(int v, int m) {
int i;
static const uint8_t map_table[MAX_PROB - 1] = {
// generated by:
// map_table[j] = split_index(j, MAX_PROB - 1, MODULUS_PARAM);
20, 21, 22, 23, 24, 25, 0, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 1, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 2, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
3, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 4, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 5, 86, 87, 88,
89, 90, 91, 92, 93, 94, 95, 96, 97, 6, 98, 99, 100, 101, 102,
103, 104, 105, 106, 107, 108, 109, 7, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 8, 122, 123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 9, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
145, 10, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 11,
158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 12, 170, 171,
172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 13, 182, 183, 184, 185,
186, 187, 188, 189, 190, 191, 192, 193, 14, 194, 195, 196, 197, 198, 199,
200, 201, 202, 203, 204, 205, 15, 206, 207, 208, 209, 210, 211, 212, 213,
214, 215, 216, 217, 16, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
228, 229, 17, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
18, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 19,
};
v--;
m--;
if ((m << 1) <= MAX_PROB)
i = recenter_nonneg(v, m) - 1;
else
i = recenter_nonneg(MAX_PROB - 1 - v, MAX_PROB - 1 - m) - 1;
i = map_table[i];
return i;
}
static int prob_diff_update_cost(aom_prob newp, aom_prob oldp) {
int delp = remap_prob(newp, oldp);
return update_bits[delp] << AV1_PROB_COST_SHIFT;
}
static void encode_uniform(aom_writer *w, int v) {
const int l = 8;
const int m = (1 << l) - 190;
if (v < m) {
aom_write_literal(w, v, l - 1);
} else {
aom_write_literal(w, m + ((v - m) >> 1), l - 1);
aom_write_literal(w, (v - m) & 1, 1);
}
}
static INLINE int write_bit_gte(aom_writer *w, int word, int test) {
aom_write_literal(w, word >= test, 1);
return word >= test;
}
static void encode_term_subexp(aom_writer *w, int word) {
if (!write_bit_gte(w, word, 16)) {
aom_write_literal(w, word, 4);
} else if (!write_bit_gte(w, word, 32)) {
aom_write_literal(w, word - 16, 4);
} else if (!write_bit_gte(w, word, 64)) {
aom_write_literal(w, word - 32, 5);
} else {
encode_uniform(w, word - 64);
}
}
void av1_write_prob_diff_update(aom_writer *w, aom_prob newp, aom_prob oldp) {
const int delp = remap_prob(newp, oldp);
encode_term_subexp(w, delp);
}
int av1_prob_diff_update_savings_search(const unsigned int *ct, aom_prob oldp,
aom_prob *bestp, aom_prob upd,
int probwt) {
const uint32_t old_b = cost_branch256(ct, oldp);
int bestsavings = 0;
aom_prob newp, bestnewp = oldp;
const int step = *bestp > oldp ? -1 : 1;
const int upd_cost = av1_cost_one(upd) - av1_cost_zero(upd);
if (old_b > (uint32_t)upd_cost + (MIN_DELP_BITS << AV1_PROB_COST_SHIFT)) {
for (newp = *bestp; newp != oldp; newp += step) {
const int new_b = cost_branch256(ct, newp);
const int update_b = prob_diff_update_cost(newp, oldp) + upd_cost;
const int savings = (int)((int64_t)old_b - new_b - update_b * probwt);
if (savings > bestsavings) {
bestsavings = savings;
bestnewp = newp;
}
}
}
*bestp = bestnewp;
return bestsavings;
}
void av1_cond_prob_diff_update(aom_writer *w, aom_prob *oldp,
const unsigned int ct[2], int probwt) {
const aom_prob upd = DIFF_UPDATE_PROB;
aom_prob newp = get_binary_prob(ct[0], ct[1]);
const int savings =
av1_prob_diff_update_savings_search(ct, *oldp, &newp, upd, probwt);
assert(newp >= 1);
if (savings > 0) {
aom_write(w, 1, upd);
av1_write_prob_diff_update(w, newp, *oldp);
*oldp = newp;
} else {
aom_write(w, 0, upd);
}
}
int av1_cond_prob_diff_update_savings(aom_prob *oldp, const unsigned int ct[2],
int probwt) {
const aom_prob upd = DIFF_UPDATE_PROB;
aom_prob newp = get_binary_prob(ct[0], ct[1]);
const int savings =
av1_prob_diff_update_savings_search(ct, *oldp, &newp, upd, probwt);
return savings;
}

View file

@ -1,42 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_ENCODER_SUBEXP_H_
#define AV1_ENCODER_SUBEXP_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "aom_dsp/bitwriter.h"
#include "aom_dsp/prob.h"
void av1_write_prob_diff_update(aom_writer *w, aom_prob newp, aom_prob oldpm);
void av1_cond_prob_diff_update(aom_writer *w, aom_prob *oldp,
const unsigned int ct[2], int probwt);
int av1_prob_diff_update_savings_search(const unsigned int *ct, aom_prob oldp,
aom_prob *bestp, aom_prob upd,
int probwt);
int av1_prob_diff_update_savings_search_model(const unsigned int *ct,
const aom_prob oldp,
aom_prob *bestp, aom_prob upd,
int stepsize, int probwt);
int av1_cond_prob_diff_update_savings(aom_prob *oldp, const unsigned int ct[2],
int probwt);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AV1_ENCODER_SUBEXP_H_

View file

@ -12,7 +12,8 @@
#include <math.h>
#include <limits.h>
#include "./aom_config.h"
#include "config/aom_config.h"
#include "av1/common/alloccommon.h"
#include "av1/common/onyxc_int.h"
#include "av1/common/quant_common.h"
@ -35,26 +36,17 @@
static void temporal_filter_predictors_mb_c(
MACROBLOCKD *xd, uint8_t *y_mb_ptr, uint8_t *u_mb_ptr, uint8_t *v_mb_ptr,
int stride, int uv_block_width, int uv_block_height, int mv_row, int mv_col,
uint8_t *pred, struct scale_factors *scale, int x, int y) {
uint8_t *pred, struct scale_factors *scale, int x, int y,
int can_use_previous) {
const int which_mv = 0;
const MV mv = { mv_row, mv_col };
enum mv_precision mv_precision_uv;
int uv_stride;
// TODO(angiebird): change plane setting accordingly
ConvolveParams conv_params = get_conv_params(which_mv, which_mv, 0);
#if USE_TEMPORALFILTER_12TAP
const InterpFilters interp_filters =
av1_broadcast_interp_filter(TEMPORALFILTER_12TAP);
(void)xd;
#else
const InterpFilters interp_filters = xd->mi[0]->mbmi.interp_filters;
#endif // USE_TEMPORALFILTER_12TAP
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
ConvolveParams conv_params = get_conv_params(which_mv, 0, 0, xd->bd);
const InterpFilters interp_filters = xd->mi[0]->interp_filters;
WarpTypesAllowed warp_types;
memset(&warp_types, 0, sizeof(WarpTypesAllowed));
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
if (uv_block_width == 8) {
uv_stride = (stride + 1) >> 1;
@ -64,55 +56,36 @@ static void temporal_filter_predictors_mb_c(
mv_precision_uv = MV_PRECISION_Q3;
}
#if CONFIG_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
av1_highbd_build_inter_predictor(y_mb_ptr, stride, &pred[0], 16, &mv, scale,
16, 16, which_mv, interp_filters,
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
&warp_types, x, y,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
0, MV_PRECISION_Q3, x, y, xd);
&warp_types, x, y, 0, MV_PRECISION_Q3, x,
y, xd, can_use_previous);
av1_highbd_build_inter_predictor(u_mb_ptr, uv_stride, &pred[256],
uv_block_width, &mv, scale, uv_block_width,
uv_block_height, which_mv, interp_filters,
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
&warp_types, x, y,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
1, mv_precision_uv, x, y, xd);
av1_highbd_build_inter_predictor(
u_mb_ptr, uv_stride, &pred[256], uv_block_width, &mv, scale,
uv_block_width, uv_block_height, which_mv, interp_filters, &warp_types,
x, y, 1, mv_precision_uv, x, y, xd, can_use_previous);
av1_highbd_build_inter_predictor(v_mb_ptr, uv_stride, &pred[512],
uv_block_width, &mv, scale, uv_block_width,
uv_block_height, which_mv, interp_filters,
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
&warp_types, x, y,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
2, mv_precision_uv, x, y, xd);
av1_highbd_build_inter_predictor(
v_mb_ptr, uv_stride, &pred[512], uv_block_width, &mv, scale,
uv_block_width, uv_block_height, which_mv, interp_filters, &warp_types,
x, y, 2, mv_precision_uv, x, y, xd, can_use_previous);
return;
}
#endif // CONFIG_HIGHBITDEPTH
av1_build_inter_predictor(y_mb_ptr, stride, &pred[0], 16, &mv, scale, 16, 16,
&conv_params, interp_filters,
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
&warp_types, x, y, 0, 0,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
MV_PRECISION_Q3, x, y, xd);
&conv_params, interp_filters, &warp_types, x, y, 0,
0, MV_PRECISION_Q3, x, y, xd, can_use_previous);
av1_build_inter_predictor(u_mb_ptr, uv_stride, &pred[256], uv_block_width,
&mv, scale, uv_block_width, uv_block_height,
&conv_params, interp_filters,
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
&warp_types, x, y, 1, 0,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
mv_precision_uv, x, y, xd);
&conv_params, interp_filters, &warp_types, x, y, 1,
0, mv_precision_uv, x, y, xd, can_use_previous);
av1_build_inter_predictor(v_mb_ptr, uv_stride, &pred[512], uv_block_width,
&mv, scale, uv_block_width, uv_block_height,
&conv_params, interp_filters,
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
&warp_types, x, y, 2, 0,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
mv_precision_uv, x, y, xd);
&conv_params, interp_filters, &warp_types, x, y, 2,
0, mv_precision_uv, x, y, xd, can_use_previous);
}
void av1_temporal_filter_apply_c(uint8_t *frame1, unsigned int stride,
@ -176,7 +149,6 @@ void av1_temporal_filter_apply_c(uint8_t *frame1, unsigned int stride,
}
}
#if CONFIG_HIGHBITDEPTH
void av1_highbd_temporal_filter_apply_c(
uint8_t *frame1_8, unsigned int stride, uint8_t *frame2_8,
unsigned int block_width, unsigned int block_height, int strength,
@ -238,7 +210,6 @@ void av1_highbd_temporal_filter_apply_c(
byte += stride - block_width;
}
}
#endif // CONFIG_HIGHBITDEPTH
static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
uint8_t *arf_frame_buf,
@ -255,7 +226,7 @@ static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
int cost_list[5];
MvLimits tmp_mv_limits = x->mv_limits;
MV best_ref_mv1 = { 0, 0 };
MV best_ref_mv1 = kZeroMv;
MV best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
// Save input state
@ -276,8 +247,8 @@ static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
av1_set_mv_search_range(&x->mv_limits, &best_ref_mv1);
x->mvcost = x->mv_cost_stack[0];
x->nmvjointcost = x->nmv_vec_cost[0];
x->mvcost = x->mv_cost_stack;
x->nmvjointcost = x->nmv_vec_cost;
// Use mv costing from x->mvcost directly
av1_hex_search(x, &best_ref_mv1_full, step_param, sadpb, 1,
@ -286,9 +257,8 @@ static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
x->mv_limits = tmp_mv_limits;
// Ignore mv costing by sending NULL pointer instead of cost array
#if CONFIG_AMVR
if (cpi->common.cur_frame_mv_precision_level == 1) {
// Ignore mv costing by sending NULL pointer instead of cost array
if (cpi->common.cur_frame_force_integer_mv == 1) {
const uint8_t *const src_address = x->plane[0].src.buf;
const int src_stride = x->plane[0].src.stride;
const uint8_t *const y = xd->plane[0].pre[0].buf;
@ -301,17 +271,15 @@ static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
bestsme = cpi->fn_ptr[BLOCK_16X16].vf(y + offset, y_stride, src_address,
src_stride, &sse);
} else {
#endif
bestsme = cpi->find_fractional_mv_step(
x, &best_ref_mv1, cpi->common.allow_high_precision_mv, x->errorperbit,
x, &cpi->common, 0, 0, &best_ref_mv1,
cpi->common.allow_high_precision_mv, x->errorperbit,
&cpi->fn_ptr[BLOCK_16X16], 0, mv_sf->subpel_iters_per_step,
cond_cost_list(cpi, cost_list), NULL, NULL, &distortion, &sse, NULL,
NULL, 0, 0, 0, 0, 0);
#if CONFIG_AMVR
}
#endif
x->e_mbd.mi[0]->bmi[0].as_mv[0] = x->best_mv;
x->e_mbd.mi[0]->mv[0] = x->best_mv;
// Restore input state
x->plane[0].src = src;
@ -321,13 +289,12 @@ static int temporal_filter_find_matching_mb_c(AV1_COMP *cpi,
}
static void temporal_filter_iterate_c(AV1_COMP *cpi,
#if CONFIG_BGSPRITE
YV12_BUFFER_CONFIG *target,
#endif // CONFIG_BGSPRITE
YV12_BUFFER_CONFIG **frames,
int frame_count, int alt_ref_index,
int strength,
struct scale_factors *scale) {
const AV1_COMMON *cm = &cpi->common;
const int num_planes = av1_num_planes(cm);
int byte;
int frame;
int mb_col, mb_row;
@ -341,28 +308,22 @@ static void temporal_filter_iterate_c(AV1_COMP *cpi,
MACROBLOCKD *mbd = &cpi->td.mb.e_mbd;
YV12_BUFFER_CONFIG *f = frames[alt_ref_index];
uint8_t *dst1, *dst2;
#if CONFIG_HIGHBITDEPTH
DECLARE_ALIGNED(16, uint16_t, predictor16[16 * 16 * 3]);
DECLARE_ALIGNED(16, uint8_t, predictor8[16 * 16 * 3]);
DECLARE_ALIGNED(32, uint16_t, predictor16[16 * 16 * 3]);
DECLARE_ALIGNED(32, uint8_t, predictor8[16 * 16 * 3]);
uint8_t *predictor;
#else
DECLARE_ALIGNED(16, uint8_t, predictor[16 * 16 * 3]);
#endif
const int mb_uv_height = 16 >> mbd->plane[1].subsampling_y;
const int mb_uv_width = 16 >> mbd->plane[1].subsampling_x;
// Save input state
uint8_t *input_buffer[MAX_MB_PLANE];
int i;
#if CONFIG_HIGHBITDEPTH
if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
predictor = CONVERT_TO_BYTEPTR(predictor16);
} else {
predictor = predictor8;
}
#endif
for (i = 0; i < MAX_MB_PLANE; i++) input_buffer[i] = mbd->plane[i].pre[0].buf;
for (i = 0; i < num_planes; i++) input_buffer[i] = mbd->plane[i].pre[0].buf;
for (mb_row = 0; mb_row < mb_rows; mb_row++) {
// Source frames are extended to 16 pixels. This is different than
@ -399,8 +360,9 @@ static void temporal_filter_iterate_c(AV1_COMP *cpi,
if (frames[frame] == NULL) continue;
mbd->mi[0]->bmi[0].as_mv[0].as_mv.row = 0;
mbd->mi[0]->bmi[0].as_mv[0].as_mv.col = 0;
mbd->mi[0]->mv[0].as_mv.row = 0;
mbd->mi[0]->mv[0].as_mv.col = 0;
mbd->mi[0]->motion_mode = SIMPLE_TRANSLATION;
if (frame == alt_ref_index) {
filter_weight = 2;
@ -422,60 +384,51 @@ static void temporal_filter_iterate_c(AV1_COMP *cpi,
mbd, frames[frame]->y_buffer + mb_y_offset,
frames[frame]->u_buffer + mb_uv_offset,
frames[frame]->v_buffer + mb_uv_offset, frames[frame]->y_stride,
mb_uv_width, mb_uv_height, mbd->mi[0]->bmi[0].as_mv[0].as_mv.row,
mbd->mi[0]->bmi[0].as_mv[0].as_mv.col, predictor, scale,
mb_col * 16, mb_row * 16);
mb_uv_width, mb_uv_height, mbd->mi[0]->mv[0].as_mv.row,
mbd->mi[0]->mv[0].as_mv.col, predictor, scale, mb_col * 16,
mb_row * 16, cm->allow_warped_motion);
// Apply the filter (YUV)
#if CONFIG_HIGHBITDEPTH
// Apply the filter (YUV)
if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
int adj_strength = strength + 2 * (mbd->bd - 8);
av1_highbd_temporal_filter_apply(
f->y_buffer + mb_y_offset, f->y_stride, predictor, 16, 16,
adj_strength, filter_weight, accumulator, count);
av1_highbd_temporal_filter_apply(
f->u_buffer + mb_uv_offset, f->uv_stride, predictor + 256,
mb_uv_width, mb_uv_height, adj_strength, filter_weight,
accumulator + 256, count + 256);
av1_highbd_temporal_filter_apply(
f->v_buffer + mb_uv_offset, f->uv_stride, predictor + 512,
mb_uv_width, mb_uv_height, adj_strength, filter_weight,
accumulator + 512, count + 512);
if (num_planes > 1) {
av1_highbd_temporal_filter_apply(
f->u_buffer + mb_uv_offset, f->uv_stride, predictor + 256,
mb_uv_width, mb_uv_height, adj_strength, filter_weight,
accumulator + 256, count + 256);
av1_highbd_temporal_filter_apply(
f->v_buffer + mb_uv_offset, f->uv_stride, predictor + 512,
mb_uv_width, mb_uv_height, adj_strength, filter_weight,
accumulator + 512, count + 512);
}
} else {
#endif // CONFIG_HIGHBITDEPTH
av1_temporal_filter_apply_c(f->y_buffer + mb_y_offset, f->y_stride,
predictor, 16, 16, strength,
filter_weight, accumulator, count);
av1_temporal_filter_apply_c(
f->u_buffer + mb_uv_offset, f->uv_stride, predictor + 256,
mb_uv_width, mb_uv_height, strength, filter_weight,
accumulator + 256, count + 256);
av1_temporal_filter_apply_c(
f->v_buffer + mb_uv_offset, f->uv_stride, predictor + 512,
mb_uv_width, mb_uv_height, strength, filter_weight,
accumulator + 512, count + 512);
#if CONFIG_HIGHBITDEPTH
if (num_planes > 1) {
av1_temporal_filter_apply_c(
f->u_buffer + mb_uv_offset, f->uv_stride, predictor + 256,
mb_uv_width, mb_uv_height, strength, filter_weight,
accumulator + 256, count + 256);
av1_temporal_filter_apply_c(
f->v_buffer + mb_uv_offset, f->uv_stride, predictor + 512,
mb_uv_width, mb_uv_height, strength, filter_weight,
accumulator + 512, count + 512);
}
}
#endif // CONFIG_HIGHBITDEPTH
}
}
// Normalize filter output to produce AltRef frame
#if CONFIG_HIGHBITDEPTH
// Normalize filter output to produce AltRef frame
if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
uint16_t *dst1_16;
uint16_t *dst2_16;
#if CONFIG_BGSPRITE
dst1 = target->y_buffer;
#else
dst1 = cpi->alt_ref_buffer.y_buffer;
#endif // CONFIG_BGSPRITE
dst1_16 = CONVERT_TO_SHORTPTR(dst1);
#if CONFIG_BGSPRITE
stride = target->y_stride;
#else
stride = cpi->alt_ref_buffer.y_stride;
#endif // CONFIG_BGSPRITE
byte = mb_y_offset;
for (i = 0, k = 0; i < 16; i++) {
for (j = 0; j < 16; j++, k++) {
@ -488,40 +441,31 @@ static void temporal_filter_iterate_c(AV1_COMP *cpi,
byte += stride - 16;
}
dst1 = cpi->alt_ref_buffer.u_buffer;
dst2 = cpi->alt_ref_buffer.v_buffer;
dst1_16 = CONVERT_TO_SHORTPTR(dst1);
dst2_16 = CONVERT_TO_SHORTPTR(dst2);
stride = cpi->alt_ref_buffer.uv_stride;
byte = mb_uv_offset;
for (i = 0, k = 256; i < mb_uv_height; i++) {
for (j = 0; j < mb_uv_width; j++, k++) {
int m = k + 256;
// U
dst1_16[byte] =
(uint16_t)OD_DIVU(accumulator[k] + (count[k] >> 1), count[k]);
// V
dst2_16[byte] =
(uint16_t)OD_DIVU(accumulator[m] + (count[m] >> 1), count[m]);
// move to next pixel
byte++;
if (num_planes > 1) {
dst1 = cpi->alt_ref_buffer.u_buffer;
dst2 = cpi->alt_ref_buffer.v_buffer;
dst1_16 = CONVERT_TO_SHORTPTR(dst1);
dst2_16 = CONVERT_TO_SHORTPTR(dst2);
stride = cpi->alt_ref_buffer.uv_stride;
byte = mb_uv_offset;
for (i = 0, k = 256; i < mb_uv_height; i++) {
for (j = 0; j < mb_uv_width; j++, k++) {
int m = k + 256;
// U
dst1_16[byte] =
(uint16_t)OD_DIVU(accumulator[k] + (count[k] >> 1), count[k]);
// V
dst2_16[byte] =
(uint16_t)OD_DIVU(accumulator[m] + (count[m] >> 1), count[m]);
// move to next pixel
byte++;
}
byte += stride - mb_uv_width;
}
byte += stride - mb_uv_width;
}
} else {
#endif // CONFIG_HIGHBITDEPTH
#if CONFIG_BGSPRITE
dst1 = target->y_buffer;
stride = target->y_stride;
#else
dst1 = cpi->alt_ref_buffer.y_buffer;
stride = cpi->alt_ref_buffer.y_stride;
#endif // CONFIG_BGSPRITE
dst1 = cpi->alt_ref_buffer.y_buffer;
stride = cpi->alt_ref_buffer.y_stride;
byte = mb_y_offset;
for (i = 0, k = 0; i < 16; i++) {
for (j = 0; j < 16; j++, k++) {
@ -533,36 +477,27 @@ static void temporal_filter_iterate_c(AV1_COMP *cpi,
}
byte += stride - 16;
}
#if CONFIG_BGSPRITE
dst1 = target->u_buffer;
dst2 = target->v_buffer;
stride = target->uv_stride;
#else
dst1 = cpi->alt_ref_buffer.u_buffer;
dst2 = cpi->alt_ref_buffer.v_buffer;
stride = cpi->alt_ref_buffer.uv_stride;
#endif // CONFIG_BGSPRITE
byte = mb_uv_offset;
for (i = 0, k = 256; i < mb_uv_height; i++) {
for (j = 0; j < mb_uv_width; j++, k++) {
int m = k + 256;
// U
dst1[byte] =
(uint8_t)OD_DIVU(accumulator[k] + (count[k] >> 1), count[k]);
// V
dst2[byte] =
(uint8_t)OD_DIVU(accumulator[m] + (count[m] >> 1), count[m]);
// move to next pixel
byte++;
if (num_planes > 1) {
dst1 = cpi->alt_ref_buffer.u_buffer;
dst2 = cpi->alt_ref_buffer.v_buffer;
stride = cpi->alt_ref_buffer.uv_stride;
byte = mb_uv_offset;
for (i = 0, k = 256; i < mb_uv_height; i++) {
for (j = 0; j < mb_uv_width; j++, k++) {
int m = k + 256;
// U
dst1[byte] =
(uint8_t)OD_DIVU(accumulator[k] + (count[k] >> 1), count[k]);
// V
dst2[byte] =
(uint8_t)OD_DIVU(accumulator[m] + (count[m] >> 1), count[m]);
// move to next pixel
byte++;
}
byte += stride - mb_uv_width;
}
byte += stride - mb_uv_width;
}
#if CONFIG_HIGHBITDEPTH
}
#endif // CONFIG_HIGHBITDEPTH
mb_y_offset += 16;
mb_uv_offset += mb_uv_width;
}
@ -571,7 +506,7 @@ static void temporal_filter_iterate_c(AV1_COMP *cpi,
}
// Restore input state
for (i = 0; i < MAX_MB_PLANE; i++) mbd->plane[i].pre[0].buf = input_buffer[i];
for (i = 0; i < num_planes; i++) mbd->plane[i].pre[0].buf = input_buffer[i];
}
// Apply buffer limits and context specific adjustments to arnr filter.
@ -633,11 +568,7 @@ static void adjust_arnr_filter(AV1_COMP *cpi, int distance, int group_boost,
*arnr_strength = strength;
}
void av1_temporal_filter(AV1_COMP *cpi,
#if CONFIG_BGSPRITE
YV12_BUFFER_CONFIG *bg, YV12_BUFFER_CONFIG *target,
#endif // CONFIG_BGSPRITE
int distance) {
void av1_temporal_filter(AV1_COMP *cpi, int distance) {
RATE_CONTROL *const rc = &cpi->rc;
int frame;
int frames_to_blur;
@ -647,17 +578,14 @@ void av1_temporal_filter(AV1_COMP *cpi,
int frames_to_blur_forward;
struct scale_factors sf;
YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS] = { NULL };
#if CONFIG_EXT_REFS
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
#endif // CONFIG_EXT_REFS
// Apply context specific adjustments to the arnr filter parameters.
adjust_arnr_filter(cpi, distance, rc->gfu_boost, &frames_to_blur, &strength);
// TODO(weitinglin): Currently, we enforce the filtering strength on
// extra ARFs' to be zeros. We should investigate in which
// case it is more beneficial to use non-zero strength
// filtering.
#if CONFIG_EXT_REFS
// TODO(weitinglin): Currently, we enforce the filtering strength on
// extra ARFs' to be zeros. We should investigate in which
// case it is more beneficial to use non-zero strength
// filtering.
if (gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE) {
strength = 0;
frames_to_blur = 1;
@ -685,7 +613,7 @@ void av1_temporal_filter(AV1_COMP *cpi,
cpi->is_arf_filter_off[which_arf] = 1;
else
cpi->is_arf_filter_off[which_arf] = 0;
#endif // CONFIG_EXT_REFS
cpi->common.showable_frame = cpi->is_arf_filter_off[which_arf];
frames_to_blur_backward = (frames_to_blur / 2);
frames_to_blur_forward = ((frames_to_blur - 1) / 2);
@ -694,40 +622,20 @@ void av1_temporal_filter(AV1_COMP *cpi,
// Setup frame pointers, NULL indicates frame not included in filter.
for (frame = 0; frame < frames_to_blur; ++frame) {
const int which_buffer = start_frame - frame;
#if CONFIG_BGSPRITE
if (frame == frames_to_blur_backward && bg != NULL) {
// Insert bg into frames at ARF index.
frames[frames_to_blur - 1 - frame] = bg;
} else {
#endif // CONFIG_BGSPRITE
struct lookahead_entry *buf =
av1_lookahead_peek(cpi->lookahead, which_buffer);
frames[frames_to_blur - 1 - frame] = &buf->img;
#if CONFIG_BGSPRITE
}
#endif // CONFIG_BGSPRITE
struct lookahead_entry *buf =
av1_lookahead_peek(cpi->lookahead, which_buffer);
frames[frames_to_blur - 1 - frame] = &buf->img;
}
if (frames_to_blur > 0) {
// Setup scaling factors. Scaling on each of the arnr frames is not
// supported.
// ARF is produced at the native frame size and resized when coded.
#if CONFIG_HIGHBITDEPTH
av1_setup_scale_factors_for_frame(
&sf, frames[0]->y_crop_width, frames[0]->y_crop_height,
frames[0]->y_crop_width, frames[0]->y_crop_height,
cpi->common.use_highbitdepth);
#else
// Setup scaling factors. Scaling on each of the arnr frames is not
// supported.
// ARF is produced at the native frame size and resized when coded.
av1_setup_scale_factors_for_frame(
&sf, frames[0]->y_crop_width, frames[0]->y_crop_height,
frames[0]->y_crop_width, frames[0]->y_crop_height);
#endif // CONFIG_HIGHBITDEPTH
}
temporal_filter_iterate_c(cpi,
#if CONFIG_BGSPRITE
target,
#endif // CONFIG_BGSPRITE
frames, frames_to_blur, frames_to_blur_backward,
strength, &sf);
temporal_filter_iterate_c(cpi, frames, frames_to_blur,
frames_to_blur_backward, strength, &sf);
}

View file

@ -16,11 +16,7 @@
extern "C" {
#endif
void av1_temporal_filter(AV1_COMP *cpi,
#if CONFIG_BGSPRITE
YV12_BUFFER_CONFIG *bg, YV12_BUFFER_CONFIG *target,
#endif // CONFIG_BGSPRITE
int distance);
void av1_temporal_filter(AV1_COMP *cpi, int distance);
#ifdef __cplusplus
} // extern "C"

View file

@ -23,314 +23,13 @@
#include "av1/encoder/cost.h"
#include "av1/encoder/encoder.h"
#if CONFIG_LV_MAP
#include "av1/encoder/encodetxb.c"
#endif
#include "av1/encoder/encodetxb.h"
#include "av1/encoder/rdopt.h"
#include "av1/encoder/tokenize.h"
static const TOKENVALUE dct_cat_lt_10_value_tokens[] = {
{ 9, 63 }, { 9, 61 }, { 9, 59 }, { 9, 57 }, { 9, 55 }, { 9, 53 }, { 9, 51 },
{ 9, 49 }, { 9, 47 }, { 9, 45 }, { 9, 43 }, { 9, 41 }, { 9, 39 }, { 9, 37 },
{ 9, 35 }, { 9, 33 }, { 9, 31 }, { 9, 29 }, { 9, 27 }, { 9, 25 }, { 9, 23 },
{ 9, 21 }, { 9, 19 }, { 9, 17 }, { 9, 15 }, { 9, 13 }, { 9, 11 }, { 9, 9 },
{ 9, 7 }, { 9, 5 }, { 9, 3 }, { 9, 1 }, { 8, 31 }, { 8, 29 }, { 8, 27 },
{ 8, 25 }, { 8, 23 }, { 8, 21 }, { 8, 19 }, { 8, 17 }, { 8, 15 }, { 8, 13 },
{ 8, 11 }, { 8, 9 }, { 8, 7 }, { 8, 5 }, { 8, 3 }, { 8, 1 }, { 7, 15 },
{ 7, 13 }, { 7, 11 }, { 7, 9 }, { 7, 7 }, { 7, 5 }, { 7, 3 }, { 7, 1 },
{ 6, 7 }, { 6, 5 }, { 6, 3 }, { 6, 1 }, { 5, 3 }, { 5, 1 }, { 4, 1 },
{ 3, 1 }, { 2, 1 }, { 1, 1 }, { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 },
{ 4, 0 }, { 5, 0 }, { 5, 2 }, { 6, 0 }, { 6, 2 }, { 6, 4 }, { 6, 6 },
{ 7, 0 }, { 7, 2 }, { 7, 4 }, { 7, 6 }, { 7, 8 }, { 7, 10 }, { 7, 12 },
{ 7, 14 }, { 8, 0 }, { 8, 2 }, { 8, 4 }, { 8, 6 }, { 8, 8 }, { 8, 10 },
{ 8, 12 }, { 8, 14 }, { 8, 16 }, { 8, 18 }, { 8, 20 }, { 8, 22 }, { 8, 24 },
{ 8, 26 }, { 8, 28 }, { 8, 30 }, { 9, 0 }, { 9, 2 }, { 9, 4 }, { 9, 6 },
{ 9, 8 }, { 9, 10 }, { 9, 12 }, { 9, 14 }, { 9, 16 }, { 9, 18 }, { 9, 20 },
{ 9, 22 }, { 9, 24 }, { 9, 26 }, { 9, 28 }, { 9, 30 }, { 9, 32 }, { 9, 34 },
{ 9, 36 }, { 9, 38 }, { 9, 40 }, { 9, 42 }, { 9, 44 }, { 9, 46 }, { 9, 48 },
{ 9, 50 }, { 9, 52 }, { 9, 54 }, { 9, 56 }, { 9, 58 }, { 9, 60 }, { 9, 62 }
};
const TOKENVALUE *av1_dct_cat_lt_10_value_tokens =
dct_cat_lt_10_value_tokens +
(sizeof(dct_cat_lt_10_value_tokens) / sizeof(*dct_cat_lt_10_value_tokens)) /
2;
// The corresponding costs of the extrabits for the tokens in the above table
// are stored in the table below. The values are obtained from looking up the
// entry for the specified extrabits in the table corresponding to the token
// (as defined in cost element av1_extra_bits)
// e.g. {9, 63} maps to cat5_cost[63 >> 1], {1, 1} maps to sign_cost[1 >> 1]
static const int dct_cat_lt_10_value_cost[] = {
3773, 3750, 3704, 3681, 3623, 3600, 3554, 3531, 3432, 3409, 3363, 3340, 3282,
3259, 3213, 3190, 3136, 3113, 3067, 3044, 2986, 2963, 2917, 2894, 2795, 2772,
2726, 2703, 2645, 2622, 2576, 2553, 3197, 3116, 3058, 2977, 2881, 2800, 2742,
2661, 2615, 2534, 2476, 2395, 2299, 2218, 2160, 2079, 2566, 2427, 2334, 2195,
2023, 1884, 1791, 1652, 1893, 1696, 1453, 1256, 1229, 864, 512, 512, 512,
512, 0, 512, 512, 512, 512, 864, 1229, 1256, 1453, 1696, 1893, 1652,
1791, 1884, 2023, 2195, 2334, 2427, 2566, 2079, 2160, 2218, 2299, 2395, 2476,
2534, 2615, 2661, 2742, 2800, 2881, 2977, 3058, 3116, 3197, 2553, 2576, 2622,
2645, 2703, 2726, 2772, 2795, 2894, 2917, 2963, 2986, 3044, 3067, 3113, 3136,
3190, 3213, 3259, 3282, 3340, 3363, 3409, 3432, 3531, 3554, 3600, 3623, 3681,
3704, 3750, 3773,
};
const int *av1_dct_cat_lt_10_value_cost =
dct_cat_lt_10_value_cost +
(sizeof(dct_cat_lt_10_value_cost) / sizeof(*dct_cat_lt_10_value_cost)) / 2;
// Array indices are identical to previously-existing CONTEXT_NODE indices
/* clang-format off */
const aom_tree_index av1_coef_tree[TREE_SIZE(ENTROPY_TOKENS)] = {
-EOB_TOKEN, 2, // 0 = EOB
-ZERO_TOKEN, 4, // 1 = ZERO
-ONE_TOKEN, 6, // 2 = ONE
8, 12, // 3 = LOW_VAL
-TWO_TOKEN, 10, // 4 = TWO
-THREE_TOKEN, -FOUR_TOKEN, // 5 = THREE
14, 16, // 6 = HIGH_LOW
-CATEGORY1_TOKEN, -CATEGORY2_TOKEN, // 7 = CAT_ONE
18, 20, // 8 = CAT_THREEFOUR
-CATEGORY3_TOKEN, -CATEGORY4_TOKEN, // 9 = CAT_THREE
-CATEGORY5_TOKEN, -CATEGORY6_TOKEN // 10 = CAT_FIVE
};
/* clang-format on */
static const int16_t zero_cost[] = { 0 };
static const int16_t sign_cost[1] = { 512 };
static const int16_t cat1_cost[1 << 1] = { 864, 1229 };
static const int16_t cat2_cost[1 << 2] = { 1256, 1453, 1696, 1893 };
static const int16_t cat3_cost[1 << 3] = { 1652, 1791, 1884, 2023,
2195, 2334, 2427, 2566 };
static const int16_t cat4_cost[1 << 4] = { 2079, 2160, 2218, 2299, 2395, 2476,
2534, 2615, 2661, 2742, 2800, 2881,
2977, 3058, 3116, 3197 };
static const int16_t cat5_cost[1 << 5] = {
2553, 2576, 2622, 2645, 2703, 2726, 2772, 2795, 2894, 2917, 2963,
2986, 3044, 3067, 3113, 3136, 3190, 3213, 3259, 3282, 3340, 3363,
3409, 3432, 3531, 3554, 3600, 3623, 3681, 3704, 3750, 3773
};
const int16_t av1_cat6_low_cost[256] = {
3378, 3390, 3401, 3413, 3435, 3447, 3458, 3470, 3517, 3529, 3540, 3552, 3574,
3586, 3597, 3609, 3671, 3683, 3694, 3706, 3728, 3740, 3751, 3763, 3810, 3822,
3833, 3845, 3867, 3879, 3890, 3902, 3973, 3985, 3996, 4008, 4030, 4042, 4053,
4065, 4112, 4124, 4135, 4147, 4169, 4181, 4192, 4204, 4266, 4278, 4289, 4301,
4323, 4335, 4346, 4358, 4405, 4417, 4428, 4440, 4462, 4474, 4485, 4497, 4253,
4265, 4276, 4288, 4310, 4322, 4333, 4345, 4392, 4404, 4415, 4427, 4449, 4461,
4472, 4484, 4546, 4558, 4569, 4581, 4603, 4615, 4626, 4638, 4685, 4697, 4708,
4720, 4742, 4754, 4765, 4777, 4848, 4860, 4871, 4883, 4905, 4917, 4928, 4940,
4987, 4999, 5010, 5022, 5044, 5056, 5067, 5079, 5141, 5153, 5164, 5176, 5198,
5210, 5221, 5233, 5280, 5292, 5303, 5315, 5337, 5349, 5360, 5372, 4988, 5000,
5011, 5023, 5045, 5057, 5068, 5080, 5127, 5139, 5150, 5162, 5184, 5196, 5207,
5219, 5281, 5293, 5304, 5316, 5338, 5350, 5361, 5373, 5420, 5432, 5443, 5455,
5477, 5489, 5500, 5512, 5583, 5595, 5606, 5618, 5640, 5652, 5663, 5675, 5722,
5734, 5745, 5757, 5779, 5791, 5802, 5814, 5876, 5888, 5899, 5911, 5933, 5945,
5956, 5968, 6015, 6027, 6038, 6050, 6072, 6084, 6095, 6107, 5863, 5875, 5886,
5898, 5920, 5932, 5943, 5955, 6002, 6014, 6025, 6037, 6059, 6071, 6082, 6094,
6156, 6168, 6179, 6191, 6213, 6225, 6236, 6248, 6295, 6307, 6318, 6330, 6352,
6364, 6375, 6387, 6458, 6470, 6481, 6493, 6515, 6527, 6538, 6550, 6597, 6609,
6620, 6632, 6654, 6666, 6677, 6689, 6751, 6763, 6774, 6786, 6808, 6820, 6831,
6843, 6890, 6902, 6913, 6925, 6947, 6959, 6970, 6982
};
const int av1_cat6_high_cost[CAT6_HIGH_COST_ENTRIES] = {
100, 2263, 2739, 4902, 3160, 5323, 5799, 7962, 3678, 5841, 6317,
8480, 6738, 8901, 9377, 11540, 3678, 5841, 6317, 8480, 6738, 8901,
9377, 11540, 7256, 9419, 9895, 12058, 10316, 12479, 12955, 15118, 3678,
5841, 6317, 8480, 6738, 8901, 9377, 11540, 7256, 9419, 9895, 12058,
10316, 12479, 12955, 15118, 7256, 9419, 9895, 12058, 10316, 12479, 12955,
15118, 10834, 12997, 13473, 15636, 13894, 16057, 16533, 18696,
#if CONFIG_HIGHBITDEPTH
4193, 6356, 6832, 8995, 7253, 9416, 9892, 12055, 7771, 9934, 10410,
12573, 10831, 12994, 13470, 15633, 7771, 9934, 10410, 12573, 10831, 12994,
13470, 15633, 11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 7771,
9934, 10410, 12573, 10831, 12994, 13470, 15633, 11349, 13512, 13988, 16151,
14409, 16572, 17048, 19211, 11349, 13512, 13988, 16151, 14409, 16572, 17048,
19211, 14927, 17090, 17566, 19729, 17987, 20150, 20626, 22789, 4193, 6356,
6832, 8995, 7253, 9416, 9892, 12055, 7771, 9934, 10410, 12573, 10831,
12994, 13470, 15633, 7771, 9934, 10410, 12573, 10831, 12994, 13470, 15633,
11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 7771, 9934, 10410,
12573, 10831, 12994, 13470, 15633, 11349, 13512, 13988, 16151, 14409, 16572,
17048, 19211, 11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 14927,
17090, 17566, 19729, 17987, 20150, 20626, 22789, 8286, 10449, 10925, 13088,
11346, 13509, 13985, 16148, 11864, 14027, 14503, 16666, 14924, 17087, 17563,
19726, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605,
18081, 20244, 18502, 20665, 21141, 23304, 11864, 14027, 14503, 16666, 14924,
17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304,
15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 19020, 21183, 21659,
23822, 22080, 24243, 24719, 26882, 4193, 6356, 6832, 8995, 7253, 9416,
9892, 12055, 7771, 9934, 10410, 12573, 10831, 12994, 13470, 15633, 7771,
9934, 10410, 12573, 10831, 12994, 13470, 15633, 11349, 13512, 13988, 16151,
14409, 16572, 17048, 19211, 7771, 9934, 10410, 12573, 10831, 12994, 13470,
15633, 11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 11349, 13512,
13988, 16151, 14409, 16572, 17048, 19211, 14927, 17090, 17566, 19729, 17987,
20150, 20626, 22789, 8286, 10449, 10925, 13088, 11346, 13509, 13985, 16148,
11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 11864, 14027, 14503,
16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502, 20665,
21141, 23304, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 15442,
17605, 18081, 20244, 18502, 20665, 21141, 23304, 15442, 17605, 18081, 20244,
18502, 20665, 21141, 23304, 19020, 21183, 21659, 23822, 22080, 24243, 24719,
26882, 8286, 10449, 10925, 13088, 11346, 13509, 13985, 16148, 11864, 14027,
14503, 16666, 14924, 17087, 17563, 19726, 11864, 14027, 14503, 16666, 14924,
17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304,
11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081,
20244, 18502, 20665, 21141, 23304, 15442, 17605, 18081, 20244, 18502, 20665,
21141, 23304, 19020, 21183, 21659, 23822, 22080, 24243, 24719, 26882, 12379,
14542, 15018, 17181, 15439, 17602, 18078, 20241, 15957, 18120, 18596, 20759,
19017, 21180, 21656, 23819, 15957, 18120, 18596, 20759, 19017, 21180, 21656,
23819, 19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397, 15957, 18120,
18596, 20759, 19017, 21180, 21656, 23819, 19535, 21698, 22174, 24337, 22595,
24758, 25234, 27397, 19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397,
23113, 25276, 25752, 27915, 26173, 28336, 28812, 30975, 4193, 6356, 6832,
8995, 7253, 9416, 9892, 12055, 7771, 9934, 10410, 12573, 10831, 12994,
13470, 15633, 7771, 9934, 10410, 12573, 10831, 12994, 13470, 15633, 11349,
13512, 13988, 16151, 14409, 16572, 17048, 19211, 7771, 9934, 10410, 12573,
10831, 12994, 13470, 15633, 11349, 13512, 13988, 16151, 14409, 16572, 17048,
19211, 11349, 13512, 13988, 16151, 14409, 16572, 17048, 19211, 14927, 17090,
17566, 19729, 17987, 20150, 20626, 22789, 8286, 10449, 10925, 13088, 11346,
13509, 13985, 16148, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726,
11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081,
20244, 18502, 20665, 21141, 23304, 11864, 14027, 14503, 16666, 14924, 17087,
17563, 19726, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 15442,
17605, 18081, 20244, 18502, 20665, 21141, 23304, 19020, 21183, 21659, 23822,
22080, 24243, 24719, 26882, 8286, 10449, 10925, 13088, 11346, 13509, 13985,
16148, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726, 11864, 14027,
14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081, 20244, 18502,
20665, 21141, 23304, 11864, 14027, 14503, 16666, 14924, 17087, 17563, 19726,
15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 15442, 17605, 18081,
20244, 18502, 20665, 21141, 23304, 19020, 21183, 21659, 23822, 22080, 24243,
24719, 26882, 12379, 14542, 15018, 17181, 15439, 17602, 18078, 20241, 15957,
18120, 18596, 20759, 19017, 21180, 21656, 23819, 15957, 18120, 18596, 20759,
19017, 21180, 21656, 23819, 19535, 21698, 22174, 24337, 22595, 24758, 25234,
27397, 15957, 18120, 18596, 20759, 19017, 21180, 21656, 23819, 19535, 21698,
22174, 24337, 22595, 24758, 25234, 27397, 19535, 21698, 22174, 24337, 22595,
24758, 25234, 27397, 23113, 25276, 25752, 27915, 26173, 28336, 28812, 30975,
8286, 10449, 10925, 13088, 11346, 13509, 13985, 16148, 11864, 14027, 14503,
16666, 14924, 17087, 17563, 19726, 11864, 14027, 14503, 16666, 14924, 17087,
17563, 19726, 15442, 17605, 18081, 20244, 18502, 20665, 21141, 23304, 11864,
14027, 14503, 16666, 14924, 17087, 17563, 19726, 15442, 17605, 18081, 20244,
18502, 20665, 21141, 23304, 15442, 17605, 18081, 20244, 18502, 20665, 21141,
23304, 19020, 21183, 21659, 23822, 22080, 24243, 24719, 26882, 12379, 14542,
15018, 17181, 15439, 17602, 18078, 20241, 15957, 18120, 18596, 20759, 19017,
21180, 21656, 23819, 15957, 18120, 18596, 20759, 19017, 21180, 21656, 23819,
19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397, 15957, 18120, 18596,
20759, 19017, 21180, 21656, 23819, 19535, 21698, 22174, 24337, 22595, 24758,
25234, 27397, 19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397, 23113,
25276, 25752, 27915, 26173, 28336, 28812, 30975, 12379, 14542, 15018, 17181,
15439, 17602, 18078, 20241, 15957, 18120, 18596, 20759, 19017, 21180, 21656,
23819, 15957, 18120, 18596, 20759, 19017, 21180, 21656, 23819, 19535, 21698,
22174, 24337, 22595, 24758, 25234, 27397, 15957, 18120, 18596, 20759, 19017,
21180, 21656, 23819, 19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397,
19535, 21698, 22174, 24337, 22595, 24758, 25234, 27397, 23113, 25276, 25752,
27915, 26173, 28336, 28812, 30975, 16472, 18635, 19111, 21274, 19532, 21695,
22171, 24334, 20050, 22213, 22689, 24852, 23110, 25273, 25749, 27912, 20050,
22213, 22689, 24852, 23110, 25273, 25749, 27912, 23628, 25791, 26267, 28430,
26688, 28851, 29327, 31490, 20050, 22213, 22689, 24852, 23110, 25273, 25749,
27912, 23628, 25791, 26267, 28430, 26688, 28851, 29327, 31490, 23628, 25791,
26267, 28430, 26688, 28851, 29327, 31490, 27206, 29369, 29845, 32008, 30266,
32429, 32905, 35068
#endif
};
const uint8_t av1_cat6_skipped_bits_discount[8] = {
0, 3, 6, 9, 12, 18, 24, 30
};
#if CONFIG_NEW_MULTISYMBOL
const av1_extra_bit av1_extra_bits[ENTROPY_TOKENS] = {
{ 0, 0, 0, zero_cost }, // ZERO_TOKEN
{ 0, 0, 1, sign_cost }, // ONE_TOKEN
{ 0, 0, 2, sign_cost }, // TWO_TOKEN
{ 0, 0, 3, sign_cost }, // THREE_TOKEN
{ 0, 0, 4, sign_cost }, // FOUR_TOKEN
{ av1_cat1_cdf, 1, CAT1_MIN_VAL, cat1_cost }, // CATEGORY1_TOKEN
{ av1_cat2_cdf, 2, CAT2_MIN_VAL, cat2_cost }, // CATEGORY2_TOKEN
{ av1_cat3_cdf, 3, CAT3_MIN_VAL, cat3_cost }, // CATEGORY3_TOKEN
{ av1_cat4_cdf, 4, CAT4_MIN_VAL, cat4_cost }, // CATEGORY4_TOKEN
{ av1_cat5_cdf, 5, CAT5_MIN_VAL, cat5_cost }, // CATEGORY5_TOKEN
{ av1_cat6_cdf, 18, CAT6_MIN_VAL, 0 }, // CATEGORY6_TOKEN
{ 0, 0, 0, zero_cost } // EOB_TOKEN
};
#else
const av1_extra_bit av1_extra_bits[ENTROPY_TOKENS] = {
{ 0, 0, 0, zero_cost }, // ZERO_TOKEN
{ 0, 0, 1, sign_cost }, // ONE_TOKEN
{ 0, 0, 2, sign_cost }, // TWO_TOKEN
{ 0, 0, 3, sign_cost }, // THREE_TOKEN
{ 0, 0, 4, sign_cost }, // FOUR_TOKEN
{ av1_cat1_prob, 1, CAT1_MIN_VAL, cat1_cost }, // CATEGORY1_TOKEN
{ av1_cat2_prob, 2, CAT2_MIN_VAL, cat2_cost }, // CATEGORY2_TOKEN
{ av1_cat3_prob, 3, CAT3_MIN_VAL, cat3_cost }, // CATEGORY3_TOKEN
{ av1_cat4_prob, 4, CAT4_MIN_VAL, cat4_cost }, // CATEGORY4_TOKEN
{ av1_cat5_prob, 5, CAT5_MIN_VAL, cat5_cost }, // CATEGORY5_TOKEN
{ av1_cat6_prob, 18, CAT6_MIN_VAL, 0 }, // CATEGORY6_TOKEN
{ 0, 0, 0, zero_cost } // EOB_TOKEN
};
#endif
#if !CONFIG_PVQ || CONFIG_VAR_TX
static void cost_coeffs_b(int plane, int block, int blk_row, int blk_col,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
struct tokenize_b_args *const args = arg;
const AV1_COMP *const cpi = args->cpi;
const AV1_COMMON *cm = &cpi->common;
ThreadData *const td = args->td;
MACROBLOCK *const x = &td->mb;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
struct macroblock_plane *p = &x->plane[plane];
struct macroblockd_plane *pd = &xd->plane[plane];
const PLANE_TYPE type = pd->plane_type;
const TX_TYPE tx_type =
av1_get_tx_type(type, xd, blk_row, blk_col, block, tx_size);
const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
const int rate = av1_cost_coeffs(
cpi, x, plane, blk_row, blk_col, block, tx_size, scan_order,
pd->above_context + blk_col, pd->left_context + blk_row, 0);
args->this_rate += rate;
(void)plane_bsize;
av1_set_contexts(xd, pd, plane, tx_size, p->eobs[block] > 0, blk_col,
blk_row);
}
static void set_entropy_context_b(int plane, int block, int blk_row,
int blk_col, BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, void *arg) {
struct tokenize_b_args *const args = arg;
ThreadData *const td = args->td;
MACROBLOCK *const x = &td->mb;
MACROBLOCKD *const xd = &x->e_mbd;
struct macroblock_plane *p = &x->plane[plane];
struct macroblockd_plane *pd = &xd->plane[plane];
(void)plane_bsize;
av1_set_contexts(xd, pd, plane, tx_size, p->eobs[block] > 0, blk_col,
blk_row);
}
static INLINE void add_token(TOKENEXTRA **t,
aom_cdf_prob (*tail_cdf)[CDF_SIZE(ENTROPY_TOKENS)],
aom_cdf_prob (*head_cdf)[CDF_SIZE(ENTROPY_TOKENS)],
int eob_val, int first_val, int32_t extra,
uint8_t token) {
(*t)->token = token;
(*t)->extra = extra;
(*t)->tail_cdf = tail_cdf;
(*t)->head_cdf = head_cdf;
(*t)->eob_val = eob_val;
(*t)->first_val = first_val;
(*t)++;
if (token == BLOCK_Z_TOKEN) {
update_cdf(*head_cdf, 0, HEAD_TOKENS + 1);
} else {
if (eob_val != LAST_EOB) {
const int symb = 2 * AOMMIN(token, TWO_TOKEN) - eob_val + first_val;
update_cdf(*head_cdf, symb, HEAD_TOKENS + first_val);
}
if (token > ONE_TOKEN)
update_cdf(*tail_cdf, token - TWO_TOKEN, TAIL_TOKENS);
}
}
#endif // !CONFIG_PVQ || CONFIG_VAR_TX
static int cost_and_tokenize_map(Av1ColorMapParam *param, TOKENEXTRA **t,
int calc_rate) {
int plane, int calc_rate, int allow_update_cdf,
FRAME_COUNTS *counts) {
const uint8_t *const color_map = param->color_map;
MapCdf map_cdf = param->map_cdf;
ColorCost color_cost = param->color_cost;
@ -338,28 +37,37 @@ static int cost_and_tokenize_map(Av1ColorMapParam *param, TOKENEXTRA **t,
const int rows = param->rows;
const int cols = param->cols;
const int n = param->n_colors;
const int palette_size_idx = n - PALETTE_MIN_SIZE;
int this_rate = 0;
uint8_t color_order[PALETTE_MAX_SIZE];
#if CONFIG_PALETTE_THROUGHPUT
(void)plane;
(void)counts;
for (int k = 1; k < rows + cols - 1; ++k) {
for (int j = AOMMIN(k, cols - 1); j >= AOMMAX(0, k - rows + 1); --j) {
int i = k - j;
#else
for (int i = 0; i < rows; ++i) {
for (int j = (i == 0 ? 1 : 0); j < cols; ++j) {
#endif // CONFIG_PALETTE_THROUGHPUT
int color_new_idx;
const int color_ctx = av1_get_palette_color_index_context(
color_map, plane_block_width, i, j, n, color_order, &color_new_idx);
assert(color_new_idx >= 0 && color_new_idx < n);
if (calc_rate) {
this_rate +=
(*color_cost)[n - PALETTE_MIN_SIZE][color_ctx][color_new_idx];
this_rate += (*color_cost)[palette_size_idx][color_ctx][color_new_idx];
} else {
(*t)->token = color_new_idx;
(*t)->color_map_cdf = map_cdf[n - PALETTE_MIN_SIZE][color_ctx];
(*t)->color_map_cdf = map_cdf[palette_size_idx][color_ctx];
++(*t);
if (allow_update_cdf)
update_cdf(map_cdf[palette_size_idx][color_ctx], color_new_idx, n);
#if CONFIG_ENTROPY_STATS
if (plane) {
++counts->palette_uv_color_index[palette_size_idx][color_ctx]
[color_new_idx];
} else {
++counts->palette_y_color_index[palette_size_idx][color_ctx]
[color_new_idx];
}
#endif
}
}
}
@ -370,7 +78,7 @@ static int cost_and_tokenize_map(Av1ColorMapParam *param, TOKENEXTRA **t,
static void get_palette_params(const MACROBLOCK *const x, int plane,
BLOCK_SIZE bsize, Av1ColorMapParam *params) {
const MACROBLOCKD *const xd = &x->e_mbd;
const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
const MB_MODE_INFO *const mbmi = xd->mi[0];
const PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
params->color_map = xd->plane[plane].color_index_map;
params->map_cdf = plane ? xd->tile_ctx->palette_uv_color_index_cdf
@ -382,263 +90,62 @@ static void get_palette_params(const MACROBLOCK *const x, int plane,
&params->rows, &params->cols);
}
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
static void get_mrc_params(const MACROBLOCK *const x, int block,
TX_SIZE tx_size, Av1ColorMapParam *params) {
memset(params, 0, sizeof(*params));
const MACROBLOCKD *const xd = &x->e_mbd;
const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
const int is_inter = is_inter_block(mbmi);
params->color_map = BLOCK_OFFSET(xd->mrc_mask, block);
params->map_cdf = is_inter ? xd->tile_ctx->mrc_mask_inter_cdf
: xd->tile_ctx->mrc_mask_intra_cdf;
params->color_cost =
is_inter ? &x->mrc_mask_inter_cost : &x->mrc_mask_intra_cost;
params->n_colors = 2;
params->plane_width = tx_size_wide[tx_size];
params->rows = tx_size_high[tx_size];
params->cols = tx_size_wide[tx_size];
}
#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
static void get_color_map_params(const MACROBLOCK *const x, int plane,
int block, BLOCK_SIZE bsize, TX_SIZE tx_size,
BLOCK_SIZE bsize, TX_SIZE tx_size,
COLOR_MAP_TYPE type,
Av1ColorMapParam *params) {
(void)block;
(void)tx_size;
memset(params, 0, sizeof(*params));
switch (type) {
case PALETTE_MAP: get_palette_params(x, plane, bsize, params); break;
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
case MRC_MAP: get_mrc_params(x, block, tx_size, params); break;
#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
default: assert(0 && "Invalid color map type"); return;
}
}
int av1_cost_color_map(const MACROBLOCK *const x, int plane, int block,
BLOCK_SIZE bsize, TX_SIZE tx_size, COLOR_MAP_TYPE type) {
int av1_cost_color_map(const MACROBLOCK *const x, int plane, BLOCK_SIZE bsize,
TX_SIZE tx_size, COLOR_MAP_TYPE type) {
assert(plane == 0 || plane == 1);
Av1ColorMapParam color_map_params;
get_color_map_params(x, plane, block, bsize, tx_size, type,
&color_map_params);
return cost_and_tokenize_map(&color_map_params, NULL, 1);
get_color_map_params(x, plane, bsize, tx_size, type, &color_map_params);
return cost_and_tokenize_map(&color_map_params, NULL, plane, 1, 0, NULL);
}
void av1_tokenize_color_map(const MACROBLOCK *const x, int plane, int block,
void av1_tokenize_color_map(const MACROBLOCK *const x, int plane,
TOKENEXTRA **t, BLOCK_SIZE bsize, TX_SIZE tx_size,
COLOR_MAP_TYPE type) {
COLOR_MAP_TYPE type, int allow_update_cdf,
FRAME_COUNTS *counts) {
assert(plane == 0 || plane == 1);
#if CONFIG_MRC_TX
if (type == MRC_MAP) {
const int is_inter = is_inter_block(&x->e_mbd.mi[0]->mbmi);
if ((is_inter && !SIGNAL_MRC_MASK_INTER) ||
(!is_inter && !SIGNAL_MRC_MASK_INTRA))
return;
}
#endif // CONFIG_MRC_TX
Av1ColorMapParam color_map_params;
get_color_map_params(x, plane, block, bsize, tx_size, type,
&color_map_params);
get_color_map_params(x, plane, bsize, tx_size, type, &color_map_params);
// The first color index does not use context or entropy.
(*t)->token = color_map_params.color_map[0];
(*t)->color_map_cdf = NULL;
++(*t);
cost_and_tokenize_map(&color_map_params, t, 0);
cost_and_tokenize_map(&color_map_params, t, plane, 0, allow_update_cdf,
counts);
}
#if CONFIG_PVQ
static void add_pvq_block(AV1_COMMON *const cm, MACROBLOCK *const x,
PVQ_INFO *pvq) {
PVQ_QUEUE *q = x->pvq_q;
if (q->curr_pos >= q->buf_len) {
int new_buf_len = 2 * q->buf_len + 1;
PVQ_INFO *new_buf;
CHECK_MEM_ERROR(cm, new_buf, aom_malloc(new_buf_len * sizeof(PVQ_INFO)));
memcpy(new_buf, q->buf, q->buf_len * sizeof(PVQ_INFO));
aom_free(q->buf);
q->buf = new_buf;
q->buf_len = new_buf_len;
}
OD_COPY(q->buf + q->curr_pos, pvq, 1);
++q->curr_pos;
}
// NOTE: This does not actually generate tokens, instead we store the encoding
// decisions made for PVQ in a queue that we will read from when
// actually writing the bitstream in write_modes_b
static void tokenize_pvq(int plane, int block, int blk_row, int blk_col,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
struct tokenize_b_args *const args = arg;
const AV1_COMP *cpi = args->cpi;
const AV1_COMMON *const cm = &cpi->common;
ThreadData *const td = args->td;
MACROBLOCK *const x = &td->mb;
PVQ_INFO *pvq_info;
(void)block;
(void)blk_row;
(void)blk_col;
(void)plane_bsize;
(void)tx_size;
assert(block < MAX_PVQ_BLOCKS_IN_SB);
pvq_info = &x->pvq[block][plane];
add_pvq_block((AV1_COMMON * const) cm, x, pvq_info);
}
#endif // CONFIG_PVQ
static void tokenize_b(int plane, int block, int blk_row, int blk_col,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg) {
#if !CONFIG_PVQ
struct tokenize_b_args *const args = arg;
const AV1_COMP *cpi = args->cpi;
const AV1_COMMON *const cm = &cpi->common;
ThreadData *const td = args->td;
MACROBLOCK *const x = &td->mb;
MACROBLOCKD *const xd = &x->e_mbd;
TOKENEXTRA **tp = args->tp;
uint8_t token_cache[MAX_TX_SQUARE];
struct macroblock_plane *p = &x->plane[plane];
struct macroblockd_plane *pd = &xd->plane[plane];
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
int pt; /* near block/prev token context index */
int c;
TOKENEXTRA *t = *tp; /* store tokens starting here */
const int eob = p->eobs[block];
const PLANE_TYPE type = pd->plane_type;
const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
#if CONFIG_SUPERTX
const int segment_id = AOMMIN(mbmi->segment_id, mbmi->segment_id_supertx);
#else
const int segment_id = mbmi->segment_id;
#endif // CONFIG_SUEPRTX
const int16_t *scan, *nb;
const TX_TYPE tx_type =
av1_get_tx_type(type, xd, blk_row, blk_col, block, tx_size);
const SCAN_ORDER *const scan_order = get_scan(cm, tx_size, tx_type, mbmi);
const int ref = is_inter_block(mbmi);
FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
aom_cdf_prob(
*const coef_head_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
ec_ctx->coef_head_cdfs[txsize_sqr_map[tx_size]][type][ref];
aom_cdf_prob(
*const coef_tail_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
ec_ctx->coef_tail_cdfs[txsize_sqr_map[tx_size]][type][ref];
int eob_val;
int first_val = 1;
const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
const uint8_t *const band = get_band_translate(tx_size);
int16_t token;
EXTRABIT extra;
(void)plane_bsize;
pt = get_entropy_context(tx_size, pd->above_context + blk_col,
pd->left_context + blk_row);
scan = scan_order->scan;
nb = scan_order->neighbors;
c = 0;
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
if (tx_type == MRC_DCT)
av1_tokenize_color_map(x, plane, block, &t, plane_bsize, tx_size, MRC_MAP);
#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
if (eob == 0)
add_token(&t, &coef_tail_cdfs[band[c]][pt], &coef_head_cdfs[band[c]][pt], 1,
1, 0, BLOCK_Z_TOKEN);
while (c < eob) {
int v = qcoeff[scan[c]];
first_val = (c == 0);
if (!v) {
add_token(&t, &coef_tail_cdfs[band[c]][pt], &coef_head_cdfs[band[c]][pt],
0, first_val, 0, ZERO_TOKEN);
token_cache[scan[c]] = 0;
} else {
eob_val =
(c + 1 == eob) ? (c + 1 == seg_eob ? LAST_EOB : EARLY_EOB) : NO_EOB;
av1_get_token_extra(v, &token, &extra);
add_token(&t, &coef_tail_cdfs[band[c]][pt], &coef_head_cdfs[band[c]][pt],
eob_val, first_val, extra, (uint8_t)token);
token_cache[scan[c]] = av1_pt_energy_class[token];
}
++c;
pt = get_coef_context(nb, token_cache, AOMMIN(c, eob - 1));
}
#if CONFIG_COEF_INTERLEAVE
t->token = EOSB_TOKEN;
t++;
#endif
*tp = t;
#if CONFIG_ADAPT_SCAN
// Since dqcoeff is not available here, we pass qcoeff into
// av1_update_scan_count_facade(). The update behavior should be the same
// because av1_update_scan_count_facade() only cares if coefficients are zero
// or not.
av1_update_scan_count_facade((AV1_COMMON *)cm, td->counts, tx_size, tx_type,
qcoeff, c);
#endif
av1_set_contexts(xd, pd, plane, tx_size, c > 0, blk_col, blk_row);
#else // !CONFIG_PVQ
tokenize_pvq(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
#endif // !CONFIG_PVQ
}
struct is_skippable_args {
uint16_t *eobs;
int *skippable;
};
static void is_skippable(int plane, int block, int blk_row, int blk_col,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *argv) {
struct is_skippable_args *args = argv;
(void)plane;
(void)plane_bsize;
(void)tx_size;
(void)blk_row;
(void)blk_col;
args->skippable[0] &= (!args->eobs[block]);
}
// TODO(yaowu): rewrite and optimize this function to remove the usage of
// av1_foreach_transform_block() and simplify is_skippable().
int av1_is_skippable_in_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
int result = 1;
struct is_skippable_args args = { x->plane[plane].eobs, &result };
av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, plane, is_skippable,
&args);
return result;
}
#if CONFIG_VAR_TX
void tokenize_vartx(ThreadData *td, TOKENEXTRA **t, RUN_TYPE dry_run,
TX_SIZE tx_size, BLOCK_SIZE plane_bsize, int blk_row,
int blk_col, int block, int plane, void *arg) {
MACROBLOCK *const x = &td->mb;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
MB_MODE_INFO *const mbmi = xd->mi[0];
const struct macroblockd_plane *const pd = &xd->plane[plane];
const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
const int tx_row = blk_row >> (1 - pd->subsampling_y);
const int tx_col = blk_col >> (1 - pd->subsampling_x);
const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
TX_SIZE plane_tx_size;
if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
plane_tx_size =
plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
: mbmi->inter_tx_size[tx_row][tx_col];
const TX_SIZE plane_tx_size =
plane ? av1_get_max_uv_txsize(mbmi->sb_type, pd->subsampling_x,
pd->subsampling_y)
: mbmi->inter_tx_size[av1_get_txb_size_index(plane_bsize, blk_row,
blk_col)];
if (tx_size == plane_tx_size) {
plane_bsize = get_plane_block_size(mbmi->sb_type, pd);
#if CONFIG_LV_MAP
if (tx_size == plane_tx_size || plane) {
plane_bsize = get_plane_block_size(mbmi->sb_type, pd->subsampling_x,
pd->subsampling_y);
if (!dry_run) {
av1_update_and_record_txb_context(plane, block, blk_row, blk_col,
plane_bsize, tx_size, arg);
@ -649,120 +156,71 @@ void tokenize_vartx(ThreadData *td, TOKENEXTRA **t, RUN_TYPE dry_run,
printf("DRY_RUN_COSTCOEFFS is not supported yet\n");
assert(0);
}
#else
if (!dry_run)
tokenize_b(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
else if (dry_run == DRY_RUN_NORMAL)
set_entropy_context_b(plane, block, blk_row, blk_col, plane_bsize,
tx_size, arg);
else if (dry_run == DRY_RUN_COSTCOEFFS)
cost_coeffs_b(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
#endif
} else {
#if CONFIG_RECT_TX_EXT
int is_qttx = plane_tx_size == quarter_txsize_lookup[plane_bsize];
const TX_SIZE sub_txs = is_qttx ? plane_tx_size : sub_tx_size_map[tx_size];
#else
// Half the block size in transform block unit.
const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
#endif
const int bsl = tx_size_wide_unit[sub_txs];
int i;
const int bsw = tx_size_wide_unit[sub_txs];
const int bsh = tx_size_high_unit[sub_txs];
const int step = bsw * bsh;
assert(bsl > 0);
assert(bsw > 0 && bsh > 0);
for (i = 0; i < 4; ++i) {
#if CONFIG_RECT_TX_EXT
int is_wide_tx = tx_size_wide_unit[sub_txs] > tx_size_high_unit[sub_txs];
const int offsetr =
is_qttx ? (is_wide_tx ? i * tx_size_high_unit[sub_txs] : 0)
: blk_row + ((i >> 1) * bsl);
const int offsetc =
is_qttx ? (is_wide_tx ? 0 : i * tx_size_wide_unit[sub_txs])
: blk_col + ((i & 0x01) * bsl);
#else
const int offsetr = blk_row + ((i >> 1) * bsl);
const int offsetc = blk_col + ((i & 0x01) * bsl);
#endif
for (int row = 0; row < tx_size_high_unit[tx_size]; row += bsh) {
for (int col = 0; col < tx_size_wide_unit[tx_size]; col += bsw) {
const int offsetr = blk_row + row;
const int offsetc = blk_col + col;
int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
tokenize_vartx(td, t, dry_run, sub_txs, plane_bsize, offsetr, offsetc,
block, plane, arg);
block += step;
tokenize_vartx(td, t, dry_run, sub_txs, plane_bsize, offsetr, offsetc,
block, plane, arg);
block += step;
}
}
}
}
void av1_tokenize_sb_vartx(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
RUN_TYPE dry_run, int mi_row, int mi_col,
BLOCK_SIZE bsize, int *rate) {
BLOCK_SIZE bsize, int *rate,
uint8_t allow_update_cdf) {
const AV1_COMMON *const cm = &cpi->common;
const int num_planes = av1_num_planes(cm);
MACROBLOCK *const x = &td->mb;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
#if CONFIG_LV_MAP
MB_MODE_INFO *const mbmi = xd->mi[0];
(void)t;
#else
TOKENEXTRA *t_backup = *t;
#endif
const int ctx = av1_get_skip_context(xd);
const int skip_inc =
!segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP);
struct tokenize_b_args arg = { cpi, td, t, 0 };
int plane;
struct tokenize_b_args arg = { cpi, td, t, 0, allow_update_cdf };
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
if (mbmi->skip) {
if (!dry_run) td->counts->skip[ctx][1] += skip_inc;
av1_reset_skip_context(xd, mi_row, mi_col, bsize);
#if !CONFIG_LV_MAP
if (dry_run) *t = t_backup;
#endif
av1_reset_skip_context(xd, mi_row, mi_col, bsize, num_planes);
return;
}
if (!dry_run) td->counts->skip[ctx][0] += skip_inc;
#if !CONFIG_LV_MAP
else
*t = t_backup;
#endif
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
#if CONFIG_CB4X4
for (int plane = 0; plane < num_planes; ++plane) {
if (!is_chroma_reference(mi_row, mi_col, bsize,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y)) {
#if !CONFIG_PVQ && !CONFIG_LV_MAP
if (!dry_run) {
(*t)->token = EOSB_TOKEN;
(*t)++;
}
#endif
continue;
}
#endif
const struct macroblockd_plane *const pd = &xd->plane[plane];
#if CONFIG_CHROMA_SUB8X8
const BLOCK_SIZE bsizec =
scale_chroma_bsize(bsize, pd->subsampling_x, pd->subsampling_y);
const BLOCK_SIZE plane_bsize =
AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
#else
const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
#endif
get_plane_block_size(bsizec, pd->subsampling_x, pd->subsampling_y);
const int mi_width = block_size_wide[plane_bsize] >> tx_size_wide_log2[0];
const int mi_height = block_size_high[plane_bsize] >> tx_size_wide_log2[0];
const TX_SIZE max_tx_size = get_vartx_max_txsize(
mbmi, plane_bsize, pd->subsampling_x || pd->subsampling_y);
const int mi_height = block_size_high[plane_bsize] >> tx_size_high_log2[0];
const TX_SIZE max_tx_size = get_vartx_max_txsize(xd, plane_bsize, plane);
const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
int bw = block_size_wide[txb_size] >> tx_size_wide_log2[0];
int bh = block_size_high[txb_size] >> tx_size_wide_log2[0];
int bh = block_size_high[txb_size] >> tx_size_high_log2[0];
int idx, idy;
int block = 0;
int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
const BLOCK_SIZE max_unit_bsize = get_plane_block_size(BLOCK_64X64, pd);
const BLOCK_SIZE max_unit_bsize =
get_plane_block_size(BLOCK_64X64, pd->subsampling_x, pd->subsampling_y);
int mu_blocks_wide =
block_size_wide[max_unit_bsize] >> tx_size_wide_log2[0];
int mu_blocks_high =
@ -785,144 +243,6 @@ void av1_tokenize_sb_vartx(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
}
}
}
#if !CONFIG_LV_MAP
if (!dry_run) {
(*t)->token = EOSB_TOKEN;
(*t)++;
}
#endif
}
if (rate) *rate += arg.this_rate;
}
#endif // CONFIG_VAR_TX
void av1_tokenize_sb(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
RUN_TYPE dry_run, BLOCK_SIZE bsize, int *rate,
const int mi_row, const int mi_col) {
const AV1_COMMON *const cm = &cpi->common;
MACROBLOCK *const x = &td->mb;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
const int ctx = av1_get_skip_context(xd);
const int skip_inc =
!segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP);
struct tokenize_b_args arg = { cpi, td, t, 0 };
if (mbmi->skip) {
if (!dry_run) td->counts->skip[ctx][1] += skip_inc;
av1_reset_skip_context(xd, mi_row, mi_col, bsize);
return;
}
if (!dry_run) {
#if CONFIG_COEF_INTERLEAVE
td->counts->skip[ctx][0] += skip_inc;
av1_foreach_transformed_block_interleave(xd, bsize, tokenize_b, &arg);
#else
int plane;
td->counts->skip[ctx][0] += skip_inc;
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
#if CONFIG_CB4X4
if (!is_chroma_reference(mi_row, mi_col, bsize,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y)) {
#if !CONFIG_PVQ
(*t)->token = EOSB_TOKEN;
(*t)++;
#endif
continue;
}
#else
(void)mi_row;
(void)mi_col;
#endif
av1_foreach_transformed_block_in_plane(xd, bsize, plane, tokenize_b,
&arg);
#if !CONFIG_PVQ
(*t)->token = EOSB_TOKEN;
(*t)++;
#endif // !CONFIG_PVQ
}
#endif
}
#if !CONFIG_PVQ
else if (dry_run == DRY_RUN_NORMAL) {
int plane;
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
#if CONFIG_CB4X4
if (!is_chroma_reference(mi_row, mi_col, bsize,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y))
continue;
#else
(void)mi_row;
(void)mi_col;
#endif
av1_foreach_transformed_block_in_plane(xd, bsize, plane,
set_entropy_context_b, &arg);
}
} else if (dry_run == DRY_RUN_COSTCOEFFS) {
int plane;
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
#if CONFIG_CB4X4
if (!is_chroma_reference(mi_row, mi_col, bsize,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y))
continue;
#else
(void)mi_row;
(void)mi_col;
#endif
av1_foreach_transformed_block_in_plane(xd, bsize, plane, cost_coeffs_b,
&arg);
}
}
#endif // !CONFIG_PVQ
if (rate) *rate += arg.this_rate;
}
#if CONFIG_SUPERTX
void av1_tokenize_sb_supertx(const AV1_COMP *cpi, ThreadData *td,
TOKENEXTRA **t, RUN_TYPE dry_run, int mi_row,
int mi_col, BLOCK_SIZE bsize, int *rate) {
const AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &td->mb.e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
TOKENEXTRA *t_backup = *t;
const int ctx = av1_get_skip_context(xd);
const int skip_inc =
!segfeature_active(&cm->seg, mbmi->segment_id_supertx, SEG_LVL_SKIP);
struct tokenize_b_args arg = { cpi, td, t, 0 };
if (mbmi->skip) {
if (!dry_run) td->counts->skip[ctx][1] += skip_inc;
av1_reset_skip_context(xd, mi_row, mi_col, bsize);
if (dry_run) *t = t_backup;
return;
}
if (!dry_run) {
int plane;
td->counts->skip[ctx][0] += skip_inc;
for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
av1_foreach_transformed_block_in_plane(xd, bsize, plane, tokenize_b,
&arg);
(*t)->token = EOSB_TOKEN;
(*t)++;
}
} else if (dry_run == DRY_RUN_NORMAL) {
int plane;
for (plane = 0; plane < MAX_MB_PLANE; ++plane)
av1_foreach_transformed_block_in_plane(xd, bsize, plane,
set_entropy_context_b, &arg);
*t = t_backup;
} else if (dry_run == DRY_RUN_COSTCOEFFS) {
int plane;
for (plane = 0; plane < MAX_MB_PLANE; ++plane)
av1_foreach_transformed_block_in_plane(xd, bsize, plane, cost_coeffs_b,
&arg);
}
if (rate) *rate += arg.this_rate;
}
#endif // CONFIG_SUPERTX

View file

@ -13,51 +13,29 @@
#define AV1_ENCODER_TOKENIZE_H_
#include "av1/common/entropy.h"
#include "av1/encoder/block.h"
#include "av1/encoder/treewriter.h"
#include "aom_dsp/bitwriter.h"
#ifdef __cplusplus
extern "C" {
#endif
#define EOSB_TOKEN 127 // Not signalled, encoder only
#if CONFIG_HIGHBITDEPTH
typedef int32_t EXTRABIT;
#else
typedef int16_t EXTRABIT;
#endif
typedef struct {
int16_t token;
EXTRABIT extra;
} TOKENVALUE;
typedef struct {
aom_cdf_prob (*tail_cdf)[CDF_SIZE(ENTROPY_TOKENS)];
aom_cdf_prob (*head_cdf)[CDF_SIZE(ENTROPY_TOKENS)];
aom_cdf_prob *color_map_cdf;
int eob_val;
int first_val;
const aom_prob *context_tree;
EXTRABIT extra;
// TODO(yaowu: use packed enum type if appropriate)
uint8_t token;
} TOKENEXTRA;
extern const aom_tree_index av1_coef_tree[];
extern const aom_tree_index av1_coef_con_tree[];
int av1_is_skippable_in_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane);
struct AV1_COMP;
struct ThreadData;
struct FRAME_COUNTS;
struct tokenize_b_args {
const struct AV1_COMP *cpi;
struct ThreadData *td;
TOKENEXTRA **tp;
int this_rate;
uint8_t allow_update_cdf;
};
typedef enum {
@ -69,78 +47,22 @@ typedef enum {
// Note in all the tokenize functions rate if non NULL is incremented
// with the coefficient token cost only if dry_run = DRY_RUN_COSTCOEFS,
// otherwise rate is not incremented.
#if CONFIG_VAR_TX
void av1_tokenize_sb_vartx(const struct AV1_COMP *cpi, struct ThreadData *td,
TOKENEXTRA **t, RUN_TYPE dry_run, int mi_row,
int mi_col, BLOCK_SIZE bsize, int *rate);
#endif
int mi_col, BLOCK_SIZE bsize, int *rate,
uint8_t allow_update_cdf);
int av1_cost_color_map(const MACROBLOCK *const x, int plane, int block,
BLOCK_SIZE bsize, TX_SIZE tx_size, COLOR_MAP_TYPE type);
int av1_cost_color_map(const MACROBLOCK *const x, int plane, BLOCK_SIZE bsize,
TX_SIZE tx_size, COLOR_MAP_TYPE type);
void av1_tokenize_color_map(const MACROBLOCK *const x, int plane, int block,
void av1_tokenize_color_map(const MACROBLOCK *const x, int plane,
TOKENEXTRA **t, BLOCK_SIZE bsize, TX_SIZE tx_size,
COLOR_MAP_TYPE type);
void av1_tokenize_sb(const struct AV1_COMP *cpi, struct ThreadData *td,
TOKENEXTRA **t, RUN_TYPE dry_run, BLOCK_SIZE bsize,
int *rate, const int mi_row, const int mi_col);
#if CONFIG_SUPERTX
void av1_tokenize_sb_supertx(const struct AV1_COMP *cpi, struct ThreadData *td,
TOKENEXTRA **t, RUN_TYPE dry_run, int mi_row,
int mi_col, BLOCK_SIZE bsize, int *rate);
#endif
extern const int16_t *av1_dct_value_cost_ptr;
/* TODO: The Token field should be broken out into a separate char array to
* improve cache locality, since it's needed for costing when the rest of the
* fields are not.
*/
extern const TOKENVALUE *av1_dct_value_tokens_ptr;
extern const TOKENVALUE *av1_dct_cat_lt_10_value_tokens;
extern const int *av1_dct_cat_lt_10_value_cost;
extern const int16_t av1_cat6_low_cost[256];
#if CONFIG_HIGHBITDEPTH
#define CAT6_HIGH_COST_ENTRIES 1024
#else
#define CAT6_HIGH_COST_ENTRIES 64
#endif
extern const int av1_cat6_high_cost[CAT6_HIGH_COST_ENTRIES];
extern const uint8_t av1_cat6_skipped_bits_discount[8];
static INLINE void av1_get_token_extra(int v, int16_t *token, EXTRABIT *extra) {
if (v >= CAT6_MIN_VAL || v <= -CAT6_MIN_VAL) {
*token = CATEGORY6_TOKEN;
if (v >= CAT6_MIN_VAL)
*extra = 2 * v - 2 * CAT6_MIN_VAL;
else
*extra = -2 * v - 2 * CAT6_MIN_VAL + 1;
return;
}
*token = av1_dct_cat_lt_10_value_tokens[v].token;
*extra = av1_dct_cat_lt_10_value_tokens[v].extra;
}
static INLINE int16_t av1_get_token(int v) {
if (v >= CAT6_MIN_VAL || v <= -CAT6_MIN_VAL) return 10;
return av1_dct_cat_lt_10_value_tokens[v].token;
}
static INLINE int av1_get_token_cost(int v, int16_t *token, int cat6_bits) {
if (v >= CAT6_MIN_VAL || v <= -CAT6_MIN_VAL) {
EXTRABIT extrabits;
*token = CATEGORY6_TOKEN;
extrabits = abs(v) - CAT6_MIN_VAL;
return av1_cat6_low_cost[extrabits & 0xff] +
av1_cat6_high_cost[extrabits >> 8] -
av1_cat6_skipped_bits_discount[18 - cat6_bits];
}
*token = av1_dct_cat_lt_10_value_tokens[v].token;
return av1_dct_cat_lt_10_value_cost[v];
}
COLOR_MAP_TYPE type, int allow_update_cdf,
struct FRAME_COUNTS *counts);
static INLINE int av1_get_tx_eob(const struct segmentation *seg, int segment_id,
TX_SIZE tx_size) {
const int eob_max = tx_size_2d[tx_size];
const int eob_max = av1_get_max_eob(tx_size);
return segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
}

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "av1/encoder/treewriter.h"
static void tree2tok(struct av1_token *tokens, const aom_tree_index *tree,
int i, int v, int l) {
v += v;
++l;
do {
const aom_tree_index j = tree[i++];
if (j <= 0) {
tokens[-j].value = v;
tokens[-j].len = l;
} else {
tree2tok(tokens, tree, j, v, l);
}
} while (++v & 1);
}
void av1_tokens_from_tree(struct av1_token *tokens,
const aom_tree_index *tree) {
tree2tok(tokens, tree, 0, 0, 0);
}
static unsigned int convert_distribution(unsigned int i, aom_tree tree,
unsigned int branch_ct[][2],
const unsigned int num_events[]) {
unsigned int left, right;
if (tree[i] <= 0)
left = num_events[-tree[i]];
else
left = convert_distribution(tree[i], tree, branch_ct, num_events);
if (tree[i + 1] <= 0)
right = num_events[-tree[i + 1]];
else
right = convert_distribution(tree[i + 1], tree, branch_ct, num_events);
branch_ct[i >> 1][0] = left;
branch_ct[i >> 1][1] = right;
return left + right;
}
void av1_tree_probs_from_distribution(aom_tree tree,
unsigned int branch_ct[/* n-1 */][2],
const unsigned int num_events[/* n */]) {
convert_distribution(0, tree, branch_ct, num_events);
}

View file

@ -1,42 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef AV1_ENCODER_TREEWRITER_H_
#define AV1_ENCODER_TREEWRITER_H_
#include "aom_dsp/bitwriter.h"
#ifdef __cplusplus
extern "C" {
#endif
void av1_tree_probs_from_distribution(aom_tree tree,
unsigned int branch_ct[/* n - 1 */][2],
const unsigned int num_events[/* n */]);
struct av1_token {
int value;
int len;
};
void av1_tokens_from_tree(struct av1_token *, const aom_tree_index *);
static INLINE void av1_write_token(aom_writer *w, const aom_tree_index *tree,
const aom_prob *probs,
const struct av1_token *token) {
aom_write_tree(w, tree, probs, token->value, token->len, 0);
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AV1_ENCODER_TREEWRITER_H_

Some files were not shown because too many files have changed in this diff Show more