(61d00a474) v0.9.7.1

This commit is contained in:
Regalis
2020-03-04 13:04:10 +01:00
parent 3c50efa5c9
commit 3c09ebe02f
5086 changed files with 786063 additions and 295871 deletions
@@ -0,0 +1,460 @@
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <arm_neon.h>
#include "vp8/encoder/denoising.h"
#include "vpx_mem/vpx_mem.h"
#include "./vp8_rtcd.h"
/*
* The filter function was modified to reduce the computational complexity.
*
* Step 1:
* Instead of applying tap coefficients for each pixel, we calculated the
* pixel adjustments vs. pixel diff value ahead of time.
* adjustment = filtered_value - current_raw
* = (filter_coefficient * diff + 128) >> 8
* where
* filter_coefficient = (255 << 8) / (256 + ((abs_diff * 330) >> 3));
* filter_coefficient += filter_coefficient /
* (3 + motion_magnitude_adjustment);
* filter_coefficient is clamped to 0 ~ 255.
*
* Step 2:
* The adjustment vs. diff curve becomes flat very quick when diff increases.
* This allowed us to use only several levels to approximate the curve without
* changing the filtering algorithm too much.
* The adjustments were further corrected by checking the motion magnitude.
* The levels used are:
* diff level adjustment w/o adjustment w/
* motion correction motion correction
* [-255, -16] 3 -6 -7
* [-15, -8] 2 -4 -5
* [-7, -4] 1 -3 -4
* [-3, 3] 0 diff diff
* [4, 7] 1 3 4
* [8, 15] 2 4 5
* [16, 255] 3 6 7
*/
int vp8_denoiser_filter_neon(unsigned char *mc_running_avg_y,
int mc_running_avg_y_stride,
unsigned char *running_avg_y,
int running_avg_y_stride, unsigned char *sig,
int sig_stride, unsigned int motion_magnitude,
int increase_denoising) {
/* If motion_magnitude is small, making the denoiser more aggressive by
* increasing the adjustment for each level, level1 adjustment is
* increased, the deltas stay the same.
*/
int shift_inc =
(increase_denoising && motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD)
? 1
: 0;
const uint8x16_t v_level1_adjustment = vmovq_n_u8(
(motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) ? 4 + shift_inc : 3);
const uint8x16_t v_delta_level_1_and_2 = vdupq_n_u8(1);
const uint8x16_t v_delta_level_2_and_3 = vdupq_n_u8(2);
const uint8x16_t v_level1_threshold = vmovq_n_u8(4 + shift_inc);
const uint8x16_t v_level2_threshold = vdupq_n_u8(8);
const uint8x16_t v_level3_threshold = vdupq_n_u8(16);
int64x2_t v_sum_diff_total = vdupq_n_s64(0);
/* Go over lines. */
int r;
for (r = 0; r < 16; ++r) {
/* Load inputs. */
const uint8x16_t v_sig = vld1q_u8(sig);
const uint8x16_t v_mc_running_avg_y = vld1q_u8(mc_running_avg_y);
/* Calculate absolute difference and sign masks. */
const uint8x16_t v_abs_diff = vabdq_u8(v_sig, v_mc_running_avg_y);
const uint8x16_t v_diff_pos_mask = vcltq_u8(v_sig, v_mc_running_avg_y);
const uint8x16_t v_diff_neg_mask = vcgtq_u8(v_sig, v_mc_running_avg_y);
/* Figure out which level that put us in. */
const uint8x16_t v_level1_mask = vcleq_u8(v_level1_threshold, v_abs_diff);
const uint8x16_t v_level2_mask = vcleq_u8(v_level2_threshold, v_abs_diff);
const uint8x16_t v_level3_mask = vcleq_u8(v_level3_threshold, v_abs_diff);
/* Calculate absolute adjustments for level 1, 2 and 3. */
const uint8x16_t v_level2_adjustment =
vandq_u8(v_level2_mask, v_delta_level_1_and_2);
const uint8x16_t v_level3_adjustment =
vandq_u8(v_level3_mask, v_delta_level_2_and_3);
const uint8x16_t v_level1and2_adjustment =
vaddq_u8(v_level1_adjustment, v_level2_adjustment);
const uint8x16_t v_level1and2and3_adjustment =
vaddq_u8(v_level1and2_adjustment, v_level3_adjustment);
/* Figure adjustment absolute value by selecting between the absolute
* difference if in level0 or the value for level 1, 2 and 3.
*/
const uint8x16_t v_abs_adjustment =
vbslq_u8(v_level1_mask, v_level1and2and3_adjustment, v_abs_diff);
/* Calculate positive and negative adjustments. Apply them to the signal
* and accumulate them. Adjustments are less than eight and the maximum
* sum of them (7 * 16) can fit in a signed char.
*/
const uint8x16_t v_pos_adjustment =
vandq_u8(v_diff_pos_mask, v_abs_adjustment);
const uint8x16_t v_neg_adjustment =
vandq_u8(v_diff_neg_mask, v_abs_adjustment);
uint8x16_t v_running_avg_y = vqaddq_u8(v_sig, v_pos_adjustment);
v_running_avg_y = vqsubq_u8(v_running_avg_y, v_neg_adjustment);
/* Store results. */
vst1q_u8(running_avg_y, v_running_avg_y);
/* Sum all the accumulators to have the sum of all pixel differences
* for this macroblock.
*/
{
const int8x16_t v_sum_diff =
vqsubq_s8(vreinterpretq_s8_u8(v_pos_adjustment),
vreinterpretq_s8_u8(v_neg_adjustment));
const int16x8_t fe_dc_ba_98_76_54_32_10 = vpaddlq_s8(v_sum_diff);
const int32x4_t fedc_ba98_7654_3210 =
vpaddlq_s16(fe_dc_ba_98_76_54_32_10);
const int64x2_t fedcba98_76543210 = vpaddlq_s32(fedc_ba98_7654_3210);
v_sum_diff_total = vqaddq_s64(v_sum_diff_total, fedcba98_76543210);
}
/* Update pointers for next iteration. */
sig += sig_stride;
mc_running_avg_y += mc_running_avg_y_stride;
running_avg_y += running_avg_y_stride;
}
/* Too much adjustments => copy block. */
{
int64x1_t x = vqadd_s64(vget_high_s64(v_sum_diff_total),
vget_low_s64(v_sum_diff_total));
int sum_diff = vget_lane_s32(vabs_s32(vreinterpret_s32_s64(x)), 0);
int sum_diff_thresh = SUM_DIFF_THRESHOLD;
if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH;
if (sum_diff > sum_diff_thresh) {
// Before returning to copy the block (i.e., apply no denoising),
// checK if we can still apply some (weaker) temporal filtering to
// this block, that would otherwise not be denoised at all. Simplest
// is to apply an additional adjustment to running_avg_y to bring it
// closer to sig. The adjustment is capped by a maximum delta, and
// chosen such that in most cases the resulting sum_diff will be
// within the accceptable range given by sum_diff_thresh.
// The delta is set by the excess of absolute pixel diff over the
// threshold.
int delta = ((sum_diff - sum_diff_thresh) >> 8) + 1;
// Only apply the adjustment for max delta up to 3.
if (delta < 4) {
const uint8x16_t k_delta = vmovq_n_u8(delta);
sig -= sig_stride * 16;
mc_running_avg_y -= mc_running_avg_y_stride * 16;
running_avg_y -= running_avg_y_stride * 16;
for (r = 0; r < 16; ++r) {
uint8x16_t v_running_avg_y = vld1q_u8(running_avg_y);
const uint8x16_t v_sig = vld1q_u8(sig);
const uint8x16_t v_mc_running_avg_y = vld1q_u8(mc_running_avg_y);
/* Calculate absolute difference and sign masks. */
const uint8x16_t v_abs_diff = vabdq_u8(v_sig, v_mc_running_avg_y);
const uint8x16_t v_diff_pos_mask =
vcltq_u8(v_sig, v_mc_running_avg_y);
const uint8x16_t v_diff_neg_mask =
vcgtq_u8(v_sig, v_mc_running_avg_y);
// Clamp absolute difference to delta to get the adjustment.
const uint8x16_t v_abs_adjustment = vminq_u8(v_abs_diff, (k_delta));
const uint8x16_t v_pos_adjustment =
vandq_u8(v_diff_pos_mask, v_abs_adjustment);
const uint8x16_t v_neg_adjustment =
vandq_u8(v_diff_neg_mask, v_abs_adjustment);
v_running_avg_y = vqsubq_u8(v_running_avg_y, v_pos_adjustment);
v_running_avg_y = vqaddq_u8(v_running_avg_y, v_neg_adjustment);
/* Store results. */
vst1q_u8(running_avg_y, v_running_avg_y);
{
const int8x16_t v_sum_diff =
vqsubq_s8(vreinterpretq_s8_u8(v_neg_adjustment),
vreinterpretq_s8_u8(v_pos_adjustment));
const int16x8_t fe_dc_ba_98_76_54_32_10 = vpaddlq_s8(v_sum_diff);
const int32x4_t fedc_ba98_7654_3210 =
vpaddlq_s16(fe_dc_ba_98_76_54_32_10);
const int64x2_t fedcba98_76543210 =
vpaddlq_s32(fedc_ba98_7654_3210);
v_sum_diff_total = vqaddq_s64(v_sum_diff_total, fedcba98_76543210);
}
/* Update pointers for next iteration. */
sig += sig_stride;
mc_running_avg_y += mc_running_avg_y_stride;
running_avg_y += running_avg_y_stride;
}
{
// Update the sum of all pixel differences of this MB.
x = vqadd_s64(vget_high_s64(v_sum_diff_total),
vget_low_s64(v_sum_diff_total));
sum_diff = vget_lane_s32(vabs_s32(vreinterpret_s32_s64(x)), 0);
if (sum_diff > sum_diff_thresh) {
return COPY_BLOCK;
}
}
} else {
return COPY_BLOCK;
}
}
}
/* Tell above level that block was filtered. */
running_avg_y -= running_avg_y_stride * 16;
sig -= sig_stride * 16;
vp8_copy_mem16x16(running_avg_y, running_avg_y_stride, sig, sig_stride);
return FILTER_BLOCK;
}
int vp8_denoiser_filter_uv_neon(unsigned char *mc_running_avg,
int mc_running_avg_stride,
unsigned char *running_avg,
int running_avg_stride, unsigned char *sig,
int sig_stride, unsigned int motion_magnitude,
int increase_denoising) {
/* If motion_magnitude is small, making the denoiser more aggressive by
* increasing the adjustment for each level, level1 adjustment is
* increased, the deltas stay the same.
*/
int shift_inc =
(increase_denoising && motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD_UV)
? 1
: 0;
const uint8x16_t v_level1_adjustment = vmovq_n_u8(
(motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD_UV) ? 4 + shift_inc : 3);
const uint8x16_t v_delta_level_1_and_2 = vdupq_n_u8(1);
const uint8x16_t v_delta_level_2_and_3 = vdupq_n_u8(2);
const uint8x16_t v_level1_threshold = vmovq_n_u8(4 + shift_inc);
const uint8x16_t v_level2_threshold = vdupq_n_u8(8);
const uint8x16_t v_level3_threshold = vdupq_n_u8(16);
int64x2_t v_sum_diff_total = vdupq_n_s64(0);
int r;
{
uint16x4_t v_sum_block = vdup_n_u16(0);
// Avoid denoising color signal if its close to average level.
for (r = 0; r < 8; ++r) {
const uint8x8_t v_sig = vld1_u8(sig);
const uint16x4_t _76_54_32_10 = vpaddl_u8(v_sig);
v_sum_block = vqadd_u16(v_sum_block, _76_54_32_10);
sig += sig_stride;
}
sig -= sig_stride * 8;
{
const uint32x2_t _7654_3210 = vpaddl_u16(v_sum_block);
const uint64x1_t _76543210 = vpaddl_u32(_7654_3210);
const int sum_block = vget_lane_s32(vreinterpret_s32_u64(_76543210), 0);
if (abs(sum_block - (128 * 8 * 8)) < SUM_DIFF_FROM_AVG_THRESH_UV) {
return COPY_BLOCK;
}
}
}
/* Go over lines. */
for (r = 0; r < 4; ++r) {
/* Load inputs. */
const uint8x8_t v_sig_lo = vld1_u8(sig);
const uint8x8_t v_sig_hi = vld1_u8(&sig[sig_stride]);
const uint8x16_t v_sig = vcombine_u8(v_sig_lo, v_sig_hi);
const uint8x8_t v_mc_running_avg_lo = vld1_u8(mc_running_avg);
const uint8x8_t v_mc_running_avg_hi =
vld1_u8(&mc_running_avg[mc_running_avg_stride]);
const uint8x16_t v_mc_running_avg =
vcombine_u8(v_mc_running_avg_lo, v_mc_running_avg_hi);
/* Calculate absolute difference and sign masks. */
const uint8x16_t v_abs_diff = vabdq_u8(v_sig, v_mc_running_avg);
const uint8x16_t v_diff_pos_mask = vcltq_u8(v_sig, v_mc_running_avg);
const uint8x16_t v_diff_neg_mask = vcgtq_u8(v_sig, v_mc_running_avg);
/* Figure out which level that put us in. */
const uint8x16_t v_level1_mask = vcleq_u8(v_level1_threshold, v_abs_diff);
const uint8x16_t v_level2_mask = vcleq_u8(v_level2_threshold, v_abs_diff);
const uint8x16_t v_level3_mask = vcleq_u8(v_level3_threshold, v_abs_diff);
/* Calculate absolute adjustments for level 1, 2 and 3. */
const uint8x16_t v_level2_adjustment =
vandq_u8(v_level2_mask, v_delta_level_1_and_2);
const uint8x16_t v_level3_adjustment =
vandq_u8(v_level3_mask, v_delta_level_2_and_3);
const uint8x16_t v_level1and2_adjustment =
vaddq_u8(v_level1_adjustment, v_level2_adjustment);
const uint8x16_t v_level1and2and3_adjustment =
vaddq_u8(v_level1and2_adjustment, v_level3_adjustment);
/* Figure adjustment absolute value by selecting between the absolute
* difference if in level0 or the value for level 1, 2 and 3.
*/
const uint8x16_t v_abs_adjustment =
vbslq_u8(v_level1_mask, v_level1and2and3_adjustment, v_abs_diff);
/* Calculate positive and negative adjustments. Apply them to the signal
* and accumulate them. Adjustments are less than eight and the maximum
* sum of them (7 * 16) can fit in a signed char.
*/
const uint8x16_t v_pos_adjustment =
vandq_u8(v_diff_pos_mask, v_abs_adjustment);
const uint8x16_t v_neg_adjustment =
vandq_u8(v_diff_neg_mask, v_abs_adjustment);
uint8x16_t v_running_avg = vqaddq_u8(v_sig, v_pos_adjustment);
v_running_avg = vqsubq_u8(v_running_avg, v_neg_adjustment);
/* Store results. */
vst1_u8(running_avg, vget_low_u8(v_running_avg));
vst1_u8(&running_avg[running_avg_stride], vget_high_u8(v_running_avg));
/* Sum all the accumulators to have the sum of all pixel differences
* for this macroblock.
*/
{
const int8x16_t v_sum_diff =
vqsubq_s8(vreinterpretq_s8_u8(v_pos_adjustment),
vreinterpretq_s8_u8(v_neg_adjustment));
const int16x8_t fe_dc_ba_98_76_54_32_10 = vpaddlq_s8(v_sum_diff);
const int32x4_t fedc_ba98_7654_3210 =
vpaddlq_s16(fe_dc_ba_98_76_54_32_10);
const int64x2_t fedcba98_76543210 = vpaddlq_s32(fedc_ba98_7654_3210);
v_sum_diff_total = vqaddq_s64(v_sum_diff_total, fedcba98_76543210);
}
/* Update pointers for next iteration. */
sig += sig_stride * 2;
mc_running_avg += mc_running_avg_stride * 2;
running_avg += running_avg_stride * 2;
}
/* Too much adjustments => copy block. */
{
int64x1_t x = vqadd_s64(vget_high_s64(v_sum_diff_total),
vget_low_s64(v_sum_diff_total));
int sum_diff = vget_lane_s32(vabs_s32(vreinterpret_s32_s64(x)), 0);
int sum_diff_thresh = SUM_DIFF_THRESHOLD_UV;
if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH_UV;
if (sum_diff > sum_diff_thresh) {
// Before returning to copy the block (i.e., apply no denoising),
// checK if we can still apply some (weaker) temporal filtering to
// this block, that would otherwise not be denoised at all. Simplest
// is to apply an additional adjustment to running_avg_y to bring it
// closer to sig. The adjustment is capped by a maximum delta, and
// chosen such that in most cases the resulting sum_diff will be
// within the accceptable range given by sum_diff_thresh.
// The delta is set by the excess of absolute pixel diff over the
// threshold.
int delta = ((sum_diff - sum_diff_thresh) >> 8) + 1;
// Only apply the adjustment for max delta up to 3.
if (delta < 4) {
const uint8x16_t k_delta = vmovq_n_u8(delta);
sig -= sig_stride * 8;
mc_running_avg -= mc_running_avg_stride * 8;
running_avg -= running_avg_stride * 8;
for (r = 0; r < 4; ++r) {
const uint8x8_t v_sig_lo = vld1_u8(sig);
const uint8x8_t v_sig_hi = vld1_u8(&sig[sig_stride]);
const uint8x16_t v_sig = vcombine_u8(v_sig_lo, v_sig_hi);
const uint8x8_t v_mc_running_avg_lo = vld1_u8(mc_running_avg);
const uint8x8_t v_mc_running_avg_hi =
vld1_u8(&mc_running_avg[mc_running_avg_stride]);
const uint8x16_t v_mc_running_avg =
vcombine_u8(v_mc_running_avg_lo, v_mc_running_avg_hi);
/* Calculate absolute difference and sign masks. */
const uint8x16_t v_abs_diff = vabdq_u8(v_sig, v_mc_running_avg);
const uint8x16_t v_diff_pos_mask = vcltq_u8(v_sig, v_mc_running_avg);
const uint8x16_t v_diff_neg_mask = vcgtq_u8(v_sig, v_mc_running_avg);
// Clamp absolute difference to delta to get the adjustment.
const uint8x16_t v_abs_adjustment = vminq_u8(v_abs_diff, (k_delta));
const uint8x16_t v_pos_adjustment =
vandq_u8(v_diff_pos_mask, v_abs_adjustment);
const uint8x16_t v_neg_adjustment =
vandq_u8(v_diff_neg_mask, v_abs_adjustment);
const uint8x8_t v_running_avg_lo = vld1_u8(running_avg);
const uint8x8_t v_running_avg_hi =
vld1_u8(&running_avg[running_avg_stride]);
uint8x16_t v_running_avg =
vcombine_u8(v_running_avg_lo, v_running_avg_hi);
v_running_avg = vqsubq_u8(v_running_avg, v_pos_adjustment);
v_running_avg = vqaddq_u8(v_running_avg, v_neg_adjustment);
/* Store results. */
vst1_u8(running_avg, vget_low_u8(v_running_avg));
vst1_u8(&running_avg[running_avg_stride],
vget_high_u8(v_running_avg));
{
const int8x16_t v_sum_diff =
vqsubq_s8(vreinterpretq_s8_u8(v_neg_adjustment),
vreinterpretq_s8_u8(v_pos_adjustment));
const int16x8_t fe_dc_ba_98_76_54_32_10 = vpaddlq_s8(v_sum_diff);
const int32x4_t fedc_ba98_7654_3210 =
vpaddlq_s16(fe_dc_ba_98_76_54_32_10);
const int64x2_t fedcba98_76543210 =
vpaddlq_s32(fedc_ba98_7654_3210);
v_sum_diff_total = vqaddq_s64(v_sum_diff_total, fedcba98_76543210);
}
/* Update pointers for next iteration. */
sig += sig_stride * 2;
mc_running_avg += mc_running_avg_stride * 2;
running_avg += running_avg_stride * 2;
}
{
// Update the sum of all pixel differences of this MB.
x = vqadd_s64(vget_high_s64(v_sum_diff_total),
vget_low_s64(v_sum_diff_total));
sum_diff = vget_lane_s32(vabs_s32(vreinterpret_s32_s64(x)), 0);
if (sum_diff > sum_diff_thresh) {
return COPY_BLOCK;
}
}
} else {
return COPY_BLOCK;
}
}
}
/* Tell above level that block was filtered. */
running_avg -= running_avg_stride * 8;
sig -= sig_stride * 8;
vp8_copy_mem8x8(running_avg, running_avg_stride, sig, sig_stride);
return FILTER_BLOCK;
}
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <arm_neon.h>
#include "./vp8_rtcd.h"
#include "vp8/encoder/block.h"
static const uint16_t inv_zig_zag[16] = { 1, 2, 6, 7, 3, 5, 8, 13,
4, 9, 12, 14, 10, 11, 15, 16 };
void vp8_fast_quantize_b_neon(BLOCK *b, BLOCKD *d) {
const int16x8_t one_q = vdupq_n_s16(-1), z0 = vld1q_s16(b->coeff),
z1 = vld1q_s16(b->coeff + 8), round0 = vld1q_s16(b->round),
round1 = vld1q_s16(b->round + 8),
quant0 = vld1q_s16(b->quant_fast),
quant1 = vld1q_s16(b->quant_fast + 8),
dequant0 = vld1q_s16(d->dequant),
dequant1 = vld1q_s16(d->dequant + 8);
const uint16x8_t zig_zag0 = vld1q_u16(inv_zig_zag),
zig_zag1 = vld1q_u16(inv_zig_zag + 8);
int16x8_t x0, x1, sz0, sz1, y0, y1;
uint16x8_t eob0, eob1;
#ifndef __aarch64__
uint16x4_t eob_d16;
uint32x2_t eob_d32;
uint32x4_t eob_q32;
#endif // __arch64__
/* sign of z: z >> 15 */
sz0 = vshrq_n_s16(z0, 15);
sz1 = vshrq_n_s16(z1, 15);
/* x = abs(z) */
x0 = vabsq_s16(z0);
x1 = vabsq_s16(z1);
/* x += round */
x0 = vaddq_s16(x0, round0);
x1 = vaddq_s16(x1, round1);
/* y = 2 * (x * quant) >> 16 */
y0 = vqdmulhq_s16(x0, quant0);
y1 = vqdmulhq_s16(x1, quant1);
/* Compensate for doubling in vqdmulhq */
y0 = vshrq_n_s16(y0, 1);
y1 = vshrq_n_s16(y1, 1);
/* Restore sign bit */
y0 = veorq_s16(y0, sz0);
y1 = veorq_s16(y1, sz1);
x0 = vsubq_s16(y0, sz0);
x1 = vsubq_s16(y1, sz1);
/* find non-zero elements */
eob0 = vtstq_s16(x0, one_q);
eob1 = vtstq_s16(x1, one_q);
/* mask zig zag */
eob0 = vandq_u16(eob0, zig_zag0);
eob1 = vandq_u16(eob1, zig_zag1);
/* select the largest value */
eob0 = vmaxq_u16(eob0, eob1);
#ifdef __aarch64__
*d->eob = (int8_t)vmaxvq_u16(eob0);
#else
eob_d16 = vmax_u16(vget_low_u16(eob0), vget_high_u16(eob0));
eob_q32 = vmovl_u16(eob_d16);
eob_d32 = vmax_u32(vget_low_u32(eob_q32), vget_high_u32(eob_q32));
eob_d32 = vpmax_u32(eob_d32, eob_d32);
vst1_lane_s8((int8_t *)d->eob, vreinterpret_s8_u32(eob_d32), 0);
#endif // __aarch64__
/* qcoeff = x */
vst1q_s16(d->qcoeff, x0);
vst1q_s16(d->qcoeff + 8, x1);
/* dqcoeff = x * dequant */
vst1q_s16(d->dqcoeff, vmulq_s16(dequant0, x0));
vst1q_s16(d->dqcoeff + 8, vmulq_s16(dequant1, x1));
}
@@ -0,0 +1,261 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <arm_neon.h>
#include "./vp8_rtcd.h"
void vp8_short_fdct4x4_neon(int16_t *input, int16_t *output, int pitch) {
int16x4_t d0s16, d1s16, d2s16, d3s16, d4s16, d5s16, d6s16, d7s16;
int16x4_t d16s16, d17s16, d26s16, dEmptys16;
uint16x4_t d4u16;
int16x8_t q0s16, q1s16;
int32x4_t q9s32, q10s32, q11s32, q12s32;
int16x4x2_t v2tmp0, v2tmp1;
int32x2x2_t v2tmp2, v2tmp3;
d16s16 = vdup_n_s16(5352);
d17s16 = vdup_n_s16(2217);
q9s32 = vdupq_n_s32(14500);
q10s32 = vdupq_n_s32(7500);
q11s32 = vdupq_n_s32(12000);
q12s32 = vdupq_n_s32(51000);
// Part one
pitch >>= 1;
d0s16 = vld1_s16(input);
input += pitch;
d1s16 = vld1_s16(input);
input += pitch;
d2s16 = vld1_s16(input);
input += pitch;
d3s16 = vld1_s16(input);
v2tmp2 = vtrn_s32(vreinterpret_s32_s16(d0s16), vreinterpret_s32_s16(d2s16));
v2tmp3 = vtrn_s32(vreinterpret_s32_s16(d1s16), vreinterpret_s32_s16(d3s16));
v2tmp0 = vtrn_s16(vreinterpret_s16_s32(v2tmp2.val[0]), // d0
vreinterpret_s16_s32(v2tmp3.val[0])); // d1
v2tmp1 = vtrn_s16(vreinterpret_s16_s32(v2tmp2.val[1]), // d2
vreinterpret_s16_s32(v2tmp3.val[1])); // d3
d4s16 = vadd_s16(v2tmp0.val[0], v2tmp1.val[1]);
d5s16 = vadd_s16(v2tmp0.val[1], v2tmp1.val[0]);
d6s16 = vsub_s16(v2tmp0.val[1], v2tmp1.val[0]);
d7s16 = vsub_s16(v2tmp0.val[0], v2tmp1.val[1]);
d4s16 = vshl_n_s16(d4s16, 3);
d5s16 = vshl_n_s16(d5s16, 3);
d6s16 = vshl_n_s16(d6s16, 3);
d7s16 = vshl_n_s16(d7s16, 3);
d0s16 = vadd_s16(d4s16, d5s16);
d2s16 = vsub_s16(d4s16, d5s16);
q9s32 = vmlal_s16(q9s32, d7s16, d16s16);
q10s32 = vmlal_s16(q10s32, d7s16, d17s16);
q9s32 = vmlal_s16(q9s32, d6s16, d17s16);
q10s32 = vmlsl_s16(q10s32, d6s16, d16s16);
d1s16 = vshrn_n_s32(q9s32, 12);
d3s16 = vshrn_n_s32(q10s32, 12);
// Part two
v2tmp2 = vtrn_s32(vreinterpret_s32_s16(d0s16), vreinterpret_s32_s16(d2s16));
v2tmp3 = vtrn_s32(vreinterpret_s32_s16(d1s16), vreinterpret_s32_s16(d3s16));
v2tmp0 = vtrn_s16(vreinterpret_s16_s32(v2tmp2.val[0]), // d0
vreinterpret_s16_s32(v2tmp3.val[0])); // d1
v2tmp1 = vtrn_s16(vreinterpret_s16_s32(v2tmp2.val[1]), // d2
vreinterpret_s16_s32(v2tmp3.val[1])); // d3
d4s16 = vadd_s16(v2tmp0.val[0], v2tmp1.val[1]);
d5s16 = vadd_s16(v2tmp0.val[1], v2tmp1.val[0]);
d6s16 = vsub_s16(v2tmp0.val[1], v2tmp1.val[0]);
d7s16 = vsub_s16(v2tmp0.val[0], v2tmp1.val[1]);
d26s16 = vdup_n_s16(7);
d4s16 = vadd_s16(d4s16, d26s16);
d0s16 = vadd_s16(d4s16, d5s16);
d2s16 = vsub_s16(d4s16, d5s16);
q11s32 = vmlal_s16(q11s32, d7s16, d16s16);
q12s32 = vmlal_s16(q12s32, d7s16, d17s16);
dEmptys16 = vdup_n_s16(0);
d4u16 = vceq_s16(d7s16, dEmptys16);
d0s16 = vshr_n_s16(d0s16, 4);
d2s16 = vshr_n_s16(d2s16, 4);
q11s32 = vmlal_s16(q11s32, d6s16, d17s16);
q12s32 = vmlsl_s16(q12s32, d6s16, d16s16);
d4u16 = vmvn_u16(d4u16);
d1s16 = vshrn_n_s32(q11s32, 16);
d1s16 = vsub_s16(d1s16, vreinterpret_s16_u16(d4u16));
d3s16 = vshrn_n_s32(q12s32, 16);
q0s16 = vcombine_s16(d0s16, d1s16);
q1s16 = vcombine_s16(d2s16, d3s16);
vst1q_s16(output, q0s16);
vst1q_s16(output + 8, q1s16);
return;
}
void vp8_short_fdct8x4_neon(int16_t *input, int16_t *output, int pitch) {
int16x4_t d0s16, d1s16, d2s16, d3s16, d4s16, d5s16, d6s16, d7s16;
int16x4_t d16s16, d17s16, d26s16, d27s16, d28s16, d29s16;
uint16x4_t d28u16, d29u16;
uint16x8_t q14u16;
int16x8_t q0s16, q1s16, q2s16, q3s16;
int16x8_t q11s16, q12s16, q13s16, q14s16, q15s16, qEmptys16;
int32x4_t q9s32, q10s32, q11s32, q12s32;
int16x8x2_t v2tmp0, v2tmp1;
int32x4x2_t v2tmp2, v2tmp3;
d16s16 = vdup_n_s16(5352);
d17s16 = vdup_n_s16(2217);
q9s32 = vdupq_n_s32(14500);
q10s32 = vdupq_n_s32(7500);
// Part one
pitch >>= 1;
q0s16 = vld1q_s16(input);
input += pitch;
q1s16 = vld1q_s16(input);
input += pitch;
q2s16 = vld1q_s16(input);
input += pitch;
q3s16 = vld1q_s16(input);
v2tmp2 =
vtrnq_s32(vreinterpretq_s32_s16(q0s16), vreinterpretq_s32_s16(q2s16));
v2tmp3 =
vtrnq_s32(vreinterpretq_s32_s16(q1s16), vreinterpretq_s32_s16(q3s16));
v2tmp0 = vtrnq_s16(vreinterpretq_s16_s32(v2tmp2.val[0]), // q0
vreinterpretq_s16_s32(v2tmp3.val[0])); // q1
v2tmp1 = vtrnq_s16(vreinterpretq_s16_s32(v2tmp2.val[1]), // q2
vreinterpretq_s16_s32(v2tmp3.val[1])); // q3
q11s16 = vaddq_s16(v2tmp0.val[0], v2tmp1.val[1]);
q12s16 = vaddq_s16(v2tmp0.val[1], v2tmp1.val[0]);
q13s16 = vsubq_s16(v2tmp0.val[1], v2tmp1.val[0]);
q14s16 = vsubq_s16(v2tmp0.val[0], v2tmp1.val[1]);
q11s16 = vshlq_n_s16(q11s16, 3);
q12s16 = vshlq_n_s16(q12s16, 3);
q13s16 = vshlq_n_s16(q13s16, 3);
q14s16 = vshlq_n_s16(q14s16, 3);
q0s16 = vaddq_s16(q11s16, q12s16);
q2s16 = vsubq_s16(q11s16, q12s16);
q11s32 = q9s32;
q12s32 = q10s32;
d26s16 = vget_low_s16(q13s16);
d27s16 = vget_high_s16(q13s16);
d28s16 = vget_low_s16(q14s16);
d29s16 = vget_high_s16(q14s16);
q9s32 = vmlal_s16(q9s32, d28s16, d16s16);
q10s32 = vmlal_s16(q10s32, d28s16, d17s16);
q11s32 = vmlal_s16(q11s32, d29s16, d16s16);
q12s32 = vmlal_s16(q12s32, d29s16, d17s16);
q9s32 = vmlal_s16(q9s32, d26s16, d17s16);
q10s32 = vmlsl_s16(q10s32, d26s16, d16s16);
q11s32 = vmlal_s16(q11s32, d27s16, d17s16);
q12s32 = vmlsl_s16(q12s32, d27s16, d16s16);
d2s16 = vshrn_n_s32(q9s32, 12);
d6s16 = vshrn_n_s32(q10s32, 12);
d3s16 = vshrn_n_s32(q11s32, 12);
d7s16 = vshrn_n_s32(q12s32, 12);
q1s16 = vcombine_s16(d2s16, d3s16);
q3s16 = vcombine_s16(d6s16, d7s16);
// Part two
q9s32 = vdupq_n_s32(12000);
q10s32 = vdupq_n_s32(51000);
v2tmp2 =
vtrnq_s32(vreinterpretq_s32_s16(q0s16), vreinterpretq_s32_s16(q2s16));
v2tmp3 =
vtrnq_s32(vreinterpretq_s32_s16(q1s16), vreinterpretq_s32_s16(q3s16));
v2tmp0 = vtrnq_s16(vreinterpretq_s16_s32(v2tmp2.val[0]), // q0
vreinterpretq_s16_s32(v2tmp3.val[0])); // q1
v2tmp1 = vtrnq_s16(vreinterpretq_s16_s32(v2tmp2.val[1]), // q2
vreinterpretq_s16_s32(v2tmp3.val[1])); // q3
q11s16 = vaddq_s16(v2tmp0.val[0], v2tmp1.val[1]);
q12s16 = vaddq_s16(v2tmp0.val[1], v2tmp1.val[0]);
q13s16 = vsubq_s16(v2tmp0.val[1], v2tmp1.val[0]);
q14s16 = vsubq_s16(v2tmp0.val[0], v2tmp1.val[1]);
q15s16 = vdupq_n_s16(7);
q11s16 = vaddq_s16(q11s16, q15s16);
q0s16 = vaddq_s16(q11s16, q12s16);
q1s16 = vsubq_s16(q11s16, q12s16);
q11s32 = q9s32;
q12s32 = q10s32;
d0s16 = vget_low_s16(q0s16);
d1s16 = vget_high_s16(q0s16);
d2s16 = vget_low_s16(q1s16);
d3s16 = vget_high_s16(q1s16);
d0s16 = vshr_n_s16(d0s16, 4);
d4s16 = vshr_n_s16(d1s16, 4);
d2s16 = vshr_n_s16(d2s16, 4);
d6s16 = vshr_n_s16(d3s16, 4);
d26s16 = vget_low_s16(q13s16);
d27s16 = vget_high_s16(q13s16);
d28s16 = vget_low_s16(q14s16);
d29s16 = vget_high_s16(q14s16);
q9s32 = vmlal_s16(q9s32, d28s16, d16s16);
q10s32 = vmlal_s16(q10s32, d28s16, d17s16);
q11s32 = vmlal_s16(q11s32, d29s16, d16s16);
q12s32 = vmlal_s16(q12s32, d29s16, d17s16);
q9s32 = vmlal_s16(q9s32, d26s16, d17s16);
q10s32 = vmlsl_s16(q10s32, d26s16, d16s16);
q11s32 = vmlal_s16(q11s32, d27s16, d17s16);
q12s32 = vmlsl_s16(q12s32, d27s16, d16s16);
d1s16 = vshrn_n_s32(q9s32, 16);
d3s16 = vshrn_n_s32(q10s32, 16);
d5s16 = vshrn_n_s32(q11s32, 16);
d7s16 = vshrn_n_s32(q12s32, 16);
qEmptys16 = vdupq_n_s16(0);
q14u16 = vceqq_s16(q14s16, qEmptys16);
q14u16 = vmvnq_u16(q14u16);
d28u16 = vget_low_u16(q14u16);
d29u16 = vget_high_u16(q14u16);
d1s16 = vsub_s16(d1s16, vreinterpret_s16_u16(d28u16));
d5s16 = vsub_s16(d5s16, vreinterpret_s16_u16(d29u16));
q0s16 = vcombine_s16(d0s16, d1s16);
q1s16 = vcombine_s16(d2s16, d3s16);
q2s16 = vcombine_s16(d4s16, d5s16);
q3s16 = vcombine_s16(d6s16, d7s16);
vst1q_s16(output, q0s16);
vst1q_s16(output + 8, q1s16);
vst1q_s16(output + 16, q2s16);
vst1q_s16(output + 24, q3s16);
return;
}
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2014 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <arm_neon.h>
#include "./vp8_rtcd.h"
#include "vpx_ports/arm.h"
#ifdef VPX_INCOMPATIBLE_GCC
#include "./vp8_rtcd.h"
void vp8_short_walsh4x4_neon(int16_t *input, int16_t *output, int pitch) {
vp8_short_walsh4x4_c(input, output, pitch);
}
#else
void vp8_short_walsh4x4_neon(int16_t *input, int16_t *output, int pitch) {
uint16x4_t d16u16;
int16x8_t q0s16, q1s16;
int16x4_t dEmptys16, d0s16, d1s16, d2s16, d3s16, d4s16, d5s16, d6s16, d7s16;
int32x4_t qEmptys32, q0s32, q1s32, q2s32, q3s32, q8s32;
int32x4_t q9s32, q10s32, q11s32, q15s32;
uint32x4_t q8u32, q9u32, q10u32, q11u32;
int16x4x2_t v2tmp0, v2tmp1;
int32x2x2_t v2tmp2, v2tmp3;
dEmptys16 = vdup_n_s16(0);
qEmptys32 = vdupq_n_s32(0);
q15s32 = vdupq_n_s32(3);
d0s16 = vld1_s16(input);
input += pitch / 2;
d1s16 = vld1_s16(input);
input += pitch / 2;
d2s16 = vld1_s16(input);
input += pitch / 2;
d3s16 = vld1_s16(input);
v2tmp2 = vtrn_s32(vreinterpret_s32_s16(d0s16), vreinterpret_s32_s16(d2s16));
v2tmp3 = vtrn_s32(vreinterpret_s32_s16(d1s16), vreinterpret_s32_s16(d3s16));
v2tmp0 = vtrn_s16(vreinterpret_s16_s32(v2tmp2.val[0]), // d0
vreinterpret_s16_s32(v2tmp3.val[0])); // d1
v2tmp1 = vtrn_s16(vreinterpret_s16_s32(v2tmp2.val[1]), // d2
vreinterpret_s16_s32(v2tmp3.val[1])); // d3
d4s16 = vadd_s16(v2tmp0.val[0], v2tmp1.val[0]);
d5s16 = vadd_s16(v2tmp0.val[1], v2tmp1.val[1]);
d6s16 = vsub_s16(v2tmp0.val[1], v2tmp1.val[1]);
d7s16 = vsub_s16(v2tmp0.val[0], v2tmp1.val[0]);
d4s16 = vshl_n_s16(d4s16, 2);
d5s16 = vshl_n_s16(d5s16, 2);
d6s16 = vshl_n_s16(d6s16, 2);
d7s16 = vshl_n_s16(d7s16, 2);
d16u16 = vceq_s16(d4s16, dEmptys16);
d16u16 = vmvn_u16(d16u16);
d0s16 = vadd_s16(d4s16, d5s16);
d3s16 = vsub_s16(d4s16, d5s16);
d1s16 = vadd_s16(d7s16, d6s16);
d2s16 = vsub_s16(d7s16, d6s16);
d0s16 = vsub_s16(d0s16, vreinterpret_s16_u16(d16u16));
// Second for-loop
v2tmp2 = vtrn_s32(vreinterpret_s32_s16(d1s16), vreinterpret_s32_s16(d3s16));
v2tmp3 = vtrn_s32(vreinterpret_s32_s16(d0s16), vreinterpret_s32_s16(d2s16));
v2tmp0 = vtrn_s16(vreinterpret_s16_s32(v2tmp3.val[1]), // d2
vreinterpret_s16_s32(v2tmp2.val[1])); // d3
v2tmp1 = vtrn_s16(vreinterpret_s16_s32(v2tmp3.val[0]), // d0
vreinterpret_s16_s32(v2tmp2.val[0])); // d1
q8s32 = vaddl_s16(v2tmp1.val[0], v2tmp0.val[0]);
q9s32 = vaddl_s16(v2tmp1.val[1], v2tmp0.val[1]);
q10s32 = vsubl_s16(v2tmp1.val[1], v2tmp0.val[1]);
q11s32 = vsubl_s16(v2tmp1.val[0], v2tmp0.val[0]);
q0s32 = vaddq_s32(q8s32, q9s32);
q1s32 = vaddq_s32(q11s32, q10s32);
q2s32 = vsubq_s32(q11s32, q10s32);
q3s32 = vsubq_s32(q8s32, q9s32);
q8u32 = vcltq_s32(q0s32, qEmptys32);
q9u32 = vcltq_s32(q1s32, qEmptys32);
q10u32 = vcltq_s32(q2s32, qEmptys32);
q11u32 = vcltq_s32(q3s32, qEmptys32);
q8s32 = vreinterpretq_s32_u32(q8u32);
q9s32 = vreinterpretq_s32_u32(q9u32);
q10s32 = vreinterpretq_s32_u32(q10u32);
q11s32 = vreinterpretq_s32_u32(q11u32);
q0s32 = vsubq_s32(q0s32, q8s32);
q1s32 = vsubq_s32(q1s32, q9s32);
q2s32 = vsubq_s32(q2s32, q10s32);
q3s32 = vsubq_s32(q3s32, q11s32);
q8s32 = vaddq_s32(q0s32, q15s32);
q9s32 = vaddq_s32(q1s32, q15s32);
q10s32 = vaddq_s32(q2s32, q15s32);
q11s32 = vaddq_s32(q3s32, q15s32);
d0s16 = vshrn_n_s32(q8s32, 3);
d1s16 = vshrn_n_s32(q9s32, 3);
d2s16 = vshrn_n_s32(q10s32, 3);
d3s16 = vshrn_n_s32(q11s32, 3);
q0s16 = vcombine_s16(d0s16, d1s16);
q1s16 = vcombine_s16(d2s16, d3s16);
vst1q_s16(output, q0s16);
vst1q_s16(output + 8, q1s16);
return;
}
#endif // VPX_INCOMPATIBLE_GCC
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_BITSTREAM_H_
#define VPX_VP8_ENCODER_BITSTREAM_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "vp8/encoder/treewriter.h"
#include "vp8/encoder/tokenize.h"
void vp8_pack_tokens(vp8_writer *w, const TOKENEXTRA *p, int xcount);
void vp8_convert_rfct_to_prob(struct VP8_COMP *const cpi);
void vp8_calc_ref_frame_costs(int *ref_frame_cost, int prob_intra,
int prob_last, int prob_garf);
int vp8_estimate_entropy_savings(struct VP8_COMP *cpi);
void vp8_update_coef_probs(struct VP8_COMP *cpi);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_BITSTREAM_H_
@@ -0,0 +1,168 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_BLOCK_H_
#define VPX_VP8_ENCODER_BLOCK_H_
#include "vp8/common/onyx.h"
#include "vp8/common/blockd.h"
#include "vp8/common/entropymv.h"
#include "vp8/common/entropy.h"
#include "vpx_ports/mem.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_MODES 20
#define MAX_ERROR_BINS 1024
/* motion search site */
typedef struct {
MV mv;
int offset;
} search_site;
typedef struct block {
/* 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries */
short *src_diff;
short *coeff;
/* 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries */
short *quant;
short *quant_fast;
short *quant_shift;
short *zbin;
short *zrun_zbin_boost;
short *round;
/* Zbin Over Quant value */
short zbin_extra;
unsigned char **base_src;
int src;
int src_stride;
} BLOCK;
typedef struct {
int count;
struct {
B_PREDICTION_MODE mode;
int_mv mv;
} bmi[16];
} PARTITION_INFO;
typedef struct macroblock {
DECLARE_ALIGNED(16, short, src_diff[400]); /* 25 blocks Y,U,V,Y2 */
DECLARE_ALIGNED(16, short, coeff[400]); /* 25 blocks Y,U,V,Y2 */
DECLARE_ALIGNED(16, unsigned char, thismb[256]);
unsigned char *thismb_ptr;
/* 16 Y, 4 U, 4 V, 1 DC 2nd order block */
BLOCK block[25];
YV12_BUFFER_CONFIG src;
MACROBLOCKD e_mbd;
PARTITION_INFO *partition_info; /* work pointer */
PARTITION_INFO *pi; /* Corresponds to upper left visible macroblock */
PARTITION_INFO *pip; /* Base of allocated array */
int ref_frame_cost[MAX_REF_FRAMES];
search_site *ss;
int ss_count;
int searches_per_step;
int errorperbit;
int sadperbit16;
int sadperbit4;
int rddiv;
int rdmult;
unsigned int *mb_activity_ptr;
int *mb_norm_activity_ptr;
signed int act_zbin_adj;
signed int last_act_zbin_adj;
int *mvcost[2];
int *mvsadcost[2];
int (*mbmode_cost)[MB_MODE_COUNT];
int (*intra_uv_mode_cost)[MB_MODE_COUNT];
int (*bmode_costs)[10][10];
int *inter_bmode_costs;
int (*token_costs)[COEF_BANDS][PREV_COEF_CONTEXTS][MAX_ENTROPY_TOKENS];
/* These define limits to motion vector components to prevent
* them from extending outside the UMV borders.
*/
int mv_col_min;
int mv_col_max;
int mv_row_min;
int mv_row_max;
int skip;
unsigned int encode_breakout;
signed char *gf_active_ptr;
unsigned char *active_ptr;
MV_CONTEXT *mvc;
int optimize;
int q_index;
int is_skin;
int denoise_zeromv;
#if CONFIG_TEMPORAL_DENOISING
int increase_denoising;
MB_PREDICTION_MODE best_sse_inter_mode;
int_mv best_sse_mv;
MV_REFERENCE_FRAME best_reference_frame;
MV_REFERENCE_FRAME best_zeromv_reference_frame;
unsigned char need_to_clamp_best_mvs;
#endif
int skip_true_count;
unsigned int coef_counts[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS]
[MAX_ENTROPY_TOKENS];
unsigned int MVcount[2][MVvals]; /* (row,col) MV cts this frame */
int ymode_count[VP8_YMODES]; /* intra MB type cts this frame */
int uv_mode_count[VP8_UV_MODES]; /* intra MB type cts this frame */
int64_t prediction_error;
int64_t intra_error;
int count_mb_ref_frame_usage[MAX_REF_FRAMES];
int rd_thresh_mult[MAX_MODES];
int rd_threshes[MAX_MODES];
unsigned int mbs_tested_so_far;
unsigned int mode_test_hit_counts[MAX_MODES];
int zbin_mode_boost_enabled;
int zbin_mode_boost;
int last_zbin_mode_boost;
int last_zbin_over_quant;
int zbin_over_quant;
int error_bins[MAX_ERROR_BINS];
void (*short_fdct4x4)(short *input, short *output, int pitch);
void (*short_fdct8x4)(short *input, short *output, int pitch);
void (*short_walsh4x4)(short *input, short *output, int pitch);
void (*quantize_b)(BLOCK *b, BLOCKD *d);
unsigned int mbs_zero_last_dot_suppress;
int zero_last_dot_suppress;
} MACROBLOCK;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_BLOCK_H_
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "boolhuff.h"
#if defined(SECTIONBITS_OUTPUT)
unsigned __int64 Sectionbits[500];
#endif
const unsigned int vp8_prob_cost[256] = {
2047, 2047, 1791, 1641, 1535, 1452, 1385, 1328, 1279, 1235, 1196, 1161, 1129,
1099, 1072, 1046, 1023, 1000, 979, 959, 940, 922, 905, 889, 873, 858,
843, 829, 816, 803, 790, 778, 767, 755, 744, 733, 723, 713, 703,
693, 684, 675, 666, 657, 649, 641, 633, 625, 617, 609, 602, 594,
587, 580, 573, 567, 560, 553, 547, 541, 534, 528, 522, 516, 511,
505, 499, 494, 488, 483, 477, 472, 467, 462, 457, 452, 447, 442,
437, 433, 428, 424, 419, 415, 410, 406, 401, 397, 393, 389, 385,
381, 377, 373, 369, 365, 361, 357, 353, 349, 346, 342, 338, 335,
331, 328, 324, 321, 317, 314, 311, 307, 304, 301, 297, 294, 291,
288, 285, 281, 278, 275, 272, 269, 266, 263, 260, 257, 255, 252,
249, 246, 243, 240, 238, 235, 232, 229, 227, 224, 221, 219, 216,
214, 211, 208, 206, 203, 201, 198, 196, 194, 191, 189, 186, 184,
181, 179, 177, 174, 172, 170, 168, 165, 163, 161, 159, 156, 154,
152, 150, 148, 145, 143, 141, 139, 137, 135, 133, 131, 129, 127,
125, 123, 121, 119, 117, 115, 113, 111, 109, 107, 105, 103, 101,
99, 97, 95, 93, 92, 90, 88, 86, 84, 82, 81, 79, 77,
75, 73, 72, 70, 68, 66, 65, 63, 61, 60, 58, 56, 55,
53, 51, 50, 48, 46, 45, 43, 41, 40, 38, 37, 35, 33,
32, 30, 29, 27, 25, 24, 22, 21, 19, 18, 16, 15, 13,
12, 10, 9, 7, 6, 4, 3, 1, 1
};
void vp8_start_encode(BOOL_CODER *bc, unsigned char *source,
unsigned char *source_end) {
bc->lowvalue = 0;
bc->range = 255;
bc->count = -24;
bc->buffer = source;
bc->buffer_end = source_end;
bc->pos = 0;
}
void vp8_stop_encode(BOOL_CODER *bc) {
int i;
for (i = 0; i < 32; ++i) vp8_encode_bool(bc, 0, 128);
}
void vp8_encode_value(BOOL_CODER *bc, int data, int bits) {
int bit;
for (bit = bits - 1; bit >= 0; bit--) {
vp8_encode_bool(bc, (1 & (data >> bit)), 0x80);
}
}
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/****************************************************************************
*
* Module Title : boolhuff.h
*
* Description : Bool Coder header file.
*
****************************************************************************/
#ifndef VPX_VP8_ENCODER_BOOLHUFF_H_
#define VPX_VP8_ENCODER_BOOLHUFF_H_
#include "vpx_ports/mem.h"
#include "vpx/internal/vpx_codec_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned int lowvalue;
unsigned int range;
int count;
unsigned int pos;
unsigned char *buffer;
unsigned char *buffer_end;
struct vpx_internal_error_info *error;
} BOOL_CODER;
void vp8_start_encode(BOOL_CODER *bc, unsigned char *source,
unsigned char *source_end);
void vp8_encode_value(BOOL_CODER *bc, int data, int bits);
void vp8_stop_encode(BOOL_CODER *bc);
extern const unsigned int vp8_prob_cost[256];
DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
static int validate_buffer(const unsigned char *start, size_t len,
const unsigned char *end,
struct vpx_internal_error_info *error) {
if (start + len > start && start + len < end) {
return 1;
} else {
vpx_internal_error(error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition ");
}
return 0;
}
static void vp8_encode_bool(BOOL_CODER *bc, int bit, int probability) {
unsigned int split;
int count = bc->count;
unsigned int range = bc->range;
unsigned int lowvalue = bc->lowvalue;
int shift;
split = 1 + (((range - 1) * probability) >> 8);
range = split;
if (bit) {
lowvalue += split;
range = bc->range - split;
}
shift = vp8_norm[range];
range <<= shift;
count += shift;
if (count >= 0) {
int offset = shift - count;
if ((lowvalue << (offset - 1)) & 0x80000000) {
int x = bc->pos - 1;
while (x >= 0 && bc->buffer[x] == 0xff) {
bc->buffer[x] = (unsigned char)0;
x--;
}
bc->buffer[x] += 1;
}
validate_buffer(bc->buffer + bc->pos, 1, bc->buffer_end, bc->error);
bc->buffer[bc->pos++] = (lowvalue >> (24 - offset) & 0xff);
lowvalue <<= offset;
shift = count;
lowvalue &= 0xffffff;
count -= 8;
}
lowvalue <<= shift;
bc->count = count;
bc->lowvalue = lowvalue;
bc->range = range;
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_BOOLHUFF_H_
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string.h>
#include "./vp8_rtcd.h"
#include "vpx/vpx_integer.h"
/* Copy 2 macroblocks to a buffer */
void vp8_copy32xn_c(const unsigned char *src_ptr, int src_stride,
unsigned char *dst_ptr, int dst_stride, int height) {
int r;
for (r = 0; r < height; ++r) {
memcpy(dst_ptr, src_ptr, 32);
src_ptr += src_stride;
dst_ptr += dst_stride;
}
}
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "./vp8_rtcd.h"
void vp8_short_fdct4x4_c(short *input, short *output, int pitch) {
int i;
int a1, b1, c1, d1;
short *ip = input;
short *op = output;
for (i = 0; i < 4; ++i) {
a1 = ((ip[0] + ip[3]) * 8);
b1 = ((ip[1] + ip[2]) * 8);
c1 = ((ip[1] - ip[2]) * 8);
d1 = ((ip[0] - ip[3]) * 8);
op[0] = a1 + b1;
op[2] = a1 - b1;
op[1] = (c1 * 2217 + d1 * 5352 + 14500) >> 12;
op[3] = (d1 * 2217 - c1 * 5352 + 7500) >> 12;
ip += pitch / 2;
op += 4;
}
ip = output;
op = output;
for (i = 0; i < 4; ++i) {
a1 = ip[0] + ip[12];
b1 = ip[4] + ip[8];
c1 = ip[4] - ip[8];
d1 = ip[0] - ip[12];
op[0] = (a1 + b1 + 7) >> 4;
op[8] = (a1 - b1 + 7) >> 4;
op[4] = ((c1 * 2217 + d1 * 5352 + 12000) >> 16) + (d1 != 0);
op[12] = (d1 * 2217 - c1 * 5352 + 51000) >> 16;
ip++;
op++;
}
}
void vp8_short_fdct8x4_c(short *input, short *output, int pitch) {
vp8_short_fdct4x4_c(input, output, pitch);
vp8_short_fdct4x4_c(input + 4, output + 16, pitch);
}
void vp8_short_walsh4x4_c(short *input, short *output, int pitch) {
int i;
int a1, b1, c1, d1;
int a2, b2, c2, d2;
short *ip = input;
short *op = output;
for (i = 0; i < 4; ++i) {
a1 = ((ip[0] + ip[2]) * 4);
d1 = ((ip[1] + ip[3]) * 4);
c1 = ((ip[1] - ip[3]) * 4);
b1 = ((ip[0] - ip[2]) * 4);
op[0] = a1 + d1 + (a1 != 0);
op[1] = b1 + c1;
op[2] = b1 - c1;
op[3] = a1 - d1;
ip += pitch / 2;
op += 4;
}
ip = output;
op = output;
for (i = 0; i < 4; ++i) {
a1 = ip[0] + ip[8];
d1 = ip[4] + ip[12];
c1 = ip[4] - ip[12];
b1 = ip[0] - ip[8];
a2 = a1 + d1;
b2 = b1 + c1;
c2 = b1 - c1;
d2 = a1 - d1;
a2 += a2 < 0;
b2 += b2 < 0;
c2 += c2 < 0;
d2 += d2 < 0;
op[0] = (a2 + 3) >> 3;
op[4] = (b2 + 3) >> 3;
op[8] = (c2 + 3) >> 3;
op[12] = (d2 + 3) >> 3;
ip++;
op++;
}
}
@@ -0,0 +1,344 @@
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_DCT_VALUE_COST_H_
#define VPX_VP8_ENCODER_DCT_VALUE_COST_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Generated file, included by tokenize.c */
/* Values generated by fill_value_tokens() */
static const short dct_value_cost[2048 * 2] = {
8285, 8277, 8267, 8259, 8253, 8245, 8226, 8218, 8212, 8204, 8194, 8186, 8180,
8172, 8150, 8142, 8136, 8128, 8118, 8110, 8104, 8096, 8077, 8069, 8063, 8055,
8045, 8037, 8031, 8023, 7997, 7989, 7983, 7975, 7965, 7957, 7951, 7943, 7924,
7916, 7910, 7902, 7892, 7884, 7878, 7870, 7848, 7840, 7834, 7826, 7816, 7808,
7802, 7794, 7775, 7767, 7761, 7753, 7743, 7735, 7729, 7721, 7923, 7915, 7909,
7901, 7891, 7883, 7877, 7869, 7850, 7842, 7836, 7828, 7818, 7810, 7804, 7796,
7774, 7766, 7760, 7752, 7742, 7734, 7728, 7720, 7701, 7693, 7687, 7679, 7669,
7661, 7655, 7647, 7621, 7613, 7607, 7599, 7589, 7581, 7575, 7567, 7548, 7540,
7534, 7526, 7516, 7508, 7502, 7494, 7472, 7464, 7458, 7450, 7440, 7432, 7426,
7418, 7399, 7391, 7385, 7377, 7367, 7359, 7353, 7345, 7479, 7471, 7465, 7457,
7447, 7439, 7433, 7425, 7406, 7398, 7392, 7384, 7374, 7366, 7360, 7352, 7330,
7322, 7316, 7308, 7298, 7290, 7284, 7276, 7257, 7249, 7243, 7235, 7225, 7217,
7211, 7203, 7177, 7169, 7163, 7155, 7145, 7137, 7131, 7123, 7104, 7096, 7090,
7082, 7072, 7064, 7058, 7050, 7028, 7020, 7014, 7006, 6996, 6988, 6982, 6974,
6955, 6947, 6941, 6933, 6923, 6915, 6909, 6901, 7632, 7624, 7618, 7610, 7600,
7592, 7586, 7578, 7559, 7551, 7545, 7537, 7527, 7519, 7513, 7505, 7483, 7475,
7469, 7461, 7451, 7443, 7437, 7429, 7410, 7402, 7396, 7388, 7378, 7370, 7364,
7356, 7330, 7322, 7316, 7308, 7298, 7290, 7284, 7276, 7257, 7249, 7243, 7235,
7225, 7217, 7211, 7203, 7181, 7173, 7167, 7159, 7149, 7141, 7135, 7127, 7108,
7100, 7094, 7086, 7076, 7068, 7062, 7054, 7188, 7180, 7174, 7166, 7156, 7148,
7142, 7134, 7115, 7107, 7101, 7093, 7083, 7075, 7069, 7061, 7039, 7031, 7025,
7017, 7007, 6999, 6993, 6985, 6966, 6958, 6952, 6944, 6934, 6926, 6920, 6912,
6886, 6878, 6872, 6864, 6854, 6846, 6840, 6832, 6813, 6805, 6799, 6791, 6781,
6773, 6767, 6759, 6737, 6729, 6723, 6715, 6705, 6697, 6691, 6683, 6664, 6656,
6650, 6642, 6632, 6624, 6618, 6610, 6812, 6804, 6798, 6790, 6780, 6772, 6766,
6758, 6739, 6731, 6725, 6717, 6707, 6699, 6693, 6685, 6663, 6655, 6649, 6641,
6631, 6623, 6617, 6609, 6590, 6582, 6576, 6568, 6558, 6550, 6544, 6536, 6510,
6502, 6496, 6488, 6478, 6470, 6464, 6456, 6437, 6429, 6423, 6415, 6405, 6397,
6391, 6383, 6361, 6353, 6347, 6339, 6329, 6321, 6315, 6307, 6288, 6280, 6274,
6266, 6256, 6248, 6242, 6234, 6368, 6360, 6354, 6346, 6336, 6328, 6322, 6314,
6295, 6287, 6281, 6273, 6263, 6255, 6249, 6241, 6219, 6211, 6205, 6197, 6187,
6179, 6173, 6165, 6146, 6138, 6132, 6124, 6114, 6106, 6100, 6092, 6066, 6058,
6052, 6044, 6034, 6026, 6020, 6012, 5993, 5985, 5979, 5971, 5961, 5953, 5947,
5939, 5917, 5909, 5903, 5895, 5885, 5877, 5871, 5863, 5844, 5836, 5830, 5822,
5812, 5804, 5798, 5790, 6697, 6689, 6683, 6675, 6665, 6657, 6651, 6643, 6624,
6616, 6610, 6602, 6592, 6584, 6578, 6570, 6548, 6540, 6534, 6526, 6516, 6508,
6502, 6494, 6475, 6467, 6461, 6453, 6443, 6435, 6429, 6421, 6395, 6387, 6381,
6373, 6363, 6355, 6349, 6341, 6322, 6314, 6308, 6300, 6290, 6282, 6276, 6268,
6246, 6238, 6232, 6224, 6214, 6206, 6200, 6192, 6173, 6165, 6159, 6151, 6141,
6133, 6127, 6119, 6253, 6245, 6239, 6231, 6221, 6213, 6207, 6199, 6180, 6172,
6166, 6158, 6148, 6140, 6134, 6126, 6104, 6096, 6090, 6082, 6072, 6064, 6058,
6050, 6031, 6023, 6017, 6009, 5999, 5991, 5985, 5977, 5951, 5943, 5937, 5929,
5919, 5911, 5905, 5897, 5878, 5870, 5864, 5856, 5846, 5838, 5832, 5824, 5802,
5794, 5788, 5780, 5770, 5762, 5756, 5748, 5729, 5721, 5715, 5707, 5697, 5689,
5683, 5675, 5877, 5869, 5863, 5855, 5845, 5837, 5831, 5823, 5804, 5796, 5790,
5782, 5772, 5764, 5758, 5750, 5728, 5720, 5714, 5706, 5696, 5688, 5682, 5674,
5655, 5647, 5641, 5633, 5623, 5615, 5609, 5601, 5575, 5567, 5561, 5553, 5543,
5535, 5529, 5521, 5502, 5494, 5488, 5480, 5470, 5462, 5456, 5448, 5426, 5418,
5412, 5404, 5394, 5386, 5380, 5372, 5353, 5345, 5339, 5331, 5321, 5313, 5307,
5299, 5433, 5425, 5419, 5411, 5401, 5393, 5387, 5379, 5360, 5352, 5346, 5338,
5328, 5320, 5314, 5306, 5284, 5276, 5270, 5262, 5252, 5244, 5238, 5230, 5211,
5203, 5197, 5189, 5179, 5171, 5165, 5157, 5131, 5123, 5117, 5109, 5099, 5091,
5085, 5077, 5058, 5050, 5044, 5036, 5026, 5018, 5012, 5004, 4982, 4974, 4968,
4960, 4950, 4942, 4936, 4928, 4909, 4901, 4895, 4887, 4877, 4869, 4863, 4855,
5586, 5578, 5572, 5564, 5554, 5546, 5540, 5532, 5513, 5505, 5499, 5491, 5481,
5473, 5467, 5459, 5437, 5429, 5423, 5415, 5405, 5397, 5391, 5383, 5364, 5356,
5350, 5342, 5332, 5324, 5318, 5310, 5284, 5276, 5270, 5262, 5252, 5244, 5238,
5230, 5211, 5203, 5197, 5189, 5179, 5171, 5165, 5157, 5135, 5127, 5121, 5113,
5103, 5095, 5089, 5081, 5062, 5054, 5048, 5040, 5030, 5022, 5016, 5008, 5142,
5134, 5128, 5120, 5110, 5102, 5096, 5088, 5069, 5061, 5055, 5047, 5037, 5029,
5023, 5015, 4993, 4985, 4979, 4971, 4961, 4953, 4947, 4939, 4920, 4912, 4906,
4898, 4888, 4880, 4874, 4866, 4840, 4832, 4826, 4818, 4808, 4800, 4794, 4786,
4767, 4759, 4753, 4745, 4735, 4727, 4721, 4713, 4691, 4683, 4677, 4669, 4659,
4651, 4645, 4637, 4618, 4610, 4604, 4596, 4586, 4578, 4572, 4564, 4766, 4758,
4752, 4744, 4734, 4726, 4720, 4712, 4693, 4685, 4679, 4671, 4661, 4653, 4647,
4639, 4617, 4609, 4603, 4595, 4585, 4577, 4571, 4563, 4544, 4536, 4530, 4522,
4512, 4504, 4498, 4490, 4464, 4456, 4450, 4442, 4432, 4424, 4418, 4410, 4391,
4383, 4377, 4369, 4359, 4351, 4345, 4337, 4315, 4307, 4301, 4293, 4283, 4275,
4269, 4261, 4242, 4234, 4228, 4220, 4210, 4202, 4196, 4188, 4322, 4314, 4308,
4300, 4290, 4282, 4276, 4268, 4249, 4241, 4235, 4227, 4217, 4209, 4203, 4195,
4173, 4165, 4159, 4151, 4141, 4133, 4127, 4119, 4100, 4092, 4086, 4078, 4068,
4060, 4054, 4046, 4020, 4012, 4006, 3998, 3988, 3980, 3974, 3966, 3947, 3939,
3933, 3925, 3915, 3907, 3901, 3893, 3871, 3863, 3857, 3849, 3839, 3831, 3825,
3817, 3798, 3790, 3784, 3776, 3766, 3758, 3752, 3744, 6697, 6689, 6683, 6675,
6665, 6657, 6651, 6643, 6624, 6616, 6610, 6602, 6592, 6584, 6578, 6570, 6548,
6540, 6534, 6526, 6516, 6508, 6502, 6494, 6475, 6467, 6461, 6453, 6443, 6435,
6429, 6421, 6395, 6387, 6381, 6373, 6363, 6355, 6349, 6341, 6322, 6314, 6308,
6300, 6290, 6282, 6276, 6268, 6246, 6238, 6232, 6224, 6214, 6206, 6200, 6192,
6173, 6165, 6159, 6151, 6141, 6133, 6127, 6119, 6253, 6245, 6239, 6231, 6221,
6213, 6207, 6199, 6180, 6172, 6166, 6158, 6148, 6140, 6134, 6126, 6104, 6096,
6090, 6082, 6072, 6064, 6058, 6050, 6031, 6023, 6017, 6009, 5999, 5991, 5985,
5977, 5951, 5943, 5937, 5929, 5919, 5911, 5905, 5897, 5878, 5870, 5864, 5856,
5846, 5838, 5832, 5824, 5802, 5794, 5788, 5780, 5770, 5762, 5756, 5748, 5729,
5721, 5715, 5707, 5697, 5689, 5683, 5675, 5877, 5869, 5863, 5855, 5845, 5837,
5831, 5823, 5804, 5796, 5790, 5782, 5772, 5764, 5758, 5750, 5728, 5720, 5714,
5706, 5696, 5688, 5682, 5674, 5655, 5647, 5641, 5633, 5623, 5615, 5609, 5601,
5575, 5567, 5561, 5553, 5543, 5535, 5529, 5521, 5502, 5494, 5488, 5480, 5470,
5462, 5456, 5448, 5426, 5418, 5412, 5404, 5394, 5386, 5380, 5372, 5353, 5345,
5339, 5331, 5321, 5313, 5307, 5299, 5433, 5425, 5419, 5411, 5401, 5393, 5387,
5379, 5360, 5352, 5346, 5338, 5328, 5320, 5314, 5306, 5284, 5276, 5270, 5262,
5252, 5244, 5238, 5230, 5211, 5203, 5197, 5189, 5179, 5171, 5165, 5157, 5131,
5123, 5117, 5109, 5099, 5091, 5085, 5077, 5058, 5050, 5044, 5036, 5026, 5018,
5012, 5004, 4982, 4974, 4968, 4960, 4950, 4942, 4936, 4928, 4909, 4901, 4895,
4887, 4877, 4869, 4863, 4855, 5586, 5578, 5572, 5564, 5554, 5546, 5540, 5532,
5513, 5505, 5499, 5491, 5481, 5473, 5467, 5459, 5437, 5429, 5423, 5415, 5405,
5397, 5391, 5383, 5364, 5356, 5350, 5342, 5332, 5324, 5318, 5310, 5284, 5276,
5270, 5262, 5252, 5244, 5238, 5230, 5211, 5203, 5197, 5189, 5179, 5171, 5165,
5157, 5135, 5127, 5121, 5113, 5103, 5095, 5089, 5081, 5062, 5054, 5048, 5040,
5030, 5022, 5016, 5008, 5142, 5134, 5128, 5120, 5110, 5102, 5096, 5088, 5069,
5061, 5055, 5047, 5037, 5029, 5023, 5015, 4993, 4985, 4979, 4971, 4961, 4953,
4947, 4939, 4920, 4912, 4906, 4898, 4888, 4880, 4874, 4866, 4840, 4832, 4826,
4818, 4808, 4800, 4794, 4786, 4767, 4759, 4753, 4745, 4735, 4727, 4721, 4713,
4691, 4683, 4677, 4669, 4659, 4651, 4645, 4637, 4618, 4610, 4604, 4596, 4586,
4578, 4572, 4564, 4766, 4758, 4752, 4744, 4734, 4726, 4720, 4712, 4693, 4685,
4679, 4671, 4661, 4653, 4647, 4639, 4617, 4609, 4603, 4595, 4585, 4577, 4571,
4563, 4544, 4536, 4530, 4522, 4512, 4504, 4498, 4490, 4464, 4456, 4450, 4442,
4432, 4424, 4418, 4410, 4391, 4383, 4377, 4369, 4359, 4351, 4345, 4337, 4315,
4307, 4301, 4293, 4283, 4275, 4269, 4261, 4242, 4234, 4228, 4220, 4210, 4202,
4196, 4188, 4322, 4314, 4308, 4300, 4290, 4282, 4276, 4268, 4249, 4241, 4235,
4227, 4217, 4209, 4203, 4195, 4173, 4165, 4159, 4151, 4141, 4133, 4127, 4119,
4100, 4092, 4086, 4078, 4068, 4060, 4054, 4046, 4020, 4012, 4006, 3998, 3988,
3980, 3974, 3966, 3947, 3939, 3933, 3925, 3915, 3907, 3901, 3893, 3871, 3863,
3857, 3849, 3839, 3831, 3825, 3817, 3798, 3790, 3784, 3776, 3766, 3758, 3752,
3744, 4651, 4643, 4637, 4629, 4619, 4611, 4605, 4597, 4578, 4570, 4564, 4556,
4546, 4538, 4532, 4524, 4502, 4494, 4488, 4480, 4470, 4462, 4456, 4448, 4429,
4421, 4415, 4407, 4397, 4389, 4383, 4375, 4349, 4341, 4335, 4327, 4317, 4309,
4303, 4295, 4276, 4268, 4262, 4254, 4244, 4236, 4230, 4222, 4200, 4192, 4186,
4178, 4168, 4160, 4154, 4146, 4127, 4119, 4113, 4105, 4095, 4087, 4081, 4073,
4207, 4199, 4193, 4185, 4175, 4167, 4161, 4153, 4134, 4126, 4120, 4112, 4102,
4094, 4088, 4080, 4058, 4050, 4044, 4036, 4026, 4018, 4012, 4004, 3985, 3977,
3971, 3963, 3953, 3945, 3939, 3931, 3905, 3897, 3891, 3883, 3873, 3865, 3859,
3851, 3832, 3824, 3818, 3810, 3800, 3792, 3786, 3778, 3756, 3748, 3742, 3734,
3724, 3716, 3710, 3702, 3683, 3675, 3669, 3661, 3651, 3643, 3637, 3629, 3831,
3823, 3817, 3809, 3799, 3791, 3785, 3777, 3758, 3750, 3744, 3736, 3726, 3718,
3712, 3704, 3682, 3674, 3668, 3660, 3650, 3642, 3636, 3628, 3609, 3601, 3595,
3587, 3577, 3569, 3563, 3555, 3529, 3521, 3515, 3507, 3497, 3489, 3483, 3475,
3456, 3448, 3442, 3434, 3424, 3416, 3410, 3402, 3380, 3372, 3366, 3358, 3348,
3340, 3334, 3326, 3307, 3299, 3293, 3285, 3275, 3267, 3261, 3253, 3387, 3379,
3373, 3365, 3355, 3347, 3341, 3333, 3314, 3306, 3300, 3292, 3282, 3274, 3268,
3260, 3238, 3230, 3224, 3216, 3206, 3198, 3192, 3184, 3165, 3157, 3151, 3143,
3133, 3125, 3119, 3111, 3085, 3077, 3071, 3063, 3053, 3045, 3039, 3031, 3012,
3004, 2998, 2990, 2980, 2972, 2966, 2958, 2936, 2928, 2922, 2914, 2904, 2896,
2890, 2882, 2863, 2855, 2849, 2841, 2831, 2823, 2817, 2809, 3540, 3532, 3526,
3518, 3508, 3500, 3494, 3486, 3467, 3459, 3453, 3445, 3435, 3427, 3421, 3413,
3391, 3383, 3377, 3369, 3359, 3351, 3345, 3337, 3318, 3310, 3304, 3296, 3286,
3278, 3272, 3264, 3238, 3230, 3224, 3216, 3206, 3198, 3192, 3184, 3165, 3157,
3151, 3143, 3133, 3125, 3119, 3111, 3089, 3081, 3075, 3067, 3057, 3049, 3043,
3035, 3016, 3008, 3002, 2994, 2984, 2976, 2970, 2962, 3096, 3088, 3082, 3074,
3064, 3056, 3050, 3042, 3023, 3015, 3009, 3001, 2991, 2983, 2977, 2969, 2947,
2939, 2933, 2925, 2915, 2907, 2901, 2893, 2874, 2866, 2860, 2852, 2842, 2834,
2828, 2820, 2794, 2786, 2780, 2772, 2762, 2754, 2748, 2740, 2721, 2713, 2707,
2699, 2689, 2681, 2675, 2667, 2645, 2637, 2631, 2623, 2613, 2605, 2599, 2591,
2572, 2564, 2558, 2550, 2540, 2532, 2526, 2518, 2720, 2712, 2706, 2698, 2688,
2680, 2674, 2666, 2647, 2639, 2633, 2625, 2615, 2607, 2601, 2593, 2571, 2563,
2557, 2549, 2539, 2531, 2525, 2517, 2498, 2490, 2484, 2476, 2466, 2458, 2452,
2444, 2418, 2410, 2404, 2396, 2386, 2378, 2372, 2364, 2345, 2337, 2331, 2323,
2313, 2305, 2299, 2291, 2269, 2261, 2255, 2247, 2237, 2229, 2223, 2215, 2196,
2188, 2182, 2174, 2164, 2156, 2150, 2142, 2276, 2268, 2262, 2254, 2244, 2236,
2230, 2222, 2203, 2195, 2189, 2181, 2171, 2163, 2157, 2149, 2127, 2119, 2113,
2105, 2095, 2087, 2081, 2073, 2054, 2046, 2040, 2032, 2022, 2014, 2008, 2000,
1974, 1966, 1960, 1952, 1942, 1934, 1928, 1920, 1901, 1893, 1887, 1879, 1869,
1861, 1855, 1847, 1825, 1817, 1811, 1803, 1793, 1785, 1779, 1771, 1752, 1744,
1738, 1730, 1720, 1712, 1706, 1698, 1897, 1883, 1860, 1846, 1819, 1805, 1782,
1768, 1723, 1709, 1686, 1672, 1645, 1631, 1608, 1594, 1574, 1560, 1537, 1523,
1496, 1482, 1459, 1445, 1400, 1386, 1363, 1349, 1322, 1308, 1285, 1271, 1608,
1565, 1535, 1492, 1446, 1403, 1373, 1330, 1312, 1269, 1239, 1196, 1150, 1107,
1077, 1034, 1291, 1218, 1171, 1098, 1015, 942, 895, 822, 953, 850, 729,
626, 618, 431, 257, 257, 257, 257, 0, 255, 255, 255, 255, 429,
616, 624, 727, 848, 951, 820, 893, 940, 1013, 1096, 1169, 1216, 1289,
1032, 1075, 1105, 1148, 1194, 1237, 1267, 1310, 1328, 1371, 1401, 1444, 1490,
1533, 1563, 1606, 1269, 1283, 1306, 1320, 1347, 1361, 1384, 1398, 1443, 1457,
1480, 1494, 1521, 1535, 1558, 1572, 1592, 1606, 1629, 1643, 1670, 1684, 1707,
1721, 1766, 1780, 1803, 1817, 1844, 1858, 1881, 1895, 1696, 1704, 1710, 1718,
1728, 1736, 1742, 1750, 1769, 1777, 1783, 1791, 1801, 1809, 1815, 1823, 1845,
1853, 1859, 1867, 1877, 1885, 1891, 1899, 1918, 1926, 1932, 1940, 1950, 1958,
1964, 1972, 1998, 2006, 2012, 2020, 2030, 2038, 2044, 2052, 2071, 2079, 2085,
2093, 2103, 2111, 2117, 2125, 2147, 2155, 2161, 2169, 2179, 2187, 2193, 2201,
2220, 2228, 2234, 2242, 2252, 2260, 2266, 2274, 2140, 2148, 2154, 2162, 2172,
2180, 2186, 2194, 2213, 2221, 2227, 2235, 2245, 2253, 2259, 2267, 2289, 2297,
2303, 2311, 2321, 2329, 2335, 2343, 2362, 2370, 2376, 2384, 2394, 2402, 2408,
2416, 2442, 2450, 2456, 2464, 2474, 2482, 2488, 2496, 2515, 2523, 2529, 2537,
2547, 2555, 2561, 2569, 2591, 2599, 2605, 2613, 2623, 2631, 2637, 2645, 2664,
2672, 2678, 2686, 2696, 2704, 2710, 2718, 2516, 2524, 2530, 2538, 2548, 2556,
2562, 2570, 2589, 2597, 2603, 2611, 2621, 2629, 2635, 2643, 2665, 2673, 2679,
2687, 2697, 2705, 2711, 2719, 2738, 2746, 2752, 2760, 2770, 2778, 2784, 2792,
2818, 2826, 2832, 2840, 2850, 2858, 2864, 2872, 2891, 2899, 2905, 2913, 2923,
2931, 2937, 2945, 2967, 2975, 2981, 2989, 2999, 3007, 3013, 3021, 3040, 3048,
3054, 3062, 3072, 3080, 3086, 3094, 2960, 2968, 2974, 2982, 2992, 3000, 3006,
3014, 3033, 3041, 3047, 3055, 3065, 3073, 3079, 3087, 3109, 3117, 3123, 3131,
3141, 3149, 3155, 3163, 3182, 3190, 3196, 3204, 3214, 3222, 3228, 3236, 3262,
3270, 3276, 3284, 3294, 3302, 3308, 3316, 3335, 3343, 3349, 3357, 3367, 3375,
3381, 3389, 3411, 3419, 3425, 3433, 3443, 3451, 3457, 3465, 3484, 3492, 3498,
3506, 3516, 3524, 3530, 3538, 2807, 2815, 2821, 2829, 2839, 2847, 2853, 2861,
2880, 2888, 2894, 2902, 2912, 2920, 2926, 2934, 2956, 2964, 2970, 2978, 2988,
2996, 3002, 3010, 3029, 3037, 3043, 3051, 3061, 3069, 3075, 3083, 3109, 3117,
3123, 3131, 3141, 3149, 3155, 3163, 3182, 3190, 3196, 3204, 3214, 3222, 3228,
3236, 3258, 3266, 3272, 3280, 3290, 3298, 3304, 3312, 3331, 3339, 3345, 3353,
3363, 3371, 3377, 3385, 3251, 3259, 3265, 3273, 3283, 3291, 3297, 3305, 3324,
3332, 3338, 3346, 3356, 3364, 3370, 3378, 3400, 3408, 3414, 3422, 3432, 3440,
3446, 3454, 3473, 3481, 3487, 3495, 3505, 3513, 3519, 3527, 3553, 3561, 3567,
3575, 3585, 3593, 3599, 3607, 3626, 3634, 3640, 3648, 3658, 3666, 3672, 3680,
3702, 3710, 3716, 3724, 3734, 3742, 3748, 3756, 3775, 3783, 3789, 3797, 3807,
3815, 3821, 3829, 3627, 3635, 3641, 3649, 3659, 3667, 3673, 3681, 3700, 3708,
3714, 3722, 3732, 3740, 3746, 3754, 3776, 3784, 3790, 3798, 3808, 3816, 3822,
3830, 3849, 3857, 3863, 3871, 3881, 3889, 3895, 3903, 3929, 3937, 3943, 3951,
3961, 3969, 3975, 3983, 4002, 4010, 4016, 4024, 4034, 4042, 4048, 4056, 4078,
4086, 4092, 4100, 4110, 4118, 4124, 4132, 4151, 4159, 4165, 4173, 4183, 4191,
4197, 4205, 4071, 4079, 4085, 4093, 4103, 4111, 4117, 4125, 4144, 4152, 4158,
4166, 4176, 4184, 4190, 4198, 4220, 4228, 4234, 4242, 4252, 4260, 4266, 4274,
4293, 4301, 4307, 4315, 4325, 4333, 4339, 4347, 4373, 4381, 4387, 4395, 4405,
4413, 4419, 4427, 4446, 4454, 4460, 4468, 4478, 4486, 4492, 4500, 4522, 4530,
4536, 4544, 4554, 4562, 4568, 4576, 4595, 4603, 4609, 4617, 4627, 4635, 4641,
4649, 3742, 3750, 3756, 3764, 3774, 3782, 3788, 3796, 3815, 3823, 3829, 3837,
3847, 3855, 3861, 3869, 3891, 3899, 3905, 3913, 3923, 3931, 3937, 3945, 3964,
3972, 3978, 3986, 3996, 4004, 4010, 4018, 4044, 4052, 4058, 4066, 4076, 4084,
4090, 4098, 4117, 4125, 4131, 4139, 4149, 4157, 4163, 4171, 4193, 4201, 4207,
4215, 4225, 4233, 4239, 4247, 4266, 4274, 4280, 4288, 4298, 4306, 4312, 4320,
4186, 4194, 4200, 4208, 4218, 4226, 4232, 4240, 4259, 4267, 4273, 4281, 4291,
4299, 4305, 4313, 4335, 4343, 4349, 4357, 4367, 4375, 4381, 4389, 4408, 4416,
4422, 4430, 4440, 4448, 4454, 4462, 4488, 4496, 4502, 4510, 4520, 4528, 4534,
4542, 4561, 4569, 4575, 4583, 4593, 4601, 4607, 4615, 4637, 4645, 4651, 4659,
4669, 4677, 4683, 4691, 4710, 4718, 4724, 4732, 4742, 4750, 4756, 4764, 4562,
4570, 4576, 4584, 4594, 4602, 4608, 4616, 4635, 4643, 4649, 4657, 4667, 4675,
4681, 4689, 4711, 4719, 4725, 4733, 4743, 4751, 4757, 4765, 4784, 4792, 4798,
4806, 4816, 4824, 4830, 4838, 4864, 4872, 4878, 4886, 4896, 4904, 4910, 4918,
4937, 4945, 4951, 4959, 4969, 4977, 4983, 4991, 5013, 5021, 5027, 5035, 5045,
5053, 5059, 5067, 5086, 5094, 5100, 5108, 5118, 5126, 5132, 5140, 5006, 5014,
5020, 5028, 5038, 5046, 5052, 5060, 5079, 5087, 5093, 5101, 5111, 5119, 5125,
5133, 5155, 5163, 5169, 5177, 5187, 5195, 5201, 5209, 5228, 5236, 5242, 5250,
5260, 5268, 5274, 5282, 5308, 5316, 5322, 5330, 5340, 5348, 5354, 5362, 5381,
5389, 5395, 5403, 5413, 5421, 5427, 5435, 5457, 5465, 5471, 5479, 5489, 5497,
5503, 5511, 5530, 5538, 5544, 5552, 5562, 5570, 5576, 5584, 4853, 4861, 4867,
4875, 4885, 4893, 4899, 4907, 4926, 4934, 4940, 4948, 4958, 4966, 4972, 4980,
5002, 5010, 5016, 5024, 5034, 5042, 5048, 5056, 5075, 5083, 5089, 5097, 5107,
5115, 5121, 5129, 5155, 5163, 5169, 5177, 5187, 5195, 5201, 5209, 5228, 5236,
5242, 5250, 5260, 5268, 5274, 5282, 5304, 5312, 5318, 5326, 5336, 5344, 5350,
5358, 5377, 5385, 5391, 5399, 5409, 5417, 5423, 5431, 5297, 5305, 5311, 5319,
5329, 5337, 5343, 5351, 5370, 5378, 5384, 5392, 5402, 5410, 5416, 5424, 5446,
5454, 5460, 5468, 5478, 5486, 5492, 5500, 5519, 5527, 5533, 5541, 5551, 5559,
5565, 5573, 5599, 5607, 5613, 5621, 5631, 5639, 5645, 5653, 5672, 5680, 5686,
5694, 5704, 5712, 5718, 5726, 5748, 5756, 5762, 5770, 5780, 5788, 5794, 5802,
5821, 5829, 5835, 5843, 5853, 5861, 5867, 5875, 5673, 5681, 5687, 5695, 5705,
5713, 5719, 5727, 5746, 5754, 5760, 5768, 5778, 5786, 5792, 5800, 5822, 5830,
5836, 5844, 5854, 5862, 5868, 5876, 5895, 5903, 5909, 5917, 5927, 5935, 5941,
5949, 5975, 5983, 5989, 5997, 6007, 6015, 6021, 6029, 6048, 6056, 6062, 6070,
6080, 6088, 6094, 6102, 6124, 6132, 6138, 6146, 6156, 6164, 6170, 6178, 6197,
6205, 6211, 6219, 6229, 6237, 6243, 6251, 6117, 6125, 6131, 6139, 6149, 6157,
6163, 6171, 6190, 6198, 6204, 6212, 6222, 6230, 6236, 6244, 6266, 6274, 6280,
6288, 6298, 6306, 6312, 6320, 6339, 6347, 6353, 6361, 6371, 6379, 6385, 6393,
6419, 6427, 6433, 6441, 6451, 6459, 6465, 6473, 6492, 6500, 6506, 6514, 6524,
6532, 6538, 6546, 6568, 6576, 6582, 6590, 6600, 6608, 6614, 6622, 6641, 6649,
6655, 6663, 6673, 6681, 6687, 6695, 3742, 3750, 3756, 3764, 3774, 3782, 3788,
3796, 3815, 3823, 3829, 3837, 3847, 3855, 3861, 3869, 3891, 3899, 3905, 3913,
3923, 3931, 3937, 3945, 3964, 3972, 3978, 3986, 3996, 4004, 4010, 4018, 4044,
4052, 4058, 4066, 4076, 4084, 4090, 4098, 4117, 4125, 4131, 4139, 4149, 4157,
4163, 4171, 4193, 4201, 4207, 4215, 4225, 4233, 4239, 4247, 4266, 4274, 4280,
4288, 4298, 4306, 4312, 4320, 4186, 4194, 4200, 4208, 4218, 4226, 4232, 4240,
4259, 4267, 4273, 4281, 4291, 4299, 4305, 4313, 4335, 4343, 4349, 4357, 4367,
4375, 4381, 4389, 4408, 4416, 4422, 4430, 4440, 4448, 4454, 4462, 4488, 4496,
4502, 4510, 4520, 4528, 4534, 4542, 4561, 4569, 4575, 4583, 4593, 4601, 4607,
4615, 4637, 4645, 4651, 4659, 4669, 4677, 4683, 4691, 4710, 4718, 4724, 4732,
4742, 4750, 4756, 4764, 4562, 4570, 4576, 4584, 4594, 4602, 4608, 4616, 4635,
4643, 4649, 4657, 4667, 4675, 4681, 4689, 4711, 4719, 4725, 4733, 4743, 4751,
4757, 4765, 4784, 4792, 4798, 4806, 4816, 4824, 4830, 4838, 4864, 4872, 4878,
4886, 4896, 4904, 4910, 4918, 4937, 4945, 4951, 4959, 4969, 4977, 4983, 4991,
5013, 5021, 5027, 5035, 5045, 5053, 5059, 5067, 5086, 5094, 5100, 5108, 5118,
5126, 5132, 5140, 5006, 5014, 5020, 5028, 5038, 5046, 5052, 5060, 5079, 5087,
5093, 5101, 5111, 5119, 5125, 5133, 5155, 5163, 5169, 5177, 5187, 5195, 5201,
5209, 5228, 5236, 5242, 5250, 5260, 5268, 5274, 5282, 5308, 5316, 5322, 5330,
5340, 5348, 5354, 5362, 5381, 5389, 5395, 5403, 5413, 5421, 5427, 5435, 5457,
5465, 5471, 5479, 5489, 5497, 5503, 5511, 5530, 5538, 5544, 5552, 5562, 5570,
5576, 5584, 4853, 4861, 4867, 4875, 4885, 4893, 4899, 4907, 4926, 4934, 4940,
4948, 4958, 4966, 4972, 4980, 5002, 5010, 5016, 5024, 5034, 5042, 5048, 5056,
5075, 5083, 5089, 5097, 5107, 5115, 5121, 5129, 5155, 5163, 5169, 5177, 5187,
5195, 5201, 5209, 5228, 5236, 5242, 5250, 5260, 5268, 5274, 5282, 5304, 5312,
5318, 5326, 5336, 5344, 5350, 5358, 5377, 5385, 5391, 5399, 5409, 5417, 5423,
5431, 5297, 5305, 5311, 5319, 5329, 5337, 5343, 5351, 5370, 5378, 5384, 5392,
5402, 5410, 5416, 5424, 5446, 5454, 5460, 5468, 5478, 5486, 5492, 5500, 5519,
5527, 5533, 5541, 5551, 5559, 5565, 5573, 5599, 5607, 5613, 5621, 5631, 5639,
5645, 5653, 5672, 5680, 5686, 5694, 5704, 5712, 5718, 5726, 5748, 5756, 5762,
5770, 5780, 5788, 5794, 5802, 5821, 5829, 5835, 5843, 5853, 5861, 5867, 5875,
5673, 5681, 5687, 5695, 5705, 5713, 5719, 5727, 5746, 5754, 5760, 5768, 5778,
5786, 5792, 5800, 5822, 5830, 5836, 5844, 5854, 5862, 5868, 5876, 5895, 5903,
5909, 5917, 5927, 5935, 5941, 5949, 5975, 5983, 5989, 5997, 6007, 6015, 6021,
6029, 6048, 6056, 6062, 6070, 6080, 6088, 6094, 6102, 6124, 6132, 6138, 6146,
6156, 6164, 6170, 6178, 6197, 6205, 6211, 6219, 6229, 6237, 6243, 6251, 6117,
6125, 6131, 6139, 6149, 6157, 6163, 6171, 6190, 6198, 6204, 6212, 6222, 6230,
6236, 6244, 6266, 6274, 6280, 6288, 6298, 6306, 6312, 6320, 6339, 6347, 6353,
6361, 6371, 6379, 6385, 6393, 6419, 6427, 6433, 6441, 6451, 6459, 6465, 6473,
6492, 6500, 6506, 6514, 6524, 6532, 6538, 6546, 6568, 6576, 6582, 6590, 6600,
6608, 6614, 6622, 6641, 6649, 6655, 6663, 6673, 6681, 6687, 6695, 5788, 5796,
5802, 5810, 5820, 5828, 5834, 5842, 5861, 5869, 5875, 5883, 5893, 5901, 5907,
5915, 5937, 5945, 5951, 5959, 5969, 5977, 5983, 5991, 6010, 6018, 6024, 6032,
6042, 6050, 6056, 6064, 6090, 6098, 6104, 6112, 6122, 6130, 6136, 6144, 6163,
6171, 6177, 6185, 6195, 6203, 6209, 6217, 6239, 6247, 6253, 6261, 6271, 6279,
6285, 6293, 6312, 6320, 6326, 6334, 6344, 6352, 6358, 6366, 6232, 6240, 6246,
6254, 6264, 6272, 6278, 6286, 6305, 6313, 6319, 6327, 6337, 6345, 6351, 6359,
6381, 6389, 6395, 6403, 6413, 6421, 6427, 6435, 6454, 6462, 6468, 6476, 6486,
6494, 6500, 6508, 6534, 6542, 6548, 6556, 6566, 6574, 6580, 6588, 6607, 6615,
6621, 6629, 6639, 6647, 6653, 6661, 6683, 6691, 6697, 6705, 6715, 6723, 6729,
6737, 6756, 6764, 6770, 6778, 6788, 6796, 6802, 6810, 6608, 6616, 6622, 6630,
6640, 6648, 6654, 6662, 6681, 6689, 6695, 6703, 6713, 6721, 6727, 6735, 6757,
6765, 6771, 6779, 6789, 6797, 6803, 6811, 6830, 6838, 6844, 6852, 6862, 6870,
6876, 6884, 6910, 6918, 6924, 6932, 6942, 6950, 6956, 6964, 6983, 6991, 6997,
7005, 7015, 7023, 7029, 7037, 7059, 7067, 7073, 7081, 7091, 7099, 7105, 7113,
7132, 7140, 7146, 7154, 7164, 7172, 7178, 7186, 7052, 7060, 7066, 7074, 7084,
7092, 7098, 7106, 7125, 7133, 7139, 7147, 7157, 7165, 7171, 7179, 7201, 7209,
7215, 7223, 7233, 7241, 7247, 7255, 7274, 7282, 7288, 7296, 7306, 7314, 7320,
7328, 7354, 7362, 7368, 7376, 7386, 7394, 7400, 7408, 7427, 7435, 7441, 7449,
7459, 7467, 7473, 7481, 7503, 7511, 7517, 7525, 7535, 7543, 7549, 7557, 7576,
7584, 7590, 7598, 7608, 7616, 7622, 7630, 6899, 6907, 6913, 6921, 6931, 6939,
6945, 6953, 6972, 6980, 6986, 6994, 7004, 7012, 7018, 7026, 7048, 7056, 7062,
7070, 7080, 7088, 7094, 7102, 7121, 7129, 7135, 7143, 7153, 7161, 7167, 7175,
7201, 7209, 7215, 7223, 7233, 7241, 7247, 7255, 7274, 7282, 7288, 7296, 7306,
7314, 7320, 7328, 7350, 7358, 7364, 7372, 7382, 7390, 7396, 7404, 7423, 7431,
7437, 7445, 7455, 7463, 7469, 7477, 7343, 7351, 7357, 7365, 7375, 7383, 7389,
7397, 7416, 7424, 7430, 7438, 7448, 7456, 7462, 7470, 7492, 7500, 7506, 7514,
7524, 7532, 7538, 7546, 7565, 7573, 7579, 7587, 7597, 7605, 7611, 7619, 7645,
7653, 7659, 7667, 7677, 7685, 7691, 7699, 7718, 7726, 7732, 7740, 7750, 7758,
7764, 7772, 7794, 7802, 7808, 7816, 7826, 7834, 7840, 7848, 7867, 7875, 7881,
7889, 7899, 7907, 7913, 7921, 7719, 7727, 7733, 7741, 7751, 7759, 7765, 7773,
7792, 7800, 7806, 7814, 7824, 7832, 7838, 7846, 7868, 7876, 7882, 7890, 7900,
7908, 7914, 7922, 7941, 7949, 7955, 7963, 7973, 7981, 7987, 7995, 8021, 8029,
8035, 8043, 8053, 8061, 8067, 8075, 8094, 8102, 8108, 8116, 8126, 8134, 8140,
8148, 8170, 8178, 8184, 8192, 8202, 8210, 8216, 8224, 8243, 8251, 8257, 8265,
8275
};
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_DCT_VALUE_COST_H_
@@ -0,0 +1,848 @@
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_DCT_VALUE_TOKENS_H_
#define VPX_VP8_ENCODER_DCT_VALUE_TOKENS_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Generated file, included by tokenize.c */
/* Values generated by fill_value_tokens() */
static const TOKENVALUE dct_value_tokens[2048 * 2] = {
{ 10, 3963 }, { 10, 3961 }, { 10, 3959 }, { 10, 3957 }, { 10, 3955 },
{ 10, 3953 }, { 10, 3951 }, { 10, 3949 }, { 10, 3947 }, { 10, 3945 },
{ 10, 3943 }, { 10, 3941 }, { 10, 3939 }, { 10, 3937 }, { 10, 3935 },
{ 10, 3933 }, { 10, 3931 }, { 10, 3929 }, { 10, 3927 }, { 10, 3925 },
{ 10, 3923 }, { 10, 3921 }, { 10, 3919 }, { 10, 3917 }, { 10, 3915 },
{ 10, 3913 }, { 10, 3911 }, { 10, 3909 }, { 10, 3907 }, { 10, 3905 },
{ 10, 3903 }, { 10, 3901 }, { 10, 3899 }, { 10, 3897 }, { 10, 3895 },
{ 10, 3893 }, { 10, 3891 }, { 10, 3889 }, { 10, 3887 }, { 10, 3885 },
{ 10, 3883 }, { 10, 3881 }, { 10, 3879 }, { 10, 3877 }, { 10, 3875 },
{ 10, 3873 }, { 10, 3871 }, { 10, 3869 }, { 10, 3867 }, { 10, 3865 },
{ 10, 3863 }, { 10, 3861 }, { 10, 3859 }, { 10, 3857 }, { 10, 3855 },
{ 10, 3853 }, { 10, 3851 }, { 10, 3849 }, { 10, 3847 }, { 10, 3845 },
{ 10, 3843 }, { 10, 3841 }, { 10, 3839 }, { 10, 3837 }, { 10, 3835 },
{ 10, 3833 }, { 10, 3831 }, { 10, 3829 }, { 10, 3827 }, { 10, 3825 },
{ 10, 3823 }, { 10, 3821 }, { 10, 3819 }, { 10, 3817 }, { 10, 3815 },
{ 10, 3813 }, { 10, 3811 }, { 10, 3809 }, { 10, 3807 }, { 10, 3805 },
{ 10, 3803 }, { 10, 3801 }, { 10, 3799 }, { 10, 3797 }, { 10, 3795 },
{ 10, 3793 }, { 10, 3791 }, { 10, 3789 }, { 10, 3787 }, { 10, 3785 },
{ 10, 3783 }, { 10, 3781 }, { 10, 3779 }, { 10, 3777 }, { 10, 3775 },
{ 10, 3773 }, { 10, 3771 }, { 10, 3769 }, { 10, 3767 }, { 10, 3765 },
{ 10, 3763 }, { 10, 3761 }, { 10, 3759 }, { 10, 3757 }, { 10, 3755 },
{ 10, 3753 }, { 10, 3751 }, { 10, 3749 }, { 10, 3747 }, { 10, 3745 },
{ 10, 3743 }, { 10, 3741 }, { 10, 3739 }, { 10, 3737 }, { 10, 3735 },
{ 10, 3733 }, { 10, 3731 }, { 10, 3729 }, { 10, 3727 }, { 10, 3725 },
{ 10, 3723 }, { 10, 3721 }, { 10, 3719 }, { 10, 3717 }, { 10, 3715 },
{ 10, 3713 }, { 10, 3711 }, { 10, 3709 }, { 10, 3707 }, { 10, 3705 },
{ 10, 3703 }, { 10, 3701 }, { 10, 3699 }, { 10, 3697 }, { 10, 3695 },
{ 10, 3693 }, { 10, 3691 }, { 10, 3689 }, { 10, 3687 }, { 10, 3685 },
{ 10, 3683 }, { 10, 3681 }, { 10, 3679 }, { 10, 3677 }, { 10, 3675 },
{ 10, 3673 }, { 10, 3671 }, { 10, 3669 }, { 10, 3667 }, { 10, 3665 },
{ 10, 3663 }, { 10, 3661 }, { 10, 3659 }, { 10, 3657 }, { 10, 3655 },
{ 10, 3653 }, { 10, 3651 }, { 10, 3649 }, { 10, 3647 }, { 10, 3645 },
{ 10, 3643 }, { 10, 3641 }, { 10, 3639 }, { 10, 3637 }, { 10, 3635 },
{ 10, 3633 }, { 10, 3631 }, { 10, 3629 }, { 10, 3627 }, { 10, 3625 },
{ 10, 3623 }, { 10, 3621 }, { 10, 3619 }, { 10, 3617 }, { 10, 3615 },
{ 10, 3613 }, { 10, 3611 }, { 10, 3609 }, { 10, 3607 }, { 10, 3605 },
{ 10, 3603 }, { 10, 3601 }, { 10, 3599 }, { 10, 3597 }, { 10, 3595 },
{ 10, 3593 }, { 10, 3591 }, { 10, 3589 }, { 10, 3587 }, { 10, 3585 },
{ 10, 3583 }, { 10, 3581 }, { 10, 3579 }, { 10, 3577 }, { 10, 3575 },
{ 10, 3573 }, { 10, 3571 }, { 10, 3569 }, { 10, 3567 }, { 10, 3565 },
{ 10, 3563 }, { 10, 3561 }, { 10, 3559 }, { 10, 3557 }, { 10, 3555 },
{ 10, 3553 }, { 10, 3551 }, { 10, 3549 }, { 10, 3547 }, { 10, 3545 },
{ 10, 3543 }, { 10, 3541 }, { 10, 3539 }, { 10, 3537 }, { 10, 3535 },
{ 10, 3533 }, { 10, 3531 }, { 10, 3529 }, { 10, 3527 }, { 10, 3525 },
{ 10, 3523 }, { 10, 3521 }, { 10, 3519 }, { 10, 3517 }, { 10, 3515 },
{ 10, 3513 }, { 10, 3511 }, { 10, 3509 }, { 10, 3507 }, { 10, 3505 },
{ 10, 3503 }, { 10, 3501 }, { 10, 3499 }, { 10, 3497 }, { 10, 3495 },
{ 10, 3493 }, { 10, 3491 }, { 10, 3489 }, { 10, 3487 }, { 10, 3485 },
{ 10, 3483 }, { 10, 3481 }, { 10, 3479 }, { 10, 3477 }, { 10, 3475 },
{ 10, 3473 }, { 10, 3471 }, { 10, 3469 }, { 10, 3467 }, { 10, 3465 },
{ 10, 3463 }, { 10, 3461 }, { 10, 3459 }, { 10, 3457 }, { 10, 3455 },
{ 10, 3453 }, { 10, 3451 }, { 10, 3449 }, { 10, 3447 }, { 10, 3445 },
{ 10, 3443 }, { 10, 3441 }, { 10, 3439 }, { 10, 3437 }, { 10, 3435 },
{ 10, 3433 }, { 10, 3431 }, { 10, 3429 }, { 10, 3427 }, { 10, 3425 },
{ 10, 3423 }, { 10, 3421 }, { 10, 3419 }, { 10, 3417 }, { 10, 3415 },
{ 10, 3413 }, { 10, 3411 }, { 10, 3409 }, { 10, 3407 }, { 10, 3405 },
{ 10, 3403 }, { 10, 3401 }, { 10, 3399 }, { 10, 3397 }, { 10, 3395 },
{ 10, 3393 }, { 10, 3391 }, { 10, 3389 }, { 10, 3387 }, { 10, 3385 },
{ 10, 3383 }, { 10, 3381 }, { 10, 3379 }, { 10, 3377 }, { 10, 3375 },
{ 10, 3373 }, { 10, 3371 }, { 10, 3369 }, { 10, 3367 }, { 10, 3365 },
{ 10, 3363 }, { 10, 3361 }, { 10, 3359 }, { 10, 3357 }, { 10, 3355 },
{ 10, 3353 }, { 10, 3351 }, { 10, 3349 }, { 10, 3347 }, { 10, 3345 },
{ 10, 3343 }, { 10, 3341 }, { 10, 3339 }, { 10, 3337 }, { 10, 3335 },
{ 10, 3333 }, { 10, 3331 }, { 10, 3329 }, { 10, 3327 }, { 10, 3325 },
{ 10, 3323 }, { 10, 3321 }, { 10, 3319 }, { 10, 3317 }, { 10, 3315 },
{ 10, 3313 }, { 10, 3311 }, { 10, 3309 }, { 10, 3307 }, { 10, 3305 },
{ 10, 3303 }, { 10, 3301 }, { 10, 3299 }, { 10, 3297 }, { 10, 3295 },
{ 10, 3293 }, { 10, 3291 }, { 10, 3289 }, { 10, 3287 }, { 10, 3285 },
{ 10, 3283 }, { 10, 3281 }, { 10, 3279 }, { 10, 3277 }, { 10, 3275 },
{ 10, 3273 }, { 10, 3271 }, { 10, 3269 }, { 10, 3267 }, { 10, 3265 },
{ 10, 3263 }, { 10, 3261 }, { 10, 3259 }, { 10, 3257 }, { 10, 3255 },
{ 10, 3253 }, { 10, 3251 }, { 10, 3249 }, { 10, 3247 }, { 10, 3245 },
{ 10, 3243 }, { 10, 3241 }, { 10, 3239 }, { 10, 3237 }, { 10, 3235 },
{ 10, 3233 }, { 10, 3231 }, { 10, 3229 }, { 10, 3227 }, { 10, 3225 },
{ 10, 3223 }, { 10, 3221 }, { 10, 3219 }, { 10, 3217 }, { 10, 3215 },
{ 10, 3213 }, { 10, 3211 }, { 10, 3209 }, { 10, 3207 }, { 10, 3205 },
{ 10, 3203 }, { 10, 3201 }, { 10, 3199 }, { 10, 3197 }, { 10, 3195 },
{ 10, 3193 }, { 10, 3191 }, { 10, 3189 }, { 10, 3187 }, { 10, 3185 },
{ 10, 3183 }, { 10, 3181 }, { 10, 3179 }, { 10, 3177 }, { 10, 3175 },
{ 10, 3173 }, { 10, 3171 }, { 10, 3169 }, { 10, 3167 }, { 10, 3165 },
{ 10, 3163 }, { 10, 3161 }, { 10, 3159 }, { 10, 3157 }, { 10, 3155 },
{ 10, 3153 }, { 10, 3151 }, { 10, 3149 }, { 10, 3147 }, { 10, 3145 },
{ 10, 3143 }, { 10, 3141 }, { 10, 3139 }, { 10, 3137 }, { 10, 3135 },
{ 10, 3133 }, { 10, 3131 }, { 10, 3129 }, { 10, 3127 }, { 10, 3125 },
{ 10, 3123 }, { 10, 3121 }, { 10, 3119 }, { 10, 3117 }, { 10, 3115 },
{ 10, 3113 }, { 10, 3111 }, { 10, 3109 }, { 10, 3107 }, { 10, 3105 },
{ 10, 3103 }, { 10, 3101 }, { 10, 3099 }, { 10, 3097 }, { 10, 3095 },
{ 10, 3093 }, { 10, 3091 }, { 10, 3089 }, { 10, 3087 }, { 10, 3085 },
{ 10, 3083 }, { 10, 3081 }, { 10, 3079 }, { 10, 3077 }, { 10, 3075 },
{ 10, 3073 }, { 10, 3071 }, { 10, 3069 }, { 10, 3067 }, { 10, 3065 },
{ 10, 3063 }, { 10, 3061 }, { 10, 3059 }, { 10, 3057 }, { 10, 3055 },
{ 10, 3053 }, { 10, 3051 }, { 10, 3049 }, { 10, 3047 }, { 10, 3045 },
{ 10, 3043 }, { 10, 3041 }, { 10, 3039 }, { 10, 3037 }, { 10, 3035 },
{ 10, 3033 }, { 10, 3031 }, { 10, 3029 }, { 10, 3027 }, { 10, 3025 },
{ 10, 3023 }, { 10, 3021 }, { 10, 3019 }, { 10, 3017 }, { 10, 3015 },
{ 10, 3013 }, { 10, 3011 }, { 10, 3009 }, { 10, 3007 }, { 10, 3005 },
{ 10, 3003 }, { 10, 3001 }, { 10, 2999 }, { 10, 2997 }, { 10, 2995 },
{ 10, 2993 }, { 10, 2991 }, { 10, 2989 }, { 10, 2987 }, { 10, 2985 },
{ 10, 2983 }, { 10, 2981 }, { 10, 2979 }, { 10, 2977 }, { 10, 2975 },
{ 10, 2973 }, { 10, 2971 }, { 10, 2969 }, { 10, 2967 }, { 10, 2965 },
{ 10, 2963 }, { 10, 2961 }, { 10, 2959 }, { 10, 2957 }, { 10, 2955 },
{ 10, 2953 }, { 10, 2951 }, { 10, 2949 }, { 10, 2947 }, { 10, 2945 },
{ 10, 2943 }, { 10, 2941 }, { 10, 2939 }, { 10, 2937 }, { 10, 2935 },
{ 10, 2933 }, { 10, 2931 }, { 10, 2929 }, { 10, 2927 }, { 10, 2925 },
{ 10, 2923 }, { 10, 2921 }, { 10, 2919 }, { 10, 2917 }, { 10, 2915 },
{ 10, 2913 }, { 10, 2911 }, { 10, 2909 }, { 10, 2907 }, { 10, 2905 },
{ 10, 2903 }, { 10, 2901 }, { 10, 2899 }, { 10, 2897 }, { 10, 2895 },
{ 10, 2893 }, { 10, 2891 }, { 10, 2889 }, { 10, 2887 }, { 10, 2885 },
{ 10, 2883 }, { 10, 2881 }, { 10, 2879 }, { 10, 2877 }, { 10, 2875 },
{ 10, 2873 }, { 10, 2871 }, { 10, 2869 }, { 10, 2867 }, { 10, 2865 },
{ 10, 2863 }, { 10, 2861 }, { 10, 2859 }, { 10, 2857 }, { 10, 2855 },
{ 10, 2853 }, { 10, 2851 }, { 10, 2849 }, { 10, 2847 }, { 10, 2845 },
{ 10, 2843 }, { 10, 2841 }, { 10, 2839 }, { 10, 2837 }, { 10, 2835 },
{ 10, 2833 }, { 10, 2831 }, { 10, 2829 }, { 10, 2827 }, { 10, 2825 },
{ 10, 2823 }, { 10, 2821 }, { 10, 2819 }, { 10, 2817 }, { 10, 2815 },
{ 10, 2813 }, { 10, 2811 }, { 10, 2809 }, { 10, 2807 }, { 10, 2805 },
{ 10, 2803 }, { 10, 2801 }, { 10, 2799 }, { 10, 2797 }, { 10, 2795 },
{ 10, 2793 }, { 10, 2791 }, { 10, 2789 }, { 10, 2787 }, { 10, 2785 },
{ 10, 2783 }, { 10, 2781 }, { 10, 2779 }, { 10, 2777 }, { 10, 2775 },
{ 10, 2773 }, { 10, 2771 }, { 10, 2769 }, { 10, 2767 }, { 10, 2765 },
{ 10, 2763 }, { 10, 2761 }, { 10, 2759 }, { 10, 2757 }, { 10, 2755 },
{ 10, 2753 }, { 10, 2751 }, { 10, 2749 }, { 10, 2747 }, { 10, 2745 },
{ 10, 2743 }, { 10, 2741 }, { 10, 2739 }, { 10, 2737 }, { 10, 2735 },
{ 10, 2733 }, { 10, 2731 }, { 10, 2729 }, { 10, 2727 }, { 10, 2725 },
{ 10, 2723 }, { 10, 2721 }, { 10, 2719 }, { 10, 2717 }, { 10, 2715 },
{ 10, 2713 }, { 10, 2711 }, { 10, 2709 }, { 10, 2707 }, { 10, 2705 },
{ 10, 2703 }, { 10, 2701 }, { 10, 2699 }, { 10, 2697 }, { 10, 2695 },
{ 10, 2693 }, { 10, 2691 }, { 10, 2689 }, { 10, 2687 }, { 10, 2685 },
{ 10, 2683 }, { 10, 2681 }, { 10, 2679 }, { 10, 2677 }, { 10, 2675 },
{ 10, 2673 }, { 10, 2671 }, { 10, 2669 }, { 10, 2667 }, { 10, 2665 },
{ 10, 2663 }, { 10, 2661 }, { 10, 2659 }, { 10, 2657 }, { 10, 2655 },
{ 10, 2653 }, { 10, 2651 }, { 10, 2649 }, { 10, 2647 }, { 10, 2645 },
{ 10, 2643 }, { 10, 2641 }, { 10, 2639 }, { 10, 2637 }, { 10, 2635 },
{ 10, 2633 }, { 10, 2631 }, { 10, 2629 }, { 10, 2627 }, { 10, 2625 },
{ 10, 2623 }, { 10, 2621 }, { 10, 2619 }, { 10, 2617 }, { 10, 2615 },
{ 10, 2613 }, { 10, 2611 }, { 10, 2609 }, { 10, 2607 }, { 10, 2605 },
{ 10, 2603 }, { 10, 2601 }, { 10, 2599 }, { 10, 2597 }, { 10, 2595 },
{ 10, 2593 }, { 10, 2591 }, { 10, 2589 }, { 10, 2587 }, { 10, 2585 },
{ 10, 2583 }, { 10, 2581 }, { 10, 2579 }, { 10, 2577 }, { 10, 2575 },
{ 10, 2573 }, { 10, 2571 }, { 10, 2569 }, { 10, 2567 }, { 10, 2565 },
{ 10, 2563 }, { 10, 2561 }, { 10, 2559 }, { 10, 2557 }, { 10, 2555 },
{ 10, 2553 }, { 10, 2551 }, { 10, 2549 }, { 10, 2547 }, { 10, 2545 },
{ 10, 2543 }, { 10, 2541 }, { 10, 2539 }, { 10, 2537 }, { 10, 2535 },
{ 10, 2533 }, { 10, 2531 }, { 10, 2529 }, { 10, 2527 }, { 10, 2525 },
{ 10, 2523 }, { 10, 2521 }, { 10, 2519 }, { 10, 2517 }, { 10, 2515 },
{ 10, 2513 }, { 10, 2511 }, { 10, 2509 }, { 10, 2507 }, { 10, 2505 },
{ 10, 2503 }, { 10, 2501 }, { 10, 2499 }, { 10, 2497 }, { 10, 2495 },
{ 10, 2493 }, { 10, 2491 }, { 10, 2489 }, { 10, 2487 }, { 10, 2485 },
{ 10, 2483 }, { 10, 2481 }, { 10, 2479 }, { 10, 2477 }, { 10, 2475 },
{ 10, 2473 }, { 10, 2471 }, { 10, 2469 }, { 10, 2467 }, { 10, 2465 },
{ 10, 2463 }, { 10, 2461 }, { 10, 2459 }, { 10, 2457 }, { 10, 2455 },
{ 10, 2453 }, { 10, 2451 }, { 10, 2449 }, { 10, 2447 }, { 10, 2445 },
{ 10, 2443 }, { 10, 2441 }, { 10, 2439 }, { 10, 2437 }, { 10, 2435 },
{ 10, 2433 }, { 10, 2431 }, { 10, 2429 }, { 10, 2427 }, { 10, 2425 },
{ 10, 2423 }, { 10, 2421 }, { 10, 2419 }, { 10, 2417 }, { 10, 2415 },
{ 10, 2413 }, { 10, 2411 }, { 10, 2409 }, { 10, 2407 }, { 10, 2405 },
{ 10, 2403 }, { 10, 2401 }, { 10, 2399 }, { 10, 2397 }, { 10, 2395 },
{ 10, 2393 }, { 10, 2391 }, { 10, 2389 }, { 10, 2387 }, { 10, 2385 },
{ 10, 2383 }, { 10, 2381 }, { 10, 2379 }, { 10, 2377 }, { 10, 2375 },
{ 10, 2373 }, { 10, 2371 }, { 10, 2369 }, { 10, 2367 }, { 10, 2365 },
{ 10, 2363 }, { 10, 2361 }, { 10, 2359 }, { 10, 2357 }, { 10, 2355 },
{ 10, 2353 }, { 10, 2351 }, { 10, 2349 }, { 10, 2347 }, { 10, 2345 },
{ 10, 2343 }, { 10, 2341 }, { 10, 2339 }, { 10, 2337 }, { 10, 2335 },
{ 10, 2333 }, { 10, 2331 }, { 10, 2329 }, { 10, 2327 }, { 10, 2325 },
{ 10, 2323 }, { 10, 2321 }, { 10, 2319 }, { 10, 2317 }, { 10, 2315 },
{ 10, 2313 }, { 10, 2311 }, { 10, 2309 }, { 10, 2307 }, { 10, 2305 },
{ 10, 2303 }, { 10, 2301 }, { 10, 2299 }, { 10, 2297 }, { 10, 2295 },
{ 10, 2293 }, { 10, 2291 }, { 10, 2289 }, { 10, 2287 }, { 10, 2285 },
{ 10, 2283 }, { 10, 2281 }, { 10, 2279 }, { 10, 2277 }, { 10, 2275 },
{ 10, 2273 }, { 10, 2271 }, { 10, 2269 }, { 10, 2267 }, { 10, 2265 },
{ 10, 2263 }, { 10, 2261 }, { 10, 2259 }, { 10, 2257 }, { 10, 2255 },
{ 10, 2253 }, { 10, 2251 }, { 10, 2249 }, { 10, 2247 }, { 10, 2245 },
{ 10, 2243 }, { 10, 2241 }, { 10, 2239 }, { 10, 2237 }, { 10, 2235 },
{ 10, 2233 }, { 10, 2231 }, { 10, 2229 }, { 10, 2227 }, { 10, 2225 },
{ 10, 2223 }, { 10, 2221 }, { 10, 2219 }, { 10, 2217 }, { 10, 2215 },
{ 10, 2213 }, { 10, 2211 }, { 10, 2209 }, { 10, 2207 }, { 10, 2205 },
{ 10, 2203 }, { 10, 2201 }, { 10, 2199 }, { 10, 2197 }, { 10, 2195 },
{ 10, 2193 }, { 10, 2191 }, { 10, 2189 }, { 10, 2187 }, { 10, 2185 },
{ 10, 2183 }, { 10, 2181 }, { 10, 2179 }, { 10, 2177 }, { 10, 2175 },
{ 10, 2173 }, { 10, 2171 }, { 10, 2169 }, { 10, 2167 }, { 10, 2165 },
{ 10, 2163 }, { 10, 2161 }, { 10, 2159 }, { 10, 2157 }, { 10, 2155 },
{ 10, 2153 }, { 10, 2151 }, { 10, 2149 }, { 10, 2147 }, { 10, 2145 },
{ 10, 2143 }, { 10, 2141 }, { 10, 2139 }, { 10, 2137 }, { 10, 2135 },
{ 10, 2133 }, { 10, 2131 }, { 10, 2129 }, { 10, 2127 }, { 10, 2125 },
{ 10, 2123 }, { 10, 2121 }, { 10, 2119 }, { 10, 2117 }, { 10, 2115 },
{ 10, 2113 }, { 10, 2111 }, { 10, 2109 }, { 10, 2107 }, { 10, 2105 },
{ 10, 2103 }, { 10, 2101 }, { 10, 2099 }, { 10, 2097 }, { 10, 2095 },
{ 10, 2093 }, { 10, 2091 }, { 10, 2089 }, { 10, 2087 }, { 10, 2085 },
{ 10, 2083 }, { 10, 2081 }, { 10, 2079 }, { 10, 2077 }, { 10, 2075 },
{ 10, 2073 }, { 10, 2071 }, { 10, 2069 }, { 10, 2067 }, { 10, 2065 },
{ 10, 2063 }, { 10, 2061 }, { 10, 2059 }, { 10, 2057 }, { 10, 2055 },
{ 10, 2053 }, { 10, 2051 }, { 10, 2049 }, { 10, 2047 }, { 10, 2045 },
{ 10, 2043 }, { 10, 2041 }, { 10, 2039 }, { 10, 2037 }, { 10, 2035 },
{ 10, 2033 }, { 10, 2031 }, { 10, 2029 }, { 10, 2027 }, { 10, 2025 },
{ 10, 2023 }, { 10, 2021 }, { 10, 2019 }, { 10, 2017 }, { 10, 2015 },
{ 10, 2013 }, { 10, 2011 }, { 10, 2009 }, { 10, 2007 }, { 10, 2005 },
{ 10, 2003 }, { 10, 2001 }, { 10, 1999 }, { 10, 1997 }, { 10, 1995 },
{ 10, 1993 }, { 10, 1991 }, { 10, 1989 }, { 10, 1987 }, { 10, 1985 },
{ 10, 1983 }, { 10, 1981 }, { 10, 1979 }, { 10, 1977 }, { 10, 1975 },
{ 10, 1973 }, { 10, 1971 }, { 10, 1969 }, { 10, 1967 }, { 10, 1965 },
{ 10, 1963 }, { 10, 1961 }, { 10, 1959 }, { 10, 1957 }, { 10, 1955 },
{ 10, 1953 }, { 10, 1951 }, { 10, 1949 }, { 10, 1947 }, { 10, 1945 },
{ 10, 1943 }, { 10, 1941 }, { 10, 1939 }, { 10, 1937 }, { 10, 1935 },
{ 10, 1933 }, { 10, 1931 }, { 10, 1929 }, { 10, 1927 }, { 10, 1925 },
{ 10, 1923 }, { 10, 1921 }, { 10, 1919 }, { 10, 1917 }, { 10, 1915 },
{ 10, 1913 }, { 10, 1911 }, { 10, 1909 }, { 10, 1907 }, { 10, 1905 },
{ 10, 1903 }, { 10, 1901 }, { 10, 1899 }, { 10, 1897 }, { 10, 1895 },
{ 10, 1893 }, { 10, 1891 }, { 10, 1889 }, { 10, 1887 }, { 10, 1885 },
{ 10, 1883 }, { 10, 1881 }, { 10, 1879 }, { 10, 1877 }, { 10, 1875 },
{ 10, 1873 }, { 10, 1871 }, { 10, 1869 }, { 10, 1867 }, { 10, 1865 },
{ 10, 1863 }, { 10, 1861 }, { 10, 1859 }, { 10, 1857 }, { 10, 1855 },
{ 10, 1853 }, { 10, 1851 }, { 10, 1849 }, { 10, 1847 }, { 10, 1845 },
{ 10, 1843 }, { 10, 1841 }, { 10, 1839 }, { 10, 1837 }, { 10, 1835 },
{ 10, 1833 }, { 10, 1831 }, { 10, 1829 }, { 10, 1827 }, { 10, 1825 },
{ 10, 1823 }, { 10, 1821 }, { 10, 1819 }, { 10, 1817 }, { 10, 1815 },
{ 10, 1813 }, { 10, 1811 }, { 10, 1809 }, { 10, 1807 }, { 10, 1805 },
{ 10, 1803 }, { 10, 1801 }, { 10, 1799 }, { 10, 1797 }, { 10, 1795 },
{ 10, 1793 }, { 10, 1791 }, { 10, 1789 }, { 10, 1787 }, { 10, 1785 },
{ 10, 1783 }, { 10, 1781 }, { 10, 1779 }, { 10, 1777 }, { 10, 1775 },
{ 10, 1773 }, { 10, 1771 }, { 10, 1769 }, { 10, 1767 }, { 10, 1765 },
{ 10, 1763 }, { 10, 1761 }, { 10, 1759 }, { 10, 1757 }, { 10, 1755 },
{ 10, 1753 }, { 10, 1751 }, { 10, 1749 }, { 10, 1747 }, { 10, 1745 },
{ 10, 1743 }, { 10, 1741 }, { 10, 1739 }, { 10, 1737 }, { 10, 1735 },
{ 10, 1733 }, { 10, 1731 }, { 10, 1729 }, { 10, 1727 }, { 10, 1725 },
{ 10, 1723 }, { 10, 1721 }, { 10, 1719 }, { 10, 1717 }, { 10, 1715 },
{ 10, 1713 }, { 10, 1711 }, { 10, 1709 }, { 10, 1707 }, { 10, 1705 },
{ 10, 1703 }, { 10, 1701 }, { 10, 1699 }, { 10, 1697 }, { 10, 1695 },
{ 10, 1693 }, { 10, 1691 }, { 10, 1689 }, { 10, 1687 }, { 10, 1685 },
{ 10, 1683 }, { 10, 1681 }, { 10, 1679 }, { 10, 1677 }, { 10, 1675 },
{ 10, 1673 }, { 10, 1671 }, { 10, 1669 }, { 10, 1667 }, { 10, 1665 },
{ 10, 1663 }, { 10, 1661 }, { 10, 1659 }, { 10, 1657 }, { 10, 1655 },
{ 10, 1653 }, { 10, 1651 }, { 10, 1649 }, { 10, 1647 }, { 10, 1645 },
{ 10, 1643 }, { 10, 1641 }, { 10, 1639 }, { 10, 1637 }, { 10, 1635 },
{ 10, 1633 }, { 10, 1631 }, { 10, 1629 }, { 10, 1627 }, { 10, 1625 },
{ 10, 1623 }, { 10, 1621 }, { 10, 1619 }, { 10, 1617 }, { 10, 1615 },
{ 10, 1613 }, { 10, 1611 }, { 10, 1609 }, { 10, 1607 }, { 10, 1605 },
{ 10, 1603 }, { 10, 1601 }, { 10, 1599 }, { 10, 1597 }, { 10, 1595 },
{ 10, 1593 }, { 10, 1591 }, { 10, 1589 }, { 10, 1587 }, { 10, 1585 },
{ 10, 1583 }, { 10, 1581 }, { 10, 1579 }, { 10, 1577 }, { 10, 1575 },
{ 10, 1573 }, { 10, 1571 }, { 10, 1569 }, { 10, 1567 }, { 10, 1565 },
{ 10, 1563 }, { 10, 1561 }, { 10, 1559 }, { 10, 1557 }, { 10, 1555 },
{ 10, 1553 }, { 10, 1551 }, { 10, 1549 }, { 10, 1547 }, { 10, 1545 },
{ 10, 1543 }, { 10, 1541 }, { 10, 1539 }, { 10, 1537 }, { 10, 1535 },
{ 10, 1533 }, { 10, 1531 }, { 10, 1529 }, { 10, 1527 }, { 10, 1525 },
{ 10, 1523 }, { 10, 1521 }, { 10, 1519 }, { 10, 1517 }, { 10, 1515 },
{ 10, 1513 }, { 10, 1511 }, { 10, 1509 }, { 10, 1507 }, { 10, 1505 },
{ 10, 1503 }, { 10, 1501 }, { 10, 1499 }, { 10, 1497 }, { 10, 1495 },
{ 10, 1493 }, { 10, 1491 }, { 10, 1489 }, { 10, 1487 }, { 10, 1485 },
{ 10, 1483 }, { 10, 1481 }, { 10, 1479 }, { 10, 1477 }, { 10, 1475 },
{ 10, 1473 }, { 10, 1471 }, { 10, 1469 }, { 10, 1467 }, { 10, 1465 },
{ 10, 1463 }, { 10, 1461 }, { 10, 1459 }, { 10, 1457 }, { 10, 1455 },
{ 10, 1453 }, { 10, 1451 }, { 10, 1449 }, { 10, 1447 }, { 10, 1445 },
{ 10, 1443 }, { 10, 1441 }, { 10, 1439 }, { 10, 1437 }, { 10, 1435 },
{ 10, 1433 }, { 10, 1431 }, { 10, 1429 }, { 10, 1427 }, { 10, 1425 },
{ 10, 1423 }, { 10, 1421 }, { 10, 1419 }, { 10, 1417 }, { 10, 1415 },
{ 10, 1413 }, { 10, 1411 }, { 10, 1409 }, { 10, 1407 }, { 10, 1405 },
{ 10, 1403 }, { 10, 1401 }, { 10, 1399 }, { 10, 1397 }, { 10, 1395 },
{ 10, 1393 }, { 10, 1391 }, { 10, 1389 }, { 10, 1387 }, { 10, 1385 },
{ 10, 1383 }, { 10, 1381 }, { 10, 1379 }, { 10, 1377 }, { 10, 1375 },
{ 10, 1373 }, { 10, 1371 }, { 10, 1369 }, { 10, 1367 }, { 10, 1365 },
{ 10, 1363 }, { 10, 1361 }, { 10, 1359 }, { 10, 1357 }, { 10, 1355 },
{ 10, 1353 }, { 10, 1351 }, { 10, 1349 }, { 10, 1347 }, { 10, 1345 },
{ 10, 1343 }, { 10, 1341 }, { 10, 1339 }, { 10, 1337 }, { 10, 1335 },
{ 10, 1333 }, { 10, 1331 }, { 10, 1329 }, { 10, 1327 }, { 10, 1325 },
{ 10, 1323 }, { 10, 1321 }, { 10, 1319 }, { 10, 1317 }, { 10, 1315 },
{ 10, 1313 }, { 10, 1311 }, { 10, 1309 }, { 10, 1307 }, { 10, 1305 },
{ 10, 1303 }, { 10, 1301 }, { 10, 1299 }, { 10, 1297 }, { 10, 1295 },
{ 10, 1293 }, { 10, 1291 }, { 10, 1289 }, { 10, 1287 }, { 10, 1285 },
{ 10, 1283 }, { 10, 1281 }, { 10, 1279 }, { 10, 1277 }, { 10, 1275 },
{ 10, 1273 }, { 10, 1271 }, { 10, 1269 }, { 10, 1267 }, { 10, 1265 },
{ 10, 1263 }, { 10, 1261 }, { 10, 1259 }, { 10, 1257 }, { 10, 1255 },
{ 10, 1253 }, { 10, 1251 }, { 10, 1249 }, { 10, 1247 }, { 10, 1245 },
{ 10, 1243 }, { 10, 1241 }, { 10, 1239 }, { 10, 1237 }, { 10, 1235 },
{ 10, 1233 }, { 10, 1231 }, { 10, 1229 }, { 10, 1227 }, { 10, 1225 },
{ 10, 1223 }, { 10, 1221 }, { 10, 1219 }, { 10, 1217 }, { 10, 1215 },
{ 10, 1213 }, { 10, 1211 }, { 10, 1209 }, { 10, 1207 }, { 10, 1205 },
{ 10, 1203 }, { 10, 1201 }, { 10, 1199 }, { 10, 1197 }, { 10, 1195 },
{ 10, 1193 }, { 10, 1191 }, { 10, 1189 }, { 10, 1187 }, { 10, 1185 },
{ 10, 1183 }, { 10, 1181 }, { 10, 1179 }, { 10, 1177 }, { 10, 1175 },
{ 10, 1173 }, { 10, 1171 }, { 10, 1169 }, { 10, 1167 }, { 10, 1165 },
{ 10, 1163 }, { 10, 1161 }, { 10, 1159 }, { 10, 1157 }, { 10, 1155 },
{ 10, 1153 }, { 10, 1151 }, { 10, 1149 }, { 10, 1147 }, { 10, 1145 },
{ 10, 1143 }, { 10, 1141 }, { 10, 1139 }, { 10, 1137 }, { 10, 1135 },
{ 10, 1133 }, { 10, 1131 }, { 10, 1129 }, { 10, 1127 }, { 10, 1125 },
{ 10, 1123 }, { 10, 1121 }, { 10, 1119 }, { 10, 1117 }, { 10, 1115 },
{ 10, 1113 }, { 10, 1111 }, { 10, 1109 }, { 10, 1107 }, { 10, 1105 },
{ 10, 1103 }, { 10, 1101 }, { 10, 1099 }, { 10, 1097 }, { 10, 1095 },
{ 10, 1093 }, { 10, 1091 }, { 10, 1089 }, { 10, 1087 }, { 10, 1085 },
{ 10, 1083 }, { 10, 1081 }, { 10, 1079 }, { 10, 1077 }, { 10, 1075 },
{ 10, 1073 }, { 10, 1071 }, { 10, 1069 }, { 10, 1067 }, { 10, 1065 },
{ 10, 1063 }, { 10, 1061 }, { 10, 1059 }, { 10, 1057 }, { 10, 1055 },
{ 10, 1053 }, { 10, 1051 }, { 10, 1049 }, { 10, 1047 }, { 10, 1045 },
{ 10, 1043 }, { 10, 1041 }, { 10, 1039 }, { 10, 1037 }, { 10, 1035 },
{ 10, 1033 }, { 10, 1031 }, { 10, 1029 }, { 10, 1027 }, { 10, 1025 },
{ 10, 1023 }, { 10, 1021 }, { 10, 1019 }, { 10, 1017 }, { 10, 1015 },
{ 10, 1013 }, { 10, 1011 }, { 10, 1009 }, { 10, 1007 }, { 10, 1005 },
{ 10, 1003 }, { 10, 1001 }, { 10, 999 }, { 10, 997 }, { 10, 995 },
{ 10, 993 }, { 10, 991 }, { 10, 989 }, { 10, 987 }, { 10, 985 },
{ 10, 983 }, { 10, 981 }, { 10, 979 }, { 10, 977 }, { 10, 975 },
{ 10, 973 }, { 10, 971 }, { 10, 969 }, { 10, 967 }, { 10, 965 },
{ 10, 963 }, { 10, 961 }, { 10, 959 }, { 10, 957 }, { 10, 955 },
{ 10, 953 }, { 10, 951 }, { 10, 949 }, { 10, 947 }, { 10, 945 },
{ 10, 943 }, { 10, 941 }, { 10, 939 }, { 10, 937 }, { 10, 935 },
{ 10, 933 }, { 10, 931 }, { 10, 929 }, { 10, 927 }, { 10, 925 },
{ 10, 923 }, { 10, 921 }, { 10, 919 }, { 10, 917 }, { 10, 915 },
{ 10, 913 }, { 10, 911 }, { 10, 909 }, { 10, 907 }, { 10, 905 },
{ 10, 903 }, { 10, 901 }, { 10, 899 }, { 10, 897 }, { 10, 895 },
{ 10, 893 }, { 10, 891 }, { 10, 889 }, { 10, 887 }, { 10, 885 },
{ 10, 883 }, { 10, 881 }, { 10, 879 }, { 10, 877 }, { 10, 875 },
{ 10, 873 }, { 10, 871 }, { 10, 869 }, { 10, 867 }, { 10, 865 },
{ 10, 863 }, { 10, 861 }, { 10, 859 }, { 10, 857 }, { 10, 855 },
{ 10, 853 }, { 10, 851 }, { 10, 849 }, { 10, 847 }, { 10, 845 },
{ 10, 843 }, { 10, 841 }, { 10, 839 }, { 10, 837 }, { 10, 835 },
{ 10, 833 }, { 10, 831 }, { 10, 829 }, { 10, 827 }, { 10, 825 },
{ 10, 823 }, { 10, 821 }, { 10, 819 }, { 10, 817 }, { 10, 815 },
{ 10, 813 }, { 10, 811 }, { 10, 809 }, { 10, 807 }, { 10, 805 },
{ 10, 803 }, { 10, 801 }, { 10, 799 }, { 10, 797 }, { 10, 795 },
{ 10, 793 }, { 10, 791 }, { 10, 789 }, { 10, 787 }, { 10, 785 },
{ 10, 783 }, { 10, 781 }, { 10, 779 }, { 10, 777 }, { 10, 775 },
{ 10, 773 }, { 10, 771 }, { 10, 769 }, { 10, 767 }, { 10, 765 },
{ 10, 763 }, { 10, 761 }, { 10, 759 }, { 10, 757 }, { 10, 755 },
{ 10, 753 }, { 10, 751 }, { 10, 749 }, { 10, 747 }, { 10, 745 },
{ 10, 743 }, { 10, 741 }, { 10, 739 }, { 10, 737 }, { 10, 735 },
{ 10, 733 }, { 10, 731 }, { 10, 729 }, { 10, 727 }, { 10, 725 },
{ 10, 723 }, { 10, 721 }, { 10, 719 }, { 10, 717 }, { 10, 715 },
{ 10, 713 }, { 10, 711 }, { 10, 709 }, { 10, 707 }, { 10, 705 },
{ 10, 703 }, { 10, 701 }, { 10, 699 }, { 10, 697 }, { 10, 695 },
{ 10, 693 }, { 10, 691 }, { 10, 689 }, { 10, 687 }, { 10, 685 },
{ 10, 683 }, { 10, 681 }, { 10, 679 }, { 10, 677 }, { 10, 675 },
{ 10, 673 }, { 10, 671 }, { 10, 669 }, { 10, 667 }, { 10, 665 },
{ 10, 663 }, { 10, 661 }, { 10, 659 }, { 10, 657 }, { 10, 655 },
{ 10, 653 }, { 10, 651 }, { 10, 649 }, { 10, 647 }, { 10, 645 },
{ 10, 643 }, { 10, 641 }, { 10, 639 }, { 10, 637 }, { 10, 635 },
{ 10, 633 }, { 10, 631 }, { 10, 629 }, { 10, 627 }, { 10, 625 },
{ 10, 623 }, { 10, 621 }, { 10, 619 }, { 10, 617 }, { 10, 615 },
{ 10, 613 }, { 10, 611 }, { 10, 609 }, { 10, 607 }, { 10, 605 },
{ 10, 603 }, { 10, 601 }, { 10, 599 }, { 10, 597 }, { 10, 595 },
{ 10, 593 }, { 10, 591 }, { 10, 589 }, { 10, 587 }, { 10, 585 },
{ 10, 583 }, { 10, 581 }, { 10, 579 }, { 10, 577 }, { 10, 575 },
{ 10, 573 }, { 10, 571 }, { 10, 569 }, { 10, 567 }, { 10, 565 },
{ 10, 563 }, { 10, 561 }, { 10, 559 }, { 10, 557 }, { 10, 555 },
{ 10, 553 }, { 10, 551 }, { 10, 549 }, { 10, 547 }, { 10, 545 },
{ 10, 543 }, { 10, 541 }, { 10, 539 }, { 10, 537 }, { 10, 535 },
{ 10, 533 }, { 10, 531 }, { 10, 529 }, { 10, 527 }, { 10, 525 },
{ 10, 523 }, { 10, 521 }, { 10, 519 }, { 10, 517 }, { 10, 515 },
{ 10, 513 }, { 10, 511 }, { 10, 509 }, { 10, 507 }, { 10, 505 },
{ 10, 503 }, { 10, 501 }, { 10, 499 }, { 10, 497 }, { 10, 495 },
{ 10, 493 }, { 10, 491 }, { 10, 489 }, { 10, 487 }, { 10, 485 },
{ 10, 483 }, { 10, 481 }, { 10, 479 }, { 10, 477 }, { 10, 475 },
{ 10, 473 }, { 10, 471 }, { 10, 469 }, { 10, 467 }, { 10, 465 },
{ 10, 463 }, { 10, 461 }, { 10, 459 }, { 10, 457 }, { 10, 455 },
{ 10, 453 }, { 10, 451 }, { 10, 449 }, { 10, 447 }, { 10, 445 },
{ 10, 443 }, { 10, 441 }, { 10, 439 }, { 10, 437 }, { 10, 435 },
{ 10, 433 }, { 10, 431 }, { 10, 429 }, { 10, 427 }, { 10, 425 },
{ 10, 423 }, { 10, 421 }, { 10, 419 }, { 10, 417 }, { 10, 415 },
{ 10, 413 }, { 10, 411 }, { 10, 409 }, { 10, 407 }, { 10, 405 },
{ 10, 403 }, { 10, 401 }, { 10, 399 }, { 10, 397 }, { 10, 395 },
{ 10, 393 }, { 10, 391 }, { 10, 389 }, { 10, 387 }, { 10, 385 },
{ 10, 383 }, { 10, 381 }, { 10, 379 }, { 10, 377 }, { 10, 375 },
{ 10, 373 }, { 10, 371 }, { 10, 369 }, { 10, 367 }, { 10, 365 },
{ 10, 363 }, { 10, 361 }, { 10, 359 }, { 10, 357 }, { 10, 355 },
{ 10, 353 }, { 10, 351 }, { 10, 349 }, { 10, 347 }, { 10, 345 },
{ 10, 343 }, { 10, 341 }, { 10, 339 }, { 10, 337 }, { 10, 335 },
{ 10, 333 }, { 10, 331 }, { 10, 329 }, { 10, 327 }, { 10, 325 },
{ 10, 323 }, { 10, 321 }, { 10, 319 }, { 10, 317 }, { 10, 315 },
{ 10, 313 }, { 10, 311 }, { 10, 309 }, { 10, 307 }, { 10, 305 },
{ 10, 303 }, { 10, 301 }, { 10, 299 }, { 10, 297 }, { 10, 295 },
{ 10, 293 }, { 10, 291 }, { 10, 289 }, { 10, 287 }, { 10, 285 },
{ 10, 283 }, { 10, 281 }, { 10, 279 }, { 10, 277 }, { 10, 275 },
{ 10, 273 }, { 10, 271 }, { 10, 269 }, { 10, 267 }, { 10, 265 },
{ 10, 263 }, { 10, 261 }, { 10, 259 }, { 10, 257 }, { 10, 255 },
{ 10, 253 }, { 10, 251 }, { 10, 249 }, { 10, 247 }, { 10, 245 },
{ 10, 243 }, { 10, 241 }, { 10, 239 }, { 10, 237 }, { 10, 235 },
{ 10, 233 }, { 10, 231 }, { 10, 229 }, { 10, 227 }, { 10, 225 },
{ 10, 223 }, { 10, 221 }, { 10, 219 }, { 10, 217 }, { 10, 215 },
{ 10, 213 }, { 10, 211 }, { 10, 209 }, { 10, 207 }, { 10, 205 },
{ 10, 203 }, { 10, 201 }, { 10, 199 }, { 10, 197 }, { 10, 195 },
{ 10, 193 }, { 10, 191 }, { 10, 189 }, { 10, 187 }, { 10, 185 },
{ 10, 183 }, { 10, 181 }, { 10, 179 }, { 10, 177 }, { 10, 175 },
{ 10, 173 }, { 10, 171 }, { 10, 169 }, { 10, 167 }, { 10, 165 },
{ 10, 163 }, { 10, 161 }, { 10, 159 }, { 10, 157 }, { 10, 155 },
{ 10, 153 }, { 10, 151 }, { 10, 149 }, { 10, 147 }, { 10, 145 },
{ 10, 143 }, { 10, 141 }, { 10, 139 }, { 10, 137 }, { 10, 135 },
{ 10, 133 }, { 10, 131 }, { 10, 129 }, { 10, 127 }, { 10, 125 },
{ 10, 123 }, { 10, 121 }, { 10, 119 }, { 10, 117 }, { 10, 115 },
{ 10, 113 }, { 10, 111 }, { 10, 109 }, { 10, 107 }, { 10, 105 },
{ 10, 103 }, { 10, 101 }, { 10, 99 }, { 10, 97 }, { 10, 95 },
{ 10, 93 }, { 10, 91 }, { 10, 89 }, { 10, 87 }, { 10, 85 },
{ 10, 83 }, { 10, 81 }, { 10, 79 }, { 10, 77 }, { 10, 75 },
{ 10, 73 }, { 10, 71 }, { 10, 69 }, { 10, 67 }, { 10, 65 },
{ 10, 63 }, { 10, 61 }, { 10, 59 }, { 10, 57 }, { 10, 55 },
{ 10, 53 }, { 10, 51 }, { 10, 49 }, { 10, 47 }, { 10, 45 },
{ 10, 43 }, { 10, 41 }, { 10, 39 }, { 10, 37 }, { 10, 35 },
{ 10, 33 }, { 10, 31 }, { 10, 29 }, { 10, 27 }, { 10, 25 },
{ 10, 23 }, { 10, 21 }, { 10, 19 }, { 10, 17 }, { 10, 15 },
{ 10, 13 }, { 10, 11 }, { 10, 9 }, { 10, 7 }, { 10, 5 },
{ 10, 3 }, { 10, 1 }, { 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 },
{ 10, 0 }, { 10, 2 }, { 10, 4 }, { 10, 6 }, { 10, 8 },
{ 10, 10 }, { 10, 12 }, { 10, 14 }, { 10, 16 }, { 10, 18 },
{ 10, 20 }, { 10, 22 }, { 10, 24 }, { 10, 26 }, { 10, 28 },
{ 10, 30 }, { 10, 32 }, { 10, 34 }, { 10, 36 }, { 10, 38 },
{ 10, 40 }, { 10, 42 }, { 10, 44 }, { 10, 46 }, { 10, 48 },
{ 10, 50 }, { 10, 52 }, { 10, 54 }, { 10, 56 }, { 10, 58 },
{ 10, 60 }, { 10, 62 }, { 10, 64 }, { 10, 66 }, { 10, 68 },
{ 10, 70 }, { 10, 72 }, { 10, 74 }, { 10, 76 }, { 10, 78 },
{ 10, 80 }, { 10, 82 }, { 10, 84 }, { 10, 86 }, { 10, 88 },
{ 10, 90 }, { 10, 92 }, { 10, 94 }, { 10, 96 }, { 10, 98 },
{ 10, 100 }, { 10, 102 }, { 10, 104 }, { 10, 106 }, { 10, 108 },
{ 10, 110 }, { 10, 112 }, { 10, 114 }, { 10, 116 }, { 10, 118 },
{ 10, 120 }, { 10, 122 }, { 10, 124 }, { 10, 126 }, { 10, 128 },
{ 10, 130 }, { 10, 132 }, { 10, 134 }, { 10, 136 }, { 10, 138 },
{ 10, 140 }, { 10, 142 }, { 10, 144 }, { 10, 146 }, { 10, 148 },
{ 10, 150 }, { 10, 152 }, { 10, 154 }, { 10, 156 }, { 10, 158 },
{ 10, 160 }, { 10, 162 }, { 10, 164 }, { 10, 166 }, { 10, 168 },
{ 10, 170 }, { 10, 172 }, { 10, 174 }, { 10, 176 }, { 10, 178 },
{ 10, 180 }, { 10, 182 }, { 10, 184 }, { 10, 186 }, { 10, 188 },
{ 10, 190 }, { 10, 192 }, { 10, 194 }, { 10, 196 }, { 10, 198 },
{ 10, 200 }, { 10, 202 }, { 10, 204 }, { 10, 206 }, { 10, 208 },
{ 10, 210 }, { 10, 212 }, { 10, 214 }, { 10, 216 }, { 10, 218 },
{ 10, 220 }, { 10, 222 }, { 10, 224 }, { 10, 226 }, { 10, 228 },
{ 10, 230 }, { 10, 232 }, { 10, 234 }, { 10, 236 }, { 10, 238 },
{ 10, 240 }, { 10, 242 }, { 10, 244 }, { 10, 246 }, { 10, 248 },
{ 10, 250 }, { 10, 252 }, { 10, 254 }, { 10, 256 }, { 10, 258 },
{ 10, 260 }, { 10, 262 }, { 10, 264 }, { 10, 266 }, { 10, 268 },
{ 10, 270 }, { 10, 272 }, { 10, 274 }, { 10, 276 }, { 10, 278 },
{ 10, 280 }, { 10, 282 }, { 10, 284 }, { 10, 286 }, { 10, 288 },
{ 10, 290 }, { 10, 292 }, { 10, 294 }, { 10, 296 }, { 10, 298 },
{ 10, 300 }, { 10, 302 }, { 10, 304 }, { 10, 306 }, { 10, 308 },
{ 10, 310 }, { 10, 312 }, { 10, 314 }, { 10, 316 }, { 10, 318 },
{ 10, 320 }, { 10, 322 }, { 10, 324 }, { 10, 326 }, { 10, 328 },
{ 10, 330 }, { 10, 332 }, { 10, 334 }, { 10, 336 }, { 10, 338 },
{ 10, 340 }, { 10, 342 }, { 10, 344 }, { 10, 346 }, { 10, 348 },
{ 10, 350 }, { 10, 352 }, { 10, 354 }, { 10, 356 }, { 10, 358 },
{ 10, 360 }, { 10, 362 }, { 10, 364 }, { 10, 366 }, { 10, 368 },
{ 10, 370 }, { 10, 372 }, { 10, 374 }, { 10, 376 }, { 10, 378 },
{ 10, 380 }, { 10, 382 }, { 10, 384 }, { 10, 386 }, { 10, 388 },
{ 10, 390 }, { 10, 392 }, { 10, 394 }, { 10, 396 }, { 10, 398 },
{ 10, 400 }, { 10, 402 }, { 10, 404 }, { 10, 406 }, { 10, 408 },
{ 10, 410 }, { 10, 412 }, { 10, 414 }, { 10, 416 }, { 10, 418 },
{ 10, 420 }, { 10, 422 }, { 10, 424 }, { 10, 426 }, { 10, 428 },
{ 10, 430 }, { 10, 432 }, { 10, 434 }, { 10, 436 }, { 10, 438 },
{ 10, 440 }, { 10, 442 }, { 10, 444 }, { 10, 446 }, { 10, 448 },
{ 10, 450 }, { 10, 452 }, { 10, 454 }, { 10, 456 }, { 10, 458 },
{ 10, 460 }, { 10, 462 }, { 10, 464 }, { 10, 466 }, { 10, 468 },
{ 10, 470 }, { 10, 472 }, { 10, 474 }, { 10, 476 }, { 10, 478 },
{ 10, 480 }, { 10, 482 }, { 10, 484 }, { 10, 486 }, { 10, 488 },
{ 10, 490 }, { 10, 492 }, { 10, 494 }, { 10, 496 }, { 10, 498 },
{ 10, 500 }, { 10, 502 }, { 10, 504 }, { 10, 506 }, { 10, 508 },
{ 10, 510 }, { 10, 512 }, { 10, 514 }, { 10, 516 }, { 10, 518 },
{ 10, 520 }, { 10, 522 }, { 10, 524 }, { 10, 526 }, { 10, 528 },
{ 10, 530 }, { 10, 532 }, { 10, 534 }, { 10, 536 }, { 10, 538 },
{ 10, 540 }, { 10, 542 }, { 10, 544 }, { 10, 546 }, { 10, 548 },
{ 10, 550 }, { 10, 552 }, { 10, 554 }, { 10, 556 }, { 10, 558 },
{ 10, 560 }, { 10, 562 }, { 10, 564 }, { 10, 566 }, { 10, 568 },
{ 10, 570 }, { 10, 572 }, { 10, 574 }, { 10, 576 }, { 10, 578 },
{ 10, 580 }, { 10, 582 }, { 10, 584 }, { 10, 586 }, { 10, 588 },
{ 10, 590 }, { 10, 592 }, { 10, 594 }, { 10, 596 }, { 10, 598 },
{ 10, 600 }, { 10, 602 }, { 10, 604 }, { 10, 606 }, { 10, 608 },
{ 10, 610 }, { 10, 612 }, { 10, 614 }, { 10, 616 }, { 10, 618 },
{ 10, 620 }, { 10, 622 }, { 10, 624 }, { 10, 626 }, { 10, 628 },
{ 10, 630 }, { 10, 632 }, { 10, 634 }, { 10, 636 }, { 10, 638 },
{ 10, 640 }, { 10, 642 }, { 10, 644 }, { 10, 646 }, { 10, 648 },
{ 10, 650 }, { 10, 652 }, { 10, 654 }, { 10, 656 }, { 10, 658 },
{ 10, 660 }, { 10, 662 }, { 10, 664 }, { 10, 666 }, { 10, 668 },
{ 10, 670 }, { 10, 672 }, { 10, 674 }, { 10, 676 }, { 10, 678 },
{ 10, 680 }, { 10, 682 }, { 10, 684 }, { 10, 686 }, { 10, 688 },
{ 10, 690 }, { 10, 692 }, { 10, 694 }, { 10, 696 }, { 10, 698 },
{ 10, 700 }, { 10, 702 }, { 10, 704 }, { 10, 706 }, { 10, 708 },
{ 10, 710 }, { 10, 712 }, { 10, 714 }, { 10, 716 }, { 10, 718 },
{ 10, 720 }, { 10, 722 }, { 10, 724 }, { 10, 726 }, { 10, 728 },
{ 10, 730 }, { 10, 732 }, { 10, 734 }, { 10, 736 }, { 10, 738 },
{ 10, 740 }, { 10, 742 }, { 10, 744 }, { 10, 746 }, { 10, 748 },
{ 10, 750 }, { 10, 752 }, { 10, 754 }, { 10, 756 }, { 10, 758 },
{ 10, 760 }, { 10, 762 }, { 10, 764 }, { 10, 766 }, { 10, 768 },
{ 10, 770 }, { 10, 772 }, { 10, 774 }, { 10, 776 }, { 10, 778 },
{ 10, 780 }, { 10, 782 }, { 10, 784 }, { 10, 786 }, { 10, 788 },
{ 10, 790 }, { 10, 792 }, { 10, 794 }, { 10, 796 }, { 10, 798 },
{ 10, 800 }, { 10, 802 }, { 10, 804 }, { 10, 806 }, { 10, 808 },
{ 10, 810 }, { 10, 812 }, { 10, 814 }, { 10, 816 }, { 10, 818 },
{ 10, 820 }, { 10, 822 }, { 10, 824 }, { 10, 826 }, { 10, 828 },
{ 10, 830 }, { 10, 832 }, { 10, 834 }, { 10, 836 }, { 10, 838 },
{ 10, 840 }, { 10, 842 }, { 10, 844 }, { 10, 846 }, { 10, 848 },
{ 10, 850 }, { 10, 852 }, { 10, 854 }, { 10, 856 }, { 10, 858 },
{ 10, 860 }, { 10, 862 }, { 10, 864 }, { 10, 866 }, { 10, 868 },
{ 10, 870 }, { 10, 872 }, { 10, 874 }, { 10, 876 }, { 10, 878 },
{ 10, 880 }, { 10, 882 }, { 10, 884 }, { 10, 886 }, { 10, 888 },
{ 10, 890 }, { 10, 892 }, { 10, 894 }, { 10, 896 }, { 10, 898 },
{ 10, 900 }, { 10, 902 }, { 10, 904 }, { 10, 906 }, { 10, 908 },
{ 10, 910 }, { 10, 912 }, { 10, 914 }, { 10, 916 }, { 10, 918 },
{ 10, 920 }, { 10, 922 }, { 10, 924 }, { 10, 926 }, { 10, 928 },
{ 10, 930 }, { 10, 932 }, { 10, 934 }, { 10, 936 }, { 10, 938 },
{ 10, 940 }, { 10, 942 }, { 10, 944 }, { 10, 946 }, { 10, 948 },
{ 10, 950 }, { 10, 952 }, { 10, 954 }, { 10, 956 }, { 10, 958 },
{ 10, 960 }, { 10, 962 }, { 10, 964 }, { 10, 966 }, { 10, 968 },
{ 10, 970 }, { 10, 972 }, { 10, 974 }, { 10, 976 }, { 10, 978 },
{ 10, 980 }, { 10, 982 }, { 10, 984 }, { 10, 986 }, { 10, 988 },
{ 10, 990 }, { 10, 992 }, { 10, 994 }, { 10, 996 }, { 10, 998 },
{ 10, 1000 }, { 10, 1002 }, { 10, 1004 }, { 10, 1006 }, { 10, 1008 },
{ 10, 1010 }, { 10, 1012 }, { 10, 1014 }, { 10, 1016 }, { 10, 1018 },
{ 10, 1020 }, { 10, 1022 }, { 10, 1024 }, { 10, 1026 }, { 10, 1028 },
{ 10, 1030 }, { 10, 1032 }, { 10, 1034 }, { 10, 1036 }, { 10, 1038 },
{ 10, 1040 }, { 10, 1042 }, { 10, 1044 }, { 10, 1046 }, { 10, 1048 },
{ 10, 1050 }, { 10, 1052 }, { 10, 1054 }, { 10, 1056 }, { 10, 1058 },
{ 10, 1060 }, { 10, 1062 }, { 10, 1064 }, { 10, 1066 }, { 10, 1068 },
{ 10, 1070 }, { 10, 1072 }, { 10, 1074 }, { 10, 1076 }, { 10, 1078 },
{ 10, 1080 }, { 10, 1082 }, { 10, 1084 }, { 10, 1086 }, { 10, 1088 },
{ 10, 1090 }, { 10, 1092 }, { 10, 1094 }, { 10, 1096 }, { 10, 1098 },
{ 10, 1100 }, { 10, 1102 }, { 10, 1104 }, { 10, 1106 }, { 10, 1108 },
{ 10, 1110 }, { 10, 1112 }, { 10, 1114 }, { 10, 1116 }, { 10, 1118 },
{ 10, 1120 }, { 10, 1122 }, { 10, 1124 }, { 10, 1126 }, { 10, 1128 },
{ 10, 1130 }, { 10, 1132 }, { 10, 1134 }, { 10, 1136 }, { 10, 1138 },
{ 10, 1140 }, { 10, 1142 }, { 10, 1144 }, { 10, 1146 }, { 10, 1148 },
{ 10, 1150 }, { 10, 1152 }, { 10, 1154 }, { 10, 1156 }, { 10, 1158 },
{ 10, 1160 }, { 10, 1162 }, { 10, 1164 }, { 10, 1166 }, { 10, 1168 },
{ 10, 1170 }, { 10, 1172 }, { 10, 1174 }, { 10, 1176 }, { 10, 1178 },
{ 10, 1180 }, { 10, 1182 }, { 10, 1184 }, { 10, 1186 }, { 10, 1188 },
{ 10, 1190 }, { 10, 1192 }, { 10, 1194 }, { 10, 1196 }, { 10, 1198 },
{ 10, 1200 }, { 10, 1202 }, { 10, 1204 }, { 10, 1206 }, { 10, 1208 },
{ 10, 1210 }, { 10, 1212 }, { 10, 1214 }, { 10, 1216 }, { 10, 1218 },
{ 10, 1220 }, { 10, 1222 }, { 10, 1224 }, { 10, 1226 }, { 10, 1228 },
{ 10, 1230 }, { 10, 1232 }, { 10, 1234 }, { 10, 1236 }, { 10, 1238 },
{ 10, 1240 }, { 10, 1242 }, { 10, 1244 }, { 10, 1246 }, { 10, 1248 },
{ 10, 1250 }, { 10, 1252 }, { 10, 1254 }, { 10, 1256 }, { 10, 1258 },
{ 10, 1260 }, { 10, 1262 }, { 10, 1264 }, { 10, 1266 }, { 10, 1268 },
{ 10, 1270 }, { 10, 1272 }, { 10, 1274 }, { 10, 1276 }, { 10, 1278 },
{ 10, 1280 }, { 10, 1282 }, { 10, 1284 }, { 10, 1286 }, { 10, 1288 },
{ 10, 1290 }, { 10, 1292 }, { 10, 1294 }, { 10, 1296 }, { 10, 1298 },
{ 10, 1300 }, { 10, 1302 }, { 10, 1304 }, { 10, 1306 }, { 10, 1308 },
{ 10, 1310 }, { 10, 1312 }, { 10, 1314 }, { 10, 1316 }, { 10, 1318 },
{ 10, 1320 }, { 10, 1322 }, { 10, 1324 }, { 10, 1326 }, { 10, 1328 },
{ 10, 1330 }, { 10, 1332 }, { 10, 1334 }, { 10, 1336 }, { 10, 1338 },
{ 10, 1340 }, { 10, 1342 }, { 10, 1344 }, { 10, 1346 }, { 10, 1348 },
{ 10, 1350 }, { 10, 1352 }, { 10, 1354 }, { 10, 1356 }, { 10, 1358 },
{ 10, 1360 }, { 10, 1362 }, { 10, 1364 }, { 10, 1366 }, { 10, 1368 },
{ 10, 1370 }, { 10, 1372 }, { 10, 1374 }, { 10, 1376 }, { 10, 1378 },
{ 10, 1380 }, { 10, 1382 }, { 10, 1384 }, { 10, 1386 }, { 10, 1388 },
{ 10, 1390 }, { 10, 1392 }, { 10, 1394 }, { 10, 1396 }, { 10, 1398 },
{ 10, 1400 }, { 10, 1402 }, { 10, 1404 }, { 10, 1406 }, { 10, 1408 },
{ 10, 1410 }, { 10, 1412 }, { 10, 1414 }, { 10, 1416 }, { 10, 1418 },
{ 10, 1420 }, { 10, 1422 }, { 10, 1424 }, { 10, 1426 }, { 10, 1428 },
{ 10, 1430 }, { 10, 1432 }, { 10, 1434 }, { 10, 1436 }, { 10, 1438 },
{ 10, 1440 }, { 10, 1442 }, { 10, 1444 }, { 10, 1446 }, { 10, 1448 },
{ 10, 1450 }, { 10, 1452 }, { 10, 1454 }, { 10, 1456 }, { 10, 1458 },
{ 10, 1460 }, { 10, 1462 }, { 10, 1464 }, { 10, 1466 }, { 10, 1468 },
{ 10, 1470 }, { 10, 1472 }, { 10, 1474 }, { 10, 1476 }, { 10, 1478 },
{ 10, 1480 }, { 10, 1482 }, { 10, 1484 }, { 10, 1486 }, { 10, 1488 },
{ 10, 1490 }, { 10, 1492 }, { 10, 1494 }, { 10, 1496 }, { 10, 1498 },
{ 10, 1500 }, { 10, 1502 }, { 10, 1504 }, { 10, 1506 }, { 10, 1508 },
{ 10, 1510 }, { 10, 1512 }, { 10, 1514 }, { 10, 1516 }, { 10, 1518 },
{ 10, 1520 }, { 10, 1522 }, { 10, 1524 }, { 10, 1526 }, { 10, 1528 },
{ 10, 1530 }, { 10, 1532 }, { 10, 1534 }, { 10, 1536 }, { 10, 1538 },
{ 10, 1540 }, { 10, 1542 }, { 10, 1544 }, { 10, 1546 }, { 10, 1548 },
{ 10, 1550 }, { 10, 1552 }, { 10, 1554 }, { 10, 1556 }, { 10, 1558 },
{ 10, 1560 }, { 10, 1562 }, { 10, 1564 }, { 10, 1566 }, { 10, 1568 },
{ 10, 1570 }, { 10, 1572 }, { 10, 1574 }, { 10, 1576 }, { 10, 1578 },
{ 10, 1580 }, { 10, 1582 }, { 10, 1584 }, { 10, 1586 }, { 10, 1588 },
{ 10, 1590 }, { 10, 1592 }, { 10, 1594 }, { 10, 1596 }, { 10, 1598 },
{ 10, 1600 }, { 10, 1602 }, { 10, 1604 }, { 10, 1606 }, { 10, 1608 },
{ 10, 1610 }, { 10, 1612 }, { 10, 1614 }, { 10, 1616 }, { 10, 1618 },
{ 10, 1620 }, { 10, 1622 }, { 10, 1624 }, { 10, 1626 }, { 10, 1628 },
{ 10, 1630 }, { 10, 1632 }, { 10, 1634 }, { 10, 1636 }, { 10, 1638 },
{ 10, 1640 }, { 10, 1642 }, { 10, 1644 }, { 10, 1646 }, { 10, 1648 },
{ 10, 1650 }, { 10, 1652 }, { 10, 1654 }, { 10, 1656 }, { 10, 1658 },
{ 10, 1660 }, { 10, 1662 }, { 10, 1664 }, { 10, 1666 }, { 10, 1668 },
{ 10, 1670 }, { 10, 1672 }, { 10, 1674 }, { 10, 1676 }, { 10, 1678 },
{ 10, 1680 }, { 10, 1682 }, { 10, 1684 }, { 10, 1686 }, { 10, 1688 },
{ 10, 1690 }, { 10, 1692 }, { 10, 1694 }, { 10, 1696 }, { 10, 1698 },
{ 10, 1700 }, { 10, 1702 }, { 10, 1704 }, { 10, 1706 }, { 10, 1708 },
{ 10, 1710 }, { 10, 1712 }, { 10, 1714 }, { 10, 1716 }, { 10, 1718 },
{ 10, 1720 }, { 10, 1722 }, { 10, 1724 }, { 10, 1726 }, { 10, 1728 },
{ 10, 1730 }, { 10, 1732 }, { 10, 1734 }, { 10, 1736 }, { 10, 1738 },
{ 10, 1740 }, { 10, 1742 }, { 10, 1744 }, { 10, 1746 }, { 10, 1748 },
{ 10, 1750 }, { 10, 1752 }, { 10, 1754 }, { 10, 1756 }, { 10, 1758 },
{ 10, 1760 }, { 10, 1762 }, { 10, 1764 }, { 10, 1766 }, { 10, 1768 },
{ 10, 1770 }, { 10, 1772 }, { 10, 1774 }, { 10, 1776 }, { 10, 1778 },
{ 10, 1780 }, { 10, 1782 }, { 10, 1784 }, { 10, 1786 }, { 10, 1788 },
{ 10, 1790 }, { 10, 1792 }, { 10, 1794 }, { 10, 1796 }, { 10, 1798 },
{ 10, 1800 }, { 10, 1802 }, { 10, 1804 }, { 10, 1806 }, { 10, 1808 },
{ 10, 1810 }, { 10, 1812 }, { 10, 1814 }, { 10, 1816 }, { 10, 1818 },
{ 10, 1820 }, { 10, 1822 }, { 10, 1824 }, { 10, 1826 }, { 10, 1828 },
{ 10, 1830 }, { 10, 1832 }, { 10, 1834 }, { 10, 1836 }, { 10, 1838 },
{ 10, 1840 }, { 10, 1842 }, { 10, 1844 }, { 10, 1846 }, { 10, 1848 },
{ 10, 1850 }, { 10, 1852 }, { 10, 1854 }, { 10, 1856 }, { 10, 1858 },
{ 10, 1860 }, { 10, 1862 }, { 10, 1864 }, { 10, 1866 }, { 10, 1868 },
{ 10, 1870 }, { 10, 1872 }, { 10, 1874 }, { 10, 1876 }, { 10, 1878 },
{ 10, 1880 }, { 10, 1882 }, { 10, 1884 }, { 10, 1886 }, { 10, 1888 },
{ 10, 1890 }, { 10, 1892 }, { 10, 1894 }, { 10, 1896 }, { 10, 1898 },
{ 10, 1900 }, { 10, 1902 }, { 10, 1904 }, { 10, 1906 }, { 10, 1908 },
{ 10, 1910 }, { 10, 1912 }, { 10, 1914 }, { 10, 1916 }, { 10, 1918 },
{ 10, 1920 }, { 10, 1922 }, { 10, 1924 }, { 10, 1926 }, { 10, 1928 },
{ 10, 1930 }, { 10, 1932 }, { 10, 1934 }, { 10, 1936 }, { 10, 1938 },
{ 10, 1940 }, { 10, 1942 }, { 10, 1944 }, { 10, 1946 }, { 10, 1948 },
{ 10, 1950 }, { 10, 1952 }, { 10, 1954 }, { 10, 1956 }, { 10, 1958 },
{ 10, 1960 }, { 10, 1962 }, { 10, 1964 }, { 10, 1966 }, { 10, 1968 },
{ 10, 1970 }, { 10, 1972 }, { 10, 1974 }, { 10, 1976 }, { 10, 1978 },
{ 10, 1980 }, { 10, 1982 }, { 10, 1984 }, { 10, 1986 }, { 10, 1988 },
{ 10, 1990 }, { 10, 1992 }, { 10, 1994 }, { 10, 1996 }, { 10, 1998 },
{ 10, 2000 }, { 10, 2002 }, { 10, 2004 }, { 10, 2006 }, { 10, 2008 },
{ 10, 2010 }, { 10, 2012 }, { 10, 2014 }, { 10, 2016 }, { 10, 2018 },
{ 10, 2020 }, { 10, 2022 }, { 10, 2024 }, { 10, 2026 }, { 10, 2028 },
{ 10, 2030 }, { 10, 2032 }, { 10, 2034 }, { 10, 2036 }, { 10, 2038 },
{ 10, 2040 }, { 10, 2042 }, { 10, 2044 }, { 10, 2046 }, { 10, 2048 },
{ 10, 2050 }, { 10, 2052 }, { 10, 2054 }, { 10, 2056 }, { 10, 2058 },
{ 10, 2060 }, { 10, 2062 }, { 10, 2064 }, { 10, 2066 }, { 10, 2068 },
{ 10, 2070 }, { 10, 2072 }, { 10, 2074 }, { 10, 2076 }, { 10, 2078 },
{ 10, 2080 }, { 10, 2082 }, { 10, 2084 }, { 10, 2086 }, { 10, 2088 },
{ 10, 2090 }, { 10, 2092 }, { 10, 2094 }, { 10, 2096 }, { 10, 2098 },
{ 10, 2100 }, { 10, 2102 }, { 10, 2104 }, { 10, 2106 }, { 10, 2108 },
{ 10, 2110 }, { 10, 2112 }, { 10, 2114 }, { 10, 2116 }, { 10, 2118 },
{ 10, 2120 }, { 10, 2122 }, { 10, 2124 }, { 10, 2126 }, { 10, 2128 },
{ 10, 2130 }, { 10, 2132 }, { 10, 2134 }, { 10, 2136 }, { 10, 2138 },
{ 10, 2140 }, { 10, 2142 }, { 10, 2144 }, { 10, 2146 }, { 10, 2148 },
{ 10, 2150 }, { 10, 2152 }, { 10, 2154 }, { 10, 2156 }, { 10, 2158 },
{ 10, 2160 }, { 10, 2162 }, { 10, 2164 }, { 10, 2166 }, { 10, 2168 },
{ 10, 2170 }, { 10, 2172 }, { 10, 2174 }, { 10, 2176 }, { 10, 2178 },
{ 10, 2180 }, { 10, 2182 }, { 10, 2184 }, { 10, 2186 }, { 10, 2188 },
{ 10, 2190 }, { 10, 2192 }, { 10, 2194 }, { 10, 2196 }, { 10, 2198 },
{ 10, 2200 }, { 10, 2202 }, { 10, 2204 }, { 10, 2206 }, { 10, 2208 },
{ 10, 2210 }, { 10, 2212 }, { 10, 2214 }, { 10, 2216 }, { 10, 2218 },
{ 10, 2220 }, { 10, 2222 }, { 10, 2224 }, { 10, 2226 }, { 10, 2228 },
{ 10, 2230 }, { 10, 2232 }, { 10, 2234 }, { 10, 2236 }, { 10, 2238 },
{ 10, 2240 }, { 10, 2242 }, { 10, 2244 }, { 10, 2246 }, { 10, 2248 },
{ 10, 2250 }, { 10, 2252 }, { 10, 2254 }, { 10, 2256 }, { 10, 2258 },
{ 10, 2260 }, { 10, 2262 }, { 10, 2264 }, { 10, 2266 }, { 10, 2268 },
{ 10, 2270 }, { 10, 2272 }, { 10, 2274 }, { 10, 2276 }, { 10, 2278 },
{ 10, 2280 }, { 10, 2282 }, { 10, 2284 }, { 10, 2286 }, { 10, 2288 },
{ 10, 2290 }, { 10, 2292 }, { 10, 2294 }, { 10, 2296 }, { 10, 2298 },
{ 10, 2300 }, { 10, 2302 }, { 10, 2304 }, { 10, 2306 }, { 10, 2308 },
{ 10, 2310 }, { 10, 2312 }, { 10, 2314 }, { 10, 2316 }, { 10, 2318 },
{ 10, 2320 }, { 10, 2322 }, { 10, 2324 }, { 10, 2326 }, { 10, 2328 },
{ 10, 2330 }, { 10, 2332 }, { 10, 2334 }, { 10, 2336 }, { 10, 2338 },
{ 10, 2340 }, { 10, 2342 }, { 10, 2344 }, { 10, 2346 }, { 10, 2348 },
{ 10, 2350 }, { 10, 2352 }, { 10, 2354 }, { 10, 2356 }, { 10, 2358 },
{ 10, 2360 }, { 10, 2362 }, { 10, 2364 }, { 10, 2366 }, { 10, 2368 },
{ 10, 2370 }, { 10, 2372 }, { 10, 2374 }, { 10, 2376 }, { 10, 2378 },
{ 10, 2380 }, { 10, 2382 }, { 10, 2384 }, { 10, 2386 }, { 10, 2388 },
{ 10, 2390 }, { 10, 2392 }, { 10, 2394 }, { 10, 2396 }, { 10, 2398 },
{ 10, 2400 }, { 10, 2402 }, { 10, 2404 }, { 10, 2406 }, { 10, 2408 },
{ 10, 2410 }, { 10, 2412 }, { 10, 2414 }, { 10, 2416 }, { 10, 2418 },
{ 10, 2420 }, { 10, 2422 }, { 10, 2424 }, { 10, 2426 }, { 10, 2428 },
{ 10, 2430 }, { 10, 2432 }, { 10, 2434 }, { 10, 2436 }, { 10, 2438 },
{ 10, 2440 }, { 10, 2442 }, { 10, 2444 }, { 10, 2446 }, { 10, 2448 },
{ 10, 2450 }, { 10, 2452 }, { 10, 2454 }, { 10, 2456 }, { 10, 2458 },
{ 10, 2460 }, { 10, 2462 }, { 10, 2464 }, { 10, 2466 }, { 10, 2468 },
{ 10, 2470 }, { 10, 2472 }, { 10, 2474 }, { 10, 2476 }, { 10, 2478 },
{ 10, 2480 }, { 10, 2482 }, { 10, 2484 }, { 10, 2486 }, { 10, 2488 },
{ 10, 2490 }, { 10, 2492 }, { 10, 2494 }, { 10, 2496 }, { 10, 2498 },
{ 10, 2500 }, { 10, 2502 }, { 10, 2504 }, { 10, 2506 }, { 10, 2508 },
{ 10, 2510 }, { 10, 2512 }, { 10, 2514 }, { 10, 2516 }, { 10, 2518 },
{ 10, 2520 }, { 10, 2522 }, { 10, 2524 }, { 10, 2526 }, { 10, 2528 },
{ 10, 2530 }, { 10, 2532 }, { 10, 2534 }, { 10, 2536 }, { 10, 2538 },
{ 10, 2540 }, { 10, 2542 }, { 10, 2544 }, { 10, 2546 }, { 10, 2548 },
{ 10, 2550 }, { 10, 2552 }, { 10, 2554 }, { 10, 2556 }, { 10, 2558 },
{ 10, 2560 }, { 10, 2562 }, { 10, 2564 }, { 10, 2566 }, { 10, 2568 },
{ 10, 2570 }, { 10, 2572 }, { 10, 2574 }, { 10, 2576 }, { 10, 2578 },
{ 10, 2580 }, { 10, 2582 }, { 10, 2584 }, { 10, 2586 }, { 10, 2588 },
{ 10, 2590 }, { 10, 2592 }, { 10, 2594 }, { 10, 2596 }, { 10, 2598 },
{ 10, 2600 }, { 10, 2602 }, { 10, 2604 }, { 10, 2606 }, { 10, 2608 },
{ 10, 2610 }, { 10, 2612 }, { 10, 2614 }, { 10, 2616 }, { 10, 2618 },
{ 10, 2620 }, { 10, 2622 }, { 10, 2624 }, { 10, 2626 }, { 10, 2628 },
{ 10, 2630 }, { 10, 2632 }, { 10, 2634 }, { 10, 2636 }, { 10, 2638 },
{ 10, 2640 }, { 10, 2642 }, { 10, 2644 }, { 10, 2646 }, { 10, 2648 },
{ 10, 2650 }, { 10, 2652 }, { 10, 2654 }, { 10, 2656 }, { 10, 2658 },
{ 10, 2660 }, { 10, 2662 }, { 10, 2664 }, { 10, 2666 }, { 10, 2668 },
{ 10, 2670 }, { 10, 2672 }, { 10, 2674 }, { 10, 2676 }, { 10, 2678 },
{ 10, 2680 }, { 10, 2682 }, { 10, 2684 }, { 10, 2686 }, { 10, 2688 },
{ 10, 2690 }, { 10, 2692 }, { 10, 2694 }, { 10, 2696 }, { 10, 2698 },
{ 10, 2700 }, { 10, 2702 }, { 10, 2704 }, { 10, 2706 }, { 10, 2708 },
{ 10, 2710 }, { 10, 2712 }, { 10, 2714 }, { 10, 2716 }, { 10, 2718 },
{ 10, 2720 }, { 10, 2722 }, { 10, 2724 }, { 10, 2726 }, { 10, 2728 },
{ 10, 2730 }, { 10, 2732 }, { 10, 2734 }, { 10, 2736 }, { 10, 2738 },
{ 10, 2740 }, { 10, 2742 }, { 10, 2744 }, { 10, 2746 }, { 10, 2748 },
{ 10, 2750 }, { 10, 2752 }, { 10, 2754 }, { 10, 2756 }, { 10, 2758 },
{ 10, 2760 }, { 10, 2762 }, { 10, 2764 }, { 10, 2766 }, { 10, 2768 },
{ 10, 2770 }, { 10, 2772 }, { 10, 2774 }, { 10, 2776 }, { 10, 2778 },
{ 10, 2780 }, { 10, 2782 }, { 10, 2784 }, { 10, 2786 }, { 10, 2788 },
{ 10, 2790 }, { 10, 2792 }, { 10, 2794 }, { 10, 2796 }, { 10, 2798 },
{ 10, 2800 }, { 10, 2802 }, { 10, 2804 }, { 10, 2806 }, { 10, 2808 },
{ 10, 2810 }, { 10, 2812 }, { 10, 2814 }, { 10, 2816 }, { 10, 2818 },
{ 10, 2820 }, { 10, 2822 }, { 10, 2824 }, { 10, 2826 }, { 10, 2828 },
{ 10, 2830 }, { 10, 2832 }, { 10, 2834 }, { 10, 2836 }, { 10, 2838 },
{ 10, 2840 }, { 10, 2842 }, { 10, 2844 }, { 10, 2846 }, { 10, 2848 },
{ 10, 2850 }, { 10, 2852 }, { 10, 2854 }, { 10, 2856 }, { 10, 2858 },
{ 10, 2860 }, { 10, 2862 }, { 10, 2864 }, { 10, 2866 }, { 10, 2868 },
{ 10, 2870 }, { 10, 2872 }, { 10, 2874 }, { 10, 2876 }, { 10, 2878 },
{ 10, 2880 }, { 10, 2882 }, { 10, 2884 }, { 10, 2886 }, { 10, 2888 },
{ 10, 2890 }, { 10, 2892 }, { 10, 2894 }, { 10, 2896 }, { 10, 2898 },
{ 10, 2900 }, { 10, 2902 }, { 10, 2904 }, { 10, 2906 }, { 10, 2908 },
{ 10, 2910 }, { 10, 2912 }, { 10, 2914 }, { 10, 2916 }, { 10, 2918 },
{ 10, 2920 }, { 10, 2922 }, { 10, 2924 }, { 10, 2926 }, { 10, 2928 },
{ 10, 2930 }, { 10, 2932 }, { 10, 2934 }, { 10, 2936 }, { 10, 2938 },
{ 10, 2940 }, { 10, 2942 }, { 10, 2944 }, { 10, 2946 }, { 10, 2948 },
{ 10, 2950 }, { 10, 2952 }, { 10, 2954 }, { 10, 2956 }, { 10, 2958 },
{ 10, 2960 }, { 10, 2962 }, { 10, 2964 }, { 10, 2966 }, { 10, 2968 },
{ 10, 2970 }, { 10, 2972 }, { 10, 2974 }, { 10, 2976 }, { 10, 2978 },
{ 10, 2980 }, { 10, 2982 }, { 10, 2984 }, { 10, 2986 }, { 10, 2988 },
{ 10, 2990 }, { 10, 2992 }, { 10, 2994 }, { 10, 2996 }, { 10, 2998 },
{ 10, 3000 }, { 10, 3002 }, { 10, 3004 }, { 10, 3006 }, { 10, 3008 },
{ 10, 3010 }, { 10, 3012 }, { 10, 3014 }, { 10, 3016 }, { 10, 3018 },
{ 10, 3020 }, { 10, 3022 }, { 10, 3024 }, { 10, 3026 }, { 10, 3028 },
{ 10, 3030 }, { 10, 3032 }, { 10, 3034 }, { 10, 3036 }, { 10, 3038 },
{ 10, 3040 }, { 10, 3042 }, { 10, 3044 }, { 10, 3046 }, { 10, 3048 },
{ 10, 3050 }, { 10, 3052 }, { 10, 3054 }, { 10, 3056 }, { 10, 3058 },
{ 10, 3060 }, { 10, 3062 }, { 10, 3064 }, { 10, 3066 }, { 10, 3068 },
{ 10, 3070 }, { 10, 3072 }, { 10, 3074 }, { 10, 3076 }, { 10, 3078 },
{ 10, 3080 }, { 10, 3082 }, { 10, 3084 }, { 10, 3086 }, { 10, 3088 },
{ 10, 3090 }, { 10, 3092 }, { 10, 3094 }, { 10, 3096 }, { 10, 3098 },
{ 10, 3100 }, { 10, 3102 }, { 10, 3104 }, { 10, 3106 }, { 10, 3108 },
{ 10, 3110 }, { 10, 3112 }, { 10, 3114 }, { 10, 3116 }, { 10, 3118 },
{ 10, 3120 }, { 10, 3122 }, { 10, 3124 }, { 10, 3126 }, { 10, 3128 },
{ 10, 3130 }, { 10, 3132 }, { 10, 3134 }, { 10, 3136 }, { 10, 3138 },
{ 10, 3140 }, { 10, 3142 }, { 10, 3144 }, { 10, 3146 }, { 10, 3148 },
{ 10, 3150 }, { 10, 3152 }, { 10, 3154 }, { 10, 3156 }, { 10, 3158 },
{ 10, 3160 }, { 10, 3162 }, { 10, 3164 }, { 10, 3166 }, { 10, 3168 },
{ 10, 3170 }, { 10, 3172 }, { 10, 3174 }, { 10, 3176 }, { 10, 3178 },
{ 10, 3180 }, { 10, 3182 }, { 10, 3184 }, { 10, 3186 }, { 10, 3188 },
{ 10, 3190 }, { 10, 3192 }, { 10, 3194 }, { 10, 3196 }, { 10, 3198 },
{ 10, 3200 }, { 10, 3202 }, { 10, 3204 }, { 10, 3206 }, { 10, 3208 },
{ 10, 3210 }, { 10, 3212 }, { 10, 3214 }, { 10, 3216 }, { 10, 3218 },
{ 10, 3220 }, { 10, 3222 }, { 10, 3224 }, { 10, 3226 }, { 10, 3228 },
{ 10, 3230 }, { 10, 3232 }, { 10, 3234 }, { 10, 3236 }, { 10, 3238 },
{ 10, 3240 }, { 10, 3242 }, { 10, 3244 }, { 10, 3246 }, { 10, 3248 },
{ 10, 3250 }, { 10, 3252 }, { 10, 3254 }, { 10, 3256 }, { 10, 3258 },
{ 10, 3260 }, { 10, 3262 }, { 10, 3264 }, { 10, 3266 }, { 10, 3268 },
{ 10, 3270 }, { 10, 3272 }, { 10, 3274 }, { 10, 3276 }, { 10, 3278 },
{ 10, 3280 }, { 10, 3282 }, { 10, 3284 }, { 10, 3286 }, { 10, 3288 },
{ 10, 3290 }, { 10, 3292 }, { 10, 3294 }, { 10, 3296 }, { 10, 3298 },
{ 10, 3300 }, { 10, 3302 }, { 10, 3304 }, { 10, 3306 }, { 10, 3308 },
{ 10, 3310 }, { 10, 3312 }, { 10, 3314 }, { 10, 3316 }, { 10, 3318 },
{ 10, 3320 }, { 10, 3322 }, { 10, 3324 }, { 10, 3326 }, { 10, 3328 },
{ 10, 3330 }, { 10, 3332 }, { 10, 3334 }, { 10, 3336 }, { 10, 3338 },
{ 10, 3340 }, { 10, 3342 }, { 10, 3344 }, { 10, 3346 }, { 10, 3348 },
{ 10, 3350 }, { 10, 3352 }, { 10, 3354 }, { 10, 3356 }, { 10, 3358 },
{ 10, 3360 }, { 10, 3362 }, { 10, 3364 }, { 10, 3366 }, { 10, 3368 },
{ 10, 3370 }, { 10, 3372 }, { 10, 3374 }, { 10, 3376 }, { 10, 3378 },
{ 10, 3380 }, { 10, 3382 }, { 10, 3384 }, { 10, 3386 }, { 10, 3388 },
{ 10, 3390 }, { 10, 3392 }, { 10, 3394 }, { 10, 3396 }, { 10, 3398 },
{ 10, 3400 }, { 10, 3402 }, { 10, 3404 }, { 10, 3406 }, { 10, 3408 },
{ 10, 3410 }, { 10, 3412 }, { 10, 3414 }, { 10, 3416 }, { 10, 3418 },
{ 10, 3420 }, { 10, 3422 }, { 10, 3424 }, { 10, 3426 }, { 10, 3428 },
{ 10, 3430 }, { 10, 3432 }, { 10, 3434 }, { 10, 3436 }, { 10, 3438 },
{ 10, 3440 }, { 10, 3442 }, { 10, 3444 }, { 10, 3446 }, { 10, 3448 },
{ 10, 3450 }, { 10, 3452 }, { 10, 3454 }, { 10, 3456 }, { 10, 3458 },
{ 10, 3460 }, { 10, 3462 }, { 10, 3464 }, { 10, 3466 }, { 10, 3468 },
{ 10, 3470 }, { 10, 3472 }, { 10, 3474 }, { 10, 3476 }, { 10, 3478 },
{ 10, 3480 }, { 10, 3482 }, { 10, 3484 }, { 10, 3486 }, { 10, 3488 },
{ 10, 3490 }, { 10, 3492 }, { 10, 3494 }, { 10, 3496 }, { 10, 3498 },
{ 10, 3500 }, { 10, 3502 }, { 10, 3504 }, { 10, 3506 }, { 10, 3508 },
{ 10, 3510 }, { 10, 3512 }, { 10, 3514 }, { 10, 3516 }, { 10, 3518 },
{ 10, 3520 }, { 10, 3522 }, { 10, 3524 }, { 10, 3526 }, { 10, 3528 },
{ 10, 3530 }, { 10, 3532 }, { 10, 3534 }, { 10, 3536 }, { 10, 3538 },
{ 10, 3540 }, { 10, 3542 }, { 10, 3544 }, { 10, 3546 }, { 10, 3548 },
{ 10, 3550 }, { 10, 3552 }, { 10, 3554 }, { 10, 3556 }, { 10, 3558 },
{ 10, 3560 }, { 10, 3562 }, { 10, 3564 }, { 10, 3566 }, { 10, 3568 },
{ 10, 3570 }, { 10, 3572 }, { 10, 3574 }, { 10, 3576 }, { 10, 3578 },
{ 10, 3580 }, { 10, 3582 }, { 10, 3584 }, { 10, 3586 }, { 10, 3588 },
{ 10, 3590 }, { 10, 3592 }, { 10, 3594 }, { 10, 3596 }, { 10, 3598 },
{ 10, 3600 }, { 10, 3602 }, { 10, 3604 }, { 10, 3606 }, { 10, 3608 },
{ 10, 3610 }, { 10, 3612 }, { 10, 3614 }, { 10, 3616 }, { 10, 3618 },
{ 10, 3620 }, { 10, 3622 }, { 10, 3624 }, { 10, 3626 }, { 10, 3628 },
{ 10, 3630 }, { 10, 3632 }, { 10, 3634 }, { 10, 3636 }, { 10, 3638 },
{ 10, 3640 }, { 10, 3642 }, { 10, 3644 }, { 10, 3646 }, { 10, 3648 },
{ 10, 3650 }, { 10, 3652 }, { 10, 3654 }, { 10, 3656 }, { 10, 3658 },
{ 10, 3660 }, { 10, 3662 }, { 10, 3664 }, { 10, 3666 }, { 10, 3668 },
{ 10, 3670 }, { 10, 3672 }, { 10, 3674 }, { 10, 3676 }, { 10, 3678 },
{ 10, 3680 }, { 10, 3682 }, { 10, 3684 }, { 10, 3686 }, { 10, 3688 },
{ 10, 3690 }, { 10, 3692 }, { 10, 3694 }, { 10, 3696 }, { 10, 3698 },
{ 10, 3700 }, { 10, 3702 }, { 10, 3704 }, { 10, 3706 }, { 10, 3708 },
{ 10, 3710 }, { 10, 3712 }, { 10, 3714 }, { 10, 3716 }, { 10, 3718 },
{ 10, 3720 }, { 10, 3722 }, { 10, 3724 }, { 10, 3726 }, { 10, 3728 },
{ 10, 3730 }, { 10, 3732 }, { 10, 3734 }, { 10, 3736 }, { 10, 3738 },
{ 10, 3740 }, { 10, 3742 }, { 10, 3744 }, { 10, 3746 }, { 10, 3748 },
{ 10, 3750 }, { 10, 3752 }, { 10, 3754 }, { 10, 3756 }, { 10, 3758 },
{ 10, 3760 }, { 10, 3762 }, { 10, 3764 }, { 10, 3766 }, { 10, 3768 },
{ 10, 3770 }, { 10, 3772 }, { 10, 3774 }, { 10, 3776 }, { 10, 3778 },
{ 10, 3780 }, { 10, 3782 }, { 10, 3784 }, { 10, 3786 }, { 10, 3788 },
{ 10, 3790 }, { 10, 3792 }, { 10, 3794 }, { 10, 3796 }, { 10, 3798 },
{ 10, 3800 }, { 10, 3802 }, { 10, 3804 }, { 10, 3806 }, { 10, 3808 },
{ 10, 3810 }, { 10, 3812 }, { 10, 3814 }, { 10, 3816 }, { 10, 3818 },
{ 10, 3820 }, { 10, 3822 }, { 10, 3824 }, { 10, 3826 }, { 10, 3828 },
{ 10, 3830 }, { 10, 3832 }, { 10, 3834 }, { 10, 3836 }, { 10, 3838 },
{ 10, 3840 }, { 10, 3842 }, { 10, 3844 }, { 10, 3846 }, { 10, 3848 },
{ 10, 3850 }, { 10, 3852 }, { 10, 3854 }, { 10, 3856 }, { 10, 3858 },
{ 10, 3860 }, { 10, 3862 }, { 10, 3864 }, { 10, 3866 }, { 10, 3868 },
{ 10, 3870 }, { 10, 3872 }, { 10, 3874 }, { 10, 3876 }, { 10, 3878 },
{ 10, 3880 }, { 10, 3882 }, { 10, 3884 }, { 10, 3886 }, { 10, 3888 },
{ 10, 3890 }, { 10, 3892 }, { 10, 3894 }, { 10, 3896 }, { 10, 3898 },
{ 10, 3900 }, { 10, 3902 }, { 10, 3904 }, { 10, 3906 }, { 10, 3908 },
{ 10, 3910 }, { 10, 3912 }, { 10, 3914 }, { 10, 3916 }, { 10, 3918 },
{ 10, 3920 }, { 10, 3922 }, { 10, 3924 }, { 10, 3926 }, { 10, 3928 },
{ 10, 3930 }, { 10, 3932 }, { 10, 3934 }, { 10, 3936 }, { 10, 3938 },
{ 10, 3940 }, { 10, 3942 }, { 10, 3944 }, { 10, 3946 }, { 10, 3948 },
{ 10, 3950 }, { 10, 3952 }, { 10, 3954 }, { 10, 3956 }, { 10, 3958 },
{ 10, 3960 }
};
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_DCT_VALUE_TOKENS_H_
@@ -0,0 +1,235 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_DEFAULTCOEFCOUNTS_H_
#define VPX_VP8_ENCODER_DEFAULTCOEFCOUNTS_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Generated file, included by entropy.c */
static const unsigned int default_coef_counts
[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][MAX_ENTROPY_TOKENS] = {
{
/* Block Type ( 0 ) */
{
/* Coeff Band ( 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 },
},
{
/* Coeff Band ( 1 ) */
{ 30190, 26544, 225, 24, 4, 0, 0, 0, 0, 0, 0, 4171593 },
{ 26846, 25157, 1241, 130, 26, 6, 1, 0, 0, 0, 0, 149987 },
{ 10484, 9538, 1006, 160, 36, 18, 0, 0, 0, 0, 0, 15104 },
},
{
/* Coeff Band ( 2 ) */
{ 25842, 40456, 1126, 83, 11, 2, 0, 0, 0, 0, 0, 0 },
{ 9338, 8010, 512, 73, 7, 3, 2, 0, 0, 0, 0, 43294 },
{ 1047, 751, 149, 31, 13, 6, 1, 0, 0, 0, 0, 879 },
},
{
/* Coeff Band ( 3 ) */
{ 26136, 9826, 252, 13, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 8134, 5574, 191, 14, 2, 0, 0, 0, 0, 0, 0, 35302 },
{ 605, 677, 116, 9, 1, 0, 0, 0, 0, 0, 0, 611 },
},
{
/* Coeff Band ( 4 ) */
{ 10263, 15463, 283, 17, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 2773, 2191, 128, 9, 2, 2, 0, 0, 0, 0, 0, 10073 },
{ 134, 125, 32, 4, 0, 2, 0, 0, 0, 0, 0, 50 },
},
{
/* Coeff Band ( 5 ) */
{ 10483, 2663, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 2137, 1251, 27, 1, 1, 0, 0, 0, 0, 0, 0, 14362 },
{ 116, 156, 14, 2, 1, 0, 0, 0, 0, 0, 0, 190 },
},
{
/* Coeff Band ( 6 ) */
{ 40977, 27614, 412, 28, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 6113, 5213, 261, 22, 3, 0, 0, 0, 0, 0, 0, 26164 },
{ 382, 312, 50, 14, 2, 0, 0, 0, 0, 0, 0, 345 },
},
{
/* Coeff Band ( 7 ) */
{ 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 319 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 },
},
},
{
/* Block Type ( 1 ) */
{
/* Coeff Band ( 0 ) */
{ 3268, 19382, 1043, 250, 93, 82, 49, 26, 17, 8, 25, 82289 },
{ 8758, 32110, 5436, 1832, 827, 668, 420, 153, 24, 0, 3, 52914 },
{ 9337, 23725, 8487, 3954, 2107, 1836, 1069, 399, 59, 0, 0,
18620 },
},
{
/* Coeff Band ( 1 ) */
{ 12419, 8420, 452, 62, 9, 1, 0, 0, 0, 0, 0, 0 },
{ 11715, 8705, 693, 92, 15, 7, 2, 0, 0, 0, 0, 53988 },
{ 7603, 8585, 2306, 778, 270, 145, 39, 5, 0, 0, 0, 9136 },
},
{
/* Coeff Band ( 2 ) */
{ 15938, 14335, 1207, 184, 55, 13, 4, 1, 0, 0, 0, 0 },
{ 7415, 6829, 1138, 244, 71, 26, 7, 0, 0, 0, 0, 9980 },
{ 1580, 1824, 655, 241, 89, 46, 10, 2, 0, 0, 0, 429 },
},
{
/* Coeff Band ( 3 ) */
{ 19453, 5260, 201, 19, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 9173, 3758, 213, 22, 1, 1, 0, 0, 0, 0, 0, 9820 },
{ 1689, 1277, 276, 51, 17, 4, 0, 0, 0, 0, 0, 679 },
},
{
/* Coeff Band ( 4 ) */
{ 12076, 10667, 620, 85, 19, 9, 5, 0, 0, 0, 0, 0 },
{ 4665, 3625, 423, 55, 19, 9, 0, 0, 0, 0, 0, 5127 },
{ 415, 440, 143, 34, 20, 7, 2, 0, 0, 0, 0, 101 },
},
{
/* Coeff Band ( 5 ) */
{ 12183, 4846, 115, 11, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 4226, 3149, 177, 21, 2, 0, 0, 0, 0, 0, 0, 7157 },
{ 375, 621, 189, 51, 11, 4, 1, 0, 0, 0, 0, 198 },
},
{
/* Coeff Band ( 6 ) */
{ 61658, 37743, 1203, 94, 10, 3, 0, 0, 0, 0, 0, 0 },
{ 15514, 11563, 903, 111, 14, 5, 0, 0, 0, 0, 0, 25195 },
{ 929, 1077, 291, 78, 14, 7, 1, 0, 0, 0, 0, 507 },
},
{
/* Coeff Band ( 7 ) */
{ 0, 990, 15, 3, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 412, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1641 },
{ 0, 18, 7, 1, 0, 0, 0, 0, 0, 0, 0, 30 },
},
},
{
/* Block Type ( 2 ) */
{
/* Coeff Band ( 0 ) */
{ 953, 24519, 628, 120, 28, 12, 4, 0, 0, 0, 0, 2248798 },
{ 1525, 25654, 2647, 617, 239, 143, 42, 5, 0, 0, 0, 66837 },
{ 1180, 11011, 3001, 1237, 532, 448, 239, 54, 5, 0, 0, 7122 },
},
{
/* Coeff Band ( 1 ) */
{ 1356, 2220, 67, 10, 4, 1, 0, 0, 0, 0, 0, 0 },
{ 1450, 2544, 102, 18, 4, 3, 0, 0, 0, 0, 0, 57063 },
{ 1182, 2110, 470, 130, 41, 21, 0, 0, 0, 0, 0, 6047 },
},
{
/* Coeff Band ( 2 ) */
{ 370, 3378, 200, 30, 5, 4, 1, 0, 0, 0, 0, 0 },
{ 293, 1006, 131, 29, 11, 0, 0, 0, 0, 0, 0, 5404 },
{ 114, 387, 98, 23, 4, 8, 1, 0, 0, 0, 0, 236 },
},
{
/* Coeff Band ( 3 ) */
{ 579, 194, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 395, 213, 5, 1, 0, 0, 0, 0, 0, 0, 0, 4157 },
{ 119, 122, 4, 0, 0, 0, 0, 0, 0, 0, 0, 300 },
},
{
/* Coeff Band ( 4 ) */
{ 38, 557, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 21, 114, 12, 1, 0, 0, 0, 0, 0, 0, 0, 427 },
{ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 },
},
{
/* Coeff Band ( 5 ) */
{ 52, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 18, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 652 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 },
},
{
/* Coeff Band ( 6 ) */
{ 640, 569, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 25, 77, 2, 0, 0, 0, 0, 0, 0, 0, 0, 517 },
{ 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
},
{
/* Coeff Band ( 7 ) */
{ 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 },
},
},
{
/* Block Type ( 3 ) */
{
/* Coeff Band ( 0 ) */
{ 2506, 20161, 2707, 767, 261, 178, 107, 30, 14, 3, 0, 100694 },
{ 8806, 36478, 8817, 3268, 1280, 850, 401, 114, 42, 0, 0, 58572 },
{ 11003, 27214, 11798, 5716, 2482, 2072, 1048, 175, 32, 0, 0,
19284 },
},
{
/* Coeff Band ( 1 ) */
{ 9738, 11313, 959, 205, 70, 18, 11, 1, 0, 0, 0, 0 },
{ 12628, 15085, 1507, 273, 52, 19, 9, 0, 0, 0, 0, 54280 },
{ 10701, 15846, 5561, 1926, 813, 570, 249, 36, 0, 0, 0, 6460 },
},
{
/* Coeff Band ( 2 ) */
{ 6781, 22539, 2784, 634, 182, 123, 20, 4, 0, 0, 0, 0 },
{ 6263, 11544, 2649, 790, 259, 168, 27, 5, 0, 0, 0, 20539 },
{ 3109, 4075, 2031, 896, 457, 386, 158, 29, 0, 0, 0, 1138 },
},
{
/* Coeff Band ( 3 ) */
{ 11515, 4079, 465, 73, 5, 14, 2, 0, 0, 0, 0, 0 },
{ 9361, 5834, 650, 96, 24, 8, 4, 0, 0, 0, 0, 22181 },
{ 4343, 3974, 1360, 415, 132, 96, 14, 1, 0, 0, 0, 1267 },
},
{
/* Coeff Band ( 4 ) */
{ 4787, 9297, 823, 168, 44, 12, 4, 0, 0, 0, 0, 0 },
{ 3619, 4472, 719, 198, 60, 31, 3, 0, 0, 0, 0, 8401 },
{ 1157, 1175, 483, 182, 88, 31, 8, 0, 0, 0, 0, 268 },
},
{
/* Coeff Band ( 5 ) */
{ 8299, 1226, 32, 5, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 3502, 1568, 57, 4, 1, 1, 0, 0, 0, 0, 0, 9811 },
{ 1055, 1070, 166, 29, 6, 1, 0, 0, 0, 0, 0, 527 },
},
{
/* Coeff Band ( 6 ) */
{ 27414, 27927, 1989, 347, 69, 26, 0, 0, 0, 0, 0, 0 },
{ 5876, 10074, 1574, 341, 91, 24, 4, 0, 0, 0, 0, 21954 },
{ 1571, 2171, 778, 324, 124, 65, 16, 0, 0, 0, 0, 979 },
},
{
/* Coeff Band ( 7 ) */
{ 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 459 },
{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13 },
},
},
};
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_DEFAULTCOEFCOUNTS_H_
@@ -0,0 +1,725 @@
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <limits.h>
#include "denoising.h"
#include "vp8/common/reconinter.h"
#include "vpx/vpx_integer.h"
#include "vpx_mem/vpx_mem.h"
#include "vp8_rtcd.h"
static const unsigned int NOISE_MOTION_THRESHOLD = 25 * 25;
/* SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming
* var(noise) ~= 100.
*/
static const unsigned int SSE_DIFF_THRESHOLD = 16 * 16 * 20;
static const unsigned int SSE_THRESHOLD = 16 * 16 * 40;
static const unsigned int SSE_THRESHOLD_HIGH = 16 * 16 * 80;
/*
* The filter function was modified to reduce the computational complexity.
* Step 1:
* Instead of applying tap coefficients for each pixel, we calculated the
* pixel adjustments vs. pixel diff value ahead of time.
* adjustment = filtered_value - current_raw
* = (filter_coefficient * diff + 128) >> 8
* where
* filter_coefficient = (255 << 8) / (256 + ((absdiff * 330) >> 3));
* filter_coefficient += filter_coefficient /
* (3 + motion_magnitude_adjustment);
* filter_coefficient is clamped to 0 ~ 255.
*
* Step 2:
* The adjustment vs. diff curve becomes flat very quick when diff increases.
* This allowed us to use only several levels to approximate the curve without
* changing the filtering algorithm too much.
* The adjustments were further corrected by checking the motion magnitude.
* The levels used are:
* diff adjustment w/o motion correction adjustment w/ motion correction
* [-255, -16] -6 -7
* [-15, -8] -4 -5
* [-7, -4] -3 -4
* [-3, 3] diff diff
* [4, 7] 3 4
* [8, 15] 4 5
* [16, 255] 6 7
*/
int vp8_denoiser_filter_c(unsigned char *mc_running_avg_y, int mc_avg_y_stride,
unsigned char *running_avg_y, int avg_y_stride,
unsigned char *sig, int sig_stride,
unsigned int motion_magnitude,
int increase_denoising) {
unsigned char *running_avg_y_start = running_avg_y;
unsigned char *sig_start = sig;
int sum_diff_thresh;
int r, c;
int sum_diff = 0;
int adj_val[3] = { 3, 4, 6 };
int shift_inc1 = 0;
int shift_inc2 = 1;
int col_sum[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* If motion_magnitude is small, making the denoiser more aggressive by
* increasing the adjustment for each level. Add another increment for
* blocks that are labeled for increase denoising. */
if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) {
if (increase_denoising) {
shift_inc1 = 1;
shift_inc2 = 2;
}
adj_val[0] += shift_inc2;
adj_val[1] += shift_inc2;
adj_val[2] += shift_inc2;
}
for (r = 0; r < 16; ++r) {
for (c = 0; c < 16; ++c) {
int diff = 0;
int adjustment = 0;
int absdiff = 0;
diff = mc_running_avg_y[c] - sig[c];
absdiff = abs(diff);
// When |diff| <= |3 + shift_inc1|, use pixel value from
// last denoised raw.
if (absdiff <= 3 + shift_inc1) {
running_avg_y[c] = mc_running_avg_y[c];
col_sum[c] += diff;
} else {
if (absdiff >= 4 + shift_inc1 && absdiff <= 7) {
adjustment = adj_val[0];
} else if (absdiff >= 8 && absdiff <= 15) {
adjustment = adj_val[1];
} else {
adjustment = adj_val[2];
}
if (diff > 0) {
if ((sig[c] + adjustment) > 255) {
running_avg_y[c] = 255;
} else {
running_avg_y[c] = sig[c] + adjustment;
}
col_sum[c] += adjustment;
} else {
if ((sig[c] - adjustment) < 0) {
running_avg_y[c] = 0;
} else {
running_avg_y[c] = sig[c] - adjustment;
}
col_sum[c] -= adjustment;
}
}
}
/* Update pointers for next iteration. */
sig += sig_stride;
mc_running_avg_y += mc_avg_y_stride;
running_avg_y += avg_y_stride;
}
for (c = 0; c < 16; ++c) {
// Below we clip the value in the same way which SSE code use.
// When adopting aggressive denoiser, the adj_val for each pixel
// could be at most 8 (this is current max adjustment of the map).
// In SSE code, we calculate the sum of adj_val for
// the columns, so the sum could be upto 128(16 rows). However,
// the range of the value is -128 ~ 127 in SSE code, that's why
// we do this change in C code.
// We don't do this for UV denoiser, since there are only 8 rows,
// and max adjustments <= 8, so the sum of the columns will not
// exceed 64.
if (col_sum[c] >= 128) {
col_sum[c] = 127;
}
sum_diff += col_sum[c];
}
sum_diff_thresh = SUM_DIFF_THRESHOLD;
if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH;
if (abs(sum_diff) > sum_diff_thresh) {
// Before returning to copy the block (i.e., apply no denoising), check
// if we can still apply some (weaker) temporal filtering to this block,
// that would otherwise not be denoised at all. Simplest is to apply
// an additional adjustment to running_avg_y to bring it closer to sig.
// The adjustment is capped by a maximum delta, and chosen such that
// in most cases the resulting sum_diff will be within the
// accceptable range given by sum_diff_thresh.
// The delta is set by the excess of absolute pixel diff over threshold.
int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
// Only apply the adjustment for max delta up to 3.
if (delta < 4) {
sig -= sig_stride * 16;
mc_running_avg_y -= mc_avg_y_stride * 16;
running_avg_y -= avg_y_stride * 16;
for (r = 0; r < 16; ++r) {
for (c = 0; c < 16; ++c) {
int diff = mc_running_avg_y[c] - sig[c];
int adjustment = abs(diff);
if (adjustment > delta) adjustment = delta;
if (diff > 0) {
// Bring denoised signal down.
if (running_avg_y[c] - adjustment < 0) {
running_avg_y[c] = 0;
} else {
running_avg_y[c] = running_avg_y[c] - adjustment;
}
col_sum[c] -= adjustment;
} else if (diff < 0) {
// Bring denoised signal up.
if (running_avg_y[c] + adjustment > 255) {
running_avg_y[c] = 255;
} else {
running_avg_y[c] = running_avg_y[c] + adjustment;
}
col_sum[c] += adjustment;
}
}
// TODO(marpan): Check here if abs(sum_diff) has gone below the
// threshold sum_diff_thresh, and if so, we can exit the row loop.
sig += sig_stride;
mc_running_avg_y += mc_avg_y_stride;
running_avg_y += avg_y_stride;
}
sum_diff = 0;
for (c = 0; c < 16; ++c) {
if (col_sum[c] >= 128) {
col_sum[c] = 127;
}
sum_diff += col_sum[c];
}
if (abs(sum_diff) > sum_diff_thresh) return COPY_BLOCK;
} else {
return COPY_BLOCK;
}
}
vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride);
return FILTER_BLOCK;
}
int vp8_denoiser_filter_uv_c(unsigned char *mc_running_avg, int mc_avg_stride,
unsigned char *running_avg, int avg_stride,
unsigned char *sig, int sig_stride,
unsigned int motion_magnitude,
int increase_denoising) {
unsigned char *running_avg_start = running_avg;
unsigned char *sig_start = sig;
int sum_diff_thresh;
int r, c;
int sum_diff = 0;
int sum_block = 0;
int adj_val[3] = { 3, 4, 6 };
int shift_inc1 = 0;
int shift_inc2 = 1;
/* If motion_magnitude is small, making the denoiser more aggressive by
* increasing the adjustment for each level. Add another increment for
* blocks that are labeled for increase denoising. */
if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD_UV) {
if (increase_denoising) {
shift_inc1 = 1;
shift_inc2 = 2;
}
adj_val[0] += shift_inc2;
adj_val[1] += shift_inc2;
adj_val[2] += shift_inc2;
}
// Avoid denoising color signal if its close to average level.
for (r = 0; r < 8; ++r) {
for (c = 0; c < 8; ++c) {
sum_block += sig[c];
}
sig += sig_stride;
}
if (abs(sum_block - (128 * 8 * 8)) < SUM_DIFF_FROM_AVG_THRESH_UV) {
return COPY_BLOCK;
}
sig -= sig_stride * 8;
for (r = 0; r < 8; ++r) {
for (c = 0; c < 8; ++c) {
int diff = 0;
int adjustment = 0;
int absdiff = 0;
diff = mc_running_avg[c] - sig[c];
absdiff = abs(diff);
// When |diff| <= |3 + shift_inc1|, use pixel value from
// last denoised raw.
if (absdiff <= 3 + shift_inc1) {
running_avg[c] = mc_running_avg[c];
sum_diff += diff;
} else {
if (absdiff >= 4 && absdiff <= 7) {
adjustment = adj_val[0];
} else if (absdiff >= 8 && absdiff <= 15) {
adjustment = adj_val[1];
} else {
adjustment = adj_val[2];
}
if (diff > 0) {
if ((sig[c] + adjustment) > 255) {
running_avg[c] = 255;
} else {
running_avg[c] = sig[c] + adjustment;
}
sum_diff += adjustment;
} else {
if ((sig[c] - adjustment) < 0) {
running_avg[c] = 0;
} else {
running_avg[c] = sig[c] - adjustment;
}
sum_diff -= adjustment;
}
}
}
/* Update pointers for next iteration. */
sig += sig_stride;
mc_running_avg += mc_avg_stride;
running_avg += avg_stride;
}
sum_diff_thresh = SUM_DIFF_THRESHOLD_UV;
if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH_UV;
if (abs(sum_diff) > sum_diff_thresh) {
// Before returning to copy the block (i.e., apply no denoising), check
// if we can still apply some (weaker) temporal filtering to this block,
// that would otherwise not be denoised at all. Simplest is to apply
// an additional adjustment to running_avg_y to bring it closer to sig.
// The adjustment is capped by a maximum delta, and chosen such that
// in most cases the resulting sum_diff will be within the
// accceptable range given by sum_diff_thresh.
// The delta is set by the excess of absolute pixel diff over threshold.
int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
// Only apply the adjustment for max delta up to 3.
if (delta < 4) {
sig -= sig_stride * 8;
mc_running_avg -= mc_avg_stride * 8;
running_avg -= avg_stride * 8;
for (r = 0; r < 8; ++r) {
for (c = 0; c < 8; ++c) {
int diff = mc_running_avg[c] - sig[c];
int adjustment = abs(diff);
if (adjustment > delta) adjustment = delta;
if (diff > 0) {
// Bring denoised signal down.
if (running_avg[c] - adjustment < 0) {
running_avg[c] = 0;
} else {
running_avg[c] = running_avg[c] - adjustment;
}
sum_diff -= adjustment;
} else if (diff < 0) {
// Bring denoised signal up.
if (running_avg[c] + adjustment > 255) {
running_avg[c] = 255;
} else {
running_avg[c] = running_avg[c] + adjustment;
}
sum_diff += adjustment;
}
}
// TODO(marpan): Check here if abs(sum_diff) has gone below the
// threshold sum_diff_thresh, and if so, we can exit the row loop.
sig += sig_stride;
mc_running_avg += mc_avg_stride;
running_avg += avg_stride;
}
if (abs(sum_diff) > sum_diff_thresh) return COPY_BLOCK;
} else {
return COPY_BLOCK;
}
}
vp8_copy_mem8x8(running_avg_start, avg_stride, sig_start, sig_stride);
return FILTER_BLOCK;
}
void vp8_denoiser_set_parameters(VP8_DENOISER *denoiser, int mode) {
assert(mode > 0); // Denoiser is allocated only if mode > 0.
if (mode == 1) {
denoiser->denoiser_mode = kDenoiserOnYOnly;
} else if (mode == 2) {
denoiser->denoiser_mode = kDenoiserOnYUV;
} else if (mode == 3) {
denoiser->denoiser_mode = kDenoiserOnYUVAggressive;
} else {
denoiser->denoiser_mode = kDenoiserOnYUV;
}
if (denoiser->denoiser_mode != kDenoiserOnYUVAggressive) {
denoiser->denoise_pars.scale_sse_thresh = 1;
denoiser->denoise_pars.scale_motion_thresh = 8;
denoiser->denoise_pars.scale_increase_filter = 0;
denoiser->denoise_pars.denoise_mv_bias = 95;
denoiser->denoise_pars.pickmode_mv_bias = 100;
denoiser->denoise_pars.qp_thresh = 0;
denoiser->denoise_pars.consec_zerolast = UINT_MAX;
denoiser->denoise_pars.spatial_blur = 0;
} else {
denoiser->denoise_pars.scale_sse_thresh = 2;
denoiser->denoise_pars.scale_motion_thresh = 16;
denoiser->denoise_pars.scale_increase_filter = 1;
denoiser->denoise_pars.denoise_mv_bias = 60;
denoiser->denoise_pars.pickmode_mv_bias = 75;
denoiser->denoise_pars.qp_thresh = 80;
denoiser->denoise_pars.consec_zerolast = 15;
denoiser->denoise_pars.spatial_blur = 0;
}
}
int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height,
int num_mb_rows, int num_mb_cols, int mode) {
int i;
assert(denoiser);
denoiser->num_mb_cols = num_mb_cols;
for (i = 0; i < MAX_REF_FRAMES; ++i) {
denoiser->yv12_running_avg[i].flags = 0;
if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg[i]), width,
height, VP8BORDERINPIXELS) < 0) {
vp8_denoiser_free(denoiser);
return 1;
}
memset(denoiser->yv12_running_avg[i].buffer_alloc, 0,
denoiser->yv12_running_avg[i].frame_size);
}
denoiser->yv12_mc_running_avg.flags = 0;
if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width,
height, VP8BORDERINPIXELS) < 0) {
vp8_denoiser_free(denoiser);
return 1;
}
memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0,
denoiser->yv12_mc_running_avg.frame_size);
if (vp8_yv12_alloc_frame_buffer(&denoiser->yv12_last_source, width, height,
VP8BORDERINPIXELS) < 0) {
vp8_denoiser_free(denoiser);
return 1;
}
memset(denoiser->yv12_last_source.buffer_alloc, 0,
denoiser->yv12_last_source.frame_size);
denoiser->denoise_state = vpx_calloc((num_mb_rows * num_mb_cols), 1);
if (!denoiser->denoise_state) {
vp8_denoiser_free(denoiser);
return 1;
}
memset(denoiser->denoise_state, 0, (num_mb_rows * num_mb_cols));
vp8_denoiser_set_parameters(denoiser, mode);
denoiser->nmse_source_diff = 0;
denoiser->nmse_source_diff_count = 0;
denoiser->qp_avg = 0;
// QP threshold below which we can go up to aggressive mode.
denoiser->qp_threshold_up = 80;
// QP threshold above which we can go back down to normal mode.
// For now keep this second threshold high, so not used currently.
denoiser->qp_threshold_down = 128;
// Bitrate thresholds and noise metric (nmse) thresholds for switching to
// aggressive mode.
// TODO(marpan): Adjust thresholds, including effect on resolution.
denoiser->bitrate_threshold = 400000; // (bits/sec).
denoiser->threshold_aggressive_mode = 80;
if (width * height > 1280 * 720) {
denoiser->bitrate_threshold = 3000000;
denoiser->threshold_aggressive_mode = 200;
} else if (width * height > 960 * 540) {
denoiser->bitrate_threshold = 1200000;
denoiser->threshold_aggressive_mode = 120;
} else if (width * height > 640 * 480) {
denoiser->bitrate_threshold = 600000;
denoiser->threshold_aggressive_mode = 100;
}
return 0;
}
void vp8_denoiser_free(VP8_DENOISER *denoiser) {
int i;
assert(denoiser);
for (i = 0; i < MAX_REF_FRAMES; ++i) {
vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]);
}
vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg);
vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_last_source);
vpx_free(denoiser->denoise_state);
}
void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, MACROBLOCK *x,
unsigned int best_sse, unsigned int zero_mv_sse,
int recon_yoffset, int recon_uvoffset,
loop_filter_info_n *lfi_n, int mb_row, int mb_col,
int block_index, int consec_zero_last)
{
int mv_row;
int mv_col;
unsigned int motion_threshold;
unsigned int motion_magnitude2;
unsigned int sse_thresh;
int sse_diff_thresh = 0;
// Spatial loop filter: only applied selectively based on
// temporal filter state of block relative to top/left neighbors.
int apply_spatial_loop_filter = 1;
MV_REFERENCE_FRAME frame = x->best_reference_frame;
MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame;
enum vp8_denoiser_decision decision = FILTER_BLOCK;
enum vp8_denoiser_decision decision_u = COPY_BLOCK;
enum vp8_denoiser_decision decision_v = COPY_BLOCK;
if (zero_frame) {
YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame];
YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg;
YV12_BUFFER_CONFIG saved_pre, saved_dst;
MB_MODE_INFO saved_mbmi;
MACROBLOCKD *filter_xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi;
int sse_diff = 0;
// Bias on zero motion vector sse.
const int zero_bias = denoiser->denoise_pars.denoise_mv_bias;
zero_mv_sse = (unsigned int)((int64_t)zero_mv_sse * zero_bias / 100);
sse_diff = (int)zero_mv_sse - (int)best_sse;
saved_mbmi = *mbmi;
/* Use the best MV for the compensation. */
mbmi->ref_frame = x->best_reference_frame;
mbmi->mode = x->best_sse_inter_mode;
mbmi->mv = x->best_sse_mv;
mbmi->need_to_clamp_mvs = x->need_to_clamp_best_mvs;
mv_col = x->best_sse_mv.as_mv.col;
mv_row = x->best_sse_mv.as_mv.row;
// Bias to zero_mv if small amount of motion.
// Note sse_diff_thresh is intialized to zero, so this ensures
// we will always choose zero_mv for denoising if
// zero_mv_see <= best_sse (i.e., sse_diff <= 0).
if ((unsigned int)(mv_row * mv_row + mv_col * mv_col) <=
NOISE_MOTION_THRESHOLD) {
sse_diff_thresh = (int)SSE_DIFF_THRESHOLD;
}
if (frame == INTRA_FRAME || sse_diff <= sse_diff_thresh) {
/*
* Handle intra blocks as referring to last frame with zero motion
* and let the absolute pixel difference affect the filter factor.
* Also consider small amount of motion as being random walk due
* to noise, if it doesn't mean that we get a much bigger error.
* Note that any changes to the mode info only affects the
* denoising.
*/
x->denoise_zeromv = 1;
mbmi->ref_frame = x->best_zeromv_reference_frame;
src = &denoiser->yv12_running_avg[zero_frame];
mbmi->mode = ZEROMV;
mbmi->mv.as_int = 0;
x->best_sse_inter_mode = ZEROMV;
x->best_sse_mv.as_int = 0;
best_sse = zero_mv_sse;
}
mv_row = x->best_sse_mv.as_mv.row;
mv_col = x->best_sse_mv.as_mv.col;
motion_magnitude2 = mv_row * mv_row + mv_col * mv_col;
motion_threshold =
denoiser->denoise_pars.scale_motion_thresh * NOISE_MOTION_THRESHOLD;
if (motion_magnitude2 <
denoiser->denoise_pars.scale_increase_filter * NOISE_MOTION_THRESHOLD) {
x->increase_denoising = 1;
}
sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD;
if (x->increase_denoising) {
sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD_HIGH;
}
if (best_sse > sse_thresh || motion_magnitude2 > motion_threshold) {
decision = COPY_BLOCK;
}
// If block is considered skin, don't denoise if the block
// (1) is selected as non-zero motion for current frame, or
// (2) has not been selected as ZERO_LAST mode at least x past frames
// in a row.
// TODO(marpan): Parameter "x" should be varied with framerate.
// In particualar, should be reduced for layers (base layer/LAST).
if (x->is_skin && (consec_zero_last < 2 || motion_magnitude2 > 0)) {
decision = COPY_BLOCK;
}
if (decision == FILTER_BLOCK) {
saved_pre = filter_xd->pre;
saved_dst = filter_xd->dst;
/* Compensate the running average. */
filter_xd->pre.y_buffer = src->y_buffer + recon_yoffset;
filter_xd->pre.u_buffer = src->u_buffer + recon_uvoffset;
filter_xd->pre.v_buffer = src->v_buffer + recon_uvoffset;
/* Write the compensated running average to the destination buffer. */
filter_xd->dst.y_buffer = dst->y_buffer + recon_yoffset;
filter_xd->dst.u_buffer = dst->u_buffer + recon_uvoffset;
filter_xd->dst.v_buffer = dst->v_buffer + recon_uvoffset;
if (!x->skip) {
vp8_build_inter_predictors_mb(filter_xd);
} else {
vp8_build_inter16x16_predictors_mb(
filter_xd, filter_xd->dst.y_buffer, filter_xd->dst.u_buffer,
filter_xd->dst.v_buffer, filter_xd->dst.y_stride,
filter_xd->dst.uv_stride);
}
filter_xd->pre = saved_pre;
filter_xd->dst = saved_dst;
*mbmi = saved_mbmi;
}
} else {
// zero_frame should always be 1 for real-time mode, as the
// ZEROMV mode is always checked, so we should never go into this branch.
// If case ZEROMV is not checked, then we will force no denoise (COPY).
decision = COPY_BLOCK;
}
if (decision == FILTER_BLOCK) {
unsigned char *mc_running_avg_y =
denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset;
int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride;
unsigned char *running_avg_y =
denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset;
int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride;
/* Filter. */
decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride,
running_avg_y, avg_y_stride, x->thismb, 16,
motion_magnitude2, x->increase_denoising);
denoiser->denoise_state[block_index] =
motion_magnitude2 > 0 ? kFilterNonZeroMV : kFilterZeroMV;
// Only denoise UV for zero motion, and if y channel was denoised.
if (denoiser->denoiser_mode != kDenoiserOnYOnly && motion_magnitude2 == 0 &&
decision == FILTER_BLOCK) {
unsigned char *mc_running_avg_u =
denoiser->yv12_mc_running_avg.u_buffer + recon_uvoffset;
unsigned char *running_avg_u =
denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset;
unsigned char *mc_running_avg_v =
denoiser->yv12_mc_running_avg.v_buffer + recon_uvoffset;
unsigned char *running_avg_v =
denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset;
int mc_avg_uv_stride = denoiser->yv12_mc_running_avg.uv_stride;
int avg_uv_stride = denoiser->yv12_running_avg[INTRA_FRAME].uv_stride;
int signal_stride = x->block[16].src_stride;
decision_u = vp8_denoiser_filter_uv(
mc_running_avg_u, mc_avg_uv_stride, running_avg_u, avg_uv_stride,
x->block[16].src + *x->block[16].base_src, signal_stride,
motion_magnitude2, 0);
decision_v = vp8_denoiser_filter_uv(
mc_running_avg_v, mc_avg_uv_stride, running_avg_v, avg_uv_stride,
x->block[20].src + *x->block[20].base_src, signal_stride,
motion_magnitude2, 0);
}
}
if (decision == COPY_BLOCK) {
/* No filtering of this block; it differs too much from the predictor,
* or the motion vector magnitude is considered too big.
*/
x->denoise_zeromv = 0;
vp8_copy_mem16x16(
x->thismb, 16,
denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
denoiser->yv12_running_avg[INTRA_FRAME].y_stride);
denoiser->denoise_state[block_index] = kNoFilter;
}
if (denoiser->denoiser_mode != kDenoiserOnYOnly) {
if (decision_u == COPY_BLOCK) {
vp8_copy_mem8x8(
x->block[16].src + *x->block[16].base_src, x->block[16].src_stride,
denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset,
denoiser->yv12_running_avg[INTRA_FRAME].uv_stride);
}
if (decision_v == COPY_BLOCK) {
vp8_copy_mem8x8(
x->block[20].src + *x->block[20].base_src, x->block[16].src_stride,
denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset,
denoiser->yv12_running_avg[INTRA_FRAME].uv_stride);
}
}
// Option to selectively deblock the denoised signal, for y channel only.
if (apply_spatial_loop_filter) {
loop_filter_info lfi;
int apply_filter_col = 0;
int apply_filter_row = 0;
int apply_filter = 0;
int y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride;
int uv_stride = denoiser->yv12_running_avg[INTRA_FRAME].uv_stride;
// Fix filter level to some nominal value for now.
int filter_level = 48;
int hev_index = lfi_n->hev_thr_lut[INTER_FRAME][filter_level];
lfi.mblim = lfi_n->mblim[filter_level];
lfi.blim = lfi_n->blim[filter_level];
lfi.lim = lfi_n->lim[filter_level];
lfi.hev_thr = lfi_n->hev_thr[hev_index];
// Apply filter if there is a difference in the denoiser filter state
// between the current and left/top block, or if non-zero motion vector
// is used for the motion-compensated filtering.
if (mb_col > 0) {
apply_filter_col =
!((denoiser->denoise_state[block_index] ==
denoiser->denoise_state[block_index - 1]) &&
denoiser->denoise_state[block_index] != kFilterNonZeroMV);
if (apply_filter_col) {
// Filter left vertical edge.
apply_filter = 1;
vp8_loop_filter_mbv(
denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
NULL, NULL, y_stride, uv_stride, &lfi);
}
}
if (mb_row > 0) {
apply_filter_row =
!((denoiser->denoise_state[block_index] ==
denoiser->denoise_state[block_index - denoiser->num_mb_cols]) &&
denoiser->denoise_state[block_index] != kFilterNonZeroMV);
if (apply_filter_row) {
// Filter top horizontal edge.
apply_filter = 1;
vp8_loop_filter_mbh(
denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
NULL, NULL, y_stride, uv_stride, &lfi);
}
}
if (apply_filter) {
// Update the signal block |x|. Pixel changes are only to top and/or
// left boundary pixels: can we avoid full block copy here.
vp8_copy_mem16x16(
denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
y_stride, x->thismb, 16);
}
}
}
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_DENOISING_H_
#define VPX_VP8_ENCODER_DENOISING_H_
#include "block.h"
#include "vp8/common/loopfilter.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SUM_DIFF_THRESHOLD 512
#define SUM_DIFF_THRESHOLD_HIGH 600
#define MOTION_MAGNITUDE_THRESHOLD (8 * 3)
#define SUM_DIFF_THRESHOLD_UV (96) // (8 * 8 * 1.5)
#define SUM_DIFF_THRESHOLD_HIGH_UV (8 * 8 * 2)
#define SUM_DIFF_FROM_AVG_THRESH_UV (8 * 8 * 8)
#define MOTION_MAGNITUDE_THRESHOLD_UV (8 * 3)
#define MAX_GF_ARF_DENOISE_RANGE (8)
enum vp8_denoiser_decision { COPY_BLOCK, FILTER_BLOCK };
enum vp8_denoiser_filter_state { kNoFilter, kFilterZeroMV, kFilterNonZeroMV };
enum vp8_denoiser_mode {
kDenoiserOff,
kDenoiserOnYOnly,
kDenoiserOnYUV,
kDenoiserOnYUVAggressive,
kDenoiserOnAdaptive
};
typedef struct {
// Scale factor on sse threshold above which no denoising is done.
unsigned int scale_sse_thresh;
// Scale factor on motion magnitude threshold above which no
// denoising is done.
unsigned int scale_motion_thresh;
// Scale factor on motion magnitude below which we increase the strength of
// the temporal filter (in function vp8_denoiser_filter).
unsigned int scale_increase_filter;
// Scale factor to bias to ZEROMV for denoising.
unsigned int denoise_mv_bias;
// Scale factor to bias to ZEROMV for coding mode selection.
unsigned int pickmode_mv_bias;
// Quantizer threshold below which we use the segmentation map to switch off
// loop filter for blocks that have been coded as ZEROMV-LAST a certain number
// (consec_zerolast) of consecutive frames. Note that the delta-QP is set to
// 0 when segmentation map is used for shutting off loop filter.
unsigned int qp_thresh;
// Threshold for number of consecutive frames for blocks coded as ZEROMV-LAST.
unsigned int consec_zerolast;
// Threshold for amount of spatial blur on Y channel. 0 means no spatial blur.
unsigned int spatial_blur;
} denoise_params;
typedef struct vp8_denoiser {
YV12_BUFFER_CONFIG yv12_running_avg[MAX_REF_FRAMES];
YV12_BUFFER_CONFIG yv12_mc_running_avg;
// TODO(marpan): Should remove yv12_last_source and use vp8_lookahead_peak.
YV12_BUFFER_CONFIG yv12_last_source;
unsigned char *denoise_state;
int num_mb_cols;
int denoiser_mode;
int threshold_aggressive_mode;
int nmse_source_diff;
int nmse_source_diff_count;
int qp_avg;
int qp_threshold_up;
int qp_threshold_down;
int bitrate_threshold;
denoise_params denoise_pars;
} VP8_DENOISER;
int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height,
int num_mb_rows, int num_mb_cols, int mode);
void vp8_denoiser_free(VP8_DENOISER *denoiser);
void vp8_denoiser_set_parameters(VP8_DENOISER *denoiser, int mode);
void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, MACROBLOCK *x,
unsigned int best_sse, unsigned int zero_mv_sse,
int recon_yoffset, int recon_uvoffset,
loop_filter_info_n *lfi_n, int mb_row, int mb_col,
int block_index, int consec_zero_last);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_DENOISING_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_ENCODEFRAME_H_
#define VPX_VP8_ENCODER_ENCODEFRAME_H_
#include "vp8/encoder/tokenize.h"
#ifdef __cplusplus
extern "C" {
#endif
struct VP8_COMP;
struct macroblock;
void vp8_activity_masking(struct VP8_COMP *cpi, MACROBLOCK *x);
void vp8_build_block_offsets(struct macroblock *x);
void vp8_setup_block_ptrs(struct macroblock *x);
void vp8_encode_frame(struct VP8_COMP *cpi);
int vp8cx_encode_inter_macroblock(struct VP8_COMP *cpi, struct macroblock *x,
TOKENEXTRA **t, int recon_yoffset,
int recon_uvoffset, int mb_row, int mb_col);
int vp8cx_encode_intra_macroblock(struct VP8_COMP *cpi, struct macroblock *x,
TOKENEXTRA **t);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_ENCODEFRAME_H_
@@ -0,0 +1,117 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vpx_config.h"
#include "vp8_rtcd.h"
#include "./vpx_dsp_rtcd.h"
#include "vp8/encoder/quantize.h"
#include "vp8/common/reconintra.h"
#include "vp8/common/reconintra4x4.h"
#include "encodemb.h"
#include "vp8/common/invtrans.h"
#include "encodeintra.h"
int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred) {
int i;
int intra_pred_var = 0;
(void)cpi;
if (use_dc_pred) {
x->e_mbd.mode_info_context->mbmi.mode = DC_PRED;
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
vp8_encode_intra16x16mby(x);
vp8_inverse_transform_mby(&x->e_mbd);
} else {
for (i = 0; i < 16; ++i) {
x->e_mbd.block[i].bmi.as_mode = B_DC_PRED;
vp8_encode_intra4x4block(x, i);
}
}
intra_pred_var = vpx_get_mb_ss(x->src_diff);
return intra_pred_var;
}
void vp8_encode_intra4x4block(MACROBLOCK *x, int ib) {
BLOCKD *b = &x->e_mbd.block[ib];
BLOCK *be = &x->block[ib];
int dst_stride = x->e_mbd.dst.y_stride;
unsigned char *dst = x->e_mbd.dst.y_buffer + b->offset;
unsigned char *Above = dst - dst_stride;
unsigned char *yleft = dst - 1;
unsigned char top_left = Above[-1];
vp8_intra4x4_predict(Above, yleft, dst_stride, b->bmi.as_mode, b->predictor,
16, top_left);
vp8_subtract_b(be, b, 16);
x->short_fdct4x4(be->src_diff, be->coeff, 32);
x->quantize_b(be, b);
if (*b->eob > 1) {
vp8_short_idct4x4llm(b->dqcoeff, b->predictor, 16, dst, dst_stride);
} else {
vp8_dc_only_idct_add(b->dqcoeff[0], b->predictor, 16, dst, dst_stride);
}
}
void vp8_encode_intra4x4mby(MACROBLOCK *mb) {
int i;
MACROBLOCKD *xd = &mb->e_mbd;
intra_prediction_down_copy(xd, xd->dst.y_buffer - xd->dst.y_stride + 16);
for (i = 0; i < 16; ++i) vp8_encode_intra4x4block(mb, i);
return;
}
void vp8_encode_intra16x16mby(MACROBLOCK *x) {
BLOCK *b = &x->block[0];
MACROBLOCKD *xd = &x->e_mbd;
vp8_build_intra_predictors_mby_s(xd, xd->dst.y_buffer - xd->dst.y_stride,
xd->dst.y_buffer - 1, xd->dst.y_stride,
xd->dst.y_buffer, xd->dst.y_stride);
vp8_subtract_mby(x->src_diff, *(b->base_src), b->src_stride, xd->dst.y_buffer,
xd->dst.y_stride);
vp8_transform_intra_mby(x);
vp8_quantize_mby(x);
if (x->optimize) vp8_optimize_mby(x);
}
void vp8_encode_intra16x16mbuv(MACROBLOCK *x) {
MACROBLOCKD *xd = &x->e_mbd;
vp8_build_intra_predictors_mbuv_s(xd, xd->dst.u_buffer - xd->dst.uv_stride,
xd->dst.v_buffer - xd->dst.uv_stride,
xd->dst.u_buffer - 1, xd->dst.v_buffer - 1,
xd->dst.uv_stride, xd->dst.u_buffer,
xd->dst.v_buffer, xd->dst.uv_stride);
vp8_subtract_mbuv(x->src_diff, x->src.u_buffer, x->src.v_buffer,
x->src.uv_stride, xd->dst.u_buffer, xd->dst.v_buffer,
xd->dst.uv_stride);
vp8_transform_mbuv(x);
vp8_quantize_mbuv(x);
if (x->optimize) vp8_optimize_mbuv(x);
}
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_ENCODEINTRA_H_
#define VPX_VP8_ENCODER_ENCODEINTRA_H_
#include "onyx_int.h"
#ifdef __cplusplus
extern "C" {
#endif
int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred);
void vp8_encode_intra16x16mby(MACROBLOCK *x);
void vp8_encode_intra16x16mbuv(MACROBLOCK *x);
void vp8_encode_intra4x4mby(MACROBLOCK *mb);
void vp8_encode_intra4x4block(MACROBLOCK *x, int ib);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_ENCODEINTRA_H_
@@ -0,0 +1,512 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vpx_dsp_rtcd.h"
#include "vpx_config.h"
#include "vp8_rtcd.h"
#include "encodemb.h"
#include "vp8/common/reconinter.h"
#include "vp8/encoder/quantize.h"
#include "tokenize.h"
#include "vp8/common/invtrans.h"
#include "vpx_mem/vpx_mem.h"
#include "rdopt.h"
void vp8_subtract_b(BLOCK *be, BLOCKD *bd, int pitch) {
unsigned char *src_ptr = (*(be->base_src) + be->src);
short *diff_ptr = be->src_diff;
unsigned char *pred_ptr = bd->predictor;
int src_stride = be->src_stride;
vpx_subtract_block(4, 4, diff_ptr, pitch, src_ptr, src_stride, pred_ptr,
pitch);
}
void vp8_subtract_mbuv(short *diff, unsigned char *usrc, unsigned char *vsrc,
int src_stride, unsigned char *upred,
unsigned char *vpred, int pred_stride) {
short *udiff = diff + 256;
short *vdiff = diff + 320;
vpx_subtract_block(8, 8, udiff, 8, usrc, src_stride, upred, pred_stride);
vpx_subtract_block(8, 8, vdiff, 8, vsrc, src_stride, vpred, pred_stride);
}
void vp8_subtract_mby(short *diff, unsigned char *src, int src_stride,
unsigned char *pred, int pred_stride) {
vpx_subtract_block(16, 16, diff, 16, src, src_stride, pred, pred_stride);
}
static void vp8_subtract_mb(MACROBLOCK *x) {
BLOCK *b = &x->block[0];
vp8_subtract_mby(x->src_diff, *(b->base_src), b->src_stride,
x->e_mbd.dst.y_buffer, x->e_mbd.dst.y_stride);
vp8_subtract_mbuv(x->src_diff, x->src.u_buffer, x->src.v_buffer,
x->src.uv_stride, x->e_mbd.dst.u_buffer,
x->e_mbd.dst.v_buffer, x->e_mbd.dst.uv_stride);
}
static void build_dcblock(MACROBLOCK *x) {
short *src_diff_ptr = &x->src_diff[384];
int i;
for (i = 0; i < 16; ++i) {
src_diff_ptr[i] = x->coeff[i * 16];
}
}
void vp8_transform_mbuv(MACROBLOCK *x) {
int i;
for (i = 16; i < 24; i += 2) {
x->short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 16);
}
}
void vp8_transform_intra_mby(MACROBLOCK *x) {
int i;
for (i = 0; i < 16; i += 2) {
x->short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32);
}
/* build dc block from 16 y dc values */
build_dcblock(x);
/* do 2nd order transform on the dc block */
x->short_walsh4x4(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8);
}
static void transform_mb(MACROBLOCK *x) {
int i;
for (i = 0; i < 16; i += 2) {
x->short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32);
}
/* build dc block from 16 y dc values */
if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV) build_dcblock(x);
for (i = 16; i < 24; i += 2) {
x->short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 16);
}
/* do 2nd order transform on the dc block */
if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV) {
x->short_walsh4x4(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8);
}
}
static void transform_mby(MACROBLOCK *x) {
int i;
for (i = 0; i < 16; i += 2) {
x->short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32);
}
/* build dc block from 16 y dc values */
if (x->e_mbd.mode_info_context->mbmi.mode != SPLITMV) {
build_dcblock(x);
x->short_walsh4x4(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8);
}
}
#define RDTRUNC(RM, DM, R, D) ((128 + (R) * (RM)) & 0xFF)
typedef struct vp8_token_state vp8_token_state;
struct vp8_token_state {
int rate;
int error;
signed char next;
signed char token;
short qc;
};
/* TODO: experiments to find optimal multiple numbers */
#define Y1_RD_MULT 4
#define UV_RD_MULT 2
#define Y2_RD_MULT 16
static const int plane_rd_mult[4] = { Y1_RD_MULT, Y2_RD_MULT, UV_RD_MULT,
Y1_RD_MULT };
static void optimize_b(MACROBLOCK *mb, int ib, int type, ENTROPY_CONTEXT *a,
ENTROPY_CONTEXT *l) {
BLOCK *b;
BLOCKD *d;
vp8_token_state tokens[17][2];
unsigned best_mask[2];
const short *dequant_ptr;
const short *coeff_ptr;
short *qcoeff_ptr;
short *dqcoeff_ptr;
int eob;
int i0;
int rc;
int x;
int sz = 0;
int next;
int rdmult;
int rddiv;
int final_eob;
int rd_cost0;
int rd_cost1;
int rate0;
int rate1;
int error0;
int error1;
int t0;
int t1;
int best;
int band;
int pt;
int i;
int err_mult = plane_rd_mult[type];
b = &mb->block[ib];
d = &mb->e_mbd.block[ib];
dequant_ptr = d->dequant;
coeff_ptr = b->coeff;
qcoeff_ptr = d->qcoeff;
dqcoeff_ptr = d->dqcoeff;
i0 = !type;
eob = *d->eob;
/* Now set up a Viterbi trellis to evaluate alternative roundings. */
rdmult = mb->rdmult * err_mult;
if (mb->e_mbd.mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
rdmult = (rdmult * 9) >> 4;
}
rddiv = mb->rddiv;
best_mask[0] = best_mask[1] = 0;
/* Initialize the sentinel node of the trellis. */
tokens[eob][0].rate = 0;
tokens[eob][0].error = 0;
tokens[eob][0].next = 16;
tokens[eob][0].token = DCT_EOB_TOKEN;
tokens[eob][0].qc = 0;
*(tokens[eob] + 1) = *(tokens[eob] + 0);
next = eob;
for (i = eob; i-- > i0;) {
int base_bits;
int d2;
int dx;
rc = vp8_default_zig_zag1d[i];
x = qcoeff_ptr[rc];
/* Only add a trellis state for non-zero coefficients. */
if (x) {
int shortcut = 0;
error0 = tokens[next][0].error;
error1 = tokens[next][1].error;
/* Evaluate the first possibility for this state. */
rate0 = tokens[next][0].rate;
rate1 = tokens[next][1].rate;
t0 = (vp8_dct_value_tokens_ptr + x)->Token;
/* Consider both possible successor states. */
if (next < 16) {
band = vp8_coef_bands[i + 1];
pt = vp8_prev_token_class[t0];
rate0 += mb->token_costs[type][band][pt][tokens[next][0].token];
rate1 += mb->token_costs[type][band][pt][tokens[next][1].token];
}
rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
if (rd_cost0 == rd_cost1) {
rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
}
/* And pick the best. */
best = rd_cost1 < rd_cost0;
base_bits = *(vp8_dct_value_cost_ptr + x);
dx = dqcoeff_ptr[rc] - coeff_ptr[rc];
d2 = dx * dx;
tokens[i][0].rate = base_bits + (best ? rate1 : rate0);
tokens[i][0].error = d2 + (best ? error1 : error0);
tokens[i][0].next = next;
tokens[i][0].token = t0;
tokens[i][0].qc = x;
best_mask[0] |= best << i;
/* Evaluate the second possibility for this state. */
rate0 = tokens[next][0].rate;
rate1 = tokens[next][1].rate;
if ((abs(x) * dequant_ptr[rc] > abs(coeff_ptr[rc])) &&
(abs(x) * dequant_ptr[rc] < abs(coeff_ptr[rc]) + dequant_ptr[rc])) {
shortcut = 1;
} else {
shortcut = 0;
}
if (shortcut) {
sz = -(x < 0);
x -= 2 * sz + 1;
}
/* Consider both possible successor states. */
if (!x) {
/* If we reduced this coefficient to zero, check to see if
* we need to move the EOB back here.
*/
t0 =
tokens[next][0].token == DCT_EOB_TOKEN ? DCT_EOB_TOKEN : ZERO_TOKEN;
t1 =
tokens[next][1].token == DCT_EOB_TOKEN ? DCT_EOB_TOKEN : ZERO_TOKEN;
} else {
t0 = t1 = (vp8_dct_value_tokens_ptr + x)->Token;
}
if (next < 16) {
band = vp8_coef_bands[i + 1];
if (t0 != DCT_EOB_TOKEN) {
pt = vp8_prev_token_class[t0];
rate0 += mb->token_costs[type][band][pt][tokens[next][0].token];
}
if (t1 != DCT_EOB_TOKEN) {
pt = vp8_prev_token_class[t1];
rate1 += mb->token_costs[type][band][pt][tokens[next][1].token];
}
}
rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
if (rd_cost0 == rd_cost1) {
rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
}
/* And pick the best. */
best = rd_cost1 < rd_cost0;
base_bits = *(vp8_dct_value_cost_ptr + x);
if (shortcut) {
dx -= (dequant_ptr[rc] + sz) ^ sz;
d2 = dx * dx;
}
tokens[i][1].rate = base_bits + (best ? rate1 : rate0);
tokens[i][1].error = d2 + (best ? error1 : error0);
tokens[i][1].next = next;
tokens[i][1].token = best ? t1 : t0;
tokens[i][1].qc = x;
best_mask[1] |= best << i;
/* Finally, make this the new head of the trellis. */
next = i;
}
/* There's no choice to make for a zero coefficient, so we don't
* add a new trellis node, but we do need to update the costs.
*/
else {
band = vp8_coef_bands[i + 1];
t0 = tokens[next][0].token;
t1 = tokens[next][1].token;
/* Update the cost of each path if we're past the EOB token. */
if (t0 != DCT_EOB_TOKEN) {
tokens[next][0].rate += mb->token_costs[type][band][0][t0];
tokens[next][0].token = ZERO_TOKEN;
}
if (t1 != DCT_EOB_TOKEN) {
tokens[next][1].rate += mb->token_costs[type][band][0][t1];
tokens[next][1].token = ZERO_TOKEN;
}
/* Don't update next, because we didn't add a new node. */
}
}
/* Now pick the best path through the whole trellis. */
band = vp8_coef_bands[i + 1];
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
rate0 = tokens[next][0].rate;
rate1 = tokens[next][1].rate;
error0 = tokens[next][0].error;
error1 = tokens[next][1].error;
t0 = tokens[next][0].token;
t1 = tokens[next][1].token;
rate0 += mb->token_costs[type][band][pt][t0];
rate1 += mb->token_costs[type][band][pt][t1];
rd_cost0 = RDCOST(rdmult, rddiv, rate0, error0);
rd_cost1 = RDCOST(rdmult, rddiv, rate1, error1);
if (rd_cost0 == rd_cost1) {
rd_cost0 = RDTRUNC(rdmult, rddiv, rate0, error0);
rd_cost1 = RDTRUNC(rdmult, rddiv, rate1, error1);
}
best = rd_cost1 < rd_cost0;
final_eob = i0 - 1;
for (i = next; i < eob; i = next) {
x = tokens[i][best].qc;
if (x) final_eob = i;
rc = vp8_default_zig_zag1d[i];
qcoeff_ptr[rc] = x;
dqcoeff_ptr[rc] = x * dequant_ptr[rc];
next = tokens[i][best].next;
best = (best_mask[best] >> i) & 1;
}
final_eob++;
*a = *l = (final_eob != !type);
*d->eob = (char)final_eob;
}
static void check_reset_2nd_coeffs(MACROBLOCKD *x, int type, ENTROPY_CONTEXT *a,
ENTROPY_CONTEXT *l) {
int sum = 0;
int i;
BLOCKD *bd = &x->block[24];
if (bd->dequant[0] >= 35 && bd->dequant[1] >= 35) return;
for (i = 0; i < (*bd->eob); ++i) {
int coef = bd->dqcoeff[vp8_default_zig_zag1d[i]];
sum += (coef >= 0) ? coef : -coef;
if (sum >= 35) return;
}
/**************************************************************************
our inverse hadamard transform effectively is weighted sum of all 16 inputs
with weight either 1 or -1. It has a last stage scaling of (sum+3)>>3. And
dc only idct is (dc+4)>>3. So if all the sums are between -35 and 29, the
output after inverse wht and idct will be all zero. A sum of absolute value
smaller than 35 guarantees all 16 different (+1/-1) weighted sums in wht
fall between -35 and +35.
**************************************************************************/
if (sum < 35) {
for (i = 0; i < (*bd->eob); ++i) {
int rc = vp8_default_zig_zag1d[i];
bd->qcoeff[rc] = 0;
bd->dqcoeff[rc] = 0;
}
*bd->eob = 0;
*a = *l = (*bd->eob != !type);
}
}
static void optimize_mb(MACROBLOCK *x) {
int b;
int type;
int has_2nd_order;
ENTROPY_CONTEXT_PLANES t_above, t_left;
ENTROPY_CONTEXT *ta;
ENTROPY_CONTEXT *tl;
memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
ta = (ENTROPY_CONTEXT *)&t_above;
tl = (ENTROPY_CONTEXT *)&t_left;
has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED &&
x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
for (b = 0; b < 16; ++b) {
optimize_b(x, b, type, ta + vp8_block2above[b], tl + vp8_block2left[b]);
}
for (b = 16; b < 24; ++b) {
optimize_b(x, b, PLANE_TYPE_UV, ta + vp8_block2above[b],
tl + vp8_block2left[b]);
}
if (has_2nd_order) {
b = 24;
optimize_b(x, b, PLANE_TYPE_Y2, ta + vp8_block2above[b],
tl + vp8_block2left[b]);
check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2, ta + vp8_block2above[b],
tl + vp8_block2left[b]);
}
}
void vp8_optimize_mby(MACROBLOCK *x) {
int b;
int type;
int has_2nd_order;
ENTROPY_CONTEXT_PLANES t_above, t_left;
ENTROPY_CONTEXT *ta;
ENTROPY_CONTEXT *tl;
if (!x->e_mbd.above_context) return;
if (!x->e_mbd.left_context) return;
memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
ta = (ENTROPY_CONTEXT *)&t_above;
tl = (ENTROPY_CONTEXT *)&t_left;
has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED &&
x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
type = has_2nd_order ? PLANE_TYPE_Y_NO_DC : PLANE_TYPE_Y_WITH_DC;
for (b = 0; b < 16; ++b) {
optimize_b(x, b, type, ta + vp8_block2above[b], tl + vp8_block2left[b]);
}
if (has_2nd_order) {
b = 24;
optimize_b(x, b, PLANE_TYPE_Y2, ta + vp8_block2above[b],
tl + vp8_block2left[b]);
check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2, ta + vp8_block2above[b],
tl + vp8_block2left[b]);
}
}
void vp8_optimize_mbuv(MACROBLOCK *x) {
int b;
ENTROPY_CONTEXT_PLANES t_above, t_left;
ENTROPY_CONTEXT *ta;
ENTROPY_CONTEXT *tl;
if (!x->e_mbd.above_context) return;
if (!x->e_mbd.left_context) return;
memcpy(&t_above, x->e_mbd.above_context, sizeof(ENTROPY_CONTEXT_PLANES));
memcpy(&t_left, x->e_mbd.left_context, sizeof(ENTROPY_CONTEXT_PLANES));
ta = (ENTROPY_CONTEXT *)&t_above;
tl = (ENTROPY_CONTEXT *)&t_left;
for (b = 16; b < 24; ++b) {
optimize_b(x, b, PLANE_TYPE_UV, ta + vp8_block2above[b],
tl + vp8_block2left[b]);
}
}
void vp8_encode_inter16x16(MACROBLOCK *x) {
vp8_build_inter_predictors_mb(&x->e_mbd);
vp8_subtract_mb(x);
transform_mb(x);
vp8_quantize_mb(x);
if (x->optimize) optimize_mb(x);
}
/* this funciton is used by first pass only */
void vp8_encode_inter16x16y(MACROBLOCK *x) {
BLOCK *b = &x->block[0];
vp8_build_inter16x16_predictors_mby(&x->e_mbd, x->e_mbd.dst.y_buffer,
x->e_mbd.dst.y_stride);
vp8_subtract_mby(x->src_diff, *(b->base_src), b->src_stride,
x->e_mbd.dst.y_buffer, x->e_mbd.dst.y_stride);
transform_mby(x);
vp8_quantize_mby(x);
vp8_inverse_transform_mby(&x->e_mbd);
}
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_ENCODEMB_H_
#define VPX_VP8_ENCODER_ENCODEMB_H_
#include "onyx_int.h"
#ifdef __cplusplus
extern "C" {
#endif
void vp8_encode_inter16x16(MACROBLOCK *x);
void vp8_subtract_b(BLOCK *be, BLOCKD *bd, int pitch);
void vp8_subtract_mbuv(short *diff, unsigned char *usrc, unsigned char *vsrc,
int src_stride, unsigned char *upred,
unsigned char *vpred, int pred_stride);
void vp8_subtract_mby(short *diff, unsigned char *src, int src_stride,
unsigned char *pred, int pred_stride);
void vp8_build_dcblock(MACROBLOCK *b);
void vp8_transform_mb(MACROBLOCK *mb);
void vp8_transform_mbuv(MACROBLOCK *x);
void vp8_transform_intra_mby(MACROBLOCK *x);
void vp8_optimize_mby(MACROBLOCK *x);
void vp8_optimize_mbuv(MACROBLOCK *x);
void vp8_encode_inter16x16y(MACROBLOCK *x);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_ENCODEMB_H_
@@ -0,0 +1,319 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp8/common/common.h"
#include "encodemv.h"
#include "vp8/common/entropymode.h"
#include "vp8/common/systemdependent.h"
#include "vpx_ports/system_state.h"
#include <math.h>
static void encode_mvcomponent(vp8_writer *const w, const int v,
const struct mv_context *mvc) {
const vp8_prob *p = mvc->prob;
const int x = v < 0 ? -v : v;
if (x < mvnum_short) { /* Small */
vp8_write(w, 0, p[mvpis_short]);
vp8_treed_write(w, vp8_small_mvtree, p + MVPshort, x, 3);
if (!x) return; /* no sign bit */
} else { /* Large */
int i = 0;
vp8_write(w, 1, p[mvpis_short]);
do
vp8_write(w, (x >> i) & 1, p[MVPbits + i]);
while (++i < 3);
i = mvlong_width - 1; /* Skip bit 3, which is sometimes implicit */
do
vp8_write(w, (x >> i) & 1, p[MVPbits + i]);
while (--i > 3);
if (x & 0xFFF0) vp8_write(w, (x >> 3) & 1, p[MVPbits + 3]);
}
vp8_write(w, v < 0, p[MVPsign]);
}
#if 0
static int max_mv_r = 0;
static int max_mv_c = 0;
#endif
void vp8_encode_motion_vector(vp8_writer *w, const MV *mv,
const MV_CONTEXT *mvc) {
#if 0
{
if (abs(mv->row >> 1) > max_mv_r)
{
FILE *f = fopen("maxmv.stt", "a");
max_mv_r = abs(mv->row >> 1);
fprintf(f, "New Mv Row Max %6d\n", (mv->row >> 1));
if ((abs(mv->row) / 2) != max_mv_r)
fprintf(f, "MV Row conversion error %6d\n", abs(mv->row) / 2);
fclose(f);
}
if (abs(mv->col >> 1) > max_mv_c)
{
FILE *f = fopen("maxmv.stt", "a");
fprintf(f, "New Mv Col Max %6d\n", (mv->col >> 1));
max_mv_c = abs(mv->col >> 1);
fclose(f);
}
}
#endif
encode_mvcomponent(w, mv->row >> 1, &mvc[0]);
encode_mvcomponent(w, mv->col >> 1, &mvc[1]);
}
static unsigned int cost_mvcomponent(const int v,
const struct mv_context *mvc) {
const vp8_prob *p = mvc->prob;
const int x = v;
unsigned int cost;
if (x < mvnum_short) {
cost = vp8_cost_zero(p[mvpis_short]) +
vp8_treed_cost(vp8_small_mvtree, p + MVPshort, x, 3);
if (!x) return cost;
} else {
int i = 0;
cost = vp8_cost_one(p[mvpis_short]);
do {
cost += vp8_cost_bit(p[MVPbits + i], (x >> i) & 1);
} while (++i < 3);
i = mvlong_width - 1; /* Skip bit 3, which is sometimes implicit */
do {
cost += vp8_cost_bit(p[MVPbits + i], (x >> i) & 1);
} while (--i > 3);
if (x & 0xFFF0) cost += vp8_cost_bit(p[MVPbits + 3], (x >> 3) & 1);
}
return cost; /* + vp8_cost_bit( p [MVPsign], v < 0); */
}
void vp8_build_component_cost_table(int *mvcost[2], const MV_CONTEXT *mvc,
int mvc_flag[2]) {
int i = 1;
unsigned int cost0 = 0;
unsigned int cost1 = 0;
vpx_clear_system_state();
i = 1;
if (mvc_flag[0]) {
mvcost[0][0] = cost_mvcomponent(0, &mvc[0]);
do {
cost0 = cost_mvcomponent(i, &mvc[0]);
mvcost[0][i] = cost0 + vp8_cost_zero(mvc[0].prob[MVPsign]);
mvcost[0][-i] = cost0 + vp8_cost_one(mvc[0].prob[MVPsign]);
} while (++i <= mv_max);
}
i = 1;
if (mvc_flag[1]) {
mvcost[1][0] = cost_mvcomponent(0, &mvc[1]);
do {
cost1 = cost_mvcomponent(i, &mvc[1]);
mvcost[1][i] = cost1 + vp8_cost_zero(mvc[1].prob[MVPsign]);
mvcost[1][-i] = cost1 + vp8_cost_one(mvc[1].prob[MVPsign]);
} while (++i <= mv_max);
}
}
/* Motion vector probability table update depends on benefit.
* Small correction allows for the fact that an update to an MV probability
* may have benefit in subsequent frames as well as the current one.
*/
#define MV_PROB_UPDATE_CORRECTION -1
static void calc_prob(vp8_prob *p, const unsigned int ct[2]) {
const unsigned int tot = ct[0] + ct[1];
if (tot) {
const vp8_prob x = ((ct[0] * 255) / tot) & -2;
*p = x ? x : 1;
}
}
static void update(vp8_writer *const w, const unsigned int ct[2],
vp8_prob *const cur_p, const vp8_prob new_p,
const vp8_prob update_p, int *updated) {
const int cur_b = vp8_cost_branch(ct, *cur_p);
const int new_b = vp8_cost_branch(ct, new_p);
const int cost =
7 + MV_PROB_UPDATE_CORRECTION +
((vp8_cost_one(update_p) - vp8_cost_zero(update_p) + 128) >> 8);
if (cur_b - new_b > cost) {
*cur_p = new_p;
vp8_write(w, 1, update_p);
vp8_write_literal(w, new_p >> 1, 7);
*updated = 1;
} else
vp8_write(w, 0, update_p);
}
static void write_component_probs(vp8_writer *const w,
struct mv_context *cur_mvc,
const struct mv_context *default_mvc_,
const struct mv_context *update_mvc,
const unsigned int events[MVvals],
unsigned int rc, int *updated) {
vp8_prob *Pcur = cur_mvc->prob;
const vp8_prob *default_mvc = default_mvc_->prob;
const vp8_prob *Pupdate = update_mvc->prob;
unsigned int is_short_ct[2], sign_ct[2];
unsigned int bit_ct[mvlong_width][2];
unsigned int short_ct[mvnum_short];
unsigned int short_bct[mvnum_short - 1][2];
vp8_prob Pnew[MVPcount];
(void)rc;
vp8_copy_array(Pnew, default_mvc, MVPcount);
vp8_zero(is_short_ct) vp8_zero(sign_ct) vp8_zero(bit_ct) vp8_zero(short_ct)
vp8_zero(short_bct)
/* j=0 */
{
const int c = events[mv_max];
is_short_ct[0] += c; /* Short vector */
short_ct[0] += c; /* Magnitude distribution */
}
/* j: 1 ~ mv_max (1023) */
{
int j = 1;
do {
const int c1 = events[mv_max + j]; /* positive */
const int c2 = events[mv_max - j]; /* negative */
const int c = c1 + c2;
int a = j;
sign_ct[0] += c1;
sign_ct[1] += c2;
if (a < mvnum_short) {
is_short_ct[0] += c; /* Short vector */
short_ct[a] += c; /* Magnitude distribution */
} else {
int k = mvlong_width - 1;
is_short_ct[1] += c; /* Long vector */
/* bit 3 not always encoded. */
do {
bit_ct[k][(a >> k) & 1] += c;
} while (--k >= 0);
}
} while (++j <= mv_max);
}
calc_prob(Pnew + mvpis_short, is_short_ct);
calc_prob(Pnew + MVPsign, sign_ct);
{
vp8_prob p[mvnum_short - 1]; /* actually only need branch ct */
int j = 0;
vp8_tree_probs_from_distribution(8, vp8_small_mvencodings, vp8_small_mvtree,
p, short_bct, short_ct, 256, 1);
do {
calc_prob(Pnew + MVPshort + j, short_bct[j]);
} while (++j < mvnum_short - 1);
}
{
int j = 0;
do {
calc_prob(Pnew + MVPbits + j, bit_ct[j]);
} while (++j < mvlong_width);
}
update(w, is_short_ct, Pcur + mvpis_short, Pnew[mvpis_short], *Pupdate++,
updated);
update(w, sign_ct, Pcur + MVPsign, Pnew[MVPsign], *Pupdate++, updated);
{
const vp8_prob *const new_p = Pnew + MVPshort;
vp8_prob *const cur_p = Pcur + MVPshort;
int j = 0;
do {
update(w, short_bct[j], cur_p + j, new_p[j], *Pupdate++, updated);
} while (++j < mvnum_short - 1);
}
{
const vp8_prob *const new_p = Pnew + MVPbits;
vp8_prob *const cur_p = Pcur + MVPbits;
int j = 0;
do {
update(w, bit_ct[j], cur_p + j, new_p[j], *Pupdate++, updated);
} while (++j < mvlong_width);
}
}
void vp8_write_mvprobs(VP8_COMP *cpi) {
vp8_writer *const w = cpi->bc;
MV_CONTEXT *mvc = cpi->common.fc.mvc;
int flags[2] = { 0, 0 };
write_component_probs(w, &mvc[0], &vp8_default_mv_context[0],
&vp8_mv_update_probs[0], cpi->mb.MVcount[0], 0,
&flags[0]);
write_component_probs(w, &mvc[1], &vp8_default_mv_context[1],
&vp8_mv_update_probs[1], cpi->mb.MVcount[1], 1,
&flags[1]);
if (flags[0] || flags[1]) {
vp8_build_component_cost_table(
cpi->mb.mvcost, (const MV_CONTEXT *)cpi->common.fc.mvc, flags);
}
}
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_ENCODEMV_H_
#define VPX_VP8_ENCODER_ENCODEMV_H_
#include "onyx_int.h"
#ifdef __cplusplus
extern "C" {
#endif
void vp8_write_mvprobs(VP8_COMP *);
void vp8_encode_motion_vector(vp8_writer *, const MV *, const MV_CONTEXT *);
void vp8_build_component_cost_table(int *mvcost[2], const MV_CONTEXT *mvc,
int mvc_flag[2]);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_ENCODEMV_H_
@@ -0,0 +1,639 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "onyx_int.h"
#include "vp8/common/threading.h"
#include "vp8/common/common.h"
#include "vp8/common/extend.h"
#include "bitstream.h"
#include "encodeframe.h"
#include "ethreading.h"
#if CONFIG_MULTITHREAD
extern void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x,
int ok_to_skip);
static THREAD_FUNCTION thread_loopfilter(void *p_data) {
VP8_COMP *cpi = (VP8_COMP *)(((LPFTHREAD_DATA *)p_data)->ptr1);
VP8_COMMON *cm = &cpi->common;
while (1) {
if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) == 0) break;
if (sem_wait(&cpi->h_event_start_lpf) == 0) {
/* we're shutting down */
if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) == 0) break;
vp8_loopfilter_frame(cpi, cm);
sem_post(&cpi->h_event_end_lpf);
}
}
return 0;
}
static THREAD_FUNCTION thread_encoding_proc(void *p_data) {
int ithread = ((ENCODETHREAD_DATA *)p_data)->ithread;
VP8_COMP *cpi = (VP8_COMP *)(((ENCODETHREAD_DATA *)p_data)->ptr1);
MB_ROW_COMP *mbri = (MB_ROW_COMP *)(((ENCODETHREAD_DATA *)p_data)->ptr2);
ENTROPY_CONTEXT_PLANES mb_row_left_context;
while (1) {
if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) == 0) break;
if (sem_wait(&cpi->h_event_start_encoding[ithread]) == 0) {
const int nsync = cpi->mt_sync_range;
VP8_COMMON *cm = &cpi->common;
int mb_row;
MACROBLOCK *x = &mbri->mb;
MACROBLOCKD *xd = &x->e_mbd;
TOKENEXTRA *tp;
#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
TOKENEXTRA *tp_start = cpi->tok + (1 + ithread) * (16 * 24);
const int num_part = (1 << cm->multi_token_partition);
#endif
int *segment_counts = mbri->segment_counts;
int *totalrate = &mbri->totalrate;
/* we're shutting down */
if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) == 0) break;
xd->mode_info_context = cm->mi + cm->mode_info_stride * (ithread + 1);
xd->mode_info_stride = cm->mode_info_stride;
for (mb_row = ithread + 1; mb_row < cm->mb_rows;
mb_row += (cpi->encoding_thread_count + 1)) {
int recon_yoffset, recon_uvoffset;
int mb_col;
int ref_fb_idx = cm->lst_fb_idx;
int dst_fb_idx = cm->new_fb_idx;
int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;
int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
int map_index = (mb_row * cm->mb_cols);
const vpx_atomic_int *last_row_current_mb_col;
vpx_atomic_int *current_mb_col = &cpi->mt_current_mb_col[mb_row];
#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
vp8_writer *w = &cpi->bc[1 + (mb_row % num_part)];
#else
tp = cpi->tok + (mb_row * (cm->mb_cols * 16 * 24));
cpi->tplist[mb_row].start = tp;
#endif
last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1];
/* reset above block coeffs */
xd->above_context = cm->above_context;
xd->left_context = &mb_row_left_context;
vp8_zero(mb_row_left_context);
xd->up_available = (mb_row != 0);
recon_yoffset = (mb_row * recon_y_stride * 16);
recon_uvoffset = (mb_row * recon_uv_stride * 8);
/* Set the mb activity pointer to the start of the row. */
x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
/* for each macroblock col in image */
for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
if (((mb_col - 1) % nsync) == 0) {
vpx_atomic_store_release(current_mb_col, mb_col - 1);
}
if (mb_row && !(mb_col & (nsync - 1))) {
vp8_atomic_spin_wait(mb_col, last_row_current_mb_col, nsync);
}
#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
tp = tp_start;
#endif
/* Distance of Mb to the various image edges.
* These specified to 8th pel as they are always compared
* to values that are in 1/8th pel units
*/
xd->mb_to_left_edge = -((mb_col * 16) << 3);
xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;
xd->mb_to_top_edge = -((mb_row * 16) << 3);
xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;
/* Set up limit values for motion vectors used to prevent
* them extending outside the UMV borders
*/
x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
x->mv_col_max =
((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));
x->mv_row_max =
((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16);
xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
xd->left_available = (mb_col != 0);
x->rddiv = cpi->RDDIV;
x->rdmult = cpi->RDMULT;
/* Copy current mb to a buffer */
vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) vp8_activity_masking(cpi, x);
/* Is segmentation enabled */
/* MB level adjustment to quantizer */
if (xd->segmentation_enabled) {
/* Code to set segment id in xd->mbmi.segment_id for
* current MB (with range checking)
*/
if (cpi->segmentation_map[map_index + mb_col] <= 3) {
xd->mode_info_context->mbmi.segment_id =
cpi->segmentation_map[map_index + mb_col];
} else {
xd->mode_info_context->mbmi.segment_id = 0;
}
vp8cx_mb_init_quantizer(cpi, x, 1);
} else {
/* Set to Segment 0 by default */
xd->mode_info_context->mbmi.segment_id = 0;
}
x->active_ptr = cpi->active_map + map_index + mb_col;
if (cm->frame_type == KEY_FRAME) {
*totalrate += vp8cx_encode_intra_macroblock(cpi, x, &tp);
#ifdef MODE_STATS
y_modes[xd->mbmi.mode]++;
#endif
} else {
*totalrate += vp8cx_encode_inter_macroblock(
cpi, x, &tp, recon_yoffset, recon_uvoffset, mb_row, mb_col);
#ifdef MODE_STATS
inter_y_modes[xd->mbmi.mode]++;
if (xd->mbmi.mode == SPLITMV) {
int b;
for (b = 0; b < xd->mbmi.partition_count; ++b) {
inter_b_modes[x->partition->bmi[b].mode]++;
}
}
#endif
// Keep track of how many (consecutive) times a block
// is coded as ZEROMV_LASTREF, for base layer frames.
// Reset to 0 if its coded as anything else.
if (cpi->current_layer == 0) {
if (xd->mode_info_context->mbmi.mode == ZEROMV &&
xd->mode_info_context->mbmi.ref_frame == LAST_FRAME) {
// Increment, check for wrap-around.
if (cpi->consec_zero_last[map_index + mb_col] < 255) {
cpi->consec_zero_last[map_index + mb_col] += 1;
}
if (cpi->consec_zero_last_mvbias[map_index + mb_col] < 255) {
cpi->consec_zero_last_mvbias[map_index + mb_col] += 1;
}
} else {
cpi->consec_zero_last[map_index + mb_col] = 0;
cpi->consec_zero_last_mvbias[map_index + mb_col] = 0;
}
if (x->zero_last_dot_suppress) {
cpi->consec_zero_last_mvbias[map_index + mb_col] = 0;
}
}
/* Special case code for cyclic refresh
* If cyclic update enabled then copy
* xd->mbmi.segment_id; (which may have been updated
* based on mode during
* vp8cx_encode_inter_macroblock()) back into the
* global segmentation map
*/
if ((cpi->current_layer == 0) &&
(cpi->cyclic_refresh_mode_enabled &&
xd->segmentation_enabled)) {
const MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
cpi->segmentation_map[map_index + mb_col] = mbmi->segment_id;
/* If the block has been refreshed mark it as clean
* (the magnitude of the -ve influences how long it
* will be before we consider another refresh):
* Else if it was coded (last frame 0,0) and has
* not already been refreshed then mark it as a
* candidate for cleanup next time (marked 0) else
* mark it as dirty (1).
*/
if (mbmi->segment_id) {
cpi->cyclic_refresh_map[map_index + mb_col] = -1;
} else if ((mbmi->mode == ZEROMV) &&
(mbmi->ref_frame == LAST_FRAME)) {
if (cpi->cyclic_refresh_map[map_index + mb_col] == 1) {
cpi->cyclic_refresh_map[map_index + mb_col] = 0;
}
} else {
cpi->cyclic_refresh_map[map_index + mb_col] = 1;
}
}
}
#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
/* pack tokens for this MB */
{
int tok_count = tp - tp_start;
vp8_pack_tokens(w, tp_start, tok_count);
}
#else
cpi->tplist[mb_row].stop = tp;
#endif
/* Increment pointer into gf usage flags structure. */
x->gf_active_ptr++;
/* Increment the activity mask pointers. */
x->mb_activity_ptr++;
/* adjust to the next column of macroblocks */
x->src.y_buffer += 16;
x->src.u_buffer += 8;
x->src.v_buffer += 8;
recon_yoffset += 16;
recon_uvoffset += 8;
/* Keep track of segment usage */
segment_counts[xd->mode_info_context->mbmi.segment_id]++;
/* skip to next mb */
xd->mode_info_context++;
x->partition_info++;
xd->above_context++;
}
vp8_extend_mb_row(&cm->yv12_fb[dst_fb_idx], xd->dst.y_buffer + 16,
xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
vpx_atomic_store_release(current_mb_col, mb_col + nsync);
/* this is to account for the border */
xd->mode_info_context++;
x->partition_info++;
x->src.y_buffer +=
16 * x->src.y_stride * (cpi->encoding_thread_count + 1) -
16 * cm->mb_cols;
x->src.u_buffer +=
8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) -
8 * cm->mb_cols;
x->src.v_buffer +=
8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) -
8 * cm->mb_cols;
xd->mode_info_context +=
xd->mode_info_stride * cpi->encoding_thread_count;
x->partition_info += xd->mode_info_stride * cpi->encoding_thread_count;
x->gf_active_ptr += cm->mb_cols * cpi->encoding_thread_count;
}
/* Signal that this thread has completed processing its rows. */
sem_post(&cpi->h_event_end_encoding[ithread]);
}
}
/* printf("exit thread %d\n", ithread); */
return 0;
}
static void setup_mbby_copy(MACROBLOCK *mbdst, MACROBLOCK *mbsrc) {
MACROBLOCK *x = mbsrc;
MACROBLOCK *z = mbdst;
int i;
z->ss = x->ss;
z->ss_count = x->ss_count;
z->searches_per_step = x->searches_per_step;
z->errorperbit = x->errorperbit;
z->sadperbit16 = x->sadperbit16;
z->sadperbit4 = x->sadperbit4;
/*
z->mv_col_min = x->mv_col_min;
z->mv_col_max = x->mv_col_max;
z->mv_row_min = x->mv_row_min;
z->mv_row_max = x->mv_row_max;
*/
z->short_fdct4x4 = x->short_fdct4x4;
z->short_fdct8x4 = x->short_fdct8x4;
z->short_walsh4x4 = x->short_walsh4x4;
z->quantize_b = x->quantize_b;
z->optimize = x->optimize;
/*
z->mvc = x->mvc;
z->src.y_buffer = x->src.y_buffer;
z->src.u_buffer = x->src.u_buffer;
z->src.v_buffer = x->src.v_buffer;
*/
z->mvcost[0] = x->mvcost[0];
z->mvcost[1] = x->mvcost[1];
z->mvsadcost[0] = x->mvsadcost[0];
z->mvsadcost[1] = x->mvsadcost[1];
z->token_costs = x->token_costs;
z->inter_bmode_costs = x->inter_bmode_costs;
z->mbmode_cost = x->mbmode_cost;
z->intra_uv_mode_cost = x->intra_uv_mode_cost;
z->bmode_costs = x->bmode_costs;
for (i = 0; i < 25; ++i) {
z->block[i].quant = x->block[i].quant;
z->block[i].quant_fast = x->block[i].quant_fast;
z->block[i].quant_shift = x->block[i].quant_shift;
z->block[i].zbin = x->block[i].zbin;
z->block[i].zrun_zbin_boost = x->block[i].zrun_zbin_boost;
z->block[i].round = x->block[i].round;
z->block[i].src_stride = x->block[i].src_stride;
}
z->q_index = x->q_index;
z->act_zbin_adj = x->act_zbin_adj;
z->last_act_zbin_adj = x->last_act_zbin_adj;
{
MACROBLOCKD *xd = &x->e_mbd;
MACROBLOCKD *zd = &z->e_mbd;
/*
zd->mode_info_context = xd->mode_info_context;
zd->mode_info = xd->mode_info;
zd->mode_info_stride = xd->mode_info_stride;
zd->frame_type = xd->frame_type;
zd->up_available = xd->up_available ;
zd->left_available = xd->left_available;
zd->left_context = xd->left_context;
zd->last_frame_dc = xd->last_frame_dc;
zd->last_frame_dccons = xd->last_frame_dccons;
zd->gold_frame_dc = xd->gold_frame_dc;
zd->gold_frame_dccons = xd->gold_frame_dccons;
zd->mb_to_left_edge = xd->mb_to_left_edge;
zd->mb_to_right_edge = xd->mb_to_right_edge;
zd->mb_to_top_edge = xd->mb_to_top_edge ;
zd->mb_to_bottom_edge = xd->mb_to_bottom_edge;
zd->gf_active_ptr = xd->gf_active_ptr;
zd->frames_since_golden = xd->frames_since_golden;
zd->frames_till_alt_ref_frame = xd->frames_till_alt_ref_frame;
*/
zd->subpixel_predict = xd->subpixel_predict;
zd->subpixel_predict8x4 = xd->subpixel_predict8x4;
zd->subpixel_predict8x8 = xd->subpixel_predict8x8;
zd->subpixel_predict16x16 = xd->subpixel_predict16x16;
zd->segmentation_enabled = xd->segmentation_enabled;
zd->mb_segement_abs_delta = xd->mb_segement_abs_delta;
memcpy(zd->segment_feature_data, xd->segment_feature_data,
sizeof(xd->segment_feature_data));
memcpy(zd->dequant_y1_dc, xd->dequant_y1_dc, sizeof(xd->dequant_y1_dc));
memcpy(zd->dequant_y1, xd->dequant_y1, sizeof(xd->dequant_y1));
memcpy(zd->dequant_y2, xd->dequant_y2, sizeof(xd->dequant_y2));
memcpy(zd->dequant_uv, xd->dequant_uv, sizeof(xd->dequant_uv));
#if 1
/*TODO: Remove dequant from BLOCKD. This is a temporary solution until
* the quantizer code uses a passed in pointer to the dequant constants.
* This will also require modifications to the x86 and neon assembly.
* */
for (i = 0; i < 16; ++i) zd->block[i].dequant = zd->dequant_y1;
for (i = 16; i < 24; ++i) zd->block[i].dequant = zd->dequant_uv;
zd->block[24].dequant = zd->dequant_y2;
#endif
memcpy(z->rd_threshes, x->rd_threshes, sizeof(x->rd_threshes));
memcpy(z->rd_thresh_mult, x->rd_thresh_mult, sizeof(x->rd_thresh_mult));
z->zbin_over_quant = x->zbin_over_quant;
z->zbin_mode_boost_enabled = x->zbin_mode_boost_enabled;
z->zbin_mode_boost = x->zbin_mode_boost;
memset(z->error_bins, 0, sizeof(z->error_bins));
}
}
void vp8cx_init_mbrthread_data(VP8_COMP *cpi, MACROBLOCK *x,
MB_ROW_COMP *mbr_ei, int count) {
VP8_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
int i;
for (i = 0; i < count; ++i) {
MACROBLOCK *mb = &mbr_ei[i].mb;
MACROBLOCKD *mbd = &mb->e_mbd;
mbd->subpixel_predict = xd->subpixel_predict;
mbd->subpixel_predict8x4 = xd->subpixel_predict8x4;
mbd->subpixel_predict8x8 = xd->subpixel_predict8x8;
mbd->subpixel_predict16x16 = xd->subpixel_predict16x16;
mb->gf_active_ptr = x->gf_active_ptr;
memset(mbr_ei[i].segment_counts, 0, sizeof(mbr_ei[i].segment_counts));
mbr_ei[i].totalrate = 0;
mb->partition_info = x->pi + x->e_mbd.mode_info_stride * (i + 1);
mbd->frame_type = cm->frame_type;
mb->src = *cpi->Source;
mbd->pre = cm->yv12_fb[cm->lst_fb_idx];
mbd->dst = cm->yv12_fb[cm->new_fb_idx];
mb->src.y_buffer += 16 * x->src.y_stride * (i + 1);
mb->src.u_buffer += 8 * x->src.uv_stride * (i + 1);
mb->src.v_buffer += 8 * x->src.uv_stride * (i + 1);
vp8_build_block_offsets(mb);
mbd->left_context = &cm->left_context;
mb->mvc = cm->fc.mvc;
setup_mbby_copy(&mbr_ei[i].mb, x);
mbd->fullpixel_mask = 0xffffffff;
if (cm->full_pixel) mbd->fullpixel_mask = 0xfffffff8;
vp8_zero(mb->coef_counts);
vp8_zero(x->ymode_count);
mb->skip_true_count = 0;
vp8_zero(mb->MVcount);
mb->prediction_error = 0;
mb->intra_error = 0;
vp8_zero(mb->count_mb_ref_frame_usage);
mb->mbs_tested_so_far = 0;
mb->mbs_zero_last_dot_suppress = 0;
}
}
int vp8cx_create_encoder_threads(VP8_COMP *cpi) {
const VP8_COMMON *cm = &cpi->common;
vpx_atomic_init(&cpi->b_multi_threaded, 0);
cpi->encoding_thread_count = 0;
cpi->b_lpf_running = 0;
if (cm->processor_core_count > 1 && cpi->oxcf.multi_threaded > 1) {
int ithread;
int th_count = cpi->oxcf.multi_threaded - 1;
int rc = 0;
/* don't allocate more threads than cores available */
if (cpi->oxcf.multi_threaded > cm->processor_core_count) {
th_count = cm->processor_core_count - 1;
}
/* we have th_count + 1 (main) threads processing one row each */
/* no point to have more threads than the sync range allows */
if (th_count > ((cm->mb_cols / cpi->mt_sync_range) - 1)) {
th_count = (cm->mb_cols / cpi->mt_sync_range) - 1;
}
if (th_count == 0) return 0;
CHECK_MEM_ERROR(cpi->h_encoding_thread,
vpx_malloc(sizeof(pthread_t) * th_count));
CHECK_MEM_ERROR(cpi->h_event_start_encoding,
vpx_malloc(sizeof(sem_t) * th_count));
CHECK_MEM_ERROR(cpi->h_event_end_encoding,
vpx_malloc(sizeof(sem_t) * th_count));
CHECK_MEM_ERROR(cpi->mb_row_ei,
vpx_memalign(32, sizeof(MB_ROW_COMP) * th_count));
memset(cpi->mb_row_ei, 0, sizeof(MB_ROW_COMP) * th_count);
CHECK_MEM_ERROR(cpi->en_thread_data,
vpx_malloc(sizeof(ENCODETHREAD_DATA) * th_count));
vpx_atomic_store_release(&cpi->b_multi_threaded, 1);
cpi->encoding_thread_count = th_count;
/*
printf("[VP8:] multi_threaded encoding is enabled with %d threads\n\n",
(cpi->encoding_thread_count +1));
*/
for (ithread = 0; ithread < th_count; ++ithread) {
ENCODETHREAD_DATA *ethd = &cpi->en_thread_data[ithread];
/* Setup block ptrs and offsets */
vp8_setup_block_ptrs(&cpi->mb_row_ei[ithread].mb);
vp8_setup_block_dptrs(&cpi->mb_row_ei[ithread].mb.e_mbd);
sem_init(&cpi->h_event_start_encoding[ithread], 0, 0);
sem_init(&cpi->h_event_end_encoding[ithread], 0, 0);
ethd->ithread = ithread;
ethd->ptr1 = (void *)cpi;
ethd->ptr2 = (void *)&cpi->mb_row_ei[ithread];
rc = pthread_create(&cpi->h_encoding_thread[ithread], 0,
thread_encoding_proc, ethd);
if (rc) break;
}
if (rc) {
/* shutdown other threads */
vpx_atomic_store_release(&cpi->b_multi_threaded, 0);
for (--ithread; ithread >= 0; ithread--) {
pthread_join(cpi->h_encoding_thread[ithread], 0);
sem_destroy(&cpi->h_event_start_encoding[ithread]);
sem_destroy(&cpi->h_event_end_encoding[ithread]);
}
/* free thread related resources */
vpx_free(cpi->h_event_start_encoding);
vpx_free(cpi->h_event_end_encoding);
vpx_free(cpi->h_encoding_thread);
vpx_free(cpi->mb_row_ei);
vpx_free(cpi->en_thread_data);
return -1;
}
{
LPFTHREAD_DATA *lpfthd = &cpi->lpf_thread_data;
sem_init(&cpi->h_event_start_lpf, 0, 0);
sem_init(&cpi->h_event_end_lpf, 0, 0);
lpfthd->ptr1 = (void *)cpi;
rc = pthread_create(&cpi->h_filter_thread, 0, thread_loopfilter, lpfthd);
if (rc) {
/* shutdown other threads */
vpx_atomic_store_release(&cpi->b_multi_threaded, 0);
for (--ithread; ithread >= 0; ithread--) {
sem_post(&cpi->h_event_start_encoding[ithread]);
sem_post(&cpi->h_event_end_encoding[ithread]);
pthread_join(cpi->h_encoding_thread[ithread], 0);
sem_destroy(&cpi->h_event_start_encoding[ithread]);
sem_destroy(&cpi->h_event_end_encoding[ithread]);
}
sem_destroy(&cpi->h_event_end_lpf);
sem_destroy(&cpi->h_event_start_lpf);
/* free thread related resources */
vpx_free(cpi->h_event_start_encoding);
vpx_free(cpi->h_event_end_encoding);
vpx_free(cpi->h_encoding_thread);
vpx_free(cpi->mb_row_ei);
vpx_free(cpi->en_thread_data);
return -2;
}
}
}
return 0;
}
void vp8cx_remove_encoder_threads(VP8_COMP *cpi) {
if (vpx_atomic_load_acquire(&cpi->b_multi_threaded)) {
/* shutdown other threads */
vpx_atomic_store_release(&cpi->b_multi_threaded, 0);
{
int i;
for (i = 0; i < cpi->encoding_thread_count; ++i) {
sem_post(&cpi->h_event_start_encoding[i]);
sem_post(&cpi->h_event_end_encoding[i]);
pthread_join(cpi->h_encoding_thread[i], 0);
sem_destroy(&cpi->h_event_start_encoding[i]);
sem_destroy(&cpi->h_event_end_encoding[i]);
}
sem_post(&cpi->h_event_start_lpf);
pthread_join(cpi->h_filter_thread, 0);
}
sem_destroy(&cpi->h_event_end_lpf);
sem_destroy(&cpi->h_event_start_lpf);
/* free thread related resources */
vpx_free(cpi->h_event_start_encoding);
vpx_free(cpi->h_event_end_encoding);
vpx_free(cpi->h_encoding_thread);
vpx_free(cpi->mb_row_ei);
vpx_free(cpi->en_thread_data);
}
}
#endif
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2017 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_ETHREADING_H_
#define VPX_VP8_ENCODER_ETHREADING_H_
#include "vp8/encoder/onyx_int.h"
#ifdef __cplusplus
extern "C" {
#endif
struct VP8_COMP;
struct macroblock;
void vp8cx_init_mbrthread_data(struct VP8_COMP *cpi, struct macroblock *x,
MB_ROW_COMP *mbr_ei, int count);
int vp8cx_create_encoder_threads(struct VP8_COMP *cpi);
void vp8cx_remove_encoder_threads(struct VP8_COMP *cpi);
#ifdef __cplusplus
}
#endif
#endif // VPX_VP8_ENCODER_ETHREADING_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_FIRSTPASS_H_
#define VPX_VP8_ENCODER_FIRSTPASS_H_
#ifdef __cplusplus
extern "C" {
#endif
extern void vp8_init_first_pass(VP8_COMP *cpi);
extern void vp8_first_pass(VP8_COMP *cpi);
extern void vp8_end_first_pass(VP8_COMP *cpi);
extern void vp8_init_second_pass(VP8_COMP *cpi);
extern void vp8_second_pass(VP8_COMP *cpi);
extern void vp8_end_second_pass(VP8_COMP *cpi);
extern size_t vp8_firstpass_stats_sz(unsigned int mb_count);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_FIRSTPASS_H_
@@ -0,0 +1,184 @@
/*
* Copyright (c) 2011 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include <stdlib.h>
#include "vpx_config.h"
#include "lookahead.h"
#include "vp8/common/extend.h"
#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY ? 1 : 25)
struct lookahead_ctx {
unsigned int max_sz; /* Absolute size of the queue */
unsigned int sz; /* Number of buffers currently in the queue */
unsigned int read_idx; /* Read index */
unsigned int write_idx; /* Write index */
struct lookahead_entry *buf; /* Buffer list */
};
/* Return the buffer at the given absolute index and increment the index */
static struct lookahead_entry *pop(struct lookahead_ctx *ctx,
unsigned int *idx) {
unsigned int index = *idx;
struct lookahead_entry *buf = ctx->buf + index;
assert(index < ctx->max_sz);
if (++index >= ctx->max_sz) index -= ctx->max_sz;
*idx = index;
return buf;
}
void vp8_lookahead_destroy(struct lookahead_ctx *ctx) {
if (ctx) {
if (ctx->buf) {
unsigned int i;
for (i = 0; i < ctx->max_sz; ++i) {
vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img);
}
free(ctx->buf);
}
free(ctx);
}
}
struct lookahead_ctx *vp8_lookahead_init(unsigned int width,
unsigned int height,
unsigned int depth) {
struct lookahead_ctx *ctx = NULL;
unsigned int i;
/* Clamp the lookahead queue depth */
if (depth < 1) {
depth = 1;
} else if (depth > MAX_LAG_BUFFERS) {
depth = MAX_LAG_BUFFERS;
}
/* Keep last frame in lookahead buffer by increasing depth by 1.*/
depth += 1;
/* Align the buffer dimensions */
width = (width + 15) & ~15;
height = (height + 15) & ~15;
/* Allocate the lookahead structures */
ctx = calloc(1, sizeof(*ctx));
if (ctx) {
ctx->max_sz = depth;
ctx->buf = calloc(depth, sizeof(*ctx->buf));
if (!ctx->buf) goto bail;
for (i = 0; i < depth; ++i) {
if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img, width, height,
VP8BORDERINPIXELS)) {
goto bail;
}
}
}
return ctx;
bail:
vp8_lookahead_destroy(ctx);
return NULL;
}
int vp8_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int64_t ts_start, int64_t ts_end, unsigned int flags,
unsigned char *active_map) {
struct lookahead_entry *buf;
int row, col, active_end;
int mb_rows = (src->y_height + 15) >> 4;
int mb_cols = (src->y_width + 15) >> 4;
if (ctx->sz + 2 > ctx->max_sz) return 1;
ctx->sz++;
buf = pop(ctx, &ctx->write_idx);
/* Only do this partial copy if the following conditions are all met:
* 1. Lookahead queue has has size of 1.
* 2. Active map is provided.
* 3. This is not a key frame, golden nor altref frame.
*/
if (ctx->max_sz == 1 && active_map && !flags) {
for (row = 0; row < mb_rows; ++row) {
col = 0;
while (1) {
/* Find the first active macroblock in this row. */
for (; col < mb_cols; ++col) {
if (active_map[col]) break;
}
/* No more active macroblock in this row. */
if (col == mb_cols) break;
/* Find the end of active region in this row. */
active_end = col;
for (; active_end < mb_cols; ++active_end) {
if (!active_map[active_end]) break;
}
/* Only copy this active region. */
vp8_copy_and_extend_frame_with_rect(src, &buf->img, row << 4, col << 4,
16, (active_end - col) << 4);
/* Start again from the end of this active region. */
col = active_end;
}
active_map += mb_cols;
}
} else {
vp8_copy_and_extend_frame(src, &buf->img);
}
buf->ts_start = ts_start;
buf->ts_end = ts_end;
buf->flags = flags;
return 0;
}
struct lookahead_entry *vp8_lookahead_pop(struct lookahead_ctx *ctx,
int drain) {
struct lookahead_entry *buf = NULL;
assert(ctx != NULL);
if (ctx->sz && (drain || ctx->sz == ctx->max_sz - 1)) {
buf = pop(ctx, &ctx->read_idx);
ctx->sz--;
}
return buf;
}
struct lookahead_entry *vp8_lookahead_peek(struct lookahead_ctx *ctx,
unsigned int index, int direction) {
struct lookahead_entry *buf = NULL;
if (direction == PEEK_FORWARD) {
assert(index < ctx->max_sz - 1);
if (index < ctx->sz) {
index += ctx->read_idx;
if (index >= ctx->max_sz) index -= ctx->max_sz;
buf = ctx->buf + index;
}
} else if (direction == PEEK_BACKWARD) {
assert(index == 1);
if (ctx->read_idx == 0) {
index = ctx->max_sz - 1;
} else {
index = ctx->read_idx - index;
}
buf = ctx->buf + index;
}
return buf;
}
unsigned int vp8_lookahead_depth(struct lookahead_ctx *ctx) { return ctx->sz; }
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2011 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_LOOKAHEAD_H_
#define VPX_VP8_ENCODER_LOOKAHEAD_H_
#include "vpx_scale/yv12config.h"
#include "vpx/vpx_integer.h"
#ifdef __cplusplus
extern "C" {
#endif
struct lookahead_entry {
YV12_BUFFER_CONFIG img;
int64_t ts_start;
int64_t ts_end;
unsigned int flags;
};
struct lookahead_ctx;
/**\brief Initializes the lookahead stage
*
* The lookahead stage is a queue of frame buffers on which some analysis
* may be done when buffers are enqueued.
*
*
*/
struct lookahead_ctx *vp8_lookahead_init(unsigned int width,
unsigned int height,
unsigned int depth);
/**\brief Destroys the lookahead stage
*
*/
void vp8_lookahead_destroy(struct lookahead_ctx *ctx);
/**\brief Enqueue a source buffer
*
* This function will copy the source image into a new framebuffer with
* the expected stride/border.
*
* If active_map is non-NULL and there is only one frame in the queue, then copy
* only active macroblocks.
*
* \param[in] ctx Pointer to the lookahead context
* \param[in] src Pointer to the image to enqueue
* \param[in] ts_start Timestamp for the start of this frame
* \param[in] ts_end Timestamp for the end of this frame
* \param[in] flags Flags set on this frame
* \param[in] active_map Map that specifies which macroblock is active
*/
int vp8_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int64_t ts_start, int64_t ts_end, unsigned int flags,
unsigned char *active_map);
/**\brief Get the next source buffer to encode
*
*
* \param[in] ctx Pointer to the lookahead context
* \param[in] drain Flag indicating the buffer should be drained
* (return a buffer regardless of the current queue depth)
*
* \retval NULL, if drain set and queue is empty
* \retval NULL, if drain not set and queue not of the configured depth
*
*/
struct lookahead_entry *vp8_lookahead_pop(struct lookahead_ctx *ctx, int drain);
#define PEEK_FORWARD 1
#define PEEK_BACKWARD (-1)
/**\brief Get a future source buffer to encode
*
* \param[in] ctx Pointer to the lookahead context
* \param[in] index Index of the frame to be returned, 0 == next frame
*
* \retval NULL, if no buffer exists at the specified index
*
*/
struct lookahead_entry *vp8_lookahead_peek(struct lookahead_ctx *ctx,
unsigned int index, int direction);
/**\brief Get the number of frames currently in the lookahead queue
*
* \param[in] ctx Pointer to the lookahead context
*/
unsigned int vp8_lookahead_depth(struct lookahead_ctx *ctx);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_LOOKAHEAD_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_MCOMP_H_
#define VPX_VP8_ENCODER_MCOMP_H_
#include "block.h"
#include "vpx_dsp/variance.h"
#ifdef __cplusplus
extern "C" {
#endif
/* The maximum number of steps in a step search given the largest allowed
* initial step
*/
#define MAX_MVSEARCH_STEPS 8
/* Max full pel mv specified in 1 pel units */
#define MAX_FULL_PEL_VAL ((1 << (MAX_MVSEARCH_STEPS)) - 1)
/* Maximum size of the first step in full pel units */
#define MAX_FIRST_STEP (1 << (MAX_MVSEARCH_STEPS - 1))
int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight);
void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride);
void vp8_init3smotion_compensation(MACROBLOCK *x, int stride);
int vp8_hex_search(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
int_mv *best_mv, int search_param, int sad_per_bit,
const vp8_variance_fn_ptr_t *vfp, int *mvsadcost[2],
int_mv *center_mv);
typedef int(fractional_mv_step_fp)(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
int_mv *bestmv, int_mv *ref_mv,
int error_per_bit,
const vp8_variance_fn_ptr_t *vfp,
int *mvcost[2], int *distortion,
unsigned int *sse);
fractional_mv_step_fp vp8_find_best_sub_pixel_step_iteratively;
fractional_mv_step_fp vp8_find_best_sub_pixel_step;
fractional_mv_step_fp vp8_find_best_half_pixel_step;
fractional_mv_step_fp vp8_skip_fractional_mv_step;
typedef int (*vp8_full_search_fn_t)(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
int_mv *ref_mv, int sad_per_bit,
int distance, vp8_variance_fn_ptr_t *fn_ptr,
int *mvcost[2], int_mv *center_mv);
typedef int (*vp8_refining_search_fn_t)(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
int_mv *ref_mv, int sad_per_bit,
int distance,
vp8_variance_fn_ptr_t *fn_ptr,
int *mvcost[2], int_mv *center_mv);
typedef int (*vp8_diamond_search_fn_t)(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
int_mv *ref_mv, int_mv *best_mv,
int search_param, int sad_per_bit,
int *num00,
vp8_variance_fn_ptr_t *fn_ptr,
int *mvcost[2], int_mv *center_mv);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_MCOMP_H_
@@ -0,0 +1,425 @@
/*
* Copyright (c) 2017 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vp8_rtcd.h"
#include "vpx_ports/mem.h"
#include "vpx_ports/asmdefs_mmi.h"
/* clang-format off */
/* TRANSPOSE_4H: transpose 4x4 matrix.
Input: ftmp1,ftmp2,ftmp3,ftmp4
Output: ftmp1,ftmp2,ftmp3,ftmp4
Note: ftmp0 always be 0, ftmp5~9 used for temporary value.
*/
#define TRANSPOSE_4H \
MMI_LI(%[tmp0], 0x93) \
"mtc1 %[tmp0], %[ftmp10] \n\t" \
"punpcklhw %[ftmp5], %[ftmp1], %[ftmp0] \n\t" \
"punpcklhw %[ftmp9], %[ftmp2], %[ftmp0] \n\t" \
"pshufh %[ftmp9], %[ftmp9], %[ftmp10] \n\t" \
"or %[ftmp5], %[ftmp5], %[ftmp9] \n\t" \
"punpckhhw %[ftmp6], %[ftmp1], %[ftmp0] \n\t" \
"punpckhhw %[ftmp9], %[ftmp2], %[ftmp0] \n\t" \
"pshufh %[ftmp9], %[ftmp9], %[ftmp10] \n\t" \
"or %[ftmp6], %[ftmp6], %[ftmp9] \n\t" \
"punpcklhw %[ftmp7], %[ftmp3], %[ftmp0] \n\t" \
"punpcklhw %[ftmp9], %[ftmp4], %[ftmp0] \n\t" \
"pshufh %[ftmp9], %[ftmp9], %[ftmp10] \n\t" \
"or %[ftmp7], %[ftmp7], %[ftmp9] \n\t" \
"punpckhhw %[ftmp8], %[ftmp3], %[ftmp0] \n\t" \
"punpckhhw %[ftmp9], %[ftmp4], %[ftmp0] \n\t" \
"pshufh %[ftmp9], %[ftmp9], %[ftmp10] \n\t" \
"or %[ftmp8], %[ftmp8], %[ftmp9] \n\t" \
"punpcklwd %[ftmp1], %[ftmp5], %[ftmp7] \n\t" \
"punpckhwd %[ftmp2], %[ftmp5], %[ftmp7] \n\t" \
"punpcklwd %[ftmp3], %[ftmp6], %[ftmp8] \n\t" \
"punpckhwd %[ftmp4], %[ftmp6], %[ftmp8] \n\t"
/* clang-format on */
void vp8_short_fdct4x4_mmi(int16_t *input, int16_t *output, int pitch) {
uint64_t tmp[1];
int16_t *ip = input;
#if _MIPS_SIM == _ABIO32
register double ftmp0 asm("$f0");
register double ftmp1 asm("$f2");
register double ftmp2 asm("$f4");
register double ftmp3 asm("$f6");
register double ftmp4 asm("$f8");
register double ftmp5 asm("$f10");
register double ftmp6 asm("$f12");
register double ftmp7 asm("$f14");
register double ftmp8 asm("$f16");
register double ftmp9 asm("$f18");
register double ftmp10 asm("$f20");
register double ftmp11 asm("$f22");
register double ftmp12 asm("$f24");
#else
register double ftmp0 asm("$f0");
register double ftmp1 asm("$f1");
register double ftmp2 asm("$f2");
register double ftmp3 asm("$f3");
register double ftmp4 asm("$f4");
register double ftmp5 asm("$f5");
register double ftmp6 asm("$f6");
register double ftmp7 asm("$f7");
register double ftmp8 asm("$f8");
register double ftmp9 asm("$f9");
register double ftmp10 asm("$f10");
register double ftmp11 asm("$f11");
register double ftmp12 asm("$f12");
#endif // _MIPS_SIM == _ABIO32
DECLARE_ALIGNED(8, const uint64_t, ff_ph_01) = { 0x0001000100010001ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_ph_07) = { 0x0007000700070007ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_12000) = { 0x00002ee000002ee0ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_51000) = { 0x0000c7380000c738ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_14500) = { 0x000038a4000038a4ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_7500) = { 0x00001d4c00001d4cULL };
DECLARE_ALIGNED(8, const uint64_t, ff_ph_op1) = { 0x14e808a914e808a9ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_ph_op3) = { 0xeb1808a9eb1808a9ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_5352) = { 0x000014e8000014e8ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_2217) = { 0x000008a9000008a9ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_ph_8) = { 0x0008000800080008ULL };
__asm__ volatile (
"xor %[ftmp0], %[ftmp0], %[ftmp0] \n\t"
"gsldlc1 %[ftmp1], 0x07(%[ip]) \n\t"
"gsldrc1 %[ftmp1], 0x00(%[ip]) \n\t"
MMI_ADDU(%[ip], %[ip], %[pitch])
"gsldlc1 %[ftmp2], 0x07(%[ip]) \n\t"
"gsldrc1 %[ftmp2], 0x00(%[ip]) \n\t"
MMI_ADDU(%[ip], %[ip], %[pitch])
"gsldlc1 %[ftmp3], 0x07(%[ip]) \n\t"
"gsldrc1 %[ftmp3], 0x00(%[ip]) \n\t"
MMI_ADDU(%[ip], %[ip], %[pitch])
"gsldlc1 %[ftmp4], 0x07(%[ip]) \n\t"
"gsldrc1 %[ftmp4], 0x00(%[ip]) \n\t"
MMI_ADDU(%[ip], %[ip], %[pitch])
TRANSPOSE_4H
"ldc1 %[ftmp11], %[ff_ph_8] \n\t"
// f1 + f4
"paddh %[ftmp5], %[ftmp1], %[ftmp4] \n\t"
// a1
"pmullh %[ftmp5], %[ftmp5], %[ftmp11] \n\t"
// f2 + f3
"paddh %[ftmp6], %[ftmp2], %[ftmp3] \n\t"
// b1
"pmullh %[ftmp6], %[ftmp6], %[ftmp11] \n\t"
// f2 - f3
"psubh %[ftmp7], %[ftmp2], %[ftmp3] \n\t"
// c1
"pmullh %[ftmp7], %[ftmp7], %[ftmp11] \n\t"
// f1 - f4
"psubh %[ftmp8], %[ftmp1], %[ftmp4] \n\t"
// d1
"pmullh %[ftmp8], %[ftmp8], %[ftmp11] \n\t"
// op[0] = a1 + b1
"paddh %[ftmp1], %[ftmp5], %[ftmp6] \n\t"
// op[2] = a1 - b1
"psubh %[ftmp3], %[ftmp5], %[ftmp6] \n\t"
// op[1] = (c1 * 2217 + d1 * 5352 + 14500) >> 12
MMI_LI(%[tmp0], 0x0c)
"mtc1 %[tmp0], %[ftmp11] \n\t"
"ldc1 %[ftmp12], %[ff_pw_14500] \n\t"
"punpcklhw %[ftmp9], %[ftmp7], %[ftmp8] \n\t"
"pmaddhw %[ftmp5], %[ftmp9], %[ff_ph_op1] \n\t"
"punpckhhw %[ftmp9], %[ftmp7], %[ftmp8] \n\t"
"pmaddhw %[ftmp6], %[ftmp9], %[ff_ph_op1] \n\t"
"paddw %[ftmp5], %[ftmp5], %[ftmp12] \n\t"
"paddw %[ftmp6], %[ftmp6], %[ftmp12] \n\t"
"psraw %[ftmp5], %[ftmp5], %[ftmp11] \n\t"
"psraw %[ftmp6], %[ftmp6], %[ftmp11] \n\t"
"packsswh %[ftmp2], %[ftmp5], %[ftmp6] \n\t"
// op[3] = (d1 * 2217 - c1 * 5352 + 7500) >> 12
"ldc1 %[ftmp12], %[ff_pw_7500] \n\t"
"punpcklhw %[ftmp9], %[ftmp8], %[ftmp7] \n\t"
"pmaddhw %[ftmp5], %[ftmp9], %[ff_ph_op3] \n\t"
"punpckhhw %[ftmp9], %[ftmp8], %[ftmp7] \n\t"
"pmaddhw %[ftmp6], %[ftmp9], %[ff_ph_op3] \n\t"
"paddw %[ftmp5], %[ftmp5], %[ftmp12] \n\t"
"paddw %[ftmp6], %[ftmp6], %[ftmp12] \n\t"
"psraw %[ftmp5], %[ftmp5], %[ftmp11] \n\t"
"psraw %[ftmp6], %[ftmp6], %[ftmp11] \n\t"
"packsswh %[ftmp4], %[ftmp5], %[ftmp6] \n\t"
TRANSPOSE_4H
"paddh %[ftmp5], %[ftmp1], %[ftmp4] \n\t"
"paddh %[ftmp6], %[ftmp2], %[ftmp3] \n\t"
"psubh %[ftmp7], %[ftmp2], %[ftmp3] \n\t"
"psubh %[ftmp8], %[ftmp1], %[ftmp4] \n\t"
"pcmpeqh %[ftmp0], %[ftmp8], %[ftmp0] \n\t"
"ldc1 %[ftmp9], %[ff_ph_01] \n\t"
"paddh %[ftmp0], %[ftmp0], %[ftmp9] \n\t"
"paddh %[ftmp1], %[ftmp5], %[ftmp6] \n\t"
"psubh %[ftmp2], %[ftmp5], %[ftmp6] \n\t"
"ldc1 %[ftmp9], %[ff_ph_07] \n\t"
"paddh %[ftmp1], %[ftmp1], %[ftmp9] \n\t"
"paddh %[ftmp2], %[ftmp2], %[ftmp9] \n\t"
MMI_LI(%[tmp0], 0x04)
"mtc1 %[tmp0], %[ftmp9] \n\t"
"psrah %[ftmp1], %[ftmp1], %[ftmp9] \n\t"
"psrah %[ftmp2], %[ftmp2], %[ftmp9] \n\t"
MMI_LI(%[tmp0], 0x10)
"mtc1 %[tmp0], %[ftmp9] \n\t"
"ldc1 %[ftmp12], %[ff_pw_12000] \n\t"
"punpcklhw %[ftmp5], %[ftmp7], %[ftmp8] \n\t"
"pmaddhw %[ftmp10], %[ftmp5], %[ff_ph_op1] \n\t"
"punpckhhw %[ftmp5], %[ftmp7], %[ftmp8] \n\t"
"pmaddhw %[ftmp11], %[ftmp5], %[ff_ph_op1] \n\t"
"paddw %[ftmp10], %[ftmp10], %[ftmp12] \n\t"
"paddw %[ftmp11], %[ftmp11], %[ftmp12] \n\t"
"psraw %[ftmp10], %[ftmp10], %[ftmp9] \n\t"
"psraw %[ftmp11], %[ftmp11], %[ftmp9] \n\t"
"packsswh %[ftmp3], %[ftmp10], %[ftmp11] \n\t"
"paddh %[ftmp3], %[ftmp3], %[ftmp0] \n\t"
"ldc1 %[ftmp12], %[ff_pw_51000] \n\t"
"punpcklhw %[ftmp5], %[ftmp8], %[ftmp7] \n\t"
"pmaddhw %[ftmp10], %[ftmp5], %[ff_ph_op3] \n\t"
"punpckhhw %[ftmp5], %[ftmp8], %[ftmp7] \n\t"
"pmaddhw %[ftmp11], %[ftmp5], %[ff_ph_op3] \n\t"
"paddw %[ftmp10], %[ftmp10], %[ftmp12] \n\t"
"paddw %[ftmp11], %[ftmp11], %[ftmp12] \n\t"
"psraw %[ftmp10], %[ftmp10], %[ftmp9] \n\t"
"psraw %[ftmp11], %[ftmp11], %[ftmp9] \n\t"
"packsswh %[ftmp4], %[ftmp10], %[ftmp11] \n\t"
"gssdlc1 %[ftmp1], 0x07(%[output]) \n\t"
"gssdrc1 %[ftmp1], 0x00(%[output]) \n\t"
"gssdlc1 %[ftmp3], 0x0f(%[output]) \n\t"
"gssdrc1 %[ftmp3], 0x08(%[output]) \n\t"
"gssdlc1 %[ftmp2], 0x17(%[output]) \n\t"
"gssdrc1 %[ftmp2], 0x10(%[output]) \n\t"
"gssdlc1 %[ftmp4], 0x1f(%[output]) \n\t"
"gssdrc1 %[ftmp4], 0x18(%[output]) \n\t"
: [ftmp0] "=&f"(ftmp0), [ftmp1] "=&f"(ftmp1), [ftmp2] "=&f"(ftmp2),
[ftmp3] "=&f"(ftmp3), [ftmp4] "=&f"(ftmp4), [ftmp5] "=&f"(ftmp5),
[ftmp6] "=&f"(ftmp6), [ftmp7] "=&f"(ftmp7), [ftmp8] "=&f"(ftmp8),
[ftmp9] "=&f"(ftmp9), [ftmp10] "=&f"(ftmp10), [ftmp11] "=&f"(ftmp11),
[ftmp12] "=&f"(ftmp12), [tmp0] "=&r"(tmp[0]), [ip]"+&r"(ip)
: [ff_ph_01] "m"(ff_ph_01), [ff_ph_07] "m"(ff_ph_07),
[ff_ph_op1] "f"(ff_ph_op1), [ff_ph_op3] "f"(ff_ph_op3),
[ff_pw_14500] "m"(ff_pw_14500), [ff_pw_7500] "m"(ff_pw_7500),
[ff_pw_12000] "m"(ff_pw_12000), [ff_pw_51000] "m"(ff_pw_51000),
[ff_pw_5352]"m"(ff_pw_5352), [ff_pw_2217]"m"(ff_pw_2217),
[ff_ph_8]"m"(ff_ph_8), [pitch]"r"(pitch), [output] "r"(output)
: "memory"
);
}
void vp8_short_fdct8x4_mmi(int16_t *input, int16_t *output, int pitch) {
vp8_short_fdct4x4_mmi(input, output, pitch);
vp8_short_fdct4x4_mmi(input + 4, output + 16, pitch);
}
void vp8_short_walsh4x4_mmi(int16_t *input, int16_t *output, int pitch) {
double ftmp[13];
uint32_t tmp[1];
DECLARE_ALIGNED(8, const uint64_t, ff_ph_01) = { 0x0001000100010001ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_01) = { 0x0000000100000001ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_03) = { 0x0000000300000003ULL };
DECLARE_ALIGNED(8, const uint64_t, ff_pw_mask) = { 0x0001000000010000ULL };
__asm__ volatile (
MMI_LI(%[tmp0], 0x02)
"xor %[ftmp0], %[ftmp0], %[ftmp0] \n\t"
"mtc1 %[tmp0], %[ftmp11] \n\t"
"gsldlc1 %[ftmp1], 0x07(%[ip]) \n\t"
"gsldrc1 %[ftmp1], 0x00(%[ip]) \n\t"
MMI_ADDU(%[ip], %[ip], %[pitch])
"gsldlc1 %[ftmp2], 0x07(%[ip]) \n\t"
"gsldrc1 %[ftmp2], 0x00(%[ip]) \n\t"
MMI_ADDU(%[ip], %[ip], %[pitch])
"gsldlc1 %[ftmp3], 0x07(%[ip]) \n\t"
"gsldrc1 %[ftmp3], 0x00(%[ip]) \n\t"
MMI_ADDU(%[ip], %[ip], %[pitch])
"gsldlc1 %[ftmp4], 0x07(%[ip]) \n\t"
"gsldrc1 %[ftmp4], 0x00(%[ip]) \n\t"
TRANSPOSE_4H
"psllh %[ftmp1], %[ftmp1], %[ftmp11] \n\t"
"psllh %[ftmp2], %[ftmp2], %[ftmp11] \n\t"
"psllh %[ftmp3], %[ftmp3], %[ftmp11] \n\t"
"psllh %[ftmp4], %[ftmp4], %[ftmp11] \n\t"
// a
"paddh %[ftmp5], %[ftmp1], %[ftmp3] \n\t"
// d
"paddh %[ftmp6], %[ftmp2], %[ftmp4] \n\t"
// c
"psubh %[ftmp7], %[ftmp2], %[ftmp4] \n\t"
// b
"psubh %[ftmp8], %[ftmp1], %[ftmp3] \n\t"
// a + d
"paddh %[ftmp1], %[ftmp5], %[ftmp6] \n\t"
// b + c
"paddh %[ftmp2], %[ftmp8], %[ftmp7] \n\t"
// b - c
"psubh %[ftmp3], %[ftmp8], %[ftmp7] \n\t"
// a - d
"psubh %[ftmp4], %[ftmp5], %[ftmp6] \n\t"
"pcmpeqh %[ftmp6], %[ftmp5], %[ftmp0] \n\t"
"paddh %[ftmp6], %[ftmp6], %[ff_ph_01] \n\t"
"paddh %[ftmp1], %[ftmp1], %[ftmp6] \n\t"
TRANSPOSE_4H
// op[2], op[0]
"pmaddhw %[ftmp5], %[ftmp1], %[ff_pw_01] \n\t"
// op[3], op[1]
"pmaddhw %[ftmp1], %[ftmp1], %[ff_pw_mask] \n\t"
// op[6], op[4]
"pmaddhw %[ftmp6], %[ftmp2], %[ff_pw_01] \n\t"
// op[7], op[5]
"pmaddhw %[ftmp2], %[ftmp2], %[ff_pw_mask] \n\t"
// op[10], op[8]
"pmaddhw %[ftmp7], %[ftmp3], %[ff_pw_01] \n\t"
// op[11], op[9]
"pmaddhw %[ftmp3], %[ftmp3], %[ff_pw_mask] \n\t"
// op[14], op[12]
"pmaddhw %[ftmp8], %[ftmp4], %[ff_pw_01] \n\t"
// op[15], op[13]
"pmaddhw %[ftmp4], %[ftmp4], %[ff_pw_mask] \n\t"
// a1, a3
"paddw %[ftmp9], %[ftmp5], %[ftmp7] \n\t"
// d1, d3
"paddw %[ftmp10], %[ftmp6], %[ftmp8] \n\t"
// c1, c3
"psubw %[ftmp11], %[ftmp6], %[ftmp8] \n\t"
// b1, b3
"psubw %[ftmp12], %[ftmp5], %[ftmp7] \n\t"
// a1 + d1, a3 + d3
"paddw %[ftmp5], %[ftmp9], %[ftmp10] \n\t"
// b1 + c1, b3 + c3
"paddw %[ftmp6], %[ftmp12], %[ftmp11] \n\t"
// b1 - c1, b3 - c3
"psubw %[ftmp7], %[ftmp12], %[ftmp11] \n\t"
// a1 - d1, a3 - d3
"psubw %[ftmp8], %[ftmp9], %[ftmp10] \n\t"
// a2, a4
"paddw %[ftmp9], %[ftmp1], %[ftmp3] \n\t"
// d2, d4
"paddw %[ftmp10], %[ftmp2], %[ftmp4] \n\t"
// c2, c4
"psubw %[ftmp11], %[ftmp2], %[ftmp4] \n\t"
// b2, b4
"psubw %[ftmp12], %[ftmp1], %[ftmp3] \n\t"
// a2 + d2, a4 + d4
"paddw %[ftmp1], %[ftmp9], %[ftmp10] \n\t"
// b2 + c2, b4 + c4
"paddw %[ftmp2], %[ftmp12], %[ftmp11] \n\t"
// b2 - c2, b4 - c4
"psubw %[ftmp3], %[ftmp12], %[ftmp11] \n\t"
// a2 - d2, a4 - d4
"psubw %[ftmp4], %[ftmp9], %[ftmp10] \n\t"
MMI_LI(%[tmp0], 0x03)
"mtc1 %[tmp0], %[ftmp11] \n\t"
"pcmpgtw %[ftmp9], %[ftmp0], %[ftmp1] \n\t"
"and %[ftmp9], %[ftmp9], %[ff_pw_01] \n\t"
"paddw %[ftmp1], %[ftmp1], %[ftmp9] \n\t"
"paddw %[ftmp1], %[ftmp1], %[ff_pw_03] \n\t"
"psraw %[ftmp1], %[ftmp1], %[ftmp11] \n\t"
"pcmpgtw %[ftmp9], %[ftmp0], %[ftmp2] \n\t"
"and %[ftmp9], %[ftmp9], %[ff_pw_01] \n\t"
"paddw %[ftmp2], %[ftmp2], %[ftmp9] \n\t"
"paddw %[ftmp2], %[ftmp2], %[ff_pw_03] \n\t"
"psraw %[ftmp2], %[ftmp2], %[ftmp11] \n\t"
"pcmpgtw %[ftmp9], %[ftmp0], %[ftmp3] \n\t"
"and %[ftmp9], %[ftmp9], %[ff_pw_01] \n\t"
"paddw %[ftmp3], %[ftmp3], %[ftmp9] \n\t"
"paddw %[ftmp3], %[ftmp3], %[ff_pw_03] \n\t"
"psraw %[ftmp3], %[ftmp3], %[ftmp11] \n\t"
"pcmpgtw %[ftmp9], %[ftmp0], %[ftmp4] \n\t"
"and %[ftmp9], %[ftmp9], %[ff_pw_01] \n\t"
"paddw %[ftmp4], %[ftmp4], %[ftmp9] \n\t"
"paddw %[ftmp4], %[ftmp4], %[ff_pw_03] \n\t"
"psraw %[ftmp4], %[ftmp4], %[ftmp11] \n\t"
"pcmpgtw %[ftmp9], %[ftmp0], %[ftmp5] \n\t"
"and %[ftmp9], %[ftmp9], %[ff_pw_01] \n\t"
"paddw %[ftmp5], %[ftmp5], %[ftmp9] \n\t"
"paddw %[ftmp5], %[ftmp5], %[ff_pw_03] \n\t"
"psraw %[ftmp5], %[ftmp5], %[ftmp11] \n\t"
"pcmpgtw %[ftmp9], %[ftmp0], %[ftmp6] \n\t"
"and %[ftmp9], %[ftmp9], %[ff_pw_01] \n\t"
"paddw %[ftmp6], %[ftmp6], %[ftmp9] \n\t"
"paddw %[ftmp6], %[ftmp6], %[ff_pw_03] \n\t"
"psraw %[ftmp6], %[ftmp6], %[ftmp11] \n\t"
"pcmpgtw %[ftmp9], %[ftmp0], %[ftmp7] \n\t"
"and %[ftmp9], %[ftmp9], %[ff_pw_01] \n\t"
"paddw %[ftmp7], %[ftmp7], %[ftmp9] \n\t"
"paddw %[ftmp7], %[ftmp7], %[ff_pw_03] \n\t"
"psraw %[ftmp7], %[ftmp7], %[ftmp11] \n\t"
"pcmpgtw %[ftmp9], %[ftmp0], %[ftmp8] \n\t"
"and %[ftmp9], %[ftmp9], %[ff_pw_01] \n\t"
"paddw %[ftmp8], %[ftmp8], %[ftmp9] \n\t"
"paddw %[ftmp8], %[ftmp8], %[ff_pw_03] \n\t"
"psraw %[ftmp8], %[ftmp8], %[ftmp11] \n\t"
"packsswh %[ftmp1], %[ftmp1], %[ftmp5] \n\t"
"packsswh %[ftmp2], %[ftmp2], %[ftmp6] \n\t"
"packsswh %[ftmp3], %[ftmp3], %[ftmp7] \n\t"
"packsswh %[ftmp4], %[ftmp4], %[ftmp8] \n\t"
MMI_LI(%[tmp0], 0x72)
"mtc1 %[tmp0], %[ftmp11] \n\t"
"pshufh %[ftmp1], %[ftmp1], %[ftmp11] \n\t"
"pshufh %[ftmp2], %[ftmp2], %[ftmp11] \n\t"
"pshufh %[ftmp3], %[ftmp3], %[ftmp11] \n\t"
"pshufh %[ftmp4], %[ftmp4], %[ftmp11] \n\t"
"gssdlc1 %[ftmp1], 0x07(%[op]) \n\t"
"gssdrc1 %[ftmp1], 0x00(%[op]) \n\t"
"gssdlc1 %[ftmp2], 0x0f(%[op]) \n\t"
"gssdrc1 %[ftmp2], 0x08(%[op]) \n\t"
"gssdlc1 %[ftmp3], 0x17(%[op]) \n\t"
"gssdrc1 %[ftmp3], 0x10(%[op]) \n\t"
"gssdlc1 %[ftmp4], 0x1f(%[op]) \n\t"
"gssdrc1 %[ftmp4], 0x18(%[op]) \n\t"
: [ftmp0]"=&f"(ftmp[0]), [ftmp1]"=&f"(ftmp[1]),
[ftmp2]"=&f"(ftmp[2]), [ftmp3]"=&f"(ftmp[3]),
[ftmp4]"=&f"(ftmp[4]), [ftmp5]"=&f"(ftmp[5]),
[ftmp6]"=&f"(ftmp[6]), [ftmp7]"=&f"(ftmp[7]),
[ftmp8]"=&f"(ftmp[8]), [ftmp9]"=&f"(ftmp[9]),
[ftmp10]"=&f"(ftmp[10]), [ftmp11]"=&f"(ftmp[11]),
[ftmp12]"=&f"(ftmp[12]),
[tmp0]"=&r"(tmp[0]),
[ip]"+&r"(input)
: [op]"r"(output),
[ff_pw_01]"f"(ff_pw_01), [pitch]"r"((mips_reg)pitch),
[ff_pw_03]"f"(ff_pw_03), [ff_pw_mask]"f"(ff_pw_mask),
[ff_ph_01]"f"(ff_ph_01)
: "memory"
);
}
@@ -0,0 +1,262 @@
/*
* Copyright (c) 2017 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/asmdefs_mmi.h"
#include "vp8/encoder/onyx_int.h"
#include "vp8/encoder/quantize.h"
#include "vp8/common/quant_common.h"
#define REGULAR_SELECT_EOB(i, rc) \
z = coeff_ptr[rc]; \
sz = (z >> 31); \
x = (z ^ sz) - sz; \
zbin = zbin_ptr[rc] + *(zbin_boost_ptr++) + zbin_oq_value; \
if (x >= zbin) { \
x += round_ptr[rc]; \
y = ((((x * quant_ptr[rc]) >> 16) + x) * quant_shift_ptr[rc]) >> 16; \
if (y) { \
x = (y ^ sz) - sz; \
qcoeff_ptr[rc] = x; \
dqcoeff_ptr[rc] = x * dequant_ptr[rc]; \
eob = i; \
zbin_boost_ptr = b->zrun_zbin_boost; \
} \
}
void vp8_fast_quantize_b_mmi(BLOCK *b, BLOCKD *d) {
const int16_t *coeff_ptr = b->coeff;
const int16_t *round_ptr = b->round;
const int16_t *quant_ptr = b->quant_fast;
int16_t *qcoeff_ptr = d->qcoeff;
int16_t *dqcoeff_ptr = d->dqcoeff;
const int16_t *dequant_ptr = d->dequant;
const int16_t *inv_zig_zag = vp8_default_inv_zig_zag;
double ftmp[13];
uint64_t tmp[1];
DECLARE_ALIGNED(8, const uint64_t, ones) = { 0xffffffffffffffffULL };
int eob = 0;
__asm__ volatile(
// loop 0 ~ 7
"xor %[ftmp0], %[ftmp0], %[ftmp0] \n\t"
"gsldlc1 %[ftmp1], 0x07(%[coeff_ptr]) \n\t"
"gsldrc1 %[ftmp1], 0x00(%[coeff_ptr]) \n\t"
"li %[tmp0], 0x0f \n\t"
"mtc1 %[tmp0], %[ftmp9] \n\t"
"gsldlc1 %[ftmp2], 0x0f(%[coeff_ptr]) \n\t"
"gsldrc1 %[ftmp2], 0x08(%[coeff_ptr]) \n\t"
"psrah %[ftmp3], %[ftmp1], %[ftmp9] \n\t"
"xor %[ftmp1], %[ftmp3], %[ftmp1] \n\t"
"psubh %[ftmp1], %[ftmp1], %[ftmp3] \n\t"
"psrah %[ftmp4], %[ftmp2], %[ftmp9] \n\t"
"xor %[ftmp2], %[ftmp4], %[ftmp2] \n\t"
"psubh %[ftmp2], %[ftmp2], %[ftmp4] \n\t"
"gsldlc1 %[ftmp5], 0x07(%[round_ptr]) \n\t"
"gsldrc1 %[ftmp5], 0x00(%[round_ptr]) \n\t"
"gsldlc1 %[ftmp6], 0x0f(%[round_ptr]) \n\t"
"gsldrc1 %[ftmp6], 0x08(%[round_ptr]) \n\t"
"paddh %[ftmp5], %[ftmp5], %[ftmp1] \n\t"
"paddh %[ftmp6], %[ftmp6], %[ftmp2] \n\t"
"gsldlc1 %[ftmp7], 0x07(%[quant_ptr]) \n\t"
"gsldrc1 %[ftmp7], 0x00(%[quant_ptr]) \n\t"
"gsldlc1 %[ftmp8], 0x0f(%[quant_ptr]) \n\t"
"gsldrc1 %[ftmp8], 0x08(%[quant_ptr]) \n\t"
"pmulhuh %[ftmp5], %[ftmp5], %[ftmp7] \n\t"
"pmulhuh %[ftmp6], %[ftmp6], %[ftmp8] \n\t"
"xor %[ftmp7], %[ftmp5], %[ftmp3] \n\t"
"xor %[ftmp8], %[ftmp6], %[ftmp4] \n\t"
"psubh %[ftmp7], %[ftmp7], %[ftmp3] \n\t"
"psubh %[ftmp8], %[ftmp8], %[ftmp4] \n\t"
"gssdlc1 %[ftmp7], 0x07(%[qcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp7], 0x00(%[qcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp8], 0x0f(%[qcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp8], 0x08(%[qcoeff_ptr]) \n\t"
"gsldlc1 %[ftmp1], 0x07(%[inv_zig_zag]) \n\t"
"gsldrc1 %[ftmp1], 0x00(%[inv_zig_zag]) \n\t"
"gsldlc1 %[ftmp2], 0x0f(%[inv_zig_zag]) \n\t"
"gsldrc1 %[ftmp2], 0x08(%[inv_zig_zag]) \n\t"
"pcmpeqh %[ftmp5], %[ftmp5], %[ftmp0] \n\t"
"pcmpeqh %[ftmp6], %[ftmp6], %[ftmp0] \n\t"
"xor %[ftmp5], %[ftmp5], %[ones] \n\t"
"xor %[ftmp6], %[ftmp6], %[ones] \n\t"
"and %[ftmp5], %[ftmp5], %[ftmp1] \n\t"
"and %[ftmp6], %[ftmp6], %[ftmp2] \n\t"
"pmaxsh %[ftmp10], %[ftmp5], %[ftmp6] \n\t"
"gsldlc1 %[ftmp5], 0x07(%[dequant_ptr]) \n\t"
"gsldrc1 %[ftmp5], 0x00(%[dequant_ptr]) \n\t"
"gsldlc1 %[ftmp6], 0x0f(%[dequant_ptr]) \n\t"
"gsldrc1 %[ftmp6], 0x08(%[dequant_ptr]) \n\t"
"pmullh %[ftmp5], %[ftmp5], %[ftmp7] \n\t"
"pmullh %[ftmp6], %[ftmp6], %[ftmp8] \n\t"
"gssdlc1 %[ftmp5], 0x07(%[dqcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp5], 0x00(%[dqcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp6], 0x0f(%[dqcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp6], 0x08(%[dqcoeff_ptr]) \n\t"
// loop 8 ~ 15
"gsldlc1 %[ftmp1], 0x17(%[coeff_ptr]) \n\t"
"gsldrc1 %[ftmp1], 0x10(%[coeff_ptr]) \n\t"
"gsldlc1 %[ftmp2], 0x1f(%[coeff_ptr]) \n\t"
"gsldrc1 %[ftmp2], 0x18(%[coeff_ptr]) \n\t"
"psrah %[ftmp3], %[ftmp1], %[ftmp9] \n\t"
"xor %[ftmp1], %[ftmp3], %[ftmp1] \n\t"
"psubh %[ftmp1], %[ftmp1], %[ftmp3] \n\t"
"psrah %[ftmp4], %[ftmp2], %[ftmp9] \n\t"
"xor %[ftmp2], %[ftmp4], %[ftmp2] \n\t"
"psubh %[ftmp2], %[ftmp2], %[ftmp4] \n\t"
"gsldlc1 %[ftmp5], 0x17(%[round_ptr]) \n\t"
"gsldrc1 %[ftmp5], 0x10(%[round_ptr]) \n\t"
"gsldlc1 %[ftmp6], 0x1f(%[round_ptr]) \n\t"
"gsldrc1 %[ftmp6], 0x18(%[round_ptr]) \n\t"
"paddh %[ftmp5], %[ftmp5], %[ftmp1] \n\t"
"paddh %[ftmp6], %[ftmp6], %[ftmp2] \n\t"
"gsldlc1 %[ftmp7], 0x17(%[quant_ptr]) \n\t"
"gsldrc1 %[ftmp7], 0x10(%[quant_ptr]) \n\t"
"gsldlc1 %[ftmp8], 0x1f(%[quant_ptr]) \n\t"
"gsldrc1 %[ftmp8], 0x18(%[quant_ptr]) \n\t"
"pmulhuh %[ftmp5], %[ftmp5], %[ftmp7] \n\t"
"pmulhuh %[ftmp6], %[ftmp6], %[ftmp8] \n\t"
"xor %[ftmp7], %[ftmp5], %[ftmp3] \n\t"
"xor %[ftmp8], %[ftmp6], %[ftmp4] \n\t"
"psubh %[ftmp7], %[ftmp7], %[ftmp3] \n\t"
"psubh %[ftmp8], %[ftmp8], %[ftmp4] \n\t"
"gssdlc1 %[ftmp7], 0x17(%[qcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp7], 0x10(%[qcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp8], 0x1f(%[qcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp8], 0x18(%[qcoeff_ptr]) \n\t"
"gsldlc1 %[ftmp1], 0x17(%[inv_zig_zag]) \n\t"
"gsldrc1 %[ftmp1], 0x10(%[inv_zig_zag]) \n\t"
"gsldlc1 %[ftmp2], 0x1f(%[inv_zig_zag]) \n\t"
"gsldrc1 %[ftmp2], 0x18(%[inv_zig_zag]) \n\t"
"pcmpeqh %[ftmp5], %[ftmp5], %[ftmp0] \n\t"
"pcmpeqh %[ftmp6], %[ftmp6], %[ftmp0] \n\t"
"xor %[ftmp5], %[ftmp5], %[ones] \n\t"
"xor %[ftmp6], %[ftmp6], %[ones] \n\t"
"and %[ftmp5], %[ftmp5], %[ftmp1] \n\t"
"and %[ftmp6], %[ftmp6], %[ftmp2] \n\t"
"pmaxsh %[ftmp11], %[ftmp5], %[ftmp6] \n\t"
"gsldlc1 %[ftmp5], 0x17(%[dequant_ptr]) \n\t"
"gsldrc1 %[ftmp5], 0x10(%[dequant_ptr]) \n\t"
"gsldlc1 %[ftmp6], 0x1f(%[dequant_ptr]) \n\t"
"gsldrc1 %[ftmp6], 0x18(%[dequant_ptr]) \n\t"
"pmullh %[ftmp5], %[ftmp5], %[ftmp7] \n\t"
"pmullh %[ftmp6], %[ftmp6], %[ftmp8] \n\t"
"gssdlc1 %[ftmp5], 0x17(%[dqcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp5], 0x10(%[dqcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp6], 0x1f(%[dqcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp6], 0x18(%[dqcoeff_ptr]) \n\t"
"li %[tmp0], 0x10 \n\t"
"mtc1 %[tmp0], %[ftmp9] \n\t"
"pmaxsh %[ftmp10], %[ftmp10], %[ftmp11] \n\t"
"psrlw %[ftmp11], %[ftmp10], %[ftmp9] \n\t"
"pmaxsh %[ftmp10], %[ftmp10], %[ftmp11] \n\t"
"li %[tmp0], 0xaa \n\t"
"mtc1 %[tmp0], %[ftmp9] \n\t"
"pshufh %[ftmp11], %[ftmp10], %[ftmp9] \n\t"
"pmaxsh %[ftmp10], %[ftmp10], %[ftmp11] \n\t"
"li %[tmp0], 0xffff \n\t"
"mtc1 %[tmp0], %[ftmp9] \n\t"
"and %[ftmp10], %[ftmp10], %[ftmp9] \n\t"
"gssdlc1 %[ftmp10], 0x07(%[eob]) \n\t"
"gssdrc1 %[ftmp10], 0x00(%[eob]) \n\t"
: [ftmp0] "=&f"(ftmp[0]), [ftmp1] "=&f"(ftmp[1]), [ftmp2] "=&f"(ftmp[2]),
[ftmp3] "=&f"(ftmp[3]), [ftmp4] "=&f"(ftmp[4]), [ftmp5] "=&f"(ftmp[5]),
[ftmp6] "=&f"(ftmp[6]), [ftmp7] "=&f"(ftmp[7]), [ftmp8] "=&f"(ftmp[8]),
[ftmp9] "=&f"(ftmp[9]), [ftmp10] "=&f"(ftmp[10]),
[ftmp11] "=&f"(ftmp[11]), [ftmp12] "=&f"(ftmp[12]), [tmp0] "=&r"(tmp[0])
: [coeff_ptr] "r"((mips_reg)coeff_ptr),
[qcoeff_ptr] "r"((mips_reg)qcoeff_ptr),
[dequant_ptr] "r"((mips_reg)dequant_ptr),
[round_ptr] "r"((mips_reg)round_ptr),
[quant_ptr] "r"((mips_reg)quant_ptr),
[dqcoeff_ptr] "r"((mips_reg)dqcoeff_ptr),
[inv_zig_zag] "r"((mips_reg)inv_zig_zag), [eob] "r"((mips_reg)&eob),
[ones] "f"(ones)
: "memory");
*d->eob = eob;
}
void vp8_regular_quantize_b_mmi(BLOCK *b, BLOCKD *d) {
int eob = 0;
int x, y, z, sz, zbin;
const int16_t *zbin_boost_ptr = b->zrun_zbin_boost;
const int16_t *coeff_ptr = b->coeff;
const int16_t *zbin_ptr = b->zbin;
const int16_t *round_ptr = b->round;
const int16_t *quant_ptr = b->quant;
const int16_t *quant_shift_ptr = b->quant_shift;
int16_t *qcoeff_ptr = d->qcoeff;
int16_t *dqcoeff_ptr = d->dqcoeff;
const int16_t *dequant_ptr = d->dequant;
const int16_t zbin_oq_value = b->zbin_extra;
register double ftmp0 asm("$f0");
// memset(qcoeff_ptr, 0, 32);
// memset(dqcoeff_ptr, 0, 32);
/* clang-format off */
__asm__ volatile (
"xor %[ftmp0], %[ftmp0], %[ftmp0] \n\t"
"gssdlc1 %[ftmp0], 0x07(%[qcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp0], 0x00(%[qcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp0], 0x0f(%[qcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp0], 0x08(%[qcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp0], 0x17(%[qcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp0], 0x10(%[qcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp0], 0x1f(%[qcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp0], 0x18(%[qcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp0], 0x07(%[dqcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp0], 0x00(%[dqcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp0], 0x0f(%[dqcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp0], 0x08(%[dqcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp0], 0x17(%[dqcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp0], 0x10(%[dqcoeff_ptr]) \n\t"
"gssdlc1 %[ftmp0], 0x1f(%[dqcoeff_ptr]) \n\t"
"gssdrc1 %[ftmp0], 0x18(%[dqcoeff_ptr]) \n\t"
: [ftmp0]"=&f"(ftmp0)
: [qcoeff_ptr]"r"(qcoeff_ptr), [dqcoeff_ptr]"r"(dqcoeff_ptr)
: "memory"
);
/* clang-format on */
REGULAR_SELECT_EOB(1, 0);
REGULAR_SELECT_EOB(2, 1);
REGULAR_SELECT_EOB(3, 4);
REGULAR_SELECT_EOB(4, 8);
REGULAR_SELECT_EOB(5, 5);
REGULAR_SELECT_EOB(6, 2);
REGULAR_SELECT_EOB(7, 3);
REGULAR_SELECT_EOB(8, 6);
REGULAR_SELECT_EOB(9, 9);
REGULAR_SELECT_EOB(10, 12);
REGULAR_SELECT_EOB(11, 13);
REGULAR_SELECT_EOB(12, 10);
REGULAR_SELECT_EOB(13, 7);
REGULAR_SELECT_EOB(14, 11);
REGULAR_SELECT_EOB(15, 14);
REGULAR_SELECT_EOB(16, 15);
*d->eob = (char)eob;
}
@@ -0,0 +1,196 @@
/*
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vp8_rtcd.h"
#include "vp8/common/mips/msa/vp8_macros_msa.h"
#define TRANSPOSE4x4_H(in0, in1, in2, in3, out0, out1, out2, out3) \
{ \
v8i16 s0_m, s1_m, tp0_m, tp1_m, tp2_m, tp3_m; \
\
ILVR_H2_SH(in2, in0, in3, in1, s0_m, s1_m); \
ILVRL_H2_SH(s1_m, s0_m, tp0_m, tp1_m); \
ILVL_H2_SH(in2, in0, in3, in1, s0_m, s1_m); \
ILVRL_H2_SH(s1_m, s0_m, tp2_m, tp3_m); \
PCKEV_D2_SH(tp2_m, tp0_m, tp3_m, tp1_m, out0, out2); \
PCKOD_D2_SH(tp2_m, tp0_m, tp3_m, tp1_m, out1, out3); \
}
#define SET_DOTP_VALUES(coeff, val0, val1, val2, const1, const2) \
{ \
v8i16 tmp0_m; \
\
SPLATI_H3_SH(coeff, val0, val1, val2, tmp0_m, const1, const2); \
ILVEV_H2_SH(tmp0_m, const1, const2, tmp0_m, const1, const2); \
}
#define RET_1_IF_NZERO_H(in0) \
({ \
v8i16 tmp0_m; \
v8i16 one_m = __msa_ldi_h(1); \
\
tmp0_m = __msa_ceqi_h(in0, 0); \
tmp0_m = tmp0_m ^ 255; \
tmp0_m = one_m & tmp0_m; \
\
tmp0_m; \
})
#define RET_1_IF_NZERO_W(in0) \
({ \
v4i32 tmp0_m; \
v4i32 one_m = __msa_ldi_w(1); \
\
tmp0_m = __msa_ceqi_w(in0, 0); \
tmp0_m = tmp0_m ^ 255; \
tmp0_m = one_m & tmp0_m; \
\
tmp0_m; \
})
#define RET_1_IF_NEG_W(in0) \
({ \
v4i32 tmp0_m; \
\
v4i32 one_m = __msa_ldi_w(1); \
tmp0_m = __msa_clti_s_w(in0, 0); \
tmp0_m = one_m & tmp0_m; \
\
tmp0_m; \
})
void vp8_short_fdct4x4_msa(int16_t *input, int16_t *output, int32_t pitch) {
v8i16 in0, in1, in2, in3;
v8i16 temp0, temp1;
v8i16 const0, const1;
v8i16 coeff = { 2217, 5352, -5352, 14500, 7500, 12000, 25000, 26000 };
v4i32 out0, out1, out2, out3;
v8i16 zero = { 0 };
LD_SH4(input, pitch / 2, in0, in1, in2, in3);
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
BUTTERFLY_4(in0, in1, in2, in3, temp0, temp1, in1, in3);
SLLI_4V(temp0, temp1, in1, in3, 3);
in0 = temp0 + temp1;
in2 = temp0 - temp1;
SET_DOTP_VALUES(coeff, 0, 1, 2, const0, const1);
temp0 = __msa_ilvr_h(in3, in1);
in1 = __msa_splati_h(coeff, 3);
out0 = (v4i32)__msa_ilvev_h(zero, in1);
coeff = __msa_ilvl_h(zero, coeff);
out1 = __msa_splati_w((v4i32)coeff, 0);
DPADD_SH2_SW(temp0, temp0, const0, const1, out0, out1);
out0 >>= 12;
out1 >>= 12;
PCKEV_H2_SH(out0, out0, out1, out1, in1, in3);
TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, in0, in1, in2, in3);
BUTTERFLY_4(in0, in1, in2, in3, temp0, temp1, in1, in3);
in0 = temp0 + temp1 + 7;
in2 = temp0 - temp1 + 7;
in0 >>= 4;
in2 >>= 4;
ILVR_H2_SW(zero, in0, zero, in2, out0, out2);
temp1 = RET_1_IF_NZERO_H(in3);
ILVR_H2_SH(zero, temp1, in3, in1, temp1, temp0);
SPLATI_W2_SW(coeff, 2, out3, out1);
out3 += out1;
out1 = __msa_splati_w((v4i32)coeff, 1);
DPADD_SH2_SW(temp0, temp0, const0, const1, out1, out3);
out1 >>= 16;
out3 >>= 16;
out1 += (v4i32)temp1;
PCKEV_H2_SH(out1, out0, out3, out2, in0, in2);
ST_SH2(in0, in2, output, 8);
}
void vp8_short_fdct8x4_msa(int16_t *input, int16_t *output, int32_t pitch) {
v8i16 in0, in1, in2, in3;
v8i16 temp0, temp1, tmp0, tmp1;
v8i16 const0, const1, const2;
v8i16 coeff = { 2217, 5352, -5352, 14500, 7500, 12000, 25000, 26000 };
v8i16 zero = { 0 };
v4i32 vec0_w, vec1_w, vec2_w, vec3_w;
LD_SH4(input, pitch / 2, in0, in1, in2, in3);
TRANSPOSE4x4_H(in0, in1, in2, in3, in0, in1, in2, in3);
BUTTERFLY_4(in0, in1, in2, in3, temp0, temp1, in1, in3);
SLLI_4V(temp0, temp1, in1, in3, 3);
in0 = temp0 + temp1;
in2 = temp0 - temp1;
SET_DOTP_VALUES(coeff, 0, 1, 2, const1, const2);
temp0 = __msa_splati_h(coeff, 3);
vec1_w = (v4i32)__msa_ilvev_h(zero, temp0);
coeff = __msa_ilvl_h(zero, coeff);
vec3_w = __msa_splati_w((v4i32)coeff, 0);
ILVRL_H2_SH(in3, in1, tmp1, tmp0);
vec0_w = vec1_w;
vec2_w = vec3_w;
DPADD_SH4_SW(tmp1, tmp0, tmp1, tmp0, const1, const1, const2, const2, vec0_w,
vec1_w, vec2_w, vec3_w);
SRA_4V(vec1_w, vec0_w, vec3_w, vec2_w, 12);
PCKEV_H2_SH(vec1_w, vec0_w, vec3_w, vec2_w, in1, in3);
TRANSPOSE4x4_H(in0, in1, in2, in3, in0, in1, in2, in3);
BUTTERFLY_4(in0, in1, in2, in3, temp0, temp1, in1, in3);
in0 = temp0 + temp1 + 7;
in2 = temp0 - temp1 + 7;
in0 >>= 4;
in2 >>= 4;
SPLATI_W2_SW(coeff, 2, vec3_w, vec1_w);
vec3_w += vec1_w;
vec1_w = __msa_splati_w((v4i32)coeff, 1);
const0 = RET_1_IF_NZERO_H(in3);
ILVRL_H2_SH(in3, in1, tmp1, tmp0);
vec0_w = vec1_w;
vec2_w = vec3_w;
DPADD_SH4_SW(tmp1, tmp0, tmp1, tmp0, const1, const1, const2, const2, vec0_w,
vec1_w, vec2_w, vec3_w);
SRA_4V(vec1_w, vec0_w, vec3_w, vec2_w, 16);
PCKEV_H2_SH(vec1_w, vec0_w, vec3_w, vec2_w, in1, in3);
in1 += const0;
PCKEV_D2_SH(in1, in0, in3, in2, temp0, temp1);
ST_SH2(temp0, temp1, output, 8);
PCKOD_D2_SH(in1, in0, in3, in2, in0, in2);
ST_SH2(in0, in2, output + 16, 8);
}
void vp8_short_walsh4x4_msa(int16_t *input, int16_t *output, int32_t pitch) {
v8i16 in0_h, in1_h, in2_h, in3_h;
v4i32 in0_w, in1_w, in2_w, in3_w, temp0, temp1, temp2, temp3;
LD_SH4(input, pitch / 2, in0_h, in1_h, in2_h, in3_h);
TRANSPOSE4x4_SH_SH(in0_h, in1_h, in2_h, in3_h, in0_h, in1_h, in2_h, in3_h);
UNPCK_R_SH_SW(in0_h, in0_w);
UNPCK_R_SH_SW(in1_h, in1_w);
UNPCK_R_SH_SW(in2_h, in2_w);
UNPCK_R_SH_SW(in3_h, in3_w);
BUTTERFLY_4(in0_w, in1_w, in3_w, in2_w, temp0, temp3, temp2, temp1);
SLLI_4V(temp0, temp1, temp2, temp3, 2);
BUTTERFLY_4(temp0, temp1, temp2, temp3, in0_w, in1_w, in2_w, in3_w);
temp0 = RET_1_IF_NZERO_W(temp0);
in0_w += temp0;
TRANSPOSE4x4_SW_SW(in0_w, in1_w, in2_w, in3_w, in0_w, in1_w, in2_w, in3_w);
BUTTERFLY_4(in0_w, in1_w, in3_w, in2_w, temp0, temp3, temp2, temp1);
BUTTERFLY_4(temp0, temp1, temp2, temp3, in0_w, in1_w, in2_w, in3_w);
in0_w += RET_1_IF_NEG_W(in0_w);
in1_w += RET_1_IF_NEG_W(in1_w);
in2_w += RET_1_IF_NEG_W(in2_w);
in3_w += RET_1_IF_NEG_W(in3_w);
ADD4(in0_w, 3, in1_w, 3, in2_w, 3, in3_w, 3, in0_w, in1_w, in2_w, in3_w);
SRA_4V(in0_w, in1_w, in2_w, in3_w, 3);
PCKEV_H2_SH(in1_w, in0_w, in3_w, in2_w, in0_h, in1_h);
ST_SH2(in0_h, in1_h, output, 8);
}
@@ -0,0 +1,568 @@
/*
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stdlib.h>
#include "./vp8_rtcd.h"
#include "vp8/common/mips/msa/vp8_macros_msa.h"
#include "vp8/encoder/denoising.h"
int32_t vp8_denoiser_filter_msa(uint8_t *mc_running_avg_y_ptr,
int32_t mc_avg_y_stride,
uint8_t *running_avg_y_ptr,
int32_t avg_y_stride, uint8_t *sig_ptr,
int32_t sig_stride, uint32_t motion_magnitude,
int32_t increase_denoising) {
uint8_t *running_avg_y_start = running_avg_y_ptr;
uint8_t *sig_start = sig_ptr;
int32_t cnt = 0;
int32_t sum_diff = 0;
int32_t shift_inc1 = 3;
int32_t delta = 0;
int32_t sum_diff_thresh;
v16u8 src0, src1, src2, src3, src4, src5, src6, src7;
v16u8 src8, src9, src10, src11, src12, src13, src14, src15;
v16u8 mc_running_avg_y0, running_avg_y, sig0;
v16u8 mc_running_avg_y1, running_avg_y1, sig1;
v16u8 coeff0, coeff1;
v8i16 diff0, diff1, abs_diff0, abs_diff1, abs_diff_neg0, abs_diff_neg1;
v8i16 adjust0, adjust1, adjust2, adjust3;
v8i16 shift_inc1_vec = { 0 };
v8i16 col_sum0 = { 0 };
v8i16 col_sum1 = { 0 };
v8i16 col_sum2 = { 0 };
v8i16 col_sum3 = { 0 };
v8i16 temp0_h, temp1_h, temp2_h, temp3_h, cmp, delta_vec;
v4i32 temp0_w;
v2i64 temp0_d, temp1_d;
v8i16 zero = { 0 };
v8i16 one = __msa_ldi_h(1);
v8i16 four = __msa_ldi_h(4);
v8i16 val_127 = __msa_ldi_h(127);
v8i16 adj_val = { 6, 4, 3, 0, -6, -4, -3, 0 };
if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) {
adj_val = __msa_add_a_h(adj_val, one);
if (increase_denoising) {
adj_val = __msa_add_a_h(adj_val, one);
shift_inc1 = 4;
}
temp0_h = zero - adj_val;
adj_val = (v8i16)__msa_ilvev_d((v2i64)temp0_h, (v2i64)adj_val);
}
adj_val = __msa_insert_h(adj_val, 3, cnt);
adj_val = __msa_insert_h(adj_val, 7, cnt);
shift_inc1_vec = __msa_fill_h(shift_inc1);
for (cnt = 8; cnt--;) {
v8i16 mask0 = { 0 };
v8i16 mask1 = { 0 };
mc_running_avg_y0 = LD_UB(mc_running_avg_y_ptr);
sig0 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
mc_running_avg_y_ptr += mc_avg_y_stride;
mc_running_avg_y1 = LD_UB(mc_running_avg_y_ptr);
sig1 = LD_UB(sig_ptr);
ILVRL_B2_UB(mc_running_avg_y0, sig0, coeff0, coeff1);
HSUB_UB2_SH(coeff0, coeff1, diff0, diff1);
abs_diff0 = __msa_add_a_h(diff0, zero);
abs_diff1 = __msa_add_a_h(diff1, zero);
cmp = __msa_clei_s_h(abs_diff0, 15);
cmp = cmp & one;
mask0 += cmp;
cmp = __msa_clei_s_h(abs_diff0, 7);
cmp = cmp & one;
mask0 += cmp;
cmp = abs_diff0 < shift_inc1_vec;
cmp = cmp & one;
mask0 += cmp;
cmp = __msa_clei_s_h(abs_diff1, 15);
cmp = cmp & one;
mask1 += cmp;
cmp = __msa_clei_s_h(abs_diff1, 7);
cmp = cmp & one;
mask1 += cmp;
cmp = abs_diff1 < shift_inc1_vec;
cmp = cmp & one;
mask1 += cmp;
temp0_h = __msa_clei_s_h(diff0, 0);
temp0_h = temp0_h & four;
mask0 += temp0_h;
temp1_h = __msa_clei_s_h(diff1, 0);
temp1_h = temp1_h & four;
mask1 += temp1_h;
VSHF_H2_SH(adj_val, adj_val, adj_val, adj_val, mask0, mask1, adjust0,
adjust1);
temp2_h = __msa_ceqi_h(adjust0, 0);
temp3_h = __msa_ceqi_h(adjust1, 0);
adjust0 = (v8i16)__msa_bmnz_v((v16u8)adjust0, (v16u8)diff0, (v16u8)temp2_h);
adjust1 = (v8i16)__msa_bmnz_v((v16u8)adjust1, (v16u8)diff1, (v16u8)temp3_h);
ADD2(col_sum0, adjust0, col_sum1, adjust1, col_sum0, col_sum1);
UNPCK_UB_SH(sig0, temp0_h, temp1_h);
ADD2(temp0_h, adjust0, temp1_h, adjust1, temp0_h, temp1_h);
MAXI_SH2_SH(temp0_h, temp1_h, 0);
SAT_UH2_SH(temp0_h, temp1_h, 7);
temp2_h = (v8i16)__msa_pckev_b((v16i8)temp3_h, (v16i8)temp2_h);
running_avg_y = (v16u8)__msa_pckev_b((v16i8)temp1_h, (v16i8)temp0_h);
running_avg_y =
__msa_bmnz_v(running_avg_y, mc_running_avg_y0, (v16u8)temp2_h);
ST_UB(running_avg_y, running_avg_y_ptr);
running_avg_y_ptr += avg_y_stride;
mask0 = zero;
mask1 = zero;
ILVRL_B2_UB(mc_running_avg_y1, sig1, coeff0, coeff1);
HSUB_UB2_SH(coeff0, coeff1, diff0, diff1);
abs_diff0 = __msa_add_a_h(diff0, zero);
abs_diff1 = __msa_add_a_h(diff1, zero);
cmp = __msa_clei_s_h(abs_diff0, 15);
cmp = cmp & one;
mask0 += cmp;
cmp = __msa_clei_s_h(abs_diff0, 7);
cmp = cmp & one;
mask0 += cmp;
cmp = abs_diff0 < shift_inc1_vec;
cmp = cmp & one;
mask0 += cmp;
cmp = __msa_clei_s_h(abs_diff1, 15);
cmp = cmp & one;
mask1 += cmp;
cmp = __msa_clei_s_h(abs_diff1, 7);
cmp = cmp & one;
mask1 += cmp;
cmp = abs_diff1 < shift_inc1_vec;
cmp = cmp & one;
mask1 += cmp;
temp0_h = __msa_clei_s_h(diff0, 0);
temp0_h = temp0_h & four;
mask0 += temp0_h;
temp1_h = __msa_clei_s_h(diff1, 0);
temp1_h = temp1_h & four;
mask1 += temp1_h;
VSHF_H2_SH(adj_val, adj_val, adj_val, adj_val, mask0, mask1, adjust0,
adjust1);
temp2_h = __msa_ceqi_h(adjust0, 0);
temp3_h = __msa_ceqi_h(adjust1, 0);
adjust0 = (v8i16)__msa_bmnz_v((v16u8)adjust0, (v16u8)diff0, (v16u8)temp2_h);
adjust1 = (v8i16)__msa_bmnz_v((v16u8)adjust1, (v16u8)diff1, (v16u8)temp3_h);
ADD2(col_sum0, adjust0, col_sum1, adjust1, col_sum0, col_sum1);
UNPCK_UB_SH(sig1, temp0_h, temp1_h);
ADD2(temp0_h, adjust0, temp1_h, adjust1, temp0_h, temp1_h);
MAXI_SH2_SH(temp0_h, temp1_h, 0);
SAT_UH2_SH(temp0_h, temp1_h, 7);
temp2_h = (v8i16)__msa_pckev_b((v16i8)temp3_h, (v16i8)temp2_h);
running_avg_y = (v16u8)__msa_pckev_b((v16i8)temp1_h, (v16i8)temp0_h);
running_avg_y =
__msa_bmnz_v(running_avg_y, mc_running_avg_y1, (v16u8)temp2_h);
ST_UB(running_avg_y, running_avg_y_ptr);
sig_ptr += sig_stride;
mc_running_avg_y_ptr += mc_avg_y_stride;
running_avg_y_ptr += avg_y_stride;
}
col_sum0 = __msa_min_s_h(col_sum0, val_127);
col_sum1 = __msa_min_s_h(col_sum1, val_127);
temp0_h = col_sum0 + col_sum1;
temp0_w = __msa_hadd_s_w(temp0_h, temp0_h);
temp0_d = __msa_hadd_s_d(temp0_w, temp0_w);
temp1_d = __msa_splati_d(temp0_d, 1);
temp0_d += temp1_d;
sum_diff = __msa_copy_s_w((v4i32)temp0_d, 0);
sig_ptr -= sig_stride * 16;
mc_running_avg_y_ptr -= mc_avg_y_stride * 16;
running_avg_y_ptr -= avg_y_stride * 16;
if (increase_denoising) {
sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH;
}
if (abs(sum_diff) > sum_diff_thresh) {
delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
delta_vec = __msa_fill_h(delta);
if (delta < 4) {
for (cnt = 8; cnt--;) {
running_avg_y = LD_UB(running_avg_y_ptr);
mc_running_avg_y0 = LD_UB(mc_running_avg_y_ptr);
sig0 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
mc_running_avg_y_ptr += mc_avg_y_stride;
running_avg_y_ptr += avg_y_stride;
mc_running_avg_y1 = LD_UB(mc_running_avg_y_ptr);
sig1 = LD_UB(sig_ptr);
running_avg_y1 = LD_UB(running_avg_y_ptr);
ILVRL_B2_UB(mc_running_avg_y0, sig0, coeff0, coeff1);
HSUB_UB2_SH(coeff0, coeff1, diff0, diff1);
abs_diff0 = __msa_add_a_h(diff0, zero);
abs_diff1 = __msa_add_a_h(diff1, zero);
temp0_h = abs_diff0 < delta_vec;
temp1_h = abs_diff1 < delta_vec;
abs_diff0 = (v8i16)__msa_bmz_v((v16u8)abs_diff0, (v16u8)delta_vec,
(v16u8)temp0_h);
abs_diff1 = (v8i16)__msa_bmz_v((v16u8)abs_diff1, (v16u8)delta_vec,
(v16u8)temp1_h);
SUB2(zero, abs_diff0, zero, abs_diff1, abs_diff_neg0, abs_diff_neg1);
abs_diff_neg0 = zero - abs_diff0;
abs_diff_neg1 = zero - abs_diff1;
temp0_h = __msa_clei_s_h(diff0, 0);
temp1_h = __msa_clei_s_h(diff1, 0);
adjust0 = (v8i16)__msa_bmnz_v((v16u8)abs_diff0, (v16u8)abs_diff_neg0,
(v16u8)temp0_h);
adjust1 = (v8i16)__msa_bmnz_v((v16u8)abs_diff1, (v16u8)abs_diff_neg1,
(v16u8)temp1_h);
ILVRL_B2_SH(zero, running_avg_y, temp2_h, temp3_h);
ADD2(temp2_h, adjust0, temp3_h, adjust1, adjust2, adjust3);
MAXI_SH2_SH(adjust2, adjust3, 0);
SAT_UH2_SH(adjust2, adjust3, 7);
temp0_h = __msa_ceqi_h(diff0, 0);
temp1_h = __msa_ceqi_h(diff1, 0);
adjust2 =
(v8i16)__msa_bmz_v((v16u8)adjust2, (v16u8)temp2_h, (v16u8)temp0_h);
adjust3 =
(v8i16)__msa_bmz_v((v16u8)adjust3, (v16u8)temp3_h, (v16u8)temp1_h);
adjust0 =
(v8i16)__msa_bmnz_v((v16u8)adjust0, (v16u8)zero, (v16u8)temp0_h);
adjust1 =
(v8i16)__msa_bmnz_v((v16u8)adjust1, (v16u8)zero, (v16u8)temp1_h);
ADD2(col_sum2, adjust0, col_sum3, adjust1, col_sum2, col_sum3);
running_avg_y = (v16u8)__msa_pckev_b((v16i8)adjust3, (v16i8)adjust2);
ST_UB(running_avg_y, running_avg_y_ptr - avg_y_stride);
ILVRL_B2_UB(mc_running_avg_y1, sig1, coeff0, coeff1);
HSUB_UB2_SH(coeff0, coeff1, diff0, diff1);
abs_diff0 = __msa_add_a_h(diff0, zero);
abs_diff1 = __msa_add_a_h(diff1, zero);
temp0_h = abs_diff0 < delta_vec;
temp1_h = abs_diff1 < delta_vec;
abs_diff0 = (v8i16)__msa_bmz_v((v16u8)abs_diff0, (v16u8)delta_vec,
(v16u8)temp0_h);
abs_diff1 = (v8i16)__msa_bmz_v((v16u8)abs_diff1, (v16u8)delta_vec,
(v16u8)temp1_h);
SUB2(zero, abs_diff0, zero, abs_diff1, abs_diff_neg0, abs_diff_neg1);
temp0_h = __msa_clei_s_h(diff0, 0);
temp1_h = __msa_clei_s_h(diff1, 0);
adjust0 = (v8i16)__msa_bmnz_v((v16u8)abs_diff0, (v16u8)abs_diff_neg0,
(v16u8)temp0_h);
adjust1 = (v8i16)__msa_bmnz_v((v16u8)abs_diff1, (v16u8)abs_diff_neg1,
(v16u8)temp1_h);
ILVRL_H2_SH(zero, running_avg_y1, temp2_h, temp3_h);
ADD2(temp2_h, adjust0, temp3_h, adjust1, adjust2, adjust3);
MAXI_SH2_SH(adjust2, adjust3, 0);
SAT_UH2_SH(adjust2, adjust3, 7);
temp0_h = __msa_ceqi_h(diff0, 0);
temp1_h = __msa_ceqi_h(diff1, 0);
adjust2 =
(v8i16)__msa_bmz_v((v16u8)adjust2, (v16u8)temp2_h, (v16u8)temp0_h);
adjust3 =
(v8i16)__msa_bmz_v((v16u8)adjust3, (v16u8)temp3_h, (v16u8)temp1_h);
adjust0 =
(v8i16)__msa_bmz_v((v16u8)adjust0, (v16u8)zero, (v16u8)temp0_h);
adjust1 =
(v8i16)__msa_bmz_v((v16u8)adjust1, (v16u8)zero, (v16u8)temp1_h);
ADD2(col_sum2, adjust0, col_sum3, adjust1, col_sum2, col_sum3);
running_avg_y = (v16u8)__msa_pckev_b((v16i8)adjust3, (v16i8)adjust2);
ST_UB(running_avg_y, running_avg_y_ptr);
running_avg_y_ptr += avg_y_stride;
}
col_sum2 = __msa_min_s_h(col_sum2, val_127);
col_sum3 = __msa_min_s_h(col_sum3, val_127);
temp0_h = col_sum2 + col_sum3;
temp0_w = __msa_hadd_s_w(temp0_h, temp0_h);
temp0_d = __msa_hadd_s_d(temp0_w, temp0_w);
temp1_d = __msa_splati_d(temp0_d, 1);
temp0_d += (v2i64)temp1_d;
sum_diff = __msa_copy_s_w((v4i32)temp0_d, 0);
if (abs(sum_diff) > SUM_DIFF_THRESHOLD) {
return COPY_BLOCK;
}
} else {
return COPY_BLOCK;
}
}
LD_UB8(sig_start, sig_stride, src0, src1, src2, src3, src4, src5, src6, src7);
sig_start += (8 * sig_stride);
LD_UB8(sig_start, sig_stride, src8, src9, src10, src11, src12, src13, src14,
src15);
ST_UB8(src0, src1, src2, src3, src4, src5, src6, src7, running_avg_y_start,
avg_y_stride);
running_avg_y_start += (8 * avg_y_stride);
ST_UB8(src8, src9, src10, src11, src12, src13, src14, src15,
running_avg_y_start, avg_y_stride);
return FILTER_BLOCK;
}
int32_t vp8_denoiser_filter_uv_msa(
uint8_t *mc_running_avg_y_ptr, int32_t mc_avg_y_stride,
uint8_t *running_avg_y_ptr, int32_t avg_y_stride, uint8_t *sig_ptr,
int32_t sig_stride, uint32_t motion_magnitude, int32_t increase_denoising) {
uint8_t *running_avg_y_start = running_avg_y_ptr;
uint8_t *sig_start = sig_ptr;
int32_t cnt = 0;
int32_t sum_diff = 0;
int32_t shift_inc1 = 3;
int32_t delta = 0;
int32_t sum_block = 0;
int32_t sum_diff_thresh;
int64_t dst0, dst1, src0, src1, src2, src3;
v16u8 mc_running_avg_y0, running_avg_y, sig0;
v16u8 mc_running_avg_y1, running_avg_y1, sig1;
v16u8 sig2, sig3, sig4, sig5, sig6, sig7;
v16u8 coeff0;
v8i16 diff0, abs_diff0, abs_diff_neg0;
v8i16 adjust0, adjust2;
v8i16 shift_inc1_vec = { 0 };
v8i16 col_sum0 = { 0 };
v8i16 temp0_h, temp2_h, cmp, delta_vec;
v4i32 temp0_w;
v2i64 temp0_d, temp1_d;
v16i8 zero = { 0 };
v8i16 one = __msa_ldi_h(1);
v8i16 four = __msa_ldi_h(4);
v8i16 adj_val = { 6, 4, 3, 0, -6, -4, -3, 0 };
sig0 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
temp0_h = (v8i16)__msa_ilvr_b(zero, (v16i8)sig0);
sig1 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
temp0_h += (v8i16)__msa_ilvr_b(zero, (v16i8)sig1);
sig2 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
temp0_h += (v8i16)__msa_ilvr_b(zero, (v16i8)sig2);
sig3 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
temp0_h += (v8i16)__msa_ilvr_b(zero, (v16i8)sig3);
sig4 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
temp0_h += (v8i16)__msa_ilvr_b(zero, (v16i8)sig4);
sig5 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
temp0_h += (v8i16)__msa_ilvr_b(zero, (v16i8)sig5);
sig6 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
temp0_h += (v8i16)__msa_ilvr_b(zero, (v16i8)sig6);
sig7 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
temp0_h += (v8i16)__msa_ilvr_b(zero, (v16i8)sig7);
temp0_w = __msa_hadd_s_w(temp0_h, temp0_h);
temp0_d = __msa_hadd_s_d(temp0_w, temp0_w);
temp1_d = __msa_splati_d(temp0_d, 1);
temp0_d += temp1_d;
sum_block = __msa_copy_s_w((v4i32)temp0_d, 0);
sig_ptr -= sig_stride * 8;
if (abs(sum_block - (128 * 8 * 8)) < SUM_DIFF_FROM_AVG_THRESH_UV) {
return COPY_BLOCK;
}
if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) {
adj_val = __msa_add_a_h(adj_val, one);
if (increase_denoising) {
adj_val = __msa_add_a_h(adj_val, one);
shift_inc1 = 4;
}
temp0_h = (v8i16)zero - adj_val;
adj_val = (v8i16)__msa_ilvev_d((v2i64)temp0_h, (v2i64)adj_val);
}
adj_val = __msa_insert_h(adj_val, 3, cnt);
adj_val = __msa_insert_h(adj_val, 7, cnt);
shift_inc1_vec = __msa_fill_h(shift_inc1);
for (cnt = 4; cnt--;) {
v8i16 mask0 = { 0 };
mc_running_avg_y0 = LD_UB(mc_running_avg_y_ptr);
sig0 = LD_UB(sig_ptr);
sig_ptr += sig_stride;
mc_running_avg_y_ptr += mc_avg_y_stride;
mc_running_avg_y1 = LD_UB(mc_running_avg_y_ptr);
sig1 = LD_UB(sig_ptr);
coeff0 = (v16u8)__msa_ilvr_b((v16i8)mc_running_avg_y0, (v16i8)sig0);
diff0 = __msa_hsub_u_h(coeff0, coeff0);
abs_diff0 = __msa_add_a_h(diff0, (v8i16)zero);
cmp = __msa_clei_s_h(abs_diff0, 15);
cmp = cmp & one;
mask0 += cmp;
cmp = __msa_clei_s_h(abs_diff0, 7);
cmp = cmp & one;
mask0 += cmp;
cmp = abs_diff0 < shift_inc1_vec;
cmp = cmp & one;
mask0 += cmp;
temp0_h = __msa_clei_s_h(diff0, 0);
temp0_h = temp0_h & four;
mask0 += temp0_h;
adjust0 = __msa_vshf_h(mask0, adj_val, adj_val);
temp2_h = __msa_ceqi_h(adjust0, 0);
adjust0 = (v8i16)__msa_bmnz_v((v16u8)adjust0, (v16u8)diff0, (v16u8)temp2_h);
col_sum0 += adjust0;
temp0_h = (v8i16)__msa_ilvr_b(zero, (v16i8)sig0);
temp0_h += adjust0;
temp0_h = __msa_maxi_s_h(temp0_h, 0);
temp0_h = (v8i16)__msa_sat_u_h((v8u16)temp0_h, 7);
temp2_h = (v8i16)__msa_pckev_b((v16i8)temp2_h, (v16i8)temp2_h);
running_avg_y = (v16u8)__msa_pckev_b((v16i8)temp0_h, (v16i8)temp0_h);
running_avg_y =
__msa_bmnz_v(running_avg_y, mc_running_avg_y0, (v16u8)temp2_h);
dst0 = __msa_copy_s_d((v2i64)running_avg_y, 0);
SD(dst0, running_avg_y_ptr);
running_avg_y_ptr += avg_y_stride;
mask0 = __msa_ldi_h(0);
coeff0 = (v16u8)__msa_ilvr_b((v16i8)mc_running_avg_y1, (v16i8)sig1);
diff0 = __msa_hsub_u_h(coeff0, coeff0);
abs_diff0 = __msa_add_a_h(diff0, (v8i16)zero);
cmp = __msa_clei_s_h(abs_diff0, 15);
cmp = cmp & one;
mask0 += cmp;
cmp = __msa_clei_s_h(abs_diff0, 7);
cmp = cmp & one;
mask0 += cmp;
cmp = abs_diff0 < shift_inc1_vec;
cmp = cmp & one;
mask0 += cmp;
temp0_h = __msa_clei_s_h(diff0, 0);
temp0_h = temp0_h & four;
mask0 += temp0_h;
adjust0 = __msa_vshf_h(mask0, adj_val, adj_val);
temp2_h = __msa_ceqi_h(adjust0, 0);
adjust0 = (v8i16)__msa_bmnz_v((v16u8)adjust0, (v16u8)diff0, (v16u8)temp2_h);
col_sum0 += adjust0;
temp0_h = (v8i16)__msa_ilvr_b(zero, (v16i8)sig1);
temp0_h += adjust0;
temp0_h = __msa_maxi_s_h(temp0_h, 0);
temp0_h = (v8i16)__msa_sat_u_h((v8u16)temp0_h, 7);
temp2_h = (v8i16)__msa_pckev_b((v16i8)temp2_h, (v16i8)temp2_h);
running_avg_y = (v16u8)__msa_pckev_b((v16i8)temp0_h, (v16i8)temp0_h);
running_avg_y =
__msa_bmnz_v(running_avg_y, mc_running_avg_y1, (v16u8)temp2_h);
dst1 = __msa_copy_s_d((v2i64)running_avg_y, 0);
SD(dst1, running_avg_y_ptr);
sig_ptr += sig_stride;
mc_running_avg_y_ptr += mc_avg_y_stride;
running_avg_y_ptr += avg_y_stride;
}
temp0_h = col_sum0;
temp0_w = __msa_hadd_s_w(temp0_h, temp0_h);
temp0_d = __msa_hadd_s_d(temp0_w, temp0_w);
temp1_d = __msa_splati_d(temp0_d, 1);
temp0_d += temp1_d;
sum_diff = __msa_copy_s_w((v4i32)temp0_d, 0);
sig_ptr -= sig_stride * 8;
mc_running_avg_y_ptr -= mc_avg_y_stride * 8;
running_avg_y_ptr -= avg_y_stride * 8;
sum_diff_thresh = SUM_DIFF_THRESHOLD_UV;
if (increase_denoising) {
sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH_UV;
}
if (abs(sum_diff) > sum_diff_thresh) {
delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
delta_vec = __msa_fill_h(delta);
if (delta < 4) {
for (cnt = 4; cnt--;) {
running_avg_y = LD_UB(running_avg_y_ptr);
mc_running_avg_y0 = LD_UB(mc_running_avg_y_ptr);
sig0 = LD_UB(sig_ptr);
/* Update pointers for next iteration. */
sig_ptr += sig_stride;
mc_running_avg_y_ptr += mc_avg_y_stride;
running_avg_y_ptr += avg_y_stride;
mc_running_avg_y1 = LD_UB(mc_running_avg_y_ptr);
sig1 = LD_UB(sig_ptr);
running_avg_y1 = LD_UB(running_avg_y_ptr);
coeff0 = (v16u8)__msa_ilvr_b((v16i8)mc_running_avg_y0, (v16i8)sig0);
diff0 = __msa_hsub_u_h(coeff0, coeff0);
abs_diff0 = __msa_add_a_h(diff0, (v8i16)zero);
temp0_h = delta_vec < abs_diff0;
abs_diff0 = (v8i16)__msa_bmnz_v((v16u8)abs_diff0, (v16u8)delta_vec,
(v16u8)temp0_h);
abs_diff_neg0 = (v8i16)zero - abs_diff0;
temp0_h = __msa_clei_s_h(diff0, 0);
adjust0 = (v8i16)__msa_bmz_v((v16u8)abs_diff0, (v16u8)abs_diff_neg0,
(v16u8)temp0_h);
temp2_h = (v8i16)__msa_ilvr_b(zero, (v16i8)running_avg_y);
adjust2 = temp2_h + adjust0;
adjust2 = __msa_maxi_s_h(adjust2, 0);
adjust2 = (v8i16)__msa_sat_u_h((v8u16)adjust2, 7);
temp0_h = __msa_ceqi_h(diff0, 0);
adjust2 =
(v8i16)__msa_bmnz_v((v16u8)adjust2, (v16u8)temp2_h, (v16u8)temp0_h);
adjust0 =
(v8i16)__msa_bmnz_v((v16u8)adjust0, (v16u8)zero, (v16u8)temp0_h);
col_sum0 += adjust0;
running_avg_y = (v16u8)__msa_pckev_b((v16i8)adjust2, (v16i8)adjust2);
dst0 = __msa_copy_s_d((v2i64)running_avg_y, 0);
SD(dst0, running_avg_y_ptr - avg_y_stride);
coeff0 = (v16u8)__msa_ilvr_b((v16i8)mc_running_avg_y1, (v16i8)sig1);
diff0 = __msa_hsub_u_h(coeff0, coeff0);
abs_diff0 = __msa_add_a_h(diff0, (v8i16)zero);
temp0_h = delta_vec < abs_diff0;
abs_diff0 = (v8i16)__msa_bmnz_v((v16u8)abs_diff0, (v16u8)delta_vec,
(v16u8)temp0_h);
abs_diff_neg0 = (v8i16)zero - abs_diff0;
temp0_h = __msa_clei_s_h(diff0, 0);
adjust0 = (v8i16)__msa_bmz_v((v16u8)abs_diff0, (v16u8)abs_diff_neg0,
(v16u8)temp0_h);
temp2_h = (v8i16)__msa_ilvr_b(zero, (v16i8)running_avg_y1);
adjust2 = temp2_h + adjust0;
adjust2 = __msa_maxi_s_h(adjust2, 0);
adjust2 = (v8i16)__msa_sat_u_h((v8u16)adjust2, 7);
temp0_h = __msa_ceqi_h(diff0, 0);
adjust2 =
(v8i16)__msa_bmnz_v((v16u8)adjust2, (v16u8)temp2_h, (v16u8)temp0_h);
adjust0 =
(v8i16)__msa_bmnz_v((v16u8)adjust0, (v16u8)zero, (v16u8)temp0_h);
col_sum0 += adjust0;
running_avg_y = (v16u8)__msa_pckev_b((v16i8)adjust2, (v16i8)adjust2);
dst1 = __msa_copy_s_d((v2i64)running_avg_y, 0);
SD(dst1, running_avg_y_ptr);
running_avg_y_ptr += avg_y_stride;
}
temp0_h = col_sum0;
temp0_w = __msa_hadd_s_w(temp0_h, temp0_h);
temp0_d = __msa_hadd_s_d(temp0_w, temp0_w);
temp1_d = __msa_splati_d(temp0_d, 1);
temp0_d += temp1_d;
sum_diff = __msa_copy_s_w((v4i32)temp0_d, 0);
if (abs(sum_diff) > sum_diff_thresh) {
return COPY_BLOCK;
}
} else {
return COPY_BLOCK;
}
}
LD4(sig_start, sig_stride, src0, src1, src2, src3);
sig_start += (4 * sig_stride);
SD4(src0, src1, src2, src3, running_avg_y_start, avg_y_stride);
running_avg_y_start += (4 * avg_y_stride);
LD4(sig_start, sig_stride, src0, src1, src2, src3);
SD4(src0, src1, src2, src3, running_avg_y_start, avg_y_stride);
return FILTER_BLOCK;
}
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vp8_rtcd.h"
#include "vp8/common/mips/msa/vp8_macros_msa.h"
#include "vp8/encoder/block.h"
int32_t vp8_block_error_msa(int16_t *coeff_ptr, int16_t *dq_coeff_ptr) {
int32_t err = 0;
uint32_t loop_cnt;
v8i16 coeff, dq_coeff, coeff0, coeff1;
v4i32 diff0, diff1;
v2i64 err0 = { 0 };
v2i64 err1 = { 0 };
for (loop_cnt = 2; loop_cnt--;) {
coeff = LD_SH(coeff_ptr);
dq_coeff = LD_SH(dq_coeff_ptr);
ILVRL_H2_SH(coeff, dq_coeff, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
DPADD_SD2_SD(diff0, diff1, err0, err1);
coeff_ptr += 8;
dq_coeff_ptr += 8;
}
err0 += __msa_splati_d(err0, 1);
err1 += __msa_splati_d(err1, 1);
err = __msa_copy_s_d(err0, 0);
err += __msa_copy_s_d(err1, 0);
return err;
}
int32_t vp8_mbblock_error_msa(MACROBLOCK *mb, int32_t dc) {
BLOCK *be;
BLOCKD *bd;
int16_t *coeff_ptr, *dq_coeff_ptr;
int32_t err = 0;
uint32_t loop_cnt;
v8i16 coeff, coeff0, coeff1, coeff2, coeff3, coeff4;
v8i16 dq_coeff, dq_coeff2, dq_coeff3, dq_coeff4;
v4i32 diff0, diff1;
v2i64 err0, err1;
v16u8 zero = { 0 };
v16u8 mask0 = (v16u8)__msa_ldi_b(255);
if (1 == dc) {
mask0 = (v16u8)__msa_insve_w((v4i32)mask0, 0, (v4i32)zero);
}
for (loop_cnt = 0; loop_cnt < 8; ++loop_cnt) {
be = &mb->block[2 * loop_cnt];
bd = &mb->e_mbd.block[2 * loop_cnt];
coeff_ptr = be->coeff;
dq_coeff_ptr = bd->dqcoeff;
coeff = LD_SH(coeff_ptr);
dq_coeff = LD_SH(dq_coeff_ptr);
coeff_ptr += 8;
dq_coeff_ptr += 8;
coeff2 = LD_SH(coeff_ptr);
dq_coeff2 = LD_SH(dq_coeff_ptr);
be = &mb->block[2 * loop_cnt + 1];
bd = &mb->e_mbd.block[2 * loop_cnt + 1];
coeff_ptr = be->coeff;
dq_coeff_ptr = bd->dqcoeff;
coeff3 = LD_SH(coeff_ptr);
dq_coeff3 = LD_SH(dq_coeff_ptr);
coeff_ptr += 8;
dq_coeff_ptr += 8;
coeff4 = LD_SH(coeff_ptr);
dq_coeff4 = LD_SH(dq_coeff_ptr);
ILVRL_H2_SH(coeff, dq_coeff, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
diff0 = (v4i32)__msa_bmnz_v(zero, (v16u8)diff0, mask0);
DOTP_SW2_SD(diff0, diff1, diff0, diff1, err0, err1);
ILVRL_H2_SH(coeff2, dq_coeff2, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
DPADD_SD2_SD(diff0, diff1, err0, err1);
err0 += __msa_splati_d(err0, 1);
err1 += __msa_splati_d(err1, 1);
err += __msa_copy_s_d(err0, 0);
err += __msa_copy_s_d(err1, 0);
ILVRL_H2_SH(coeff3, dq_coeff3, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
diff0 = (v4i32)__msa_bmnz_v(zero, (v16u8)diff0, mask0);
DOTP_SW2_SD(diff0, diff1, diff0, diff1, err0, err1);
ILVRL_H2_SH(coeff4, dq_coeff4, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
DPADD_SD2_SD(diff0, diff1, err0, err1);
err0 += __msa_splati_d(err0, 1);
err1 += __msa_splati_d(err1, 1);
err += __msa_copy_s_d(err0, 0);
err += __msa_copy_s_d(err1, 0);
}
return err;
}
int32_t vp8_mbuverror_msa(MACROBLOCK *mb) {
BLOCK *be;
BLOCKD *bd;
int16_t *coeff_ptr, *dq_coeff_ptr;
int32_t err = 0;
uint32_t loop_cnt;
v8i16 coeff, coeff0, coeff1, coeff2, coeff3, coeff4;
v8i16 dq_coeff, dq_coeff2, dq_coeff3, dq_coeff4;
v4i32 diff0, diff1;
v2i64 err0, err1, err_dup0, err_dup1;
for (loop_cnt = 16; loop_cnt < 24; loop_cnt += 2) {
be = &mb->block[loop_cnt];
bd = &mb->e_mbd.block[loop_cnt];
coeff_ptr = be->coeff;
dq_coeff_ptr = bd->dqcoeff;
coeff = LD_SH(coeff_ptr);
dq_coeff = LD_SH(dq_coeff_ptr);
coeff_ptr += 8;
dq_coeff_ptr += 8;
coeff2 = LD_SH(coeff_ptr);
dq_coeff2 = LD_SH(dq_coeff_ptr);
be = &mb->block[loop_cnt + 1];
bd = &mb->e_mbd.block[loop_cnt + 1];
coeff_ptr = be->coeff;
dq_coeff_ptr = bd->dqcoeff;
coeff3 = LD_SH(coeff_ptr);
dq_coeff3 = LD_SH(dq_coeff_ptr);
coeff_ptr += 8;
dq_coeff_ptr += 8;
coeff4 = LD_SH(coeff_ptr);
dq_coeff4 = LD_SH(dq_coeff_ptr);
ILVRL_H2_SH(coeff, dq_coeff, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
DOTP_SW2_SD(diff0, diff1, diff0, diff1, err0, err1);
ILVRL_H2_SH(coeff2, dq_coeff2, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
DPADD_SD2_SD(diff0, diff1, err0, err1);
err_dup0 = __msa_splati_d(err0, 1);
err_dup1 = __msa_splati_d(err1, 1);
ADD2(err0, err_dup0, err1, err_dup1, err0, err1);
err += __msa_copy_s_d(err0, 0);
err += __msa_copy_s_d(err1, 0);
ILVRL_H2_SH(coeff3, dq_coeff3, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
DOTP_SW2_SD(diff0, diff1, diff0, diff1, err0, err1);
ILVRL_H2_SH(coeff4, dq_coeff4, coeff0, coeff1);
HSUB_UH2_SW(coeff0, coeff1, diff0, diff1);
DPADD_SD2_SD(diff0, diff1, err0, err1);
err_dup0 = __msa_splati_d(err0, 1);
err_dup1 = __msa_splati_d(err1, 1);
ADD2(err0, err_dup0, err1, err_dup1, err0, err1);
err += __msa_copy_s_d(err0, 0);
err += __msa_copy_s_d(err1, 0);
}
return err;
}
@@ -0,0 +1,211 @@
/*
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vp8_rtcd.h"
#include "vp8/common/mips/msa/vp8_macros_msa.h"
#include "vp8/encoder/block.h"
static int8_t fast_quantize_b_msa(int16_t *coeff_ptr, int16_t *round,
int16_t *quant, int16_t *de_quant,
int16_t *q_coeff, int16_t *dq_coeff) {
int32_t cnt, eob;
v16i8 inv_zig_zag = { 0, 1, 5, 6, 2, 4, 7, 12, 3, 8, 11, 13, 9, 10, 14, 15 };
v8i16 round0, round1;
v8i16 sign_z0, sign_z1;
v8i16 q_coeff0, q_coeff1;
v8i16 x0, x1, de_quant0, de_quant1;
v8i16 coeff0, coeff1, z0, z1;
v8i16 quant0, quant1, quant2, quant3;
v8i16 zero = { 0 };
v8i16 inv_zig_zag0, inv_zig_zag1;
v8i16 zigzag_mask0 = { 0, 1, 4, 8, 5, 2, 3, 6 };
v8i16 zigzag_mask1 = { 9, 12, 13, 10, 7, 11, 14, 15 };
v8i16 temp0_h, temp1_h, temp2_h, temp3_h;
v4i32 temp0_w, temp1_w, temp2_w, temp3_w;
ILVRL_B2_SH(zero, inv_zig_zag, inv_zig_zag0, inv_zig_zag1);
eob = -1;
LD_SH2(coeff_ptr, 8, coeff0, coeff1);
VSHF_H2_SH(coeff0, coeff1, coeff0, coeff1, zigzag_mask0, zigzag_mask1, z0,
z1);
LD_SH2(round, 8, coeff0, coeff1);
VSHF_H2_SH(coeff0, coeff1, coeff0, coeff1, zigzag_mask0, zigzag_mask1, round0,
round1);
LD_SH2(quant, 8, coeff0, coeff1);
VSHF_H2_SH(coeff0, coeff1, coeff0, coeff1, zigzag_mask0, zigzag_mask1, quant0,
quant2);
sign_z0 = z0 >> 15;
sign_z1 = z1 >> 15;
x0 = __msa_add_a_h(z0, zero);
x1 = __msa_add_a_h(z1, zero);
ILVL_H2_SH(quant0, quant0, quant2, quant2, quant1, quant3);
ILVR_H2_SH(quant0, quant0, quant2, quant2, quant0, quant2);
ILVL_H2_SH(round0, x0, round1, x1, temp1_h, temp3_h);
ILVR_H2_SH(round0, x0, round1, x1, temp0_h, temp2_h);
DOTP_SH4_SW(temp0_h, temp1_h, temp2_h, temp3_h, quant0, quant1, quant2,
quant3, temp0_w, temp1_w, temp2_w, temp3_w);
SRA_4V(temp0_w, temp1_w, temp2_w, temp3_w, 16);
PCKEV_H2_SH(temp1_w, temp0_w, temp3_w, temp2_w, x0, x1);
x0 = x0 ^ sign_z0;
x1 = x1 ^ sign_z1;
SUB2(x0, sign_z0, x1, sign_z1, x0, x1);
VSHF_H2_SH(x0, x1, x0, x1, inv_zig_zag0, inv_zig_zag1, q_coeff0, q_coeff1);
ST_SH2(q_coeff0, q_coeff1, q_coeff, 8);
LD_SH2(de_quant, 8, de_quant0, de_quant1);
q_coeff0 *= de_quant0;
q_coeff1 *= de_quant1;
ST_SH2(q_coeff0, q_coeff1, dq_coeff, 8);
for (cnt = 0; cnt < 16; ++cnt) {
if ((cnt <= 7) && (x1[7 - cnt] != 0)) {
eob = (15 - cnt);
break;
}
if ((cnt > 7) && (x0[7 - (cnt - 8)] != 0)) {
eob = (7 - (cnt - 8));
break;
}
}
return (int8_t)(eob + 1);
}
static int8_t exact_regular_quantize_b_msa(
int16_t *zbin_boost, int16_t *coeff_ptr, int16_t *zbin, int16_t *round,
int16_t *quant, int16_t *quant_shift, int16_t *de_quant, int16_t zbin_oq_in,
int16_t *q_coeff, int16_t *dq_coeff) {
int32_t cnt, eob;
int16_t *boost_temp = zbin_boost;
v16i8 inv_zig_zag = { 0, 1, 5, 6, 2, 4, 7, 12, 3, 8, 11, 13, 9, 10, 14, 15 };
v8i16 round0, round1;
v8i16 sign_z0, sign_z1;
v8i16 q_coeff0, q_coeff1;
v8i16 z_bin0, z_bin1, zbin_o_q;
v8i16 x0, x1, sign_x0, sign_x1, de_quant0, de_quant1;
v8i16 coeff0, coeff1, z0, z1;
v8i16 quant0, quant1, quant2, quant3;
v8i16 zero = { 0 };
v8i16 inv_zig_zag0, inv_zig_zag1;
v8i16 zigzag_mask0 = { 0, 1, 4, 8, 5, 2, 3, 6 };
v8i16 zigzag_mask1 = { 9, 12, 13, 10, 7, 11, 14, 15 };
v8i16 temp0_h, temp1_h, temp2_h, temp3_h;
v4i32 temp0_w, temp1_w, temp2_w, temp3_w;
ILVRL_B2_SH(zero, inv_zig_zag, inv_zig_zag0, inv_zig_zag1);
zbin_o_q = __msa_fill_h(zbin_oq_in);
eob = -1;
LD_SH2(coeff_ptr, 8, coeff0, coeff1);
VSHF_H2_SH(coeff0, coeff1, coeff0, coeff1, zigzag_mask0, zigzag_mask1, z0,
z1);
LD_SH2(round, 8, coeff0, coeff1);
VSHF_H2_SH(coeff0, coeff1, coeff0, coeff1, zigzag_mask0, zigzag_mask1, round0,
round1);
LD_SH2(quant, 8, coeff0, coeff1);
VSHF_H2_SH(coeff0, coeff1, coeff0, coeff1, zigzag_mask0, zigzag_mask1, quant0,
quant2);
LD_SH2(zbin, 8, coeff0, coeff1);
VSHF_H2_SH(coeff0, coeff1, coeff0, coeff1, zigzag_mask0, zigzag_mask1, z_bin0,
z_bin1);
sign_z0 = z0 >> 15;
sign_z1 = z1 >> 15;
x0 = __msa_add_a_h(z0, zero);
x1 = __msa_add_a_h(z1, zero);
SUB2(x0, z_bin0, x1, z_bin1, z_bin0, z_bin1);
SUB2(z_bin0, zbin_o_q, z_bin1, zbin_o_q, z_bin0, z_bin1);
ILVL_H2_SH(quant0, quant0, quant2, quant2, quant1, quant3);
ILVR_H2_SH(quant0, quant0, quant2, quant2, quant0, quant2);
ILVL_H2_SH(round0, x0, round1, x1, temp1_h, temp3_h);
ILVR_H2_SH(round0, x0, round1, x1, temp0_h, temp2_h);
DOTP_SH4_SW(temp0_h, temp1_h, temp2_h, temp3_h, quant0, quant1, quant2,
quant3, temp0_w, temp1_w, temp2_w, temp3_w);
SRA_4V(temp0_w, temp1_w, temp2_w, temp3_w, 16);
PCKEV_H2_SH(temp1_w, temp0_w, temp3_w, temp2_w, temp0_h, temp2_h);
LD_SH2(quant_shift, 8, coeff0, coeff1);
VSHF_H2_SH(coeff0, coeff1, coeff0, coeff1, zigzag_mask0, zigzag_mask1, quant0,
quant2);
ILVL_H2_SH(quant0, quant0, quant2, quant2, quant1, quant3);
ILVR_H2_SH(quant0, quant0, quant2, quant2, quant0, quant2);
ADD2(x0, round0, x1, round1, x0, x1);
ILVL_H2_SH(temp0_h, x0, temp2_h, x1, temp1_h, temp3_h);
ILVR_H2_SH(temp0_h, x0, temp2_h, x1, temp0_h, temp2_h);
DOTP_SH4_SW(temp0_h, temp1_h, temp2_h, temp3_h, quant0, quant1, quant2,
quant3, temp0_w, temp1_w, temp2_w, temp3_w);
SRA_4V(temp0_w, temp1_w, temp2_w, temp3_w, 16);
PCKEV_H2_SH(temp1_w, temp0_w, temp3_w, temp2_w, x0, x1);
sign_x0 = x0 ^ sign_z0;
sign_x1 = x1 ^ sign_z1;
SUB2(sign_x0, sign_z0, sign_x1, sign_z1, sign_x0, sign_x1);
for (cnt = 0; cnt < 16; ++cnt) {
if (cnt <= 7) {
if (boost_temp[0] <= z_bin0[cnt]) {
if (x0[cnt]) {
eob = cnt;
boost_temp = zbin_boost;
} else {
boost_temp++;
}
} else {
sign_x0[cnt] = 0;
boost_temp++;
}
} else {
if (boost_temp[0] <= z_bin1[cnt - 8]) {
if (x1[cnt - 8]) {
eob = cnt;
boost_temp = zbin_boost;
} else {
boost_temp++;
}
} else {
sign_x1[cnt - 8] = 0;
boost_temp++;
}
}
}
VSHF_H2_SH(sign_x0, sign_x1, sign_x0, sign_x1, inv_zig_zag0, inv_zig_zag1,
q_coeff0, q_coeff1);
ST_SH2(q_coeff0, q_coeff1, q_coeff, 8);
LD_SH2(de_quant, 8, de_quant0, de_quant1);
MUL2(de_quant0, q_coeff0, de_quant1, q_coeff1, de_quant0, de_quant1);
ST_SH2(de_quant0, de_quant1, dq_coeff, 8);
return (int8_t)(eob + 1);
}
void vp8_fast_quantize_b_msa(BLOCK *b, BLOCKD *d) {
int16_t *coeff_ptr = b->coeff;
int16_t *round_ptr = b->round;
int16_t *quant_ptr = b->quant_fast;
int16_t *qcoeff_ptr = d->qcoeff;
int16_t *dqcoeff_ptr = d->dqcoeff;
int16_t *dequant_ptr = d->dequant;
*d->eob = fast_quantize_b_msa(coeff_ptr, round_ptr, quant_ptr, dequant_ptr,
qcoeff_ptr, dqcoeff_ptr);
}
void vp8_regular_quantize_b_msa(BLOCK *b, BLOCKD *d) {
int16_t *zbin_boost_ptr = b->zrun_zbin_boost;
int16_t *coeff_ptr = b->coeff;
int16_t *zbin_ptr = b->zbin;
int16_t *round_ptr = b->round;
int16_t *quant_ptr = b->quant;
int16_t *quant_shift_ptr = b->quant_shift;
int16_t *qcoeff_ptr = d->qcoeff;
int16_t *dqcoeff_ptr = d->dqcoeff;
int16_t *dequant_ptr = d->dequant;
int16_t zbin_oq_value = b->zbin_extra;
*d->eob = exact_regular_quantize_b_msa(
zbin_boost_ptr, coeff_ptr, zbin_ptr, round_ptr, quant_ptr,
quant_shift_ptr, dequant_ptr, zbin_oq_value, qcoeff_ptr, dqcoeff_ptr);
}
@@ -0,0 +1,284 @@
/*
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vp8_rtcd.h"
#include "vp8/common/mips/msa/vp8_macros_msa.h"
static void temporal_filter_apply_16size_msa(
uint8_t *frame1_ptr, uint32_t stride, uint8_t *frame2_ptr,
int32_t strength_in, int32_t filter_wt_in, uint32_t *acc, uint16_t *cnt) {
uint32_t row;
v16i8 frame1_0_b, frame1_1_b, frame2_0_b, frame2_1_b;
v16u8 frame_l, frame_h;
v16i8 zero = { 0 };
v8i16 frame2_0_h, frame2_1_h, mod0_h, mod1_h;
v8i16 diff0, diff1, cnt0, cnt1;
v4i32 const3, const16, filter_wt, strength;
v4i32 mod0_w, mod1_w, mod2_w, mod3_w;
v4i32 diff0_r, diff0_l, diff1_r, diff1_l;
v4i32 frame2_0, frame2_1, frame2_2, frame2_3;
v4i32 acc0, acc1, acc2, acc3;
filter_wt = __msa_fill_w(filter_wt_in);
strength = __msa_fill_w(strength_in);
const3 = __msa_ldi_w(3);
const16 = __msa_ldi_w(16);
for (row = 8; row--;) {
frame1_0_b = LD_SB(frame1_ptr);
frame2_0_b = LD_SB(frame2_ptr);
frame1_ptr += stride;
frame2_ptr += 16;
frame1_1_b = LD_SB(frame1_ptr);
frame2_1_b = LD_SB(frame2_ptr);
LD_SW2(acc, 4, acc0, acc1);
LD_SW2(acc + 8, 4, acc2, acc3);
LD_SH2(cnt, 8, cnt0, cnt1);
ILVRL_B2_UB(frame1_0_b, frame2_0_b, frame_l, frame_h);
HSUB_UB2_SH(frame_l, frame_h, diff0, diff1);
UNPCK_SH_SW(diff0, diff0_r, diff0_l);
UNPCK_SH_SW(diff1, diff1_r, diff1_l);
MUL4(diff0_r, diff0_r, diff0_l, diff0_l, diff1_r, diff1_r, diff1_l, diff1_l,
mod0_w, mod1_w, mod2_w, mod3_w);
MUL4(mod0_w, const3, mod1_w, const3, mod2_w, const3, mod3_w, const3, mod0_w,
mod1_w, mod2_w, mod3_w);
SRAR_W4_SW(mod0_w, mod1_w, mod2_w, mod3_w, strength);
diff0_r = (mod0_w < const16);
diff0_l = (mod1_w < const16);
diff1_r = (mod2_w < const16);
diff1_l = (mod3_w < const16);
SUB4(const16, mod0_w, const16, mod1_w, const16, mod2_w, const16, mod3_w,
mod0_w, mod1_w, mod2_w, mod3_w);
mod0_w = diff0_r & mod0_w;
mod1_w = diff0_l & mod1_w;
mod2_w = diff1_r & mod2_w;
mod3_w = diff1_l & mod3_w;
MUL4(mod0_w, filter_wt, mod1_w, filter_wt, mod2_w, filter_wt, mod3_w,
filter_wt, mod0_w, mod1_w, mod2_w, mod3_w);
PCKEV_H2_SH(mod1_w, mod0_w, mod3_w, mod2_w, mod0_h, mod1_h)
ADD2(mod0_h, cnt0, mod1_h, cnt1, mod0_h, mod1_h);
ST_SH2(mod0_h, mod1_h, cnt, 8);
cnt += 16;
ILVRL_B2_SH(zero, frame2_0_b, frame2_0_h, frame2_1_h);
UNPCK_SH_SW(frame2_0_h, frame2_0, frame2_1);
UNPCK_SH_SW(frame2_1_h, frame2_2, frame2_3);
MUL4(mod0_w, frame2_0, mod1_w, frame2_1, mod2_w, frame2_2, mod3_w, frame2_3,
mod0_w, mod1_w, mod2_w, mod3_w);
ADD4(mod0_w, acc0, mod1_w, acc1, mod2_w, acc2, mod3_w, acc3, mod0_w, mod1_w,
mod2_w, mod3_w);
ST_SW2(mod0_w, mod1_w, acc, 4);
ST_SW2(mod2_w, mod3_w, acc + 8, 4);
acc += 16;
LD_SW2(acc, 4, acc0, acc1);
LD_SW2(acc + 8, 4, acc2, acc3);
LD_SH2(cnt, 8, cnt0, cnt1);
ILVRL_B2_UB(frame1_1_b, frame2_1_b, frame_l, frame_h);
HSUB_UB2_SH(frame_l, frame_h, diff0, diff1);
UNPCK_SH_SW(diff0, diff0_r, diff0_l);
UNPCK_SH_SW(diff1, diff1_r, diff1_l);
MUL4(diff0_r, diff0_r, diff0_l, diff0_l, diff1_r, diff1_r, diff1_l, diff1_l,
mod0_w, mod1_w, mod2_w, mod3_w);
MUL4(mod0_w, const3, mod1_w, const3, mod2_w, const3, mod3_w, const3, mod0_w,
mod1_w, mod2_w, mod3_w);
SRAR_W4_SW(mod0_w, mod1_w, mod2_w, mod3_w, strength);
diff0_r = (mod0_w < const16);
diff0_l = (mod1_w < const16);
diff1_r = (mod2_w < const16);
diff1_l = (mod3_w < const16);
SUB4(const16, mod0_w, const16, mod1_w, const16, mod2_w, const16, mod3_w,
mod0_w, mod1_w, mod2_w, mod3_w);
mod0_w = diff0_r & mod0_w;
mod1_w = diff0_l & mod1_w;
mod2_w = diff1_r & mod2_w;
mod3_w = diff1_l & mod3_w;
MUL4(mod0_w, filter_wt, mod1_w, filter_wt, mod2_w, filter_wt, mod3_w,
filter_wt, mod0_w, mod1_w, mod2_w, mod3_w);
PCKEV_H2_SH(mod1_w, mod0_w, mod3_w, mod2_w, mod0_h, mod1_h);
ADD2(mod0_h, cnt0, mod1_h, cnt1, mod0_h, mod1_h);
ST_SH2(mod0_h, mod1_h, cnt, 8);
cnt += 16;
UNPCK_UB_SH(frame2_1_b, frame2_0_h, frame2_1_h);
UNPCK_SH_SW(frame2_0_h, frame2_0, frame2_1);
UNPCK_SH_SW(frame2_1_h, frame2_2, frame2_3);
MUL4(mod0_w, frame2_0, mod1_w, frame2_1, mod2_w, frame2_2, mod3_w, frame2_3,
mod0_w, mod1_w, mod2_w, mod3_w);
ADD4(mod0_w, acc0, mod1_w, acc1, mod2_w, acc2, mod3_w, acc3, mod0_w, mod1_w,
mod2_w, mod3_w);
ST_SW2(mod0_w, mod1_w, acc, 4);
ST_SW2(mod2_w, mod3_w, acc + 8, 4);
acc += 16;
frame1_ptr += stride;
frame2_ptr += 16;
}
}
static void temporal_filter_apply_8size_msa(
uint8_t *frame1_ptr, uint32_t stride, uint8_t *frame2_ptr,
int32_t strength_in, int32_t filter_wt_in, uint32_t *acc, uint16_t *cnt) {
uint32_t row;
uint64_t f0, f1, f2, f3, f4, f5, f6, f7;
v16i8 frame1 = { 0 };
v16i8 frame2 = { 0 };
v16i8 frame3 = { 0 };
v16i8 frame4 = { 0 };
v16u8 frame_l, frame_h;
v8i16 frame2_0_h, frame2_1_h, mod0_h, mod1_h;
v8i16 diff0, diff1, cnt0, cnt1;
v4i32 const3, const16;
v4i32 filter_wt, strength;
v4i32 mod0_w, mod1_w, mod2_w, mod3_w;
v4i32 diff0_r, diff0_l, diff1_r, diff1_l;
v4i32 frame2_0, frame2_1, frame2_2, frame2_3;
v4i32 acc0, acc1, acc2, acc3;
filter_wt = __msa_fill_w(filter_wt_in);
strength = __msa_fill_w(strength_in);
const3 = __msa_ldi_w(3);
const16 = __msa_ldi_w(16);
for (row = 2; row--;) {
LD2(frame1_ptr, stride, f0, f1);
frame1_ptr += (2 * stride);
LD2(frame2_ptr, 8, f2, f3);
frame2_ptr += 16;
LD2(frame1_ptr, stride, f4, f5);
frame1_ptr += (2 * stride);
LD2(frame2_ptr, 8, f6, f7);
frame2_ptr += 16;
LD_SW2(acc, 4, acc0, acc1);
LD_SW2(acc + 8, 4, acc2, acc3);
LD_SH2(cnt, 8, cnt0, cnt1);
INSERT_D2_SB(f0, f1, frame1);
INSERT_D2_SB(f2, f3, frame2);
INSERT_D2_SB(f4, f5, frame3);
INSERT_D2_SB(f6, f7, frame4);
ILVRL_B2_UB(frame1, frame2, frame_l, frame_h);
HSUB_UB2_SH(frame_l, frame_h, diff0, diff1);
UNPCK_SH_SW(diff0, diff0_r, diff0_l);
UNPCK_SH_SW(diff1, diff1_r, diff1_l);
MUL4(diff0_r, diff0_r, diff0_l, diff0_l, diff1_r, diff1_r, diff1_l, diff1_l,
mod0_w, mod1_w, mod2_w, mod3_w);
MUL4(mod0_w, const3, mod1_w, const3, mod2_w, const3, mod3_w, const3, mod0_w,
mod1_w, mod2_w, mod3_w);
SRAR_W4_SW(mod0_w, mod1_w, mod2_w, mod3_w, strength);
diff0_r = (mod0_w < const16);
diff0_l = (mod1_w < const16);
diff1_r = (mod2_w < const16);
diff1_l = (mod3_w < const16);
SUB4(const16, mod0_w, const16, mod1_w, const16, mod2_w, const16, mod3_w,
mod0_w, mod1_w, mod2_w, mod3_w);
mod0_w = diff0_r & mod0_w;
mod1_w = diff0_l & mod1_w;
mod2_w = diff1_r & mod2_w;
mod3_w = diff1_l & mod3_w;
MUL4(mod0_w, filter_wt, mod1_w, filter_wt, mod2_w, filter_wt, mod3_w,
filter_wt, mod0_w, mod1_w, mod2_w, mod3_w);
PCKEV_H2_SH(mod1_w, mod0_w, mod3_w, mod2_w, mod0_h, mod1_h);
ADD2(mod0_h, cnt0, mod1_h, cnt1, mod0_h, mod1_h);
ST_SH2(mod0_h, mod1_h, cnt, 8);
cnt += 16;
UNPCK_UB_SH(frame2, frame2_0_h, frame2_1_h);
UNPCK_SH_SW(frame2_0_h, frame2_0, frame2_1);
UNPCK_SH_SW(frame2_1_h, frame2_2, frame2_3);
MUL4(mod0_w, frame2_0, mod1_w, frame2_1, mod2_w, frame2_2, mod3_w, frame2_3,
mod0_w, mod1_w, mod2_w, mod3_w);
ADD4(mod0_w, acc0, mod1_w, acc1, mod2_w, acc2, mod3_w, acc3, mod0_w, mod1_w,
mod2_w, mod3_w);
ST_SW2(mod0_w, mod1_w, acc, 4);
ST_SW2(mod2_w, mod3_w, acc + 8, 4);
acc += 16;
LD_SW2(acc, 4, acc0, acc1);
LD_SW2(acc + 8, 4, acc2, acc3);
LD_SH2(cnt, 8, cnt0, cnt1);
ILVRL_B2_UB(frame3, frame4, frame_l, frame_h);
HSUB_UB2_SH(frame_l, frame_h, diff0, diff1);
UNPCK_SH_SW(diff0, diff0_r, diff0_l);
UNPCK_SH_SW(diff1, diff1_r, diff1_l);
MUL4(diff0_r, diff0_r, diff0_l, diff0_l, diff1_r, diff1_r, diff1_l, diff1_l,
mod0_w, mod1_w, mod2_w, mod3_w);
MUL4(mod0_w, const3, mod1_w, const3, mod2_w, const3, mod3_w, const3, mod0_w,
mod1_w, mod2_w, mod3_w);
SRAR_W4_SW(mod0_w, mod1_w, mod2_w, mod3_w, strength);
diff0_r = (mod0_w < const16);
diff0_l = (mod1_w < const16);
diff1_r = (mod2_w < const16);
diff1_l = (mod3_w < const16);
SUB4(const16, mod0_w, const16, mod1_w, const16, mod2_w, const16, mod3_w,
mod0_w, mod1_w, mod2_w, mod3_w);
mod0_w = diff0_r & mod0_w;
mod1_w = diff0_l & mod1_w;
mod2_w = diff1_r & mod2_w;
mod3_w = diff1_l & mod3_w;
MUL4(mod0_w, filter_wt, mod1_w, filter_wt, mod2_w, filter_wt, mod3_w,
filter_wt, mod0_w, mod1_w, mod2_w, mod3_w);
PCKEV_H2_SH(mod1_w, mod0_w, mod3_w, mod2_w, mod0_h, mod1_h);
ADD2(mod0_h, cnt0, mod1_h, cnt1, mod0_h, mod1_h);
ST_SH2(mod0_h, mod1_h, cnt, 8);
cnt += 16;
UNPCK_UB_SH(frame4, frame2_0_h, frame2_1_h);
UNPCK_SH_SW(frame2_0_h, frame2_0, frame2_1);
UNPCK_SH_SW(frame2_1_h, frame2_2, frame2_3);
MUL4(mod0_w, frame2_0, mod1_w, frame2_1, mod2_w, frame2_2, mod3_w, frame2_3,
mod0_w, mod1_w, mod2_w, mod3_w);
ADD4(mod0_w, acc0, mod1_w, acc1, mod2_w, acc2, mod3_w, acc3, mod0_w, mod1_w,
mod2_w, mod3_w);
ST_SW2(mod0_w, mod1_w, acc, 4);
ST_SW2(mod2_w, mod3_w, acc + 8, 4);
acc += 16;
}
}
void vp8_temporal_filter_apply_msa(uint8_t *frame1, uint32_t stride,
uint8_t *frame2, uint32_t block_size,
int32_t strength, int32_t filter_weight,
uint32_t *accumulator, uint16_t *count) {
if (8 == block_size) {
temporal_filter_apply_8size_msa(frame1, stride, frame2, strength,
filter_weight, accumulator, count);
} else if (16 == block_size) {
temporal_filter_apply_16size_msa(frame1, stride, frame2, strength,
filter_weight, accumulator, count);
} else {
uint32_t i, j, k;
int32_t modifier;
int32_t byte = 0;
const int32_t rounding = strength > 0 ? 1 << (strength - 1) : 0;
for (i = 0, k = 0; i < block_size; ++i) {
for (j = 0; j < block_size; ++j, ++k) {
int src_byte = frame1[byte];
int pixel_value = *frame2++;
modifier = src_byte - pixel_value;
modifier *= modifier;
modifier *= 3;
modifier += rounding;
modifier >>= strength;
if (modifier > 16) modifier = 16;
modifier = 16 - modifier;
modifier *= filter_weight;
count[k] += modifier;
accumulator[k] += modifier * pixel_value;
byte++;
}
byte += stride - block_size;
}
}
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp8/common/blockd.h"
#include "modecosts.h"
#include "onyx_int.h"
#include "treewriter.h"
#include "vp8/common/entropymode.h"
void vp8_init_mode_costs(VP8_COMP *c) {
VP8_COMMON *x = &c->common;
struct rd_costs_struct *rd_costs = &c->rd_costs;
{
const vp8_tree_p T = vp8_bmode_tree;
int i = 0;
do {
int j = 0;
do {
vp8_cost_tokens(rd_costs->bmode_costs[i][j], vp8_kf_bmode_prob[i][j],
T);
} while (++j < VP8_BINTRAMODES);
} while (++i < VP8_BINTRAMODES);
vp8_cost_tokens(rd_costs->inter_bmode_costs, x->fc.bmode_prob, T);
}
vp8_cost_tokens(rd_costs->inter_bmode_costs, x->fc.sub_mv_ref_prob,
vp8_sub_mv_ref_tree);
vp8_cost_tokens(rd_costs->mbmode_cost[1], x->fc.ymode_prob, vp8_ymode_tree);
vp8_cost_tokens(rd_costs->mbmode_cost[0], vp8_kf_ymode_prob,
vp8_kf_ymode_tree);
vp8_cost_tokens(rd_costs->intra_uv_mode_cost[1], x->fc.uv_mode_prob,
vp8_uv_mode_tree);
vp8_cost_tokens(rd_costs->intra_uv_mode_cost[0], vp8_kf_uv_mode_prob,
vp8_uv_mode_tree);
}
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_MODECOSTS_H_
#define VPX_VP8_ENCODER_MODECOSTS_H_
#ifdef __cplusplus
extern "C" {
#endif
struct VP8_COMP;
void vp8_init_mode_costs(struct VP8_COMP *c);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_MODECOSTS_H_
@@ -0,0 +1,215 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <limits.h>
#include "vpx_config.h"
#include "onyx_int.h"
#include "mr_dissim.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_mem/vpx_mem.h"
#include "rdopt.h"
#include "vp8/common/common.h"
void vp8_cal_low_res_mb_cols(VP8_COMP *cpi) {
int low_res_w;
/* Support arbitrary down-sampling factor */
unsigned int iw = cpi->oxcf.Width * cpi->oxcf.mr_down_sampling_factor.den +
cpi->oxcf.mr_down_sampling_factor.num - 1;
low_res_w = iw / cpi->oxcf.mr_down_sampling_factor.num;
cpi->mr_low_res_mb_cols = ((low_res_w + 15) >> 4);
}
#define GET_MV(x) \
if (x->mbmi.ref_frame != INTRA_FRAME) { \
mvx[cnt] = x->mbmi.mv.as_mv.row; \
mvy[cnt] = x->mbmi.mv.as_mv.col; \
cnt++; \
}
#define GET_MV_SIGN(x) \
if (x->mbmi.ref_frame != INTRA_FRAME) { \
mvx[cnt] = x->mbmi.mv.as_mv.row; \
mvy[cnt] = x->mbmi.mv.as_mv.col; \
if (cm->ref_frame_sign_bias[x->mbmi.ref_frame] != \
cm->ref_frame_sign_bias[tmp->mbmi.ref_frame]) { \
mvx[cnt] *= -1; \
mvy[cnt] *= -1; \
} \
cnt++; \
}
void vp8_cal_dissimilarity(VP8_COMP *cpi) {
VP8_COMMON *cm = &cpi->common;
int i;
/* Note: The first row & first column in mip are outside the frame, which
* were initialized to all 0.(ref_frame, mode, mv...)
* Their ref_frame = 0 means they won't be counted in the following
* calculation.
*/
if (cpi->oxcf.mr_total_resolutions > 1 &&
cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) {
/* Store info for show/no-show frames for supporting alt_ref.
* If parent frame is alt_ref, child has one too.
*/
LOWER_RES_FRAME_INFO *store_info =
(LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info;
store_info->frame_type = cm->frame_type;
if (cm->frame_type != KEY_FRAME) {
store_info->is_frame_dropped = 0;
for (i = 1; i < MAX_REF_FRAMES; ++i)
store_info->low_res_ref_frames[i] = cpi->current_ref_frames[i];
}
if (cm->frame_type != KEY_FRAME) {
int mb_row;
int mb_col;
/* Point to beginning of allocated MODE_INFO arrays. */
MODE_INFO *tmp = cm->mip + cm->mode_info_stride;
LOWER_RES_MB_INFO *store_mode_info = store_info->mb_info;
for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
tmp++;
for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
int dissim = INT_MAX;
if (tmp->mbmi.ref_frame != INTRA_FRAME) {
int mvx[8];
int mvy[8];
int mmvx;
int mmvy;
int cnt = 0;
const MODE_INFO *here = tmp;
const MODE_INFO *above = here - cm->mode_info_stride;
const MODE_INFO *left = here - 1;
const MODE_INFO *aboveleft = above - 1;
const MODE_INFO *aboveright = NULL;
const MODE_INFO *right = NULL;
const MODE_INFO *belowleft = NULL;
const MODE_INFO *below = NULL;
const MODE_INFO *belowright = NULL;
/* If alternate reference frame is used, we have to
* check sign of MV. */
if (cpi->oxcf.play_alternate) {
/* Gather mv of neighboring MBs */
GET_MV_SIGN(above)
GET_MV_SIGN(left)
GET_MV_SIGN(aboveleft)
if (mb_col < (cm->mb_cols - 1)) {
right = here + 1;
aboveright = above + 1;
GET_MV_SIGN(right)
GET_MV_SIGN(aboveright)
}
if (mb_row < (cm->mb_rows - 1)) {
below = here + cm->mode_info_stride;
belowleft = below - 1;
GET_MV_SIGN(below)
GET_MV_SIGN(belowleft)
}
if (mb_col < (cm->mb_cols - 1) && mb_row < (cm->mb_rows - 1)) {
belowright = below + 1;
GET_MV_SIGN(belowright)
}
} else {
/* No alt_ref and gather mv of neighboring MBs */
GET_MV(above)
GET_MV(left)
GET_MV(aboveleft)
if (mb_col < (cm->mb_cols - 1)) {
right = here + 1;
aboveright = above + 1;
GET_MV(right)
GET_MV(aboveright)
}
if (mb_row < (cm->mb_rows - 1)) {
below = here + cm->mode_info_stride;
belowleft = below - 1;
GET_MV(below)
GET_MV(belowleft)
}
if (mb_col < (cm->mb_cols - 1) && mb_row < (cm->mb_rows - 1)) {
belowright = below + 1;
GET_MV(belowright)
}
}
if (cnt > 0) {
int max_mvx = mvx[0];
int min_mvx = mvx[0];
int max_mvy = mvy[0];
int min_mvy = mvy[0];
int i;
if (cnt > 1) {
for (i = 1; i < cnt; ++i) {
if (mvx[i] > max_mvx)
max_mvx = mvx[i];
else if (mvx[i] < min_mvx)
min_mvx = mvx[i];
if (mvy[i] > max_mvy)
max_mvy = mvy[i];
else if (mvy[i] < min_mvy)
min_mvy = mvy[i];
}
}
mmvx = VPXMAX(abs(min_mvx - here->mbmi.mv.as_mv.row),
abs(max_mvx - here->mbmi.mv.as_mv.row));
mmvy = VPXMAX(abs(min_mvy - here->mbmi.mv.as_mv.col),
abs(max_mvy - here->mbmi.mv.as_mv.col));
dissim = VPXMAX(mmvx, mmvy);
}
}
/* Store mode info for next resolution encoding */
store_mode_info->mode = tmp->mbmi.mode;
store_mode_info->ref_frame = tmp->mbmi.ref_frame;
store_mode_info->mv.as_int = tmp->mbmi.mv.as_int;
store_mode_info->dissim = dissim;
tmp++;
store_mode_info++;
}
}
}
}
}
/* This function is called only when this frame is dropped at current
resolution level. */
void vp8_store_drop_frame_info(VP8_COMP *cpi) {
/* If the frame is dropped in lower-resolution encoding, this information
is passed to higher resolution level so that the encoder knows there
is no mode & motion info available.
*/
if (cpi->oxcf.mr_total_resolutions > 1 &&
cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) {
/* Store info for show/no-show frames for supporting alt_ref.
* If parent frame is alt_ref, child has one too.
*/
LOWER_RES_FRAME_INFO *store_info =
(LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info;
/* Set frame_type to be INTER_FRAME since we won't drop key frame. */
store_info->frame_type = INTER_FRAME;
store_info->is_frame_dropped = 1;
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_MR_DISSIM_H_
#define VPX_VP8_ENCODER_MR_DISSIM_H_
#include "vpx_config.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void vp8_cal_low_res_mb_cols(VP8_COMP *cpi);
extern void vp8_cal_dissimilarity(VP8_COMP *cpi);
extern void vp8_store_drop_frame_info(VP8_COMP *cpi);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_MR_DISSIM_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,743 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_ONYX_INT_H_
#define VPX_VP8_ENCODER_ONYX_INT_H_
#include <stdio.h>
#include "vpx_config.h"
#include "vp8/common/onyx.h"
#include "treewriter.h"
#include "tokenize.h"
#include "vp8/common/onyxc_int.h"
#include "vpx_dsp/variance.h"
#include "encodemb.h"
#include "vp8/encoder/quantize.h"
#include "vp8/common/entropy.h"
#include "vp8/common/threading.h"
#include "vpx_ports/mem.h"
#include "vpx/internal/vpx_codec_internal.h"
#include "vpx/vp8.h"
#include "mcomp.h"
#include "vp8/common/findnearmv.h"
#include "lookahead.h"
#if CONFIG_TEMPORAL_DENOISING
#include "vp8/encoder/denoising.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define MIN_GF_INTERVAL 4
#define DEFAULT_GF_INTERVAL 7
#define KEY_FRAME_CONTEXT 5
#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY ? 1 : 25)
#define AF_THRESH 25
#define AF_THRESH2 100
#define ARF_DECAY_THRESH 12
#define MIN_THRESHMULT 32
#define MAX_THRESHMULT 512
#define GF_ZEROMV_ZBIN_BOOST 12
#define LF_ZEROMV_ZBIN_BOOST 6
#define MV_ZBIN_BOOST 4
#define ZBIN_OQ_MAX 192
#define VP8_TEMPORAL_ALT_REF !CONFIG_REALTIME_ONLY
/* vp8 uses 10,000,000 ticks/second as time stamp */
#define TICKS_PER_SEC 10000000
typedef struct {
int kf_indicated;
unsigned int frames_since_key;
unsigned int frames_since_golden;
int filter_level;
int frames_till_gf_update_due;
int recent_ref_frame_usage[MAX_REF_FRAMES];
MV_CONTEXT mvc[2];
int mvcosts[2][MVvals + 1];
#ifdef MODE_STATS
int y_modes[5];
int uv_modes[4];
int b_modes[10];
int inter_y_modes[10];
int inter_uv_modes[4];
int inter_b_modes[10];
#endif
vp8_prob ymode_prob[4], uv_mode_prob[3]; /* interframe intra mode probs */
vp8_prob kf_ymode_prob[4], kf_uv_mode_prob[3]; /* keyframe "" */
int ymode_count[5], uv_mode_count[4]; /* intra MB type cts this frame */
int count_mb_ref_frame_usage[MAX_REF_FRAMES];
int this_frame_percent_intra;
int last_frame_percent_intra;
} CODING_CONTEXT;
typedef struct {
double frame;
double intra_error;
double coded_error;
double ssim_weighted_pred_err;
double pcnt_inter;
double pcnt_motion;
double pcnt_second_ref;
double pcnt_neutral;
double MVr;
double mvr_abs;
double MVc;
double mvc_abs;
double MVrv;
double MVcv;
double mv_in_out_count;
double new_mv_count;
double duration;
double count;
} FIRSTPASS_STATS;
typedef struct {
int frames_so_far;
double frame_intra_error;
double frame_coded_error;
double frame_pcnt_inter;
double frame_pcnt_motion;
double frame_mvr;
double frame_mvr_abs;
double frame_mvc;
double frame_mvc_abs;
} ONEPASS_FRAMESTATS;
typedef enum {
THR_ZERO1 = 0,
THR_DC = 1,
THR_NEAREST1 = 2,
THR_NEAR1 = 3,
THR_ZERO2 = 4,
THR_NEAREST2 = 5,
THR_ZERO3 = 6,
THR_NEAREST3 = 7,
THR_NEAR2 = 8,
THR_NEAR3 = 9,
THR_V_PRED = 10,
THR_H_PRED = 11,
THR_TM = 12,
THR_NEW1 = 13,
THR_NEW2 = 14,
THR_NEW3 = 15,
THR_SPLIT1 = 16,
THR_SPLIT2 = 17,
THR_SPLIT3 = 18,
THR_B_PRED = 19
} THR_MODES;
typedef enum { DIAMOND = 0, NSTEP = 1, HEX = 2 } SEARCH_METHODS;
typedef struct {
int RD;
SEARCH_METHODS search_method;
int improved_quant;
int improved_dct;
int auto_filter;
int recode_loop;
int iterative_sub_pixel;
int half_pixel_search;
int quarter_pixel_search;
int thresh_mult[MAX_MODES];
int max_step_search_steps;
int first_step;
int optimize_coefficients;
int use_fastquant_for_pick;
int no_skip_block4x4_search;
int improved_mv_pred;
} SPEED_FEATURES;
typedef struct {
MACROBLOCK mb;
int segment_counts[MAX_MB_SEGMENTS];
int totalrate;
} MB_ROW_COMP;
typedef struct {
TOKENEXTRA *start;
TOKENEXTRA *stop;
} TOKENLIST;
typedef struct {
int ithread;
void *ptr1;
void *ptr2;
} ENCODETHREAD_DATA;
typedef struct {
int ithread;
void *ptr1;
} LPFTHREAD_DATA;
enum {
BLOCK_16X8,
BLOCK_8X16,
BLOCK_8X8,
BLOCK_4X4,
BLOCK_16X16,
BLOCK_MAX_SEGMENTS
};
typedef struct {
/* Layer configuration */
double framerate;
int target_bandwidth;
/* Layer specific coding parameters */
int64_t starting_buffer_level;
int64_t optimal_buffer_level;
int64_t maximum_buffer_size;
int64_t starting_buffer_level_in_ms;
int64_t optimal_buffer_level_in_ms;
int64_t maximum_buffer_size_in_ms;
int avg_frame_size_for_layer;
int64_t buffer_level;
int64_t bits_off_target;
int64_t total_actual_bits;
int total_target_vs_actual;
int worst_quality;
int active_worst_quality;
int best_quality;
int active_best_quality;
int ni_av_qi;
int ni_tot_qi;
int ni_frames;
int avg_frame_qindex;
double rate_correction_factor;
double key_frame_rate_correction_factor;
double gf_rate_correction_factor;
int zbin_over_quant;
int inter_frame_target;
int64_t total_byte_count;
int filter_level;
int frames_since_last_drop_overshoot;
int force_maxqp;
int last_frame_percent_intra;
int count_mb_ref_frame_usage[MAX_REF_FRAMES];
int last_q[2];
} LAYER_CONTEXT;
typedef struct VP8_COMP {
DECLARE_ALIGNED(16, short, Y1quant[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y1quant_shift[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y1zbin[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y1round[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y2quant[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y2quant_shift[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y2zbin[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y2round[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, UVquant[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, UVquant_shift[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, UVzbin[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, UVround[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, zrun_zbin_boost_y1[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, zrun_zbin_boost_y2[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, zrun_zbin_boost_uv[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y1quant_fast[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, Y2quant_fast[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, UVquant_fast[QINDEX_RANGE][16]);
MACROBLOCK mb;
VP8_COMMON common;
vp8_writer bc[9]; /* one boolcoder for each partition */
VP8_CONFIG oxcf;
struct lookahead_ctx *lookahead;
struct lookahead_entry *source;
struct lookahead_entry *alt_ref_source;
struct lookahead_entry *last_source;
YV12_BUFFER_CONFIG *Source;
YV12_BUFFER_CONFIG *un_scaled_source;
YV12_BUFFER_CONFIG scaled_source;
YV12_BUFFER_CONFIG *last_frame_unscaled_source;
unsigned int frames_till_alt_ref_frame;
/* frame in src_buffers has been identified to be encoded as an alt ref */
int source_alt_ref_pending;
/* an alt ref frame has been encoded and is usable */
int source_alt_ref_active;
/* source of frame to encode is an exact copy of an alt ref frame */
int is_src_frame_alt_ref;
/* golden frame same as last frame ( short circuit gold searches) */
int gold_is_last;
/* Alt reference frame same as last ( short circuit altref search) */
int alt_is_last;
/* don't do both alt and gold search ( just do gold). */
int gold_is_alt;
YV12_BUFFER_CONFIG pick_lf_lvl_frame;
TOKENEXTRA *tok;
unsigned int tok_count;
unsigned int frames_since_key;
unsigned int key_frame_frequency;
unsigned int this_key_frame_forced;
unsigned int next_key_frame_forced;
/* Ambient reconstruction err target for force key frames */
int ambient_err;
unsigned int mode_check_freq[MAX_MODES];
int rd_baseline_thresh[MAX_MODES];
int RDMULT;
int RDDIV;
CODING_CONTEXT coding_context;
/* Rate targetting variables */
int64_t last_prediction_error;
int64_t last_intra_error;
int this_frame_target;
int projected_frame_size;
int last_q[2]; /* Separate values for Intra/Inter */
double rate_correction_factor;
double key_frame_rate_correction_factor;
double gf_rate_correction_factor;
int frames_since_golden;
/* Count down till next GF */
int frames_till_gf_update_due;
/* GF interval chosen when we coded the last GF */
int current_gf_interval;
/* Total bits overspent becasue of GF boost (cumulative) */
int gf_overspend_bits;
/* Used in the few frames following a GF to recover the extra bits
* spent in that GF
*/
int non_gf_bitrate_adjustment;
/* Extra bits spent on key frames that need to be recovered */
int kf_overspend_bits;
/* Current number of bit s to try and recover on each inter frame. */
int kf_bitrate_adjustment;
int max_gf_interval;
int baseline_gf_interval;
int active_arnr_frames;
int64_t key_frame_count;
int prior_key_frame_distance[KEY_FRAME_CONTEXT];
/* Current section per frame bandwidth target */
int per_frame_bandwidth;
/* Average frame size target for clip */
int av_per_frame_bandwidth;
/* Minimum allocation that should be used for any frame */
int min_frame_bandwidth;
int inter_frame_target;
double output_framerate;
int64_t last_time_stamp_seen;
int64_t last_end_time_stamp_seen;
int64_t first_time_stamp_ever;
int ni_av_qi;
int ni_tot_qi;
int ni_frames;
int avg_frame_qindex;
int64_t total_byte_count;
int buffered_mode;
double framerate;
double ref_framerate;
int64_t buffer_level;
int64_t bits_off_target;
int rolling_target_bits;
int rolling_actual_bits;
int long_rolling_target_bits;
int long_rolling_actual_bits;
int64_t total_actual_bits;
int total_target_vs_actual; /* debug stats */
int worst_quality;
int active_worst_quality;
int best_quality;
int active_best_quality;
int cq_target_quality;
int drop_frames_allowed; /* Are we permitted to drop frames? */
int drop_frame; /* Drop this frame? */
#if defined(DROP_UNCODED_FRAMES)
int drop_frame_count;
#endif
vp8_prob frame_coef_probs[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS]
[ENTROPY_NODES];
char update_probs[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS][ENTROPY_NODES];
unsigned int frame_branch_ct[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS]
[ENTROPY_NODES][2];
int gfu_boost;
int kf_boost;
int last_boost;
int target_bandwidth;
struct vpx_codec_pkt_list *output_pkt_list;
#if 0
/* Experimental code for lagged and one pass */
ONEPASS_FRAMESTATS one_pass_frame_stats[MAX_LAG_BUFFERS];
int one_pass_frame_index;
#endif
int decimation_factor;
int decimation_count;
/* for real time encoding */
int avg_encode_time; /* microsecond */
int avg_pick_mode_time; /* microsecond */
int Speed;
int compressor_speed;
int auto_gold;
int auto_adjust_gold_quantizer;
int auto_worst_q;
int cpu_used;
int pass;
int prob_intra_coded;
int prob_last_coded;
int prob_gf_coded;
int prob_skip_false;
int last_skip_false_probs[3];
int last_skip_probs_q[3];
int recent_ref_frame_usage[MAX_REF_FRAMES];
int this_frame_percent_intra;
int last_frame_percent_intra;
int ref_frame_flags;
SPEED_FEATURES sf;
/* Count ZEROMV on all reference frames. */
int zeromv_count;
int lf_zeromv_pct;
unsigned char *skin_map;
unsigned char *segmentation_map;
signed char segment_feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
int segment_encode_breakout[MAX_MB_SEGMENTS];
unsigned char *active_map;
unsigned int active_map_enabled;
/* Video conferencing cyclic refresh mode flags. This is a mode
* designed to clean up the background over time in live encoding
* scenarious. It uses segmentation.
*/
int cyclic_refresh_mode_enabled;
int cyclic_refresh_mode_max_mbs_perframe;
int cyclic_refresh_mode_index;
int cyclic_refresh_q;
signed char *cyclic_refresh_map;
// Count on how many (consecutive) times a macroblock uses ZER0MV_LAST.
unsigned char *consec_zero_last;
// Counter that is reset when a block is checked for a mode-bias against
// ZEROMV_LASTREF.
unsigned char *consec_zero_last_mvbias;
// Frame counter for the temporal pattern. Counter is rest when the temporal
// layers are changed dynamically (run-time change).
unsigned int temporal_pattern_counter;
// Temporal layer id.
int temporal_layer_id;
// Measure of average squared difference between source and denoised signal.
int mse_source_denoised;
int force_maxqp;
int frames_since_last_drop_overshoot;
int last_pred_err_mb;
// GF update for 1 pass cbr.
int gf_update_onepass_cbr;
int gf_interval_onepass_cbr;
int gf_noboost_onepass_cbr;
#if CONFIG_MULTITHREAD
/* multithread data */
vpx_atomic_int *mt_current_mb_col;
int mt_sync_range;
vpx_atomic_int b_multi_threaded;
int encoding_thread_count;
int b_lpf_running;
pthread_t *h_encoding_thread;
pthread_t h_filter_thread;
MB_ROW_COMP *mb_row_ei;
ENCODETHREAD_DATA *en_thread_data;
LPFTHREAD_DATA lpf_thread_data;
/* events */
sem_t *h_event_start_encoding;
sem_t *h_event_end_encoding;
sem_t h_event_start_lpf;
sem_t h_event_end_lpf;
#endif
TOKENLIST *tplist;
unsigned int partition_sz[MAX_PARTITIONS];
unsigned char *partition_d[MAX_PARTITIONS];
unsigned char *partition_d_end[MAX_PARTITIONS];
fractional_mv_step_fp *find_fractional_mv_step;
vp8_full_search_fn_t full_search_sad;
vp8_refining_search_fn_t refining_search_sad;
vp8_diamond_search_fn_t diamond_search_sad;
vp8_variance_fn_ptr_t fn_ptr[BLOCK_MAX_SEGMENTS];
uint64_t time_receive_data;
uint64_t time_compress_data;
uint64_t time_pick_lpf;
uint64_t time_encode_mb_row;
int base_skip_false_prob[128];
FRAME_CONTEXT lfc_n; /* last frame entropy */
FRAME_CONTEXT lfc_a; /* last alt ref entropy */
FRAME_CONTEXT lfc_g; /* last gold ref entropy */
struct twopass_rc {
unsigned int section_intra_rating;
double section_max_qfactor;
unsigned int next_iiratio;
unsigned int this_iiratio;
FIRSTPASS_STATS total_stats;
FIRSTPASS_STATS this_frame_stats;
FIRSTPASS_STATS *stats_in, *stats_in_end, *stats_in_start;
FIRSTPASS_STATS total_left_stats;
int first_pass_done;
int64_t bits_left;
int64_t clip_bits_total;
double avg_iiratio;
double modified_error_total;
double modified_error_used;
double modified_error_left;
double kf_intra_err_min;
double gf_intra_err_min;
int frames_to_key;
int maxq_max_limit;
int maxq_min_limit;
int gf_decay_rate;
int static_scene_max_gf_interval;
int kf_bits;
/* Remaining error from uncoded frames in a gf group. */
int gf_group_error_left;
/* Projected total bits available for a key frame group of frames */
int64_t kf_group_bits;
/* Error score of frames still to be coded in kf group */
int64_t kf_group_error_left;
/* Projected Bits available for a group including 1 GF or ARF */
int64_t gf_group_bits;
/* Bits for the golden frame or ARF */
int gf_bits;
int alt_extra_bits;
double est_max_qcorrection_factor;
} twopass;
#if VP8_TEMPORAL_ALT_REF
YV12_BUFFER_CONFIG alt_ref_buffer;
YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS];
int fixed_divide[512];
#endif
#if CONFIG_INTERNAL_STATS
int count;
double total_y;
double total_u;
double total_v;
double total;
double total_sq_error;
double totalp_y;
double totalp_u;
double totalp_v;
double totalp;
double total_sq_error2;
int bytes;
double summed_quality;
double summed_weights;
unsigned int tot_recode_hits;
int b_calculate_ssimg;
#endif
int b_calculate_psnr;
/* Per MB activity measurement */
unsigned int activity_avg;
unsigned int *mb_activity_map;
/* Record of which MBs still refer to last golden frame either
* directly or through 0,0
*/
unsigned char *gf_active_flags;
int gf_active_count;
int output_partition;
/* Store last frame's MV info for next frame MV prediction */
int_mv *lfmv;
int *lf_ref_frame_sign_bias;
int *lf_ref_frame;
/* force next frame to intra when kf_auto says so */
int force_next_frame_intra;
int droppable;
int initial_width;
int initial_height;
#if CONFIG_TEMPORAL_DENOISING
VP8_DENOISER denoiser;
#endif
/* Coding layer state variables */
unsigned int current_layer;
LAYER_CONTEXT layer_context[VPX_TS_MAX_LAYERS];
int64_t frames_in_layer[VPX_TS_MAX_LAYERS];
int64_t bytes_in_layer[VPX_TS_MAX_LAYERS];
double sum_psnr[VPX_TS_MAX_LAYERS];
double sum_psnr_p[VPX_TS_MAX_LAYERS];
double total_error2[VPX_TS_MAX_LAYERS];
double total_error2_p[VPX_TS_MAX_LAYERS];
double sum_ssim[VPX_TS_MAX_LAYERS];
double sum_weights[VPX_TS_MAX_LAYERS];
double total_ssimg_y_in_layer[VPX_TS_MAX_LAYERS];
double total_ssimg_u_in_layer[VPX_TS_MAX_LAYERS];
double total_ssimg_v_in_layer[VPX_TS_MAX_LAYERS];
double total_ssimg_all_in_layer[VPX_TS_MAX_LAYERS];
#if CONFIG_MULTI_RES_ENCODING
/* Number of MBs per row at lower-resolution level */
int mr_low_res_mb_cols;
/* Indicate if lower-res mv info is available */
unsigned char mr_low_res_mv_avail;
#endif
/* The frame number of each reference frames */
unsigned int current_ref_frames[MAX_REF_FRAMES];
// Closest reference frame to current frame.
MV_REFERENCE_FRAME closest_reference_frame;
struct rd_costs_struct {
int mvcosts[2][MVvals + 1];
int mvsadcosts[2][MVfpvals + 1];
int mbmode_cost[2][MB_MODE_COUNT];
int intra_uv_mode_cost[2][MB_MODE_COUNT];
int bmode_costs[10][10][10];
int inter_bmode_costs[B_MODE_COUNT];
int token_costs[BLOCK_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS]
[MAX_ENTROPY_TOKENS];
} rd_costs;
// Use the static threshold from ROI settings.
int use_roi_static_threshold;
int ext_refresh_frame_flags_pending;
} VP8_COMP;
void vp8_initialize_enc(void);
void vp8_alloc_compressor_data(VP8_COMP *cpi);
int vp8_reverse_trans(int x);
void vp8_new_framerate(VP8_COMP *cpi, double framerate);
void vp8_loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm);
void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest,
unsigned char *dest_end, size_t *size);
void vp8_tokenize_mb(VP8_COMP *, MACROBLOCK *, TOKENEXTRA **);
void vp8_set_speed_features(VP8_COMP *cpi);
#if CONFIG_DEBUG
#define CHECK_MEM_ERROR(lval, expr) \
do { \
(lval) = (expr); \
if (!(lval)) \
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, \
"Failed to allocate " #lval " at %s:%d", __FILE__, \
__LINE__); \
} while (0)
#else
#define CHECK_MEM_ERROR(lval, expr) \
do { \
(lval) = (expr); \
if (!(lval)) \
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, \
"Failed to allocate " #lval); \
} while (0)
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_ONYX_INT_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_PICKINTER_H_
#define VPX_VP8_ENCODER_PICKINTER_H_
#include "vpx_config.h"
#include "vp8/common/onyxc_int.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
int recon_uvoffset, int *returnrate,
int *returndistortion, int *returnintra,
int mb_row, int mb_col);
extern void vp8_pick_intra_mode(MACROBLOCK *x, int *rate);
extern int vp8_get_inter_mbpred_error(MACROBLOCK *mb,
const vp8_variance_fn_ptr_t *vfp,
unsigned int *sse, int_mv this_mv);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_PICKINTER_H_
@@ -0,0 +1,392 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "./vpx_dsp_rtcd.h"
#include "./vpx_scale_rtcd.h"
#include "vp8/common/onyxc_int.h"
#include "onyx_int.h"
#include "vp8/encoder/picklpf.h"
#include "vp8/encoder/quantize.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_scale/vpx_scale.h"
#include "vp8/common/alloccommon.h"
#include "vp8/common/loopfilter.h"
#if VPX_ARCH_ARM
#include "vpx_ports/arm.h"
#endif
extern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source,
YV12_BUFFER_CONFIG *dest);
static void yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc,
YV12_BUFFER_CONFIG *dst_ybc) {
unsigned char *src_y, *dst_y;
int yheight;
int ystride;
int yoffset;
int linestocopy;
yheight = src_ybc->y_height;
ystride = src_ybc->y_stride;
/* number of MB rows to use in partial filtering */
linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION;
linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
/* Copy extra 4 so that full filter context is available if filtering done
* on the copied partial frame and not original. Partial filter does mb
* filtering for top row also, which can modify3 pixels above.
*/
linestocopy += 4;
/* partial image starts at ~middle of frame (macroblock border)*/
yoffset = ystride * (((yheight >> 5) * 16) - 4);
src_y = src_ybc->y_buffer + yoffset;
dst_y = dst_ybc->y_buffer + yoffset;
memcpy(dst_y, src_y, ystride * linestocopy);
}
static int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source,
YV12_BUFFER_CONFIG *dest) {
int i, j;
int Total = 0;
int srcoffset, dstoffset;
unsigned char *src = source->y_buffer;
unsigned char *dst = dest->y_buffer;
int linestocopy;
/* number of MB rows to use in partial filtering */
linestocopy = (source->y_height >> 4) / PARTIAL_FRAME_FRACTION;
linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
/* partial image starts at ~middle of frame (macroblock border)*/
srcoffset = source->y_stride * ((dest->y_height >> 5) * 16);
dstoffset = dest->y_stride * ((dest->y_height >> 5) * 16);
src += srcoffset;
dst += dstoffset;
/* Loop through the Y plane raw and reconstruction data summing
* (square differences)
*/
for (i = 0; i < linestocopy; i += 16) {
for (j = 0; j < source->y_width; j += 16) {
unsigned int sse;
Total += vpx_mse16x16(src + j, source->y_stride, dst + j, dest->y_stride,
&sse);
}
src += 16 * source->y_stride;
dst += 16 * dest->y_stride;
}
return Total;
}
/* Enforce a minimum filter level based upon baseline Q */
static int get_min_filter_level(VP8_COMP *cpi, int base_qindex) {
int min_filter_level;
if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame &&
!cpi->common.refresh_alt_ref_frame) {
min_filter_level = 0;
} else {
if (base_qindex <= 6) {
min_filter_level = 0;
} else if (base_qindex <= 16) {
min_filter_level = 1;
} else {
min_filter_level = (base_qindex / 8);
}
}
return min_filter_level;
}
/* Enforce a maximum filter level based upon baseline Q */
static int get_max_filter_level(VP8_COMP *cpi, int base_qindex) {
/* PGW August 2006: Highest filter values almost always a bad idea */
/* jbb chg: 20100118 - not so any more with this overquant stuff allow
* high values with lots of intra coming in.
*/
int max_filter_level = MAX_LOOP_FILTER;
(void)base_qindex;
if (cpi->twopass.section_intra_rating > 8) {
max_filter_level = MAX_LOOP_FILTER * 3 / 4;
}
return max_filter_level;
}
void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) {
VP8_COMMON *cm = &cpi->common;
int best_err = 0;
int filt_err = 0;
int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
int filt_val;
int best_filt_val;
YV12_BUFFER_CONFIG *saved_frame = cm->frame_to_show;
/* Replace unfiltered frame buffer with a new one */
cm->frame_to_show = &cpi->pick_lf_lvl_frame;
if (cm->frame_type == KEY_FRAME) {
cm->sharpness_level = 0;
} else {
cm->sharpness_level = cpi->oxcf.Sharpness;
}
if (cm->sharpness_level != cm->last_sharpness_level) {
vp8_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level);
cm->last_sharpness_level = cm->sharpness_level;
}
/* Start the search at the previous frame filter level unless it is
* now out of range.
*/
if (cm->filter_level < min_filter_level) {
cm->filter_level = min_filter_level;
} else if (cm->filter_level > max_filter_level) {
cm->filter_level = max_filter_level;
}
filt_val = cm->filter_level;
best_filt_val = filt_val;
/* Get the err using the previous frame's filter value. */
/* Copy the unfiltered / processed recon buffer to the new buffer */
yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
best_err = calc_partial_ssl_err(sd, cm->frame_to_show);
filt_val -= 1 + (filt_val > 10);
/* Search lower filter levels */
while (filt_val >= min_filter_level) {
/* Apply the loop filter */
yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
/* Get the err for filtered frame */
filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
/* Update the best case record or exit loop. */
if (filt_err < best_err) {
best_err = filt_err;
best_filt_val = filt_val;
} else {
break;
}
/* Adjust filter level */
filt_val -= 1 + (filt_val > 10);
}
/* Search up (note that we have already done filt_val = cm->filter_level) */
filt_val = cm->filter_level + 1 + (filt_val > 10);
if (best_filt_val == cm->filter_level) {
/* Resist raising filter level for very small gains */
best_err -= (best_err >> 10);
while (filt_val < max_filter_level) {
/* Apply the loop filter */
yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
/* Get the err for filtered frame */
filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
/* Update the best case record or exit loop. */
if (filt_err < best_err) {
/* Do not raise filter level if improvement is < 1 part
* in 4096
*/
best_err = filt_err - (filt_err >> 10);
best_filt_val = filt_val;
} else {
break;
}
/* Adjust filter level */
filt_val += 1 + (filt_val > 10);
}
}
cm->filter_level = best_filt_val;
if (cm->filter_level < min_filter_level) cm->filter_level = min_filter_level;
if (cm->filter_level > max_filter_level) cm->filter_level = max_filter_level;
/* restore unfiltered frame pointer */
cm->frame_to_show = saved_frame;
}
/* Stub function for now Alt LF not used */
void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val) {
MACROBLOCKD *mbd = &cpi->mb.e_mbd;
(void)filt_val;
mbd->segment_feature_data[MB_LVL_ALT_LF][0] =
cpi->segment_feature_data[MB_LVL_ALT_LF][0];
mbd->segment_feature_data[MB_LVL_ALT_LF][1] =
cpi->segment_feature_data[MB_LVL_ALT_LF][1];
mbd->segment_feature_data[MB_LVL_ALT_LF][2] =
cpi->segment_feature_data[MB_LVL_ALT_LF][2];
mbd->segment_feature_data[MB_LVL_ALT_LF][3] =
cpi->segment_feature_data[MB_LVL_ALT_LF][3];
}
void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) {
VP8_COMMON *cm = &cpi->common;
int best_err = 0;
int filt_err = 0;
int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
int filter_step;
int filt_high = 0;
int filt_mid;
int filt_low = 0;
int filt_best;
int filt_direction = 0;
/* Bias against raising loop filter and in favor of lowering it */
int Bias = 0;
int ss_err[MAX_LOOP_FILTER + 1];
YV12_BUFFER_CONFIG *saved_frame = cm->frame_to_show;
memset(ss_err, 0, sizeof(ss_err));
/* Replace unfiltered frame buffer with a new one */
cm->frame_to_show = &cpi->pick_lf_lvl_frame;
if (cm->frame_type == KEY_FRAME) {
cm->sharpness_level = 0;
} else {
cm->sharpness_level = cpi->oxcf.Sharpness;
}
/* Start the search at the previous frame filter level unless it is
* now out of range.
*/
filt_mid = cm->filter_level;
if (filt_mid < min_filter_level) {
filt_mid = min_filter_level;
} else if (filt_mid > max_filter_level) {
filt_mid = max_filter_level;
}
/* Define the initial step size */
filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
/* Get baseline error score */
/* Copy the unfiltered / processed recon buffer to the new buffer */
vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
vp8cx_set_alt_lf_level(cpi, filt_mid);
vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
best_err = vp8_calc_ss_err(sd, cm->frame_to_show);
ss_err[filt_mid] = best_err;
filt_best = filt_mid;
while (filter_step > 0) {
Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step;
if (cpi->twopass.section_intra_rating < 20) {
Bias = Bias * cpi->twopass.section_intra_rating / 20;
}
filt_high = ((filt_mid + filter_step) > max_filter_level)
? max_filter_level
: (filt_mid + filter_step);
filt_low = ((filt_mid - filter_step) < min_filter_level)
? min_filter_level
: (filt_mid - filter_step);
if ((filt_direction <= 0) && (filt_low != filt_mid)) {
if (ss_err[filt_low] == 0) {
/* Get Low filter error score */
vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
vp8cx_set_alt_lf_level(cpi, filt_low);
vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
ss_err[filt_low] = filt_err;
} else {
filt_err = ss_err[filt_low];
}
/* If value is close to the best so far then bias towards a
* lower loop filter value.
*/
if ((filt_err - Bias) < best_err) {
/* Was it actually better than the previous best? */
if (filt_err < best_err) best_err = filt_err;
filt_best = filt_low;
}
}
/* Now look at filt_high */
if ((filt_direction >= 0) && (filt_high != filt_mid)) {
if (ss_err[filt_high] == 0) {
vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
vp8cx_set_alt_lf_level(cpi, filt_high);
vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
ss_err[filt_high] = filt_err;
} else {
filt_err = ss_err[filt_high];
}
/* Was it better than the previous best? */
if (filt_err < (best_err - Bias)) {
best_err = filt_err;
filt_best = filt_high;
}
}
/* Half the step distance if the best filter value was the same
* as last time
*/
if (filt_best == filt_mid) {
filter_step = filter_step / 2;
filt_direction = 0;
} else {
filt_direction = (filt_best < filt_mid) ? -1 : 1;
filt_mid = filt_best;
}
}
cm->filter_level = filt_best;
/* restore unfiltered frame pointer */
cm->frame_to_show = saved_frame;
}
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2017 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_PICKLPF_H_
#define VPX_VP8_ENCODER_PICKLPF_H_
#ifdef __cplusplus
extern "C" {
#endif
struct VP8_COMP;
struct yv12_buffer_config;
void vp8cx_pick_filter_level_fast(struct yv12_buffer_config *sd,
struct VP8_COMP *cpi);
void vp8cx_set_alt_lf_level(struct VP8_COMP *cpi, int filt_val);
void vp8cx_pick_filter_level(struct yv12_buffer_config *sd, VP8_COMP *cpi);
#ifdef __cplusplus
}
#endif
#endif // VPX_VP8_ENCODER_PICKLPF_H_
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_QUANTIZE_H_
#define VPX_VP8_ENCODER_QUANTIZE_H_
#ifdef __cplusplus
extern "C" {
#endif
struct VP8_COMP;
struct macroblock;
extern void vp8_quantize_mb(struct macroblock *x);
extern void vp8_quantize_mby(struct macroblock *x);
extern void vp8_quantize_mbuv(struct macroblock *x);
extern void vp8_set_quantizer(struct VP8_COMP *cpi, int Q);
extern void vp8cx_frame_init_quantizer(struct VP8_COMP *cpi);
extern void vp8_update_zbin_extra(struct VP8_COMP *cpi, struct macroblock *x);
extern void vp8cx_mb_init_quantizer(struct VP8_COMP *cpi, struct macroblock *x,
int ok_to_skip);
extern void vp8cx_init_quantizer(struct VP8_COMP *cpi);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_QUANTIZE_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_RATECTRL_H_
#define VPX_VP8_ENCODER_RATECTRL_H_
#include "onyx_int.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void vp8_save_coding_context(VP8_COMP *cpi);
extern void vp8_restore_coding_context(VP8_COMP *cpi);
extern void vp8_setup_key_frame(VP8_COMP *cpi);
extern void vp8_update_rate_correction_factors(VP8_COMP *cpi, int damp_var);
extern int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame);
extern void vp8_adjust_key_frame_context(VP8_COMP *cpi);
extern void vp8_compute_frame_size_bounds(VP8_COMP *cpi,
int *frame_under_shoot_limit,
int *frame_over_shoot_limit);
/* return of 0 means drop frame */
extern int vp8_pick_frame_size(VP8_COMP *cpi);
extern int vp8_drop_encodedframe_overshoot(VP8_COMP *cpi, int Q);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_RATECTRL_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_RDOPT_H_
#define VPX_VP8_ENCODER_RDOPT_H_
#include "./vpx_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#define RDCOST(RM, DM, R, D) (((128 + (R) * (RM)) >> 8) + (DM) * (D))
void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex);
void vp8_auto_select_speed(VP8_COMP *cpi);
static INLINE void insertsortmv(int arr[], int len) {
int i, j, k;
for (i = 1; i <= len - 1; ++i) {
for (j = 0; j < i; ++j) {
if (arr[j] > arr[i]) {
int temp;
temp = arr[i];
for (k = i; k > j; k--) arr[k] = arr[k - 1];
arr[j] = temp;
}
}
}
}
static INLINE void insertsortsad(int arr[], int idx[], int len) {
int i, j, k;
for (i = 1; i <= len - 1; ++i) {
for (j = 0; j < i; ++j) {
if (arr[j] > arr[i]) {
int temp, tempi;
temp = arr[i];
tempi = idx[i];
for (k = i; k > j; k--) {
arr[k] = arr[k - 1];
idx[k] = idx[k - 1];
}
arr[j] = temp;
idx[j] = tempi;
}
}
}
}
void vp8_initialize_rd_consts(VP8_COMP *cpi, MACROBLOCK *x, int Qvalue);
void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
int recon_uvoffset, int *returnrate,
int *returndistortion, int *returnintra, int mb_row,
int mb_col);
void vp8_rd_pick_intra_mode(MACROBLOCK *x, int *rate);
static INLINE void get_plane_pointers(const YV12_BUFFER_CONFIG *fb,
unsigned char *plane[3],
unsigned int recon_yoffset,
unsigned int recon_uvoffset) {
plane[0] = fb->y_buffer + recon_yoffset;
plane[1] = fb->u_buffer + recon_uvoffset;
plane[2] = fb->v_buffer + recon_uvoffset;
}
static INLINE void get_predictor_pointers(const VP8_COMP *cpi,
unsigned char *plane[4][3],
unsigned int recon_yoffset,
unsigned int recon_uvoffset) {
if (cpi->ref_frame_flags & VP8_LAST_FRAME) {
get_plane_pointers(&cpi->common.yv12_fb[cpi->common.lst_fb_idx],
plane[LAST_FRAME], recon_yoffset, recon_uvoffset);
}
if (cpi->ref_frame_flags & VP8_GOLD_FRAME) {
get_plane_pointers(&cpi->common.yv12_fb[cpi->common.gld_fb_idx],
plane[GOLDEN_FRAME], recon_yoffset, recon_uvoffset);
}
if (cpi->ref_frame_flags & VP8_ALTR_FRAME) {
get_plane_pointers(&cpi->common.yv12_fb[cpi->common.alt_fb_idx],
plane[ALTREF_FRAME], recon_yoffset, recon_uvoffset);
}
}
static INLINE void get_reference_search_order(const VP8_COMP *cpi,
int ref_frame_map[4]) {
int i = 0;
ref_frame_map[i++] = INTRA_FRAME;
if (cpi->ref_frame_flags & VP8_LAST_FRAME) ref_frame_map[i++] = LAST_FRAME;
if (cpi->ref_frame_flags & VP8_GOLD_FRAME) ref_frame_map[i++] = GOLDEN_FRAME;
if (cpi->ref_frame_flags & VP8_ALTR_FRAME) ref_frame_map[i++] = ALTREF_FRAME;
for (; i < 4; ++i) ref_frame_map[i] = -1;
}
void vp8_mv_pred(VP8_COMP *cpi, MACROBLOCKD *xd, const MODE_INFO *here,
int_mv *mvp, int refframe, int *ref_frame_sign_bias, int *sr,
int near_sadidx[]);
void vp8_cal_sad(VP8_COMP *cpi, MACROBLOCKD *xd, MACROBLOCK *x,
int recon_yoffset, int near_sadidx[]);
int VP8_UVSSE(MACROBLOCK *x);
int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4]);
void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_RDOPT_H_
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "segmentation.h"
#include "vpx_mem/vpx_mem.h"
void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm, MACROBLOCK *x) {
int mb_row, mb_col;
MODE_INFO *this_mb_mode_info = cm->mi;
x->gf_active_ptr = (signed char *)cpi->gf_active_flags;
if ((cm->frame_type == KEY_FRAME) || (cm->refresh_golden_frame)) {
/* Reset Gf useage monitors */
memset(cpi->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
} else {
/* for each macroblock row in image */
for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
/* for each macroblock col in image */
for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
/* If using golden then set GF active flag if not already set.
* If using last frame 0,0 mode then leave flag as it is
* else if using non 0,0 motion or intra modes then clear
* flag if it is currently set
*/
if ((this_mb_mode_info->mbmi.ref_frame == GOLDEN_FRAME) ||
(this_mb_mode_info->mbmi.ref_frame == ALTREF_FRAME)) {
if (*(x->gf_active_ptr) == 0) {
*(x->gf_active_ptr) = 1;
cpi->gf_active_count++;
}
} else if ((this_mb_mode_info->mbmi.mode != ZEROMV) &&
*(x->gf_active_ptr)) {
*(x->gf_active_ptr) = 0;
cpi->gf_active_count--;
}
x->gf_active_ptr++; /* Step onto next entry */
this_mb_mode_info++; /* skip to next mb */
}
/* this is to account for the border */
this_mb_mode_info++;
}
}
}
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_SEGMENTATION_H_
#define VPX_VP8_ENCODER_SEGMENTATION_H_
#include "string.h"
#include "vp8/common/blockd.h"
#include "onyx_int.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void vp8_update_gf_useage_maps(VP8_COMP *cpi, VP8_COMMON *cm,
MACROBLOCK *x);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_SEGMENTATION_H_
@@ -0,0 +1,434 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vp8/common/onyxc_int.h"
#include "onyx_int.h"
#include "vp8/common/systemdependent.h"
#include "vp8/encoder/quantize.h"
#include "vp8/common/alloccommon.h"
#include "mcomp.h"
#include "firstpass.h"
#include "vpx_scale/vpx_scale.h"
#include "vp8/common/extend.h"
#include "ratectrl.h"
#include "vp8/common/quant_common.h"
#include "segmentation.h"
#include "temporal_filter.h"
#include "vpx_mem/vpx_mem.h"
#include "vp8/common/swapyv12buffer.h"
#include "vp8/common/threading.h"
#include "vpx_ports/vpx_timer.h"
#include <math.h>
#include <limits.h>
#define ALT_REF_MC_ENABLED 1 /* toggle MC in AltRef filtering */
#define ALT_REF_SUBPEL_ENABLED 1 /* toggle subpel in MC AltRef filtering */
#if VP8_TEMPORAL_ALT_REF
static void vp8_temporal_filter_predictors_mb_c(
MACROBLOCKD *x, unsigned char *y_mb_ptr, unsigned char *u_mb_ptr,
unsigned char *v_mb_ptr, int stride, int mv_row, int mv_col,
unsigned char *pred) {
int offset;
unsigned char *yptr, *uptr, *vptr;
/* Y */
yptr = y_mb_ptr + (mv_row >> 3) * stride + (mv_col >> 3);
if ((mv_row | mv_col) & 7) {
x->subpixel_predict16x16(yptr, stride, mv_col & 7, mv_row & 7, &pred[0],
16);
} else {
vp8_copy_mem16x16(yptr, stride, &pred[0], 16);
}
/* U & V */
mv_row >>= 1;
mv_col >>= 1;
stride = (stride + 1) >> 1;
offset = (mv_row >> 3) * stride + (mv_col >> 3);
uptr = u_mb_ptr + offset;
vptr = v_mb_ptr + offset;
if ((mv_row | mv_col) & 7) {
x->subpixel_predict8x8(uptr, stride, mv_col & 7, mv_row & 7, &pred[256], 8);
x->subpixel_predict8x8(vptr, stride, mv_col & 7, mv_row & 7, &pred[320], 8);
} else {
vp8_copy_mem8x8(uptr, stride, &pred[256], 8);
vp8_copy_mem8x8(vptr, stride, &pred[320], 8);
}
}
void vp8_temporal_filter_apply_c(unsigned char *frame1, unsigned int stride,
unsigned char *frame2, unsigned int block_size,
int strength, int filter_weight,
unsigned int *accumulator,
unsigned short *count) {
unsigned int i, j, k;
int modifier;
int byte = 0;
const int rounding = strength > 0 ? 1 << (strength - 1) : 0;
for (i = 0, k = 0; i < block_size; ++i) {
for (j = 0; j < block_size; j++, k++) {
int src_byte = frame1[byte];
int pixel_value = *frame2++;
modifier = src_byte - pixel_value;
/* This is an integer approximation of:
* float coeff = (3.0 * modifer * modifier) / pow(2, strength);
* modifier = (int)roundf(coeff > 16 ? 0 : 16-coeff);
*/
modifier *= modifier;
modifier *= 3;
modifier += rounding;
modifier >>= strength;
if (modifier > 16) modifier = 16;
modifier = 16 - modifier;
modifier *= filter_weight;
count[k] += modifier;
accumulator[k] += modifier * pixel_value;
byte++;
}
byte += stride - block_size;
}
}
#if ALT_REF_MC_ENABLED
static int vp8_temporal_filter_find_matching_mb_c(VP8_COMP *cpi,
YV12_BUFFER_CONFIG *arf_frame,
YV12_BUFFER_CONFIG *frame_ptr,
int mb_offset,
int error_thresh) {
MACROBLOCK *x = &cpi->mb;
int step_param;
int sadpb = x->sadperbit16;
int bestsme = INT_MAX;
BLOCK *b = &x->block[0];
BLOCKD *d = &x->e_mbd.block[0];
int_mv best_ref_mv1;
int_mv best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
/* Save input state */
unsigned char **base_src = b->base_src;
int src = b->src;
int src_stride = b->src_stride;
unsigned char *base_pre = x->e_mbd.pre.y_buffer;
int pre = d->offset;
int pre_stride = x->e_mbd.pre.y_stride;
(void)error_thresh;
best_ref_mv1.as_int = 0;
best_ref_mv1_full.as_mv.col = best_ref_mv1.as_mv.col >> 3;
best_ref_mv1_full.as_mv.row = best_ref_mv1.as_mv.row >> 3;
/* Setup frame pointers */
b->base_src = &arf_frame->y_buffer;
b->src_stride = arf_frame->y_stride;
b->src = mb_offset;
x->e_mbd.pre.y_buffer = frame_ptr->y_buffer;
x->e_mbd.pre.y_stride = frame_ptr->y_stride;
d->offset = mb_offset;
/* Further step/diamond searches as necessary */
if (cpi->Speed < 8) {
step_param = cpi->sf.first_step + (cpi->Speed > 5);
} else {
step_param = cpi->sf.first_step + 2;
}
/* TODO Check that the 16x16 vf & sdf are selected here */
/* Ignore mv costing by sending NULL cost arrays */
bestsme =
vp8_hex_search(x, b, d, &best_ref_mv1_full, &d->bmi.mv, step_param, sadpb,
&cpi->fn_ptr[BLOCK_16X16], NULL, &best_ref_mv1);
(void)bestsme; // Ignore unused return value.
#if ALT_REF_SUBPEL_ENABLED
/* Try sub-pixel MC? */
{
int distortion;
unsigned int sse;
/* Ignore mv costing by sending NULL cost array */
bestsme = cpi->find_fractional_mv_step(
x, b, d, &d->bmi.mv, &best_ref_mv1, x->errorperbit,
&cpi->fn_ptr[BLOCK_16X16], NULL, &distortion, &sse);
}
#endif
/* Save input state */
b->base_src = base_src;
b->src = src;
b->src_stride = src_stride;
x->e_mbd.pre.y_buffer = base_pre;
d->offset = pre;
x->e_mbd.pre.y_stride = pre_stride;
return bestsme;
}
#endif
static void vp8_temporal_filter_iterate_c(VP8_COMP *cpi, int frame_count,
int alt_ref_index, int strength) {
int byte;
int frame;
int mb_col, mb_row;
unsigned int filter_weight;
int mb_cols = cpi->common.mb_cols;
int mb_rows = cpi->common.mb_rows;
int mb_y_offset = 0;
int mb_uv_offset = 0;
DECLARE_ALIGNED(16, unsigned int, accumulator[16 * 16 + 8 * 8 + 8 * 8]);
DECLARE_ALIGNED(16, unsigned short, count[16 * 16 + 8 * 8 + 8 * 8]);
MACROBLOCKD *mbd = &cpi->mb.e_mbd;
YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index];
unsigned char *dst1, *dst2;
DECLARE_ALIGNED(16, unsigned char, predictor[16 * 16 + 8 * 8 + 8 * 8]);
/* Save input state */
unsigned char *y_buffer = mbd->pre.y_buffer;
unsigned char *u_buffer = mbd->pre.u_buffer;
unsigned char *v_buffer = mbd->pre.v_buffer;
for (mb_row = 0; mb_row < mb_rows; ++mb_row) {
#if ALT_REF_MC_ENABLED
/* Source frames are extended to 16 pixels. This is different than
* L/A/G reference frames that have a border of 32 (VP8BORDERINPIXELS)
* A 6 tap filter is used for motion search. This requires 2 pixels
* before and 3 pixels after. So the largest Y mv on a border would
* then be 16 - 3. The UV blocks are half the size of the Y and
* therefore only extended by 8. The largest mv that a UV block
* can support is 8 - 3. A UV mv is half of a Y mv.
* (16 - 3) >> 1 == 6 which is greater than 8 - 3.
* To keep the mv in play for both Y and UV planes the max that it
* can be on a border is therefore 16 - 5.
*/
cpi->mb.mv_row_min = -((mb_row * 16) + (16 - 5));
cpi->mb.mv_row_max = ((cpi->common.mb_rows - 1 - mb_row) * 16) + (16 - 5);
#endif
for (mb_col = 0; mb_col < mb_cols; ++mb_col) {
int i, j, k;
int stride;
memset(accumulator, 0, 384 * sizeof(unsigned int));
memset(count, 0, 384 * sizeof(unsigned short));
#if ALT_REF_MC_ENABLED
cpi->mb.mv_col_min = -((mb_col * 16) + (16 - 5));
cpi->mb.mv_col_max = ((cpi->common.mb_cols - 1 - mb_col) * 16) + (16 - 5);
#endif
for (frame = 0; frame < frame_count; ++frame) {
if (cpi->frames[frame] == NULL) continue;
mbd->block[0].bmi.mv.as_mv.row = 0;
mbd->block[0].bmi.mv.as_mv.col = 0;
if (frame == alt_ref_index) {
filter_weight = 2;
} else {
int err = 0;
#if ALT_REF_MC_ENABLED
#define THRESH_LOW 10000
#define THRESH_HIGH 20000
/* Find best match in this frame by MC */
err = vp8_temporal_filter_find_matching_mb_c(
cpi, cpi->frames[alt_ref_index], cpi->frames[frame], mb_y_offset,
THRESH_LOW);
#endif
/* Assign higher weight to matching MB if it's error
* score is lower. If not applying MC default behavior
* is to weight all MBs equal.
*/
filter_weight = err < THRESH_LOW ? 2 : err < THRESH_HIGH ? 1 : 0;
}
if (filter_weight != 0) {
/* Construct the predictors */
vp8_temporal_filter_predictors_mb_c(
mbd, cpi->frames[frame]->y_buffer + mb_y_offset,
cpi->frames[frame]->u_buffer + mb_uv_offset,
cpi->frames[frame]->v_buffer + mb_uv_offset,
cpi->frames[frame]->y_stride, mbd->block[0].bmi.mv.as_mv.row,
mbd->block[0].bmi.mv.as_mv.col, predictor);
/* Apply the filter (YUV) */
vp8_temporal_filter_apply(f->y_buffer + mb_y_offset, f->y_stride,
predictor, 16, strength, filter_weight,
accumulator, count);
vp8_temporal_filter_apply(f->u_buffer + mb_uv_offset, f->uv_stride,
predictor + 256, 8, strength, filter_weight,
accumulator + 256, count + 256);
vp8_temporal_filter_apply(f->v_buffer + mb_uv_offset, f->uv_stride,
predictor + 320, 8, strength, filter_weight,
accumulator + 320, count + 320);
}
}
/* Normalize filter output to produce AltRef frame */
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++) {
unsigned int pval = accumulator[k] + (count[k] >> 1);
pval *= cpi->fixed_divide[count[k]];
pval >>= 19;
dst1[byte] = (unsigned char)pval;
/* move to next pixel */
byte++;
}
byte += stride - 16;
}
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 < 8; ++i) {
for (j = 0; j < 8; j++, k++) {
int m = k + 64;
/* U */
unsigned int pval = accumulator[k] + (count[k] >> 1);
pval *= cpi->fixed_divide[count[k]];
pval >>= 19;
dst1[byte] = (unsigned char)pval;
/* V */
pval = accumulator[m] + (count[m] >> 1);
pval *= cpi->fixed_divide[count[m]];
pval >>= 19;
dst2[byte] = (unsigned char)pval;
/* move to next pixel */
byte++;
}
byte += stride - 8;
}
mb_y_offset += 16;
mb_uv_offset += 8;
}
mb_y_offset += 16 * (f->y_stride - mb_cols);
mb_uv_offset += 8 * (f->uv_stride - mb_cols);
}
/* Restore input state */
mbd->pre.y_buffer = y_buffer;
mbd->pre.u_buffer = u_buffer;
mbd->pre.v_buffer = v_buffer;
}
void vp8_temporal_filter_prepare_c(VP8_COMP *cpi, int distance) {
int frame = 0;
int num_frames_backward = 0;
int num_frames_forward = 0;
int frames_to_blur_backward = 0;
int frames_to_blur_forward = 0;
int frames_to_blur = 0;
int start_frame = 0;
int strength = cpi->oxcf.arnr_strength;
int blur_type = cpi->oxcf.arnr_type;
int max_frames = cpi->active_arnr_frames;
num_frames_backward = distance;
num_frames_forward =
vp8_lookahead_depth(cpi->lookahead) - (num_frames_backward + 1);
switch (blur_type) {
case 1:
/* Backward Blur */
frames_to_blur_backward = num_frames_backward;
if (frames_to_blur_backward >= max_frames) {
frames_to_blur_backward = max_frames - 1;
}
frames_to_blur = frames_to_blur_backward + 1;
break;
case 2:
/* Forward Blur */
frames_to_blur_forward = num_frames_forward;
if (frames_to_blur_forward >= max_frames) {
frames_to_blur_forward = max_frames - 1;
}
frames_to_blur = frames_to_blur_forward + 1;
break;
case 3:
default:
/* Center Blur */
frames_to_blur_forward = num_frames_forward;
frames_to_blur_backward = num_frames_backward;
if (frames_to_blur_forward > frames_to_blur_backward) {
frames_to_blur_forward = frames_to_blur_backward;
}
if (frames_to_blur_backward > frames_to_blur_forward) {
frames_to_blur_backward = frames_to_blur_forward;
}
/* When max_frames is even we have 1 more frame backward than forward */
if (frames_to_blur_forward > (max_frames - 1) / 2) {
frames_to_blur_forward = ((max_frames - 1) / 2);
}
if (frames_to_blur_backward > (max_frames / 2)) {
frames_to_blur_backward = (max_frames / 2);
}
frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
break;
}
start_frame = distance + frames_to_blur_forward;
/* Setup frame pointers, NULL indicates frame not included in filter */
memset(cpi->frames, 0, max_frames * sizeof(YV12_BUFFER_CONFIG *));
for (frame = 0; frame < frames_to_blur; ++frame) {
int which_buffer = start_frame - frame;
struct lookahead_entry *buf =
vp8_lookahead_peek(cpi->lookahead, which_buffer, PEEK_FORWARD);
cpi->frames[frames_to_blur - 1 - frame] = &buf->img;
}
vp8_temporal_filter_iterate_c(cpi, frames_to_blur, frames_to_blur_backward,
strength);
}
#endif
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2017 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_TEMPORAL_FILTER_H_
#define VPX_VP8_ENCODER_TEMPORAL_FILTER_H_
#ifdef __cplusplus
extern "C" {
#endif
struct VP8_COMP;
void vp8_temporal_filter_prepare_c(struct VP8_COMP *cpi, int distance);
#ifdef __cplusplus
}
#endif
#endif // VPX_VP8_ENCODER_TEMPORAL_FILTER_H_
@@ -0,0 +1,468 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "onyx_int.h"
#include "tokenize.h"
#include "vpx_mem/vpx_mem.h"
/* Global event counters used for accumulating statistics across several
compressions, then generating context.c = initial stats. */
void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t);
void vp8_fix_contexts(MACROBLOCKD *x);
#include "dct_value_tokens.h"
#include "dct_value_cost.h"
const TOKENVALUE *const vp8_dct_value_tokens_ptr =
dct_value_tokens + DCT_MAX_VALUE;
const short *const vp8_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
#if 0
int skip_true_count = 0;
int skip_false_count = 0;
#endif
/* function used to generate dct_value_tokens and dct_value_cost tables */
/*
static void fill_value_tokens()
{
TOKENVALUE *t = dct_value_tokens + DCT_MAX_VALUE;
const vp8_extra_bit_struct *e = vp8_extra_bits;
int i = -DCT_MAX_VALUE;
int sign = 1;
do
{
if (!i)
sign = 0;
{
const int a = sign ? -i : i;
int eb = sign;
if (a > 4)
{
int j = 4;
while (++j < 11 && e[j].base_val <= a) {}
t[i].Token = --j;
eb |= (a - e[j].base_val) << 1;
}
else
t[i].Token = a;
t[i].Extra = eb;
}
// initialize the cost for extra bits for all possible coefficient
value.
{
int cost = 0;
const vp8_extra_bit_struct *p = vp8_extra_bits + t[i].Token;
if (p->base_val)
{
const int extra = t[i].Extra;
const int Length = p->Len;
if (Length)
cost += vp8_treed_cost(p->tree, p->prob, extra >> 1,
Length);
cost += vp8_cost_bit(vp8_prob_half, extra & 1); // sign
dct_value_cost[i + DCT_MAX_VALUE] = cost;
}
}
}
while (++i < DCT_MAX_VALUE);
vp8_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE;
vp8_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
}
*/
static void tokenize2nd_order_b(MACROBLOCK *x, TOKENEXTRA **tp, VP8_COMP *cpi) {
MACROBLOCKD *xd = &x->e_mbd;
int pt; /* near block/prev token context index */
int c; /* start at DC */
TOKENEXTRA *t = *tp; /* store tokens starting here */
const BLOCKD *b;
const short *qcoeff_ptr;
ENTROPY_CONTEXT *a;
ENTROPY_CONTEXT *l;
int band, rc, v, token;
int eob;
b = xd->block + 24;
qcoeff_ptr = b->qcoeff;
a = (ENTROPY_CONTEXT *)xd->above_context + 8;
l = (ENTROPY_CONTEXT *)xd->left_context + 8;
eob = xd->eobs[24];
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
if (!eob) {
/* c = band for this case */
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
t->skip_eob_node = 0;
++x->coef_counts[1][0][pt][DCT_EOB_TOKEN];
t++;
*tp = t;
*a = *l = 0;
return;
}
v = qcoeff_ptr[0];
t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
token = vp8_dct_value_tokens_ptr[v].Token;
t->Token = token;
t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
t->skip_eob_node = 0;
++x->coef_counts[1][0][pt][token];
pt = vp8_prev_token_class[token];
t++;
c = 1;
for (; c < eob; ++c) {
rc = vp8_default_zig_zag1d[c];
band = vp8_coef_bands[c];
v = qcoeff_ptr[rc];
t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
token = vp8_dct_value_tokens_ptr[v].Token;
t->Token = token;
t->context_tree = cpi->common.fc.coef_probs[1][band][pt];
t->skip_eob_node = ((pt == 0));
++x->coef_counts[1][band][pt][token];
pt = vp8_prev_token_class[token];
t++;
}
if (c < 16) {
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[1][band][pt];
t->skip_eob_node = 0;
++x->coef_counts[1][band][pt][DCT_EOB_TOKEN];
t++;
}
*tp = t;
*a = *l = 1;
}
static void tokenize1st_order_b(
MACROBLOCK *x, TOKENEXTRA **tp,
int type, /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
VP8_COMP *cpi) {
MACROBLOCKD *xd = &x->e_mbd;
unsigned int block;
const BLOCKD *b;
int pt; /* near block/prev token context index */
int c;
int token;
TOKENEXTRA *t = *tp; /* store tokens starting here */
const short *qcoeff_ptr;
ENTROPY_CONTEXT *a;
ENTROPY_CONTEXT *l;
int band, rc, v;
int tmp1, tmp2;
b = xd->block;
/* Luma */
for (block = 0; block < 16; block++, b++) {
const int eob = *b->eob;
tmp1 = vp8_block2above[block];
tmp2 = vp8_block2left[block];
qcoeff_ptr = b->qcoeff;
a = (ENTROPY_CONTEXT *)xd->above_context + tmp1;
l = (ENTROPY_CONTEXT *)xd->left_context + tmp2;
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
c = type ? 0 : 1;
if (c >= eob) {
/* c = band for this case */
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[type][c][pt];
t->skip_eob_node = 0;
++x->coef_counts[type][c][pt][DCT_EOB_TOKEN];
t++;
*tp = t;
*a = *l = 0;
continue;
}
v = qcoeff_ptr[c];
t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
token = vp8_dct_value_tokens_ptr[v].Token;
t->Token = token;
t->context_tree = cpi->common.fc.coef_probs[type][c][pt];
t->skip_eob_node = 0;
++x->coef_counts[type][c][pt][token];
pt = vp8_prev_token_class[token];
t++;
c++;
assert(eob <= 16);
for (; c < eob; ++c) {
rc = vp8_default_zig_zag1d[c];
band = vp8_coef_bands[c];
v = qcoeff_ptr[rc];
t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
token = vp8_dct_value_tokens_ptr[v].Token;
t->Token = token;
t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
t->skip_eob_node = (pt == 0);
++x->coef_counts[type][band][pt][token];
pt = vp8_prev_token_class[token];
t++;
}
if (c < 16) {
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
t->skip_eob_node = 0;
++x->coef_counts[type][band][pt][DCT_EOB_TOKEN];
t++;
}
*tp = t;
*a = *l = 1;
}
/* Chroma */
for (block = 16; block < 24; block++, b++) {
const int eob = *b->eob;
tmp1 = vp8_block2above[block];
tmp2 = vp8_block2left[block];
qcoeff_ptr = b->qcoeff;
a = (ENTROPY_CONTEXT *)xd->above_context + tmp1;
l = (ENTROPY_CONTEXT *)xd->left_context + tmp2;
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
if (!eob) {
/* c = band for this case */
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
t->skip_eob_node = 0;
++x->coef_counts[2][0][pt][DCT_EOB_TOKEN];
t++;
*tp = t;
*a = *l = 0;
continue;
}
v = qcoeff_ptr[0];
t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
token = vp8_dct_value_tokens_ptr[v].Token;
t->Token = token;
t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
t->skip_eob_node = 0;
++x->coef_counts[2][0][pt][token];
pt = vp8_prev_token_class[token];
t++;
c = 1;
assert(eob <= 16);
for (; c < eob; ++c) {
rc = vp8_default_zig_zag1d[c];
band = vp8_coef_bands[c];
v = qcoeff_ptr[rc];
t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
token = vp8_dct_value_tokens_ptr[v].Token;
t->Token = token;
t->context_tree = cpi->common.fc.coef_probs[2][band][pt];
t->skip_eob_node = (pt == 0);
++x->coef_counts[2][band][pt][token];
pt = vp8_prev_token_class[token];
t++;
}
if (c < 16) {
band = vp8_coef_bands[c];
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[2][band][pt];
t->skip_eob_node = 0;
++x->coef_counts[2][band][pt][DCT_EOB_TOKEN];
t++;
}
*tp = t;
*a = *l = 1;
}
}
static int mb_is_skippable(MACROBLOCKD *x, int has_y2_block) {
int skip = 1;
int i = 0;
if (has_y2_block) {
for (i = 0; i < 16; ++i) skip &= (x->eobs[i] < 2);
}
for (; i < 24 + has_y2_block; ++i) skip &= (!x->eobs[i]);
return skip;
}
void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t) {
MACROBLOCKD *xd = &x->e_mbd;
int plane_type;
int has_y2_block;
has_y2_block = (xd->mode_info_context->mbmi.mode != B_PRED &&
xd->mode_info_context->mbmi.mode != SPLITMV);
xd->mode_info_context->mbmi.mb_skip_coeff = mb_is_skippable(xd, has_y2_block);
if (xd->mode_info_context->mbmi.mb_skip_coeff) {
if (!cpi->common.mb_no_coeff_skip) {
vp8_stuff_mb(cpi, x, t);
} else {
vp8_fix_contexts(xd);
x->skip_true_count++;
}
return;
}
plane_type = 3;
if (has_y2_block) {
tokenize2nd_order_b(x, t, cpi);
plane_type = 0;
}
tokenize1st_order_b(x, t, plane_type, cpi);
}
static void stuff2nd_order_b(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
ENTROPY_CONTEXT *l, VP8_COMP *cpi, MACROBLOCK *x) {
int pt; /* near block/prev token context index */
TOKENEXTRA *t = *tp; /* store tokens starting here */
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[1][0][pt];
t->skip_eob_node = 0;
++x->coef_counts[1][0][pt][DCT_EOB_TOKEN];
++t;
*tp = t;
pt = 0;
*a = *l = pt;
}
static void stuff1st_order_b(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
ENTROPY_CONTEXT *l, int type, VP8_COMP *cpi,
MACROBLOCK *x) {
int pt; /* near block/prev token context index */
int band;
TOKENEXTRA *t = *tp; /* store tokens starting here */
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
band = type ? 0 : 1;
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[type][band][pt];
t->skip_eob_node = 0;
++x->coef_counts[type][band][pt][DCT_EOB_TOKEN];
++t;
*tp = t;
pt = 0; /* 0 <-> all coeff data is zero */
*a = *l = pt;
}
static void stuff1st_order_buv(TOKENEXTRA **tp, ENTROPY_CONTEXT *a,
ENTROPY_CONTEXT *l, VP8_COMP *cpi,
MACROBLOCK *x) {
int pt; /* near block/prev token context index */
TOKENEXTRA *t = *tp; /* store tokens starting here */
VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
t->Token = DCT_EOB_TOKEN;
t->context_tree = cpi->common.fc.coef_probs[2][0][pt];
t->skip_eob_node = 0;
++x->coef_counts[2][0][pt][DCT_EOB_TOKEN];
++t;
*tp = t;
pt = 0; /* 0 <-> all coeff data is zero */
*a = *l = pt;
}
void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t) {
MACROBLOCKD *xd = &x->e_mbd;
ENTROPY_CONTEXT *A = (ENTROPY_CONTEXT *)xd->above_context;
ENTROPY_CONTEXT *L = (ENTROPY_CONTEXT *)xd->left_context;
int plane_type;
int b;
plane_type = 3;
if ((xd->mode_info_context->mbmi.mode != B_PRED &&
xd->mode_info_context->mbmi.mode != SPLITMV)) {
stuff2nd_order_b(t, A + vp8_block2above[24], L + vp8_block2left[24], cpi,
x);
plane_type = 0;
}
for (b = 0; b < 16; ++b) {
stuff1st_order_b(t, A + vp8_block2above[b], L + vp8_block2left[b],
plane_type, cpi, x);
}
for (b = 16; b < 24; ++b) {
stuff1st_order_buv(t, A + vp8_block2above[b], L + vp8_block2left[b], cpi,
x);
}
}
void vp8_fix_contexts(MACROBLOCKD *x) {
/* Clear entropy contexts for Y2 blocks */
if (x->mode_info_context->mbmi.mode != B_PRED &&
x->mode_info_context->mbmi.mode != SPLITMV) {
memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
} else {
memset(x->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) - 1);
memset(x->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) - 1);
}
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_TOKENIZE_H_
#define VPX_VP8_ENCODER_TOKENIZE_H_
#include "vp8/common/entropy.h"
#include "block.h"
#ifdef __cplusplus
extern "C" {
#endif
void vp8_tokenize_initialize();
typedef struct {
short Token;
short Extra;
} TOKENVALUE;
typedef struct {
const vp8_prob *context_tree;
short Extra;
unsigned char Token;
unsigned char skip_eob_node;
} TOKENEXTRA;
int rd_cost_mby(MACROBLOCKD *);
extern const short *const vp8_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 *const vp8_dct_value_tokens_ptr;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_TOKENIZE_H_
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "treewriter.h"
static void cost(int *const C, vp8_tree T, const vp8_prob *const P, int i,
int c) {
const vp8_prob p = P[i >> 1];
do {
const vp8_tree_index j = T[i];
const int d = c + vp8_cost_bit(p, i & 1);
if (j <= 0) {
C[-j] = d;
} else {
cost(C, T, P, j, d);
}
} while (++i & 1);
}
void vp8_cost_tokens(int *c, const vp8_prob *p, vp8_tree t) {
cost(c, t, p, 0, 0);
}
void vp8_cost_tokens2(int *c, const vp8_prob *p, vp8_tree t, int start) {
cost(c, t, p, start, 0);
}
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_VP8_ENCODER_TREEWRITER_H_
#define VPX_VP8_ENCODER_TREEWRITER_H_
/* Trees map alphabets into huffman-like codes suitable for an arithmetic
bit coder. Timothy S Murphy 11 October 2004 */
#include "./vpx_config.h"
#include "vp8/common/treecoder.h"
#include "boolhuff.h" /* for now */
#ifdef __cplusplus
extern "C" {
#endif
typedef BOOL_CODER vp8_writer;
#define vp8_write vp8_encode_bool
#define vp8_write_literal vp8_encode_value
#define vp8_write_bit(W, V) vp8_write(W, V, vp8_prob_half)
#define vp8bc_write vp8bc_write_bool
#define vp8bc_write_literal vp8bc_write_bits
#define vp8bc_write_bit(W, V) vp8bc_write_bits(W, V, 1)
/* Approximate length of an encoded bool in 256ths of a bit at given prob */
#define vp8_cost_zero(x) (vp8_prob_cost[x])
#define vp8_cost_one(x) vp8_cost_zero(vp8_complement(x))
#define vp8_cost_bit(x, b) vp8_cost_zero((b) ? vp8_complement(x) : (x))
/* VP8BC version is scaled by 2^20 rather than 2^8; see bool_coder.h */
/* Both of these return bits, not scaled bits. */
static INLINE unsigned int vp8_cost_branch(const unsigned int ct[2],
vp8_prob p) {
/* Imitate existing calculation */
return ((ct[0] * vp8_cost_zero(p)) + (ct[1] * vp8_cost_one(p))) >> 8;
}
/* Small functions to write explicit values and tokens, as well as
estimate their lengths. */
static void vp8_treed_write(vp8_writer *const w, vp8_tree t,
const vp8_prob *const p, int v,
int n) { /* number of bits in v, assumed nonzero */
vp8_tree_index i = 0;
do {
const int b = (v >> --n) & 1;
vp8_write(w, b, p[i >> 1]);
i = t[i + b];
} while (n);
}
static INLINE void vp8_write_token(vp8_writer *const w, vp8_tree t,
const vp8_prob *const p,
vp8_token *const x) {
vp8_treed_write(w, t, p, x->value, x->Len);
}
static int vp8_treed_cost(vp8_tree t, const vp8_prob *const p, int v,
int n) { /* number of bits in v, assumed nonzero */
int c = 0;
vp8_tree_index i = 0;
do {
const int b = (v >> --n) & 1;
c += vp8_cost_bit(p[i >> 1], b);
i = t[i + b];
} while (n);
return c;
}
static INLINE int vp8_cost_token(vp8_tree t, const vp8_prob *const p,
vp8_token *const x) {
return vp8_treed_cost(t, p, x->value, x->Len);
}
/* Fill array of costs for all possible token values. */
void vp8_cost_tokens(int *c, const vp8_prob *, vp8_tree);
void vp8_cost_tokens2(int *c, const vp8_prob *, vp8_tree, int);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VPX_VP8_ENCODER_TREEWRITER_H_
@@ -0,0 +1,489 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "vpx_mem/vpx_mem.h"
#include "onyx_int.h"
#include "vp8/encoder/quantize.h"
#include "vp8/common/quant_common.h"
void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d) {
int i, rc, eob;
int x, y, z, sz;
short *coeff_ptr = b->coeff;
short *round_ptr = b->round;
short *quant_ptr = b->quant_fast;
short *qcoeff_ptr = d->qcoeff;
short *dqcoeff_ptr = d->dqcoeff;
short *dequant_ptr = d->dequant;
eob = -1;
for (i = 0; i < 16; ++i) {
rc = vp8_default_zig_zag1d[i];
z = coeff_ptr[rc];
sz = (z >> 31); /* sign of z */
x = (z ^ sz) - sz; /* x = abs(z) */
y = ((x + round_ptr[rc]) * quant_ptr[rc]) >> 16; /* quantize (x) */
x = (y ^ sz) - sz; /* get the sign back */
qcoeff_ptr[rc] = x; /* write to destination */
dqcoeff_ptr[rc] = x * dequant_ptr[rc]; /* dequantized value */
if (y) {
eob = i; /* last nonzero coeffs */
}
}
*d->eob = (char)(eob + 1);
}
void vp8_regular_quantize_b_c(BLOCK *b, BLOCKD *d) {
int i, rc, eob;
int zbin;
int x, y, z, sz;
short *zbin_boost_ptr = b->zrun_zbin_boost;
short *coeff_ptr = b->coeff;
short *zbin_ptr = b->zbin;
short *round_ptr = b->round;
short *quant_ptr = b->quant;
short *quant_shift_ptr = b->quant_shift;
short *qcoeff_ptr = d->qcoeff;
short *dqcoeff_ptr = d->dqcoeff;
short *dequant_ptr = d->dequant;
short zbin_oq_value = b->zbin_extra;
memset(qcoeff_ptr, 0, 32);
memset(dqcoeff_ptr, 0, 32);
eob = -1;
for (i = 0; i < 16; ++i) {
rc = vp8_default_zig_zag1d[i];
z = coeff_ptr[rc];
zbin = zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value;
zbin_boost_ptr++;
sz = (z >> 31); /* sign of z */
x = (z ^ sz) - sz; /* x = abs(z) */
if (x >= zbin) {
x += round_ptr[rc];
y = ((((x * quant_ptr[rc]) >> 16) + x) * quant_shift_ptr[rc]) >>
16; /* quantize (x) */
x = (y ^ sz) - sz; /* get the sign back */
qcoeff_ptr[rc] = x; /* write to destination */
dqcoeff_ptr[rc] = x * dequant_ptr[rc]; /* dequantized value */
if (y) {
eob = i; /* last nonzero coeffs */
zbin_boost_ptr = b->zrun_zbin_boost; /* reset zero runlength */
}
}
}
*d->eob = (char)(eob + 1);
}
void vp8_quantize_mby(MACROBLOCK *x) {
int i;
int has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED &&
x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
for (i = 0; i < 16; ++i) x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
if (has_2nd_order) x->quantize_b(&x->block[24], &x->e_mbd.block[24]);
}
void vp8_quantize_mb(MACROBLOCK *x) {
int i;
int has_2nd_order = (x->e_mbd.mode_info_context->mbmi.mode != B_PRED &&
x->e_mbd.mode_info_context->mbmi.mode != SPLITMV);
for (i = 0; i < 24 + has_2nd_order; ++i) {
x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
}
}
void vp8_quantize_mbuv(MACROBLOCK *x) {
int i;
for (i = 16; i < 24; ++i) x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
}
static const int qrounding_factors[129] = {
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
};
static const int qzbin_factors[129] = {
84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 80, 80, 80, 80, 80, 80, 80, 80, 80,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
};
static const int qrounding_factors_y2[129] = {
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
};
static const int qzbin_factors_y2[129] = {
84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 80, 80, 80, 80, 80, 80, 80, 80, 80,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
};
static void invert_quant(int improved_quant, short *quant, short *shift,
short d) {
if (improved_quant) {
unsigned t;
int l, m;
t = d;
for (l = 0; t > 1; ++l) t >>= 1;
m = 1 + (1 << (16 + l)) / d;
*quant = (short)(m - (1 << 16));
*shift = l;
/* use multiplication and constant shift by 16 */
*shift = 1 << (16 - *shift);
} else {
*quant = (1 << 16) / d;
*shift = 0;
}
}
void vp8cx_init_quantizer(VP8_COMP *cpi) {
int i;
int quant_val;
int Q;
int zbin_boost[16] = { 0, 0, 8, 10, 12, 14, 16, 20,
24, 28, 32, 36, 40, 44, 44, 44 };
for (Q = 0; Q < QINDEX_RANGE; ++Q) {
/* dc values */
quant_val = vp8_dc_quant(Q, cpi->common.y1dc_delta_q);
cpi->Y1quant_fast[Q][0] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + 0,
cpi->Y1quant_shift[Q] + 0, quant_val);
cpi->Y1zbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
cpi->Y1round[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
cpi->common.Y1dequant[Q][0] = quant_val;
cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
quant_val = vp8_dc2quant(Q, cpi->common.y2dc_delta_q);
cpi->Y2quant_fast[Q][0] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + 0,
cpi->Y2quant_shift[Q] + 0, quant_val);
cpi->Y2zbin[Q][0] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
cpi->Y2round[Q][0] = (qrounding_factors_y2[Q] * quant_val) >> 7;
cpi->common.Y2dequant[Q][0] = quant_val;
cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
quant_val = vp8_dc_uv_quant(Q, cpi->common.uvdc_delta_q);
cpi->UVquant_fast[Q][0] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + 0,
cpi->UVquant_shift[Q] + 0, quant_val);
cpi->UVzbin[Q][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
cpi->UVround[Q][0] = (qrounding_factors[Q] * quant_val) >> 7;
cpi->common.UVdequant[Q][0] = quant_val;
cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
/* all the ac values = ; */
quant_val = vp8_ac_yquant(Q);
cpi->Y1quant_fast[Q][1] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->Y1quant[Q] + 1,
cpi->Y1quant_shift[Q] + 1, quant_val);
cpi->Y1zbin[Q][1] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
cpi->Y1round[Q][1] = (qrounding_factors[Q] * quant_val) >> 7;
cpi->common.Y1dequant[Q][1] = quant_val;
cpi->zrun_zbin_boost_y1[Q][1] = (quant_val * zbin_boost[1]) >> 7;
quant_val = vp8_ac2quant(Q, cpi->common.y2ac_delta_q);
cpi->Y2quant_fast[Q][1] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->Y2quant[Q] + 1,
cpi->Y2quant_shift[Q] + 1, quant_val);
cpi->Y2zbin[Q][1] = ((qzbin_factors_y2[Q] * quant_val) + 64) >> 7;
cpi->Y2round[Q][1] = (qrounding_factors_y2[Q] * quant_val) >> 7;
cpi->common.Y2dequant[Q][1] = quant_val;
cpi->zrun_zbin_boost_y2[Q][1] = (quant_val * zbin_boost[1]) >> 7;
quant_val = vp8_ac_uv_quant(Q, cpi->common.uvac_delta_q);
cpi->UVquant_fast[Q][1] = (1 << 16) / quant_val;
invert_quant(cpi->sf.improved_quant, cpi->UVquant[Q] + 1,
cpi->UVquant_shift[Q] + 1, quant_val);
cpi->UVzbin[Q][1] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
cpi->UVround[Q][1] = (qrounding_factors[Q] * quant_val) >> 7;
cpi->common.UVdequant[Q][1] = quant_val;
cpi->zrun_zbin_boost_uv[Q][1] = (quant_val * zbin_boost[1]) >> 7;
for (i = 2; i < 16; ++i) {
cpi->Y1quant_fast[Q][i] = cpi->Y1quant_fast[Q][1];
cpi->Y1quant[Q][i] = cpi->Y1quant[Q][1];
cpi->Y1quant_shift[Q][i] = cpi->Y1quant_shift[Q][1];
cpi->Y1zbin[Q][i] = cpi->Y1zbin[Q][1];
cpi->Y1round[Q][i] = cpi->Y1round[Q][1];
cpi->zrun_zbin_boost_y1[Q][i] =
(cpi->common.Y1dequant[Q][1] * zbin_boost[i]) >> 7;
cpi->Y2quant_fast[Q][i] = cpi->Y2quant_fast[Q][1];
cpi->Y2quant[Q][i] = cpi->Y2quant[Q][1];
cpi->Y2quant_shift[Q][i] = cpi->Y2quant_shift[Q][1];
cpi->Y2zbin[Q][i] = cpi->Y2zbin[Q][1];
cpi->Y2round[Q][i] = cpi->Y2round[Q][1];
cpi->zrun_zbin_boost_y2[Q][i] =
(cpi->common.Y2dequant[Q][1] * zbin_boost[i]) >> 7;
cpi->UVquant_fast[Q][i] = cpi->UVquant_fast[Q][1];
cpi->UVquant[Q][i] = cpi->UVquant[Q][1];
cpi->UVquant_shift[Q][i] = cpi->UVquant_shift[Q][1];
cpi->UVzbin[Q][i] = cpi->UVzbin[Q][1];
cpi->UVround[Q][i] = cpi->UVround[Q][1];
cpi->zrun_zbin_boost_uv[Q][i] =
(cpi->common.UVdequant[Q][1] * zbin_boost[i]) >> 7;
}
}
}
#define ZBIN_EXTRA_Y \
((cpi->common.Y1dequant[QIndex][1] * \
(x->zbin_over_quant + x->zbin_mode_boost + x->act_zbin_adj)) >> \
7)
#define ZBIN_EXTRA_UV \
((cpi->common.UVdequant[QIndex][1] * \
(x->zbin_over_quant + x->zbin_mode_boost + x->act_zbin_adj)) >> \
7)
#define ZBIN_EXTRA_Y2 \
((cpi->common.Y2dequant[QIndex][1] * \
((x->zbin_over_quant / 2) + x->zbin_mode_boost + x->act_zbin_adj)) >> \
7)
void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x, int ok_to_skip) {
int i;
int QIndex;
MACROBLOCKD *xd = &x->e_mbd;
int zbin_extra;
/* Select the baseline MB Q index. */
if (xd->segmentation_enabled) {
/* Abs Value */
if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA) {
QIndex = xd->segment_feature_data[MB_LVL_ALT_Q]
[xd->mode_info_context->mbmi.segment_id];
/* Delta Value */
} else {
QIndex = cpi->common.base_qindex +
xd->segment_feature_data[MB_LVL_ALT_Q]
[xd->mode_info_context->mbmi.segment_id];
/* Clamp to valid range */
QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0;
}
} else {
QIndex = cpi->common.base_qindex;
}
/* This initialization should be called at least once. Use ok_to_skip to
* decide if it is ok to skip.
* Before encoding a frame, this function is always called with ok_to_skip
* =0, which means no skiping of calculations. The "last" values are
* initialized at that time.
*/
if (!ok_to_skip || QIndex != x->q_index) {
xd->dequant_y1_dc[0] = 1;
xd->dequant_y1[0] = cpi->common.Y1dequant[QIndex][0];
xd->dequant_y2[0] = cpi->common.Y2dequant[QIndex][0];
xd->dequant_uv[0] = cpi->common.UVdequant[QIndex][0];
for (i = 1; i < 16; ++i) {
xd->dequant_y1_dc[i] = xd->dequant_y1[i] =
cpi->common.Y1dequant[QIndex][1];
xd->dequant_y2[i] = cpi->common.Y2dequant[QIndex][1];
xd->dequant_uv[i] = cpi->common.UVdequant[QIndex][1];
}
#if 1
/*TODO: Remove dequant from BLOCKD. This is a temporary solution until
* the quantizer code uses a passed in pointer to the dequant constants.
* This will also require modifications to the x86 and neon assembly.
* */
for (i = 0; i < 16; ++i) x->e_mbd.block[i].dequant = xd->dequant_y1;
for (i = 16; i < 24; ++i) x->e_mbd.block[i].dequant = xd->dequant_uv;
x->e_mbd.block[24].dequant = xd->dequant_y2;
#endif
/* Y */
zbin_extra = ZBIN_EXTRA_Y;
for (i = 0; i < 16; ++i) {
x->block[i].quant = cpi->Y1quant[QIndex];
x->block[i].quant_fast = cpi->Y1quant_fast[QIndex];
x->block[i].quant_shift = cpi->Y1quant_shift[QIndex];
x->block[i].zbin = cpi->Y1zbin[QIndex];
x->block[i].round = cpi->Y1round[QIndex];
x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_y1[QIndex];
x->block[i].zbin_extra = (short)zbin_extra;
}
/* UV */
zbin_extra = ZBIN_EXTRA_UV;
for (i = 16; i < 24; ++i) {
x->block[i].quant = cpi->UVquant[QIndex];
x->block[i].quant_fast = cpi->UVquant_fast[QIndex];
x->block[i].quant_shift = cpi->UVquant_shift[QIndex];
x->block[i].zbin = cpi->UVzbin[QIndex];
x->block[i].round = cpi->UVround[QIndex];
x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_uv[QIndex];
x->block[i].zbin_extra = (short)zbin_extra;
}
/* Y2 */
zbin_extra = ZBIN_EXTRA_Y2;
x->block[24].quant_fast = cpi->Y2quant_fast[QIndex];
x->block[24].quant = cpi->Y2quant[QIndex];
x->block[24].quant_shift = cpi->Y2quant_shift[QIndex];
x->block[24].zbin = cpi->Y2zbin[QIndex];
x->block[24].round = cpi->Y2round[QIndex];
x->block[24].zrun_zbin_boost = cpi->zrun_zbin_boost_y2[QIndex];
x->block[24].zbin_extra = (short)zbin_extra;
/* save this macroblock QIndex for vp8_update_zbin_extra() */
x->q_index = QIndex;
x->last_zbin_over_quant = x->zbin_over_quant;
x->last_zbin_mode_boost = x->zbin_mode_boost;
x->last_act_zbin_adj = x->act_zbin_adj;
} else if (x->last_zbin_over_quant != x->zbin_over_quant ||
x->last_zbin_mode_boost != x->zbin_mode_boost ||
x->last_act_zbin_adj != x->act_zbin_adj) {
/* Y */
zbin_extra = ZBIN_EXTRA_Y;
for (i = 0; i < 16; ++i) x->block[i].zbin_extra = (short)zbin_extra;
/* UV */
zbin_extra = ZBIN_EXTRA_UV;
for (i = 16; i < 24; ++i) x->block[i].zbin_extra = (short)zbin_extra;
/* Y2 */
zbin_extra = ZBIN_EXTRA_Y2;
x->block[24].zbin_extra = (short)zbin_extra;
x->last_zbin_over_quant = x->zbin_over_quant;
x->last_zbin_mode_boost = x->zbin_mode_boost;
x->last_act_zbin_adj = x->act_zbin_adj;
}
}
void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x) {
int i;
int QIndex = x->q_index;
int zbin_extra;
/* Y */
zbin_extra = ZBIN_EXTRA_Y;
for (i = 0; i < 16; ++i) x->block[i].zbin_extra = (short)zbin_extra;
/* UV */
zbin_extra = ZBIN_EXTRA_UV;
for (i = 16; i < 24; ++i) x->block[i].zbin_extra = (short)zbin_extra;
/* Y2 */
zbin_extra = ZBIN_EXTRA_Y2;
x->block[24].zbin_extra = (short)zbin_extra;
}
#undef ZBIN_EXTRA_Y
#undef ZBIN_EXTRA_UV
#undef ZBIN_EXTRA_Y2
void vp8cx_frame_init_quantizer(VP8_COMP *cpi) {
/* Clear Zbin mode boost for default case */
cpi->mb.zbin_mode_boost = 0;
/* MB level quantizer setup */
vp8cx_mb_init_quantizer(cpi, &cpi->mb, 0);
}
void vp8_set_quantizer(struct VP8_COMP *cpi, int Q) {
VP8_COMMON *cm = &cpi->common;
MACROBLOCKD *mbd = &cpi->mb.e_mbd;
int update = 0;
int new_delta_q;
int new_uv_delta_q;
cm->base_qindex = Q;
/* if any of the delta_q values are changing update flag has to be set */
/* currently only y2dc_delta_q may change */
cm->y1dc_delta_q = 0;
cm->y2ac_delta_q = 0;
if (Q < 4) {
new_delta_q = 4 - Q;
} else {
new_delta_q = 0;
}
update |= cm->y2dc_delta_q != new_delta_q;
cm->y2dc_delta_q = new_delta_q;
new_uv_delta_q = 0;
// For screen content, lower the q value for UV channel. For now, select
// conservative delta; same delta for dc and ac, and decrease it with lower
// Q, and set to 0 below some threshold. May want to condition this in
// future on the variance/energy in UV channel.
if (cpi->oxcf.screen_content_mode && Q > 40) {
new_uv_delta_q = -(int)(0.15 * Q);
// Check range: magnitude of delta is 4 bits.
if (new_uv_delta_q < -15) {
new_uv_delta_q = -15;
}
}
update |= cm->uvdc_delta_q != new_uv_delta_q;
cm->uvdc_delta_q = new_uv_delta_q;
cm->uvac_delta_q = new_uv_delta_q;
/* Set Segment specific quatizers */
mbd->segment_feature_data[MB_LVL_ALT_Q][0] =
cpi->segment_feature_data[MB_LVL_ALT_Q][0];
mbd->segment_feature_data[MB_LVL_ALT_Q][1] =
cpi->segment_feature_data[MB_LVL_ALT_Q][1];
mbd->segment_feature_data[MB_LVL_ALT_Q][2] =
cpi->segment_feature_data[MB_LVL_ALT_Q][2];
mbd->segment_feature_data[MB_LVL_ALT_Q][3] =
cpi->segment_feature_data[MB_LVL_ALT_Q][3];
/* quantizer has to be reinitialized for any delta_q changes */
if (update) vp8cx_init_quantizer(cpi);
}