Merge "Cleaning up entropy probability update in encoder."
diff --git a/examples.mk b/examples.mk
index 36d20df..2600a9d 100644
--- a/examples.mk
+++ b/examples.mk
@@ -37,7 +37,7 @@
vpxdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
vpxdec.DESCRIPTION = Full featured decoder
UTILS-$(CONFIG_ENCODERS) += vpxenc.c
-vpxenc.SRCS += args.c args.h y4minput.c y4minput.h
+vpxenc.SRCS += args.c args.h y4minput.c y4minput.h vpxenc.h
vpxenc.SRCS += ivfdec.c ivfdec.h
vpxenc.SRCS += ivfenc.c ivfenc.h
vpxenc.SRCS += tools_common.c tools_common.h
diff --git a/test/convolve_test.cc b/test/convolve_test.cc
index abeb4bd..9ab60b1 100644
--- a/test/convolve_test.cc
+++ b/test/convolve_test.cc
@@ -44,6 +44,8 @@
convolve_fn_t hv8_avg_;
};
+typedef std::tr1::tuple<int, int, const ConvolveFunctions*> convolve_param_t;
+
// Reference 8-tap subpixel filter, slightly modified to fit into this test.
#define VP9_FILTER_WEIGHT 128
#define VP9_FILTER_SHIFT 7
@@ -169,7 +171,7 @@
output_width, output_height);
}
-class ConvolveTest : public PARAMS(int, int, const ConvolveFunctions*) {
+class ConvolveTest : public ::testing::TestWithParam<convolve_param_t> {
public:
static void SetUpTestCase() {
// Force input_ to be unaligned, output to be 16 byte aligned.
diff --git a/test/dct16x16_test.cc b/test/dct16x16_test.cc
index b61df8d..5496d0b 100644
--- a/test/dct16x16_test.cc
+++ b/test/dct16x16_test.cc
@@ -264,6 +264,9 @@
typedef void (*iht_t) (const int16_t *in, uint8_t *out, int stride,
int tx_type);
+typedef std::tr1::tuple<fdct_t, idct_t, int> dct_16x16_param_t;
+typedef std::tr1::tuple<fht_t, iht_t, int> ht_16x16_param_t;
+
void fdct16x16_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
vp9_fdct16x16_c(in, out, stride);
}
@@ -412,8 +415,9 @@
fht_t fwd_txfm_ref;
};
-class Trans16x16DCT : public Trans16x16TestBase,
- public PARAMS(fdct_t, idct_t, int) {
+class Trans16x16DCT
+ : public Trans16x16TestBase,
+ public ::testing::TestWithParam<dct_16x16_param_t> {
public:
virtual ~Trans16x16DCT() {}
@@ -454,8 +458,9 @@
RunInvAccuracyCheck();
}
-class Trans16x16HT : public Trans16x16TestBase,
- public PARAMS(fht_t, iht_t, int) {
+class Trans16x16HT
+ : public Trans16x16TestBase,
+ public ::testing::TestWithParam<ht_16x16_param_t> {
public:
virtual ~Trans16x16HT() {}
diff --git a/test/dct32x32_test.cc b/test/dct32x32_test.cc
index 1e792da..2df3b6f 100644
--- a/test/dct32x32_test.cc
+++ b/test/dct32x32_test.cc
@@ -77,7 +77,9 @@
typedef void (*fwd_txfm_t)(const int16_t *in, int16_t *out, int stride);
typedef void (*inv_txfm_t)(const int16_t *in, uint8_t *out, int stride);
-class Trans32x32Test : public PARAMS(fwd_txfm_t, inv_txfm_t, int) {
+typedef std::tr1::tuple<fwd_txfm_t, inv_txfm_t, int> trans_32x32_param_t;
+
+class Trans32x32Test : public ::testing::TestWithParam<trans_32x32_param_t> {
public:
virtual ~Trans32x32Test() {}
virtual void SetUp() {
diff --git a/test/fdct4x4_test.cc b/test/fdct4x4_test.cc
index 9d8b0bd..67426eb 100644
--- a/test/fdct4x4_test.cc
+++ b/test/fdct4x4_test.cc
@@ -36,6 +36,9 @@
typedef void (*iht_t) (const int16_t *in, uint8_t *out, int stride,
int tx_type);
+typedef std::tr1::tuple<fdct_t, idct_t, int> dct_4x4_param_t;
+typedef std::tr1::tuple<fht_t, iht_t, int> ht_4x4_param_t;
+
void fdct4x4_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
vp9_fdct4x4_c(in, out, stride);
}
@@ -183,7 +186,7 @@
class Trans4x4DCT
: public Trans4x4TestBase,
- public PARAMS(fdct_t, idct_t, int) {
+ public ::testing::TestWithParam<dct_4x4_param_t> {
public:
virtual ~Trans4x4DCT() {}
@@ -226,7 +229,7 @@
class Trans4x4HT
: public Trans4x4TestBase,
- public PARAMS(fht_t, iht_t, int) {
+ public ::testing::TestWithParam<ht_4x4_param_t> {
public:
virtual ~Trans4x4HT() {}
diff --git a/test/fdct8x8_test.cc b/test/fdct8x8_test.cc
index 3777b11..19ffe26 100644
--- a/test/fdct8x8_test.cc
+++ b/test/fdct8x8_test.cc
@@ -35,6 +35,9 @@
typedef void (*iht_t) (const int16_t *in, uint8_t *out, int stride,
int tx_type);
+typedef std::tr1::tuple<fdct_t, idct_t, int> dct_8x8_param_t;
+typedef std::tr1::tuple<fht_t, iht_t, int> ht_8x8_param_t;
+
void fdct8x8_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
vp9_fdct8x8_c(in, out, stride);
}
@@ -215,8 +218,9 @@
fht_t fwd_txfm_ref;
};
-class FwdTrans8x8DCT : public FwdTrans8x8TestBase,
- public PARAMS(fdct_t, idct_t, int) {
+class FwdTrans8x8DCT
+ : public FwdTrans8x8TestBase,
+ public ::testing::TestWithParam<dct_8x8_param_t> {
public:
virtual ~FwdTrans8x8DCT() {}
@@ -254,8 +258,9 @@
RunExtremalCheck();
}
-class FwdTrans8x8HT : public FwdTrans8x8TestBase,
- public PARAMS(fht_t, iht_t, int) {
+class FwdTrans8x8HT
+ : public FwdTrans8x8TestBase,
+ public ::testing::TestWithParam<ht_8x8_param_t> {
public:
virtual ~FwdTrans8x8HT() {}
diff --git a/test/sixtap_predict_test.cc b/test/sixtap_predict_test.cc
index ee4faac..655146d 100644
--- a/test/sixtap_predict_test.cc
+++ b/test/sixtap_predict_test.cc
@@ -32,7 +32,10 @@
uint8_t *dst_ptr,
int dst_pitch);
-class SixtapPredictTest : public PARAMS(int, int, sixtap_predict_fn_t) {
+typedef std::tr1::tuple<int, int, sixtap_predict_fn_t> sixtap_predict_param_t;
+
+class SixtapPredictTest
+ : public ::testing::TestWithParam<sixtap_predict_param_t> {
public:
static void SetUpTestCase() {
src_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kSrcSize));
diff --git a/test/util.h b/test/util.h
index 4d7f3d4..3c45721 100644
--- a/test/util.h
+++ b/test/util.h
@@ -17,7 +17,6 @@
#include "vpx/vpx_image.h"
// Macros
-#define PARAMS(...) ::testing::TestWithParam< std::tr1::tuple< __VA_ARGS__ > >
#define GET_PARAM(k) std::tr1::get< k >(GetParam())
static double compute_psnr(const vpx_image_t *img1,
diff --git a/test/vp9_subtract_test.cc b/test/vp9_subtract_test.cc
index 332a839..e4c4cfe 100644
--- a/test/vp9_subtract_test.cc
+++ b/test/vp9_subtract_test.cc
@@ -41,8 +41,8 @@
// FIXME(rbultje) split in its own file
for (BLOCK_SIZE bsize = BLOCK_4X4; bsize < BLOCK_SIZES;
bsize = static_cast<BLOCK_SIZE>(static_cast<int>(bsize) + 1)) {
- const int block_width = 4 << b_width_log2(bsize);
- const int block_height = 4 << b_height_log2(bsize);
+ const int block_width = 4 * num_4x4_blocks_wide_lookup[bsize];
+ const int block_height = 4 * num_4x4_blocks_high_lookup[bsize];
int16_t *diff = reinterpret_cast<int16_t *>(
vpx_memalign(16, sizeof(*diff) * block_width * block_height * 2));
uint8_t *pred = reinterpret_cast<uint8_t *>(
diff --git a/vp9/common/arm/neon/vp9_loopfilter_16_neon.asm b/vp9/common/arm/neon/vp9_loopfilter_16_neon.asm
new file mode 100644
index 0000000..e559272
--- /dev/null
+++ b/vp9/common/arm/neon/vp9_loopfilter_16_neon.asm
@@ -0,0 +1,198 @@
+;
+; Copyright (c) 2013 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.
+;
+
+ EXPORT |vp9_loop_filter_horizontal_edge_16_neon|
+ ARM
+
+ AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;void vp9_loop_filter_horizontal_edge_16_neon(uint8_t *s, int p,
+; const uint8_t *blimit0,
+; const uint8_t *limit0,
+; const uint8_t *thresh0,
+; const uint8_t *blimit1,
+; const uint8_t *limit1,
+; const uint8_t *thresh1)
+; r0 uint8_t *s,
+; r1 int p,
+; r2 const uint8_t *blimit0,
+; r3 const uint8_t *limit0,
+; sp const uint8_t *thresh0,
+; sp+4 const uint8_t *blimit1,
+; sp+8 const uint8_t *limit1,
+; sp+12 const uint8_t *thresh1,
+
+|vp9_loop_filter_horizontal_edge_16_neon| PROC
+ push {lr}
+
+ ldr r12, [sp, #4] ; load thresh0
+ vld1.8 {d0}, [r2] ; load blimit0 to first half q
+ vld1.8 {d2}, [r3] ; load limit0 to first half q
+
+ add r1, r1, r1 ; double pitch
+ ldr r2, [sp, #8] ; load blimit1
+
+ vld1.8 {d4}, [r12] ; load thresh0 to first half q
+
+ ldr r3, [sp, #12] ; load limit1
+ ldr r12, [sp, #16] ; load thresh1
+ vld1.8 {d1}, [r2] ; load blimit1 to 2nd half q
+
+ sub r2, r0, r1, lsl #1 ; s[-4 * p]
+
+ vld1.8 {d3}, [r3] ; load limit1 to 2nd half q
+ vld1.8 {d5}, [r12] ; load thresh1 to 2nd half q
+
+ vpush {d8-d15} ; save neon registers
+
+ add r3, r2, r1, lsr #1 ; s[-3 * p]
+
+ vld1.u8 {q3}, [r2@64], r1 ; p3
+ vld1.u8 {q4}, [r3@64], r1 ; p2
+ vld1.u8 {q5}, [r2@64], r1 ; p1
+ vld1.u8 {q6}, [r3@64], r1 ; p0
+ vld1.u8 {q7}, [r2@64], r1 ; q0
+ vld1.u8 {q8}, [r3@64], r1 ; q1
+ vld1.u8 {q9}, [r2@64] ; q2
+ vld1.u8 {q10}, [r3@64] ; q3
+
+ sub r2, r2, r1, lsl #1
+ sub r3, r3, r1, lsl #1
+
+ bl vp9_loop_filter_neon_16
+
+ vst1.u8 {q5}, [r2@64], r1 ; store op1
+ vst1.u8 {q6}, [r3@64], r1 ; store op0
+ vst1.u8 {q7}, [r2@64], r1 ; store oq0
+ vst1.u8 {q8}, [r3@64], r1 ; store oq1
+
+ vpop {d8-d15} ; restore neon registers
+
+ pop {pc}
+ ENDP ; |vp9_loop_filter_horizontal_edge_16_neon|
+
+; void vp9_loop_filter_neon_16();
+; This is a helper function for the loopfilters. The invidual functions do the
+; necessary load, transpose (if necessary) and store. This function uses
+; registers d8-d15, so the calling function must save those registers.
+;
+; r0-r3, r12 PRESERVE
+; q0 blimit
+; q1 limit
+; q2 thresh
+; q3 p3
+; q4 p2
+; q5 p1
+; q6 p0
+; q7 q0
+; q8 q1
+; q9 q2
+; q10 q3
+;
+; Outputs:
+; q5 op1
+; q6 op0
+; q7 oq0
+; q8 oq1
+|vp9_loop_filter_neon_16| PROC
+
+ ; filter_mask
+ vabd.u8 q11, q3, q4 ; m1 = abs(p3 - p2)
+ vabd.u8 q12, q4, q5 ; m2 = abs(p2 - p1)
+ vabd.u8 q13, q5, q6 ; m3 = abs(p1 - p0)
+ vabd.u8 q14, q8, q7 ; m4 = abs(q1 - q0)
+ vabd.u8 q3, q9, q8 ; m5 = abs(q2 - q1)
+ vabd.u8 q4, q10, q9 ; m6 = abs(q3 - q2)
+
+ ; only compare the largest value to limit
+ vmax.u8 q11, q11, q12 ; m1 = max(m1, m2)
+ vmax.u8 q12, q13, q14 ; m2 = max(m3, m4)
+
+ vabd.u8 q9, q6, q7 ; abs(p0 - q0)
+
+ vmax.u8 q3, q3, q4 ; m3 = max(m5, m6)
+
+ vmov.u8 q10, #0x80
+
+ vmax.u8 q15, q11, q12 ; m1 = max(m1, m2)
+
+ vcgt.u8 q13, q13, q2 ; (abs(p1 - p0) > thresh)*-1
+ vcgt.u8 q14, q14, q2 ; (abs(q1 - q0) > thresh)*-1
+ vmax.u8 q15, q15, q3 ; m1 = max(m1, m3)
+
+ vabd.u8 q2, q5, q8 ; a = abs(p1 - q1)
+ vqadd.u8 q9, q9, q9 ; b = abs(p0 - q0) * 2
+
+ veor q7, q7, q10 ; qs0
+
+ vcge.u8 q15, q1, q15 ; abs(m1) > limit
+
+ vshr.u8 q2, q2, #1 ; a = a / 2
+ veor q6, q6, q10 ; ps0
+
+ veor q5, q5, q10 ; ps1
+ vqadd.u8 q9, q9, q2 ; a = b + a
+
+ veor q8, q8, q10 ; qs1
+
+ vmov.u8 q4, #3
+
+ vsubl.s8 q2, d14, d12 ; ( qs0 - ps0)
+ vsubl.s8 q11, d15, d13
+
+ vcge.u8 q9, q0, q9 ; a > blimit
+
+ vqsub.s8 q1, q5, q8 ; filter = clamp(ps1-qs1)
+ vorr q14, q13, q14 ; hevmask
+
+ vmul.i16 q2, q2, q4 ; 3 * ( qs0 - ps0)
+ vmul.i16 q11, q11, q4
+
+ vand q1, q1, q14 ; filter &= hev
+ vand q15, q15, q9 ; filter_mask
+
+ vaddw.s8 q2, q2, d2 ; filter + 3 * (qs0 - ps0)
+ vaddw.s8 q11, q11, d3
+
+ vmov.u8 q9, #4
+
+ ; filter = clamp(filter + 3 * ( qs0 - ps0))
+ vqmovn.s16 d2, q2
+ vqmovn.s16 d3, q11
+ vand q1, q1, q15 ; filter &= mask
+
+ vqadd.s8 q2, q1, q4 ; filter2 = clamp(filter+3)
+ vqadd.s8 q1, q1, q9 ; filter1 = clamp(filter+4)
+ vshr.s8 q2, q2, #3 ; filter2 >>= 3
+ vshr.s8 q1, q1, #3 ; filter1 >>= 3
+
+
+ vqadd.s8 q11, q6, q2 ; u = clamp(ps0 + filter2)
+ vqsub.s8 q0, q7, q1 ; u = clamp(qs0 - filter1)
+
+ ; outer tap adjustments
+ vrshr.s8 q1, q1, #1 ; filter = ++filter1 >> 1
+
+ veor q6, q11, q10 ; *op0 = u^0x80
+
+ vbic q1, q1, q14 ; filter &= ~hev
+
+ vqadd.s8 q13, q5, q1 ; u = clamp(ps1 + filter)
+ vqsub.s8 q12, q8, q1 ; u = clamp(qs1 - filter)
+
+
+ veor q7, q0, q10 ; *oq0 = u^0x80
+ veor q5, q13, q10 ; *op1 = u^0x80
+ veor q8, q12, q10 ; *oq1 = u^0x80
+
+ bx lr
+ ENDP ; |vp9_loop_filter_neon_16|
+
+ END
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 121947b..df963d1 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -286,16 +286,6 @@
return bs;
}
-static INLINE int plane_block_width(BLOCK_SIZE bsize,
- const struct macroblockd_plane* plane) {
- return 4 << (b_width_log2(bsize) - plane->subsampling_x);
-}
-
-static INLINE int plane_block_height(BLOCK_SIZE bsize,
- const struct macroblockd_plane* plane) {
- return 4 << (b_height_log2(bsize) - plane->subsampling_y);
-}
-
typedef void (*foreach_transformed_block_visitor)(int plane, int block,
BLOCK_SIZE plane_bsize,
TX_SIZE tx_size,
@@ -394,21 +384,18 @@
}
static void extend_for_intra(MACROBLOCKD *xd, BLOCK_SIZE plane_bsize,
- int plane, int block, TX_SIZE tx_size) {
+ int plane, int aoff, int loff) {
struct macroblockd_plane *const pd = &xd->plane[plane];
uint8_t *const buf = pd->dst.buf;
const int stride = pd->dst.stride;
-
- int x, y;
- txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x, &y);
- x = x * 4 - 1;
- y = y * 4 - 1;
+ const int x = aoff * 4 - 1;
+ const int y = loff * 4 - 1;
// Copy a pixel into the umv if we are in a situation where the block size
// extends into the UMV.
// TODO(JBB): Should be able to do the full extend in place so we don't have
// to do this multiple times.
if (xd->mb_to_right_edge < 0) {
- const int bw = 4 << b_width_log2(plane_bsize);
+ const int bw = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
const int umv_border_start = bw + (xd->mb_to_right_edge >>
(3 + pd->subsampling_x));
@@ -419,7 +406,7 @@
if (xd->mb_to_bottom_edge < 0) {
if (xd->left_available || x >= 0) {
- const int bh = 4 << b_height_log2(plane_bsize);
+ const int bh = 4 * num_4x4_blocks_high_lookup[plane_bsize];
const int umv_border_start =
bh + (xd->mb_to_bottom_edge >> (3 + pd->subsampling_y));
diff --git a/vp9/common/vp9_entropy.c b/vp9/common/vp9_entropy.c
index 82aa77e..0f978cc 100644
--- a/vp9/common/vp9_entropy.c
+++ b/vp9/common/vp9_entropy.c
@@ -128,6 +128,20 @@
-DCT_VAL_CATEGORY5, -DCT_VAL_CATEGORY6 /* 10 = CAT_FIVE */
};
+// Unconstrained Node Tree
+const vp9_tree_index vp9_coef_con_tree[TREE_SIZE(MAX_ENTROPY_TOKENS)] = {
+ 2, 6, /* 0 = LOW_VAL */
+ -TWO_TOKEN, 4, /* 1 = TWO */
+ -THREE_TOKEN, -FOUR_TOKEN, /* 2 = THREE */
+ 8, 10, /* 3 = HIGH_LOW */
+ -DCT_VAL_CATEGORY1, -DCT_VAL_CATEGORY2, /* 4 = CAT_ONE */
+ 12, 14, /* 5 = CAT_THREEFOUR */
+ -DCT_VAL_CATEGORY3, -DCT_VAL_CATEGORY4, /* 6 = CAT_THREE */
+ -DCT_VAL_CATEGORY5, -DCT_VAL_CATEGORY6 /* 7 = CAT_FIVE */
+};
+
+
+
struct vp9_token vp9_coef_encodings[MAX_ENTROPY_TOKENS];
/* Trees for extra bits. Probabilities are constant and
@@ -158,143 +172,11 @@
// beta = 8
-
-static const vp9_prob pareto8_probs[COEFPROB_MODELS][MODEL_NODES] = {
- { 3, 86, 128, 6, 86, 23, 88, 29},
- { 9, 86, 129, 17, 88, 61, 94, 76},
- { 15, 87, 129, 28, 89, 93, 100, 110},
- { 20, 88, 130, 38, 91, 118, 106, 136},
- { 26, 89, 131, 48, 92, 139, 111, 156},
- { 31, 90, 131, 58, 94, 156, 117, 171},
- { 37, 90, 132, 66, 95, 171, 122, 184},
- { 42, 91, 132, 75, 97, 183, 127, 194},
- { 47, 92, 133, 83, 98, 193, 132, 202},
- { 52, 93, 133, 90, 100, 201, 137, 208},
- { 57, 94, 134, 98, 101, 208, 142, 214},
- { 62, 94, 135, 105, 103, 214, 146, 218},
- { 66, 95, 135, 111, 104, 219, 151, 222},
- { 71, 96, 136, 117, 106, 224, 155, 225},
- { 76, 97, 136, 123, 107, 227, 159, 228},
- { 80, 98, 137, 129, 109, 231, 162, 231},
- { 84, 98, 138, 134, 110, 234, 166, 233},
- { 89, 99, 138, 140, 112, 236, 170, 235},
- { 93, 100, 139, 145, 113, 238, 173, 236},
- { 97, 101, 140, 149, 115, 240, 176, 238},
- {101, 102, 140, 154, 116, 242, 179, 239},
- {105, 103, 141, 158, 118, 243, 182, 240},
- {109, 104, 141, 162, 119, 244, 185, 241},
- {113, 104, 142, 166, 120, 245, 187, 242},
- {116, 105, 143, 170, 122, 246, 190, 243},
- {120, 106, 143, 173, 123, 247, 192, 244},
- {123, 107, 144, 177, 125, 248, 195, 244},
- {127, 108, 145, 180, 126, 249, 197, 245},
- {130, 109, 145, 183, 128, 249, 199, 245},
- {134, 110, 146, 186, 129, 250, 201, 246},
- {137, 111, 147, 189, 131, 251, 203, 246},
- {140, 112, 147, 192, 132, 251, 205, 247},
- {143, 113, 148, 194, 133, 251, 207, 247},
- {146, 114, 149, 197, 135, 252, 208, 248},
- {149, 115, 149, 199, 136, 252, 210, 248},
- {152, 115, 150, 201, 138, 252, 211, 248},
- {155, 116, 151, 204, 139, 253, 213, 249},
- {158, 117, 151, 206, 140, 253, 214, 249},
- {161, 118, 152, 208, 142, 253, 216, 249},
- {163, 119, 153, 210, 143, 253, 217, 249},
- {166, 120, 153, 212, 144, 254, 218, 250},
- {168, 121, 154, 213, 146, 254, 220, 250},
- {171, 122, 155, 215, 147, 254, 221, 250},
- {173, 123, 155, 217, 148, 254, 222, 250},
- {176, 124, 156, 218, 150, 254, 223, 250},
- {178, 125, 157, 220, 151, 254, 224, 251},
- {180, 126, 157, 221, 152, 254, 225, 251},
- {183, 127, 158, 222, 153, 254, 226, 251},
- {185, 128, 159, 224, 155, 255, 227, 251},
- {187, 129, 160, 225, 156, 255, 228, 251},
- {189, 131, 160, 226, 157, 255, 228, 251},
- {191, 132, 161, 227, 159, 255, 229, 251},
- {193, 133, 162, 228, 160, 255, 230, 252},
- {195, 134, 163, 230, 161, 255, 231, 252},
- {197, 135, 163, 231, 162, 255, 231, 252},
- {199, 136, 164, 232, 163, 255, 232, 252},
- {201, 137, 165, 233, 165, 255, 233, 252},
- {202, 138, 166, 233, 166, 255, 233, 252},
- {204, 139, 166, 234, 167, 255, 234, 252},
- {206, 140, 167, 235, 168, 255, 235, 252},
- {207, 141, 168, 236, 169, 255, 235, 252},
- {209, 142, 169, 237, 171, 255, 236, 252},
- {210, 144, 169, 237, 172, 255, 236, 252},
- {212, 145, 170, 238, 173, 255, 237, 252},
- {214, 146, 171, 239, 174, 255, 237, 253},
- {215, 147, 172, 240, 175, 255, 238, 253},
- {216, 148, 173, 240, 176, 255, 238, 253},
- {218, 149, 173, 241, 177, 255, 239, 253},
- {219, 150, 174, 241, 179, 255, 239, 253},
- {220, 152, 175, 242, 180, 255, 240, 253},
- {222, 153, 176, 242, 181, 255, 240, 253},
- {223, 154, 177, 243, 182, 255, 240, 253},
- {224, 155, 178, 244, 183, 255, 241, 253},
- {225, 156, 178, 244, 184, 255, 241, 253},
- {226, 158, 179, 244, 185, 255, 242, 253},
- {228, 159, 180, 245, 186, 255, 242, 253},
- {229, 160, 181, 245, 187, 255, 242, 253},
- {230, 161, 182, 246, 188, 255, 243, 253},
- {231, 163, 183, 246, 189, 255, 243, 253},
- {232, 164, 184, 247, 190, 255, 243, 253},
- {233, 165, 185, 247, 191, 255, 244, 253},
- {234, 166, 185, 247, 192, 255, 244, 253},
- {235, 168, 186, 248, 193, 255, 244, 253},
- {236, 169, 187, 248, 194, 255, 244, 253},
- {236, 170, 188, 248, 195, 255, 245, 253},
- {237, 171, 189, 249, 196, 255, 245, 254},
- {238, 173, 190, 249, 197, 255, 245, 254},
- {239, 174, 191, 249, 198, 255, 245, 254},
- {240, 175, 192, 249, 199, 255, 246, 254},
- {240, 177, 193, 250, 200, 255, 246, 254},
- {241, 178, 194, 250, 201, 255, 246, 254},
- {242, 179, 195, 250, 202, 255, 246, 254},
- {242, 181, 196, 250, 203, 255, 247, 254},
- {243, 182, 197, 251, 204, 255, 247, 254},
- {244, 184, 198, 251, 205, 255, 247, 254},
- {244, 185, 199, 251, 206, 255, 247, 254},
- {245, 186, 200, 251, 207, 255, 247, 254},
- {246, 188, 201, 252, 207, 255, 248, 254},
- {246, 189, 202, 252, 208, 255, 248, 254},
- {247, 191, 203, 252, 209, 255, 248, 254},
- {247, 192, 204, 252, 210, 255, 248, 254},
- {248, 194, 205, 252, 211, 255, 248, 254},
- {248, 195, 206, 252, 212, 255, 249, 254},
- {249, 197, 207, 253, 213, 255, 249, 254},
- {249, 198, 208, 253, 214, 255, 249, 254},
- {250, 200, 210, 253, 215, 255, 249, 254},
- {250, 201, 211, 253, 215, 255, 249, 254},
- {250, 203, 212, 253, 216, 255, 249, 254},
- {251, 204, 213, 253, 217, 255, 250, 254},
- {251, 206, 214, 254, 218, 255, 250, 254},
- {252, 207, 216, 254, 219, 255, 250, 254},
- {252, 209, 217, 254, 220, 255, 250, 254},
- {252, 211, 218, 254, 221, 255, 250, 254},
- {253, 213, 219, 254, 222, 255, 250, 254},
- {253, 214, 221, 254, 223, 255, 250, 254},
- {253, 216, 222, 254, 224, 255, 251, 254},
- {253, 218, 224, 254, 225, 255, 251, 254},
- {254, 220, 225, 254, 225, 255, 251, 254},
- {254, 222, 227, 255, 226, 255, 251, 254},
- {254, 224, 228, 255, 227, 255, 251, 254},
- {254, 226, 230, 255, 228, 255, 251, 254},
- {255, 228, 231, 255, 230, 255, 251, 254},
- {255, 230, 233, 255, 231, 255, 252, 254},
- {255, 232, 235, 255, 232, 255, 252, 254},
- {255, 235, 237, 255, 233, 255, 252, 254},
- {255, 238, 240, 255, 235, 255, 252, 255},
- {255, 241, 243, 255, 236, 255, 252, 254},
- {255, 246, 247, 255, 239, 255, 253, 255}
-};
-
-// This table is an expansion of the table : modelcoefprobs_pareto8
-// to all 255 probabilities using the code as follows to do the expansion:
-// tree_probs[i] = (model[l][i - UNCONSTRAINED_NODES] +
-// model[l + 1][i - UNCONSTRAINED_NODES]) >> 1;
-const vp9_prob vp9_pareto8_full[255][MODEL_NODES] = {
+// Every odd line in this table can be generated from the even lines
+// by averaging :
+// vp9_pareto8_full[l][node] = ( vp9_pareto8_full[l-1][node] +
+// vp9_pareto8_full[l+1][node] ) >> 1;
+const vp9_prob vp9_pareto8_full[256][MODEL_NODES] = {
{ 3, 86, 128, 6, 86, 23, 88, 29},
{ 6, 86, 128, 11, 87, 42, 91, 52},
{ 9, 86, 129, 17, 88, 61, 94, 76},
@@ -550,19 +432,12 @@
{255, 241, 243, 255, 236, 255, 252, 254},
{255, 243, 245, 255, 237, 255, 252, 254},
{255, 246, 247, 255, 239, 255, 253, 255},
+ {255, 246, 247, 255, 239, 255, 253, 255},
};
static void extend_to_full_distribution(vp9_prob *probs, vp9_prob p) {
- const int l = (p - 1) / 2;
- if (p & 1) {
- // Just copy
- vpx_memcpy(probs, pareto8_probs[l], MODEL_NODES * sizeof(vp9_prob));
- } else {
- // Interpolate
- int i;
- for (i = 0; i < MODEL_NODES; ++i)
- probs[i] = (pareto8_probs[l][i] + pareto8_probs[l + 1][i]) >> 1;
- }
+ vpx_memcpy(probs, vp9_pareto8_full[p = 0 ? 0 : p - 1],
+ MODEL_NODES * sizeof(vp9_prob));
}
void vp9_model_to_full_probs(const vp9_prob *model, vp9_prob *full) {
diff --git a/vp9/common/vp9_entropy.h b/vp9/common/vp9_entropy.h
index 0370b32..b98bef0 100644
--- a/vp9/common/vp9_entropy.h
+++ b/vp9/common/vp9_entropy.h
@@ -46,6 +46,8 @@
extern const vp9_tree_index vp9_coef_tree[TREE_SIZE(MAX_ENTROPY_TOKENS)];
+extern const vp9_tree_index vp9_coef_con_tree[];
+
#define DCT_EOB_MODEL_TOKEN 3 /* EOB Extra Bits 0+0 */
extern const vp9_tree_index vp9_coefmodel_tree[];
@@ -143,7 +145,7 @@
#define PIVOT_NODE 2 // which node is pivot
#define MODEL_NODES (ENTROPY_NODES - UNCONSTRAINED_NODES)
-extern const vp9_prob vp9_pareto8_full[255][MODEL_NODES];
+extern const vp9_prob vp9_pareto8_full[256][MODEL_NODES];
typedef vp9_prob vp9_coeff_probs_model[REF_TYPES][COEF_BANDS]
[PREV_COEF_CONTEXTS]
diff --git a/vp9/common/vp9_entropymv.h b/vp9/common/vp9_entropymv.h
index d843f5b..b62f7c4 100644
--- a/vp9/common/vp9_entropymv.h
+++ b/vp9/common/vp9_entropymv.h
@@ -62,6 +62,7 @@
#define CLASS0_BITS 1 /* bits at integer precision for class 0 */
#define CLASS0_SIZE (1 << CLASS0_BITS)
#define MV_OFFSET_BITS (MV_CLASSES + CLASS0_BITS - 2)
+#define MV_FP_SIZE 4
#define MV_MAX_BITS (MV_CLASSES + CLASS0_BITS + 2)
#define MV_MAX ((1 << MV_MAX_BITS) - 1)
@@ -80,7 +81,7 @@
extern const vp9_tree_index vp9_mv_class0_tree[TREE_SIZE(CLASS0_SIZE)];
extern struct vp9_token vp9_mv_class0_encodings[CLASS0_SIZE];
-extern const vp9_tree_index vp9_mv_fp_tree[TREE_SIZE(4)];
+extern const vp9_tree_index vp9_mv_fp_tree[TREE_SIZE(MV_FP_SIZE)];
extern struct vp9_token vp9_mv_fp_encodings[4];
typedef struct {
@@ -88,8 +89,8 @@
vp9_prob classes[MV_CLASSES - 1];
vp9_prob class0[CLASS0_SIZE - 1];
vp9_prob bits[MV_OFFSET_BITS];
- vp9_prob class0_fp[CLASS0_SIZE][4 - 1];
- vp9_prob fp[4 - 1];
+ vp9_prob class0_fp[CLASS0_SIZE][MV_FP_SIZE - 1];
+ vp9_prob fp[MV_FP_SIZE - 1];
vp9_prob class0_hp;
vp9_prob hp;
} nmv_component;
@@ -116,8 +117,8 @@
unsigned int classes[MV_CLASSES];
unsigned int class0[CLASS0_SIZE];
unsigned int bits[MV_OFFSET_BITS][2];
- unsigned int class0_fp[CLASS0_SIZE][4];
- unsigned int fp[4];
+ unsigned int class0_fp[CLASS0_SIZE][MV_FP_SIZE];
+ unsigned int fp[MV_FP_SIZE];
unsigned int class0_hp[2];
unsigned int hp[2];
} nmv_component_counts;
diff --git a/vp9/common/vp9_idct.c b/vp9/common/vp9_idct.c
index 149362a..533f7f3 100644
--- a/vp9/common/vp9_idct.c
+++ b/vp9/common/vp9_idct.c
@@ -1345,43 +1345,37 @@
// coefficients. Use eobs to decide what to do.
// TODO(yunqingwang): "eobs = 1" case is also handled in vp9_short_idct8x8_c.
// Combine that with code here.
- if (eob) {
- if (eob == 1)
- // DC only DCT coefficient
- vp9_idct8x8_1_add(input, dest, stride);
- else if (eob <= 10)
- vp9_idct8x8_10_add(input, dest, stride);
- else
- vp9_idct8x8_64_add(input, dest, stride);
- }
+ if (eob == 1)
+ // DC only DCT coefficient
+ vp9_idct8x8_1_add(input, dest, stride);
+ else if (eob <= 10)
+ vp9_idct8x8_10_add(input, dest, stride);
+ else
+ vp9_idct8x8_64_add(input, dest, stride);
}
void vp9_idct16x16_add(const int16_t *input, uint8_t *dest, int stride,
int eob) {
/* The calculation can be simplified if there are not many non-zero dct
* coefficients. Use eobs to separate different cases. */
- if (eob) {
- if (eob == 1)
- /* DC only DCT coefficient. */
- vp9_idct16x16_1_add(input, dest, stride);
- else if (eob <= 10)
- vp9_idct16x16_10_add(input, dest, stride);
- else
- vp9_idct16x16_256_add(input, dest, stride);
- }
+ if (eob == 1)
+ /* DC only DCT coefficient. */
+ vp9_idct16x16_1_add(input, dest, stride);
+ else if (eob <= 10)
+ vp9_idct16x16_10_add(input, dest, stride);
+ else
+ vp9_idct16x16_256_add(input, dest, stride);
}
void vp9_idct32x32_add(const int16_t *input, uint8_t *dest, int stride,
int eob) {
- if (eob) {
- if (eob == 1)
- vp9_idct32x32_1_add(input, dest, stride);
- else if (eob <= 34)
- // non-zero coeff only in upper-left 8x8
- vp9_idct32x32_34_add(input, dest, stride);
- else
- vp9_idct32x32_1024_add(input, dest, stride);
- }
+ if (eob == 1)
+ vp9_idct32x32_1_add(input, dest, stride);
+ else if (eob <= 34)
+ // non-zero coeff only in upper-left 8x8
+ vp9_idct32x32_34_add(input, dest, stride);
+ else
+ vp9_idct32x32_1024_add(input, dest, stride);
}
// iht
@@ -1398,9 +1392,7 @@
if (tx_type == DCT_DCT) {
vp9_idct8x8_add(input, dest, stride, eob);
} else {
- if (eob > 0) {
- vp9_iht8x8_64_add(input, dest, stride, tx_type);
- }
+ vp9_iht8x8_64_add(input, dest, stride, tx_type);
}
}
@@ -1409,8 +1401,6 @@
if (tx_type == DCT_DCT) {
vp9_idct16x16_add(input, dest, stride, eob);
} else {
- if (eob > 0) {
- vp9_iht16x16_256_add(input, dest, stride, tx_type);
- }
+ vp9_iht16x16_256_add(input, dest, stride, tx_type);
}
}
diff --git a/vp9/common/vp9_idct.h b/vp9/common/vp9_idct.h
index 2b3f35f..183c50a 100644
--- a/vp9/common/vp9_idct.h
+++ b/vp9/common/vp9_idct.h
@@ -77,8 +77,7 @@
static INLINE int dct_const_round_shift(int input) {
int rv = ROUND_POWER_OF_TWO(input, DCT_CONST_BITS);
- assert(INT16_MIN <= rv && rv <= INT16_MAX);
- return rv;
+ return (int16_t)rv;
}
typedef void (*transform_1d)(const int16_t*, int16_t*);
diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c
index 8e13afb..0b48de2 100644
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -323,40 +323,111 @@
}
}
-static void filter_selectively_vert(uint8_t *s, int pitch,
- unsigned int mask_16x16,
- unsigned int mask_8x8,
- unsigned int mask_4x4,
- unsigned int mask_4x4_int,
- const loop_filter_info_n *lfi_n,
- const uint8_t *lfl) {
+static void filter_selectively_vert_row2(PLANE_TYPE plane_type,
+ uint8_t *s, int pitch,
+ unsigned int mask_16x16_l,
+ unsigned int mask_8x8_l,
+ unsigned int mask_4x4_l,
+ unsigned int mask_4x4_int_l,
+ const loop_filter_info_n *lfi_n,
+ const uint8_t *lfl) {
+ const int mask_shift = plane_type ? 4 : 8;
+ const int mask_cutoff = plane_type ? 0xf : 0xff;
+ const int lfl_forward = plane_type ? 4 : 8;
+
+ unsigned int mask_16x16_0 = mask_16x16_l & mask_cutoff;
+ unsigned int mask_8x8_0 = mask_8x8_l & mask_cutoff;
+ unsigned int mask_4x4_0 = mask_4x4_l & mask_cutoff;
+ unsigned int mask_4x4_int_0 = mask_4x4_int_l & mask_cutoff;
+ unsigned int mask_16x16_1 = (mask_16x16_l >> mask_shift) & mask_cutoff;
+ unsigned int mask_8x8_1 = (mask_8x8_l >> mask_shift) & mask_cutoff;
+ unsigned int mask_4x4_1 = (mask_4x4_l >> mask_shift) & mask_cutoff;
+ unsigned int mask_4x4_int_1 = (mask_4x4_int_l >> mask_shift) & mask_cutoff;
unsigned int mask;
- for (mask = mask_16x16 | mask_8x8 | mask_4x4 | mask_4x4_int;
- mask; mask >>= 1) {
- const loop_filter_thresh *lfi = lfi_n->lfthr + *lfl;
+ for (mask = mask_16x16_0 | mask_8x8_0 | mask_4x4_0 | mask_4x4_int_0 |
+ mask_16x16_1 | mask_8x8_1 | mask_4x4_1 | mask_4x4_int_1;
+ mask; mask >>= 1) {
+ const loop_filter_thresh *lfi0 = lfi_n->lfthr + *lfl;
+ const loop_filter_thresh *lfi1 = lfi_n->lfthr + *(lfl + lfl_forward);
+ // TODO(yunqingwang): count in loopfilter functions should be removed.
if (mask & 1) {
- if (mask_16x16 & 1) {
- vp9_mb_lpf_vertical_edge_w(s, pitch, lfi->mblim, lfi->lim,
- lfi->hev_thr);
- } else if (mask_8x8 & 1) {
- vp9_mbloop_filter_vertical_edge(s, pitch, lfi->mblim, lfi->lim,
- lfi->hev_thr, 1);
- } else if (mask_4x4 & 1) {
- vp9_loop_filter_vertical_edge(s, pitch, lfi->mblim, lfi->lim,
- lfi->hev_thr, 1);
+ if ((mask_16x16_0 | mask_16x16_1) & 1) {
+ if ((mask_16x16_0 & mask_16x16_1) & 1) {
+ // TODO(yunqingwang): Combine 2 calls as 1 wide filtering.
+ vp9_mb_lpf_vertical_edge_w(s, pitch, lfi0->mblim, lfi0->lim,
+ lfi0->hev_thr);
+ vp9_mb_lpf_vertical_edge_w(s + 8 *pitch, pitch, lfi1->mblim,
+ lfi1->lim, lfi1->hev_thr);
+ } else if (mask_16x16_0 & 1) {
+ vp9_mb_lpf_vertical_edge_w(s, pitch, lfi0->mblim, lfi0->lim,
+ lfi0->hev_thr);
+ } else {
+ vp9_mb_lpf_vertical_edge_w(s + 8 *pitch, pitch, lfi1->mblim,
+ lfi1->lim, lfi1->hev_thr);
+ }
+ }
+
+ if ((mask_8x8_0 | mask_8x8_1) & 1) {
+ if ((mask_8x8_0 & mask_8x8_1) & 1) {
+ // TODO(yunqingwang): Combine 2 calls as 1 wide filtering.
+ vp9_mbloop_filter_vertical_edge(s, pitch, lfi0->mblim, lfi0->lim,
+ lfi0->hev_thr, 1);
+ vp9_mbloop_filter_vertical_edge(s + 8 *pitch, pitch, lfi1->mblim,
+ lfi1->lim, lfi1->hev_thr, 1);
+ } else if (mask_8x8_0 & 1) {
+ vp9_mbloop_filter_vertical_edge(s, pitch, lfi0->mblim, lfi0->lim,
+ lfi0->hev_thr, 1);
+ } else {
+ vp9_mbloop_filter_vertical_edge(s + 8 *pitch, pitch, lfi1->mblim,
+ lfi1->lim, lfi1->hev_thr, 1);
+ }
+ }
+
+ if ((mask_4x4_0 | mask_4x4_1) & 1) {
+ if ((mask_4x4_0 & mask_4x4_1) & 1) {
+ // TODO(yunqingwang): Combine 2 calls as 1 wide filtering.
+ vp9_loop_filter_vertical_edge(s, pitch, lfi0->mblim, lfi0->lim,
+ lfi0->hev_thr, 1);
+ vp9_loop_filter_vertical_edge(s + 8 *pitch, pitch, lfi1->mblim,
+ lfi1->lim, lfi1->hev_thr, 1);
+ } else if (mask_4x4_0 & 1) {
+ vp9_loop_filter_vertical_edge(s, pitch, lfi0->mblim, lfi0->lim,
+ lfi0->hev_thr, 1);
+ } else {
+ vp9_loop_filter_vertical_edge(s + 8 *pitch, pitch, lfi1->mblim,
+ lfi1->lim, lfi1->hev_thr, 1);
+ }
+ }
+
+ if ((mask_4x4_int_0 | mask_4x4_int_1) & 1) {
+ if ((mask_4x4_int_0 & mask_4x4_int_1) & 1) {
+ // TODO(yunqingwang): Combine 2 calls as 1 wide filtering.
+ vp9_loop_filter_vertical_edge(s + 4, pitch, lfi0->mblim, lfi0->lim,
+ lfi0->hev_thr, 1);
+ vp9_loop_filter_vertical_edge(s + 8 *pitch + 4, pitch, lfi1->mblim,
+ lfi1->lim, lfi1->hev_thr, 1);
+ } else if (mask_4x4_int_0 & 1) {
+ vp9_loop_filter_vertical_edge(s + 4, pitch, lfi0->mblim, lfi0->lim,
+ lfi0->hev_thr, 1);
+ } else {
+ vp9_loop_filter_vertical_edge(s + 8 *pitch + 4, pitch, lfi1->mblim,
+ lfi1->lim, lfi1->hev_thr, 1);
+ }
}
}
- if (mask_4x4_int & 1)
- vp9_loop_filter_vertical_edge(s + 4, pitch, lfi->mblim, lfi->lim,
- lfi->hev_thr, 1);
+
s += 8;
lfl += 1;
- mask_16x16 >>= 1;
- mask_8x8 >>= 1;
- mask_4x4 >>= 1;
- mask_4x4_int >>= 1;
+ mask_16x16_0 >>= 1;
+ mask_8x8_0 >>= 1;
+ mask_4x4_0 >>= 1;
+ mask_4x4_int_0 >>= 1;
+ mask_16x16_1 >>= 1;
+ mask_8x8_1 >>= 1;
+ mask_4x4_1 >>= 1;
+ mask_4x4_int_1 >>= 1;
}
}
@@ -863,6 +934,43 @@
return filter_level;
}
+static void filter_selectively_vert(uint8_t *s, int pitch,
+ unsigned int mask_16x16,
+ unsigned int mask_8x8,
+ unsigned int mask_4x4,
+ unsigned int mask_4x4_int,
+ const loop_filter_info_n *lfi_n,
+ const uint8_t *lfl) {
+ unsigned int mask;
+
+ for (mask = mask_16x16 | mask_8x8 | mask_4x4 | mask_4x4_int;
+ mask; mask >>= 1) {
+ const loop_filter_thresh *lfi = lfi_n->lfthr + *lfl;
+
+ if (mask & 1) {
+ if (mask_16x16 & 1) {
+ vp9_mb_lpf_vertical_edge_w(s, pitch, lfi->mblim, lfi->lim,
+ lfi->hev_thr);
+ } else if (mask_8x8 & 1) {
+ vp9_mbloop_filter_vertical_edge(s, pitch, lfi->mblim, lfi->lim,
+ lfi->hev_thr, 1);
+ } else if (mask_4x4 & 1) {
+ vp9_loop_filter_vertical_edge(s, pitch, lfi->mblim, lfi->lim,
+ lfi->hev_thr, 1);
+ }
+ }
+ if (mask_4x4_int & 1)
+ vp9_loop_filter_vertical_edge(s + 4, pitch, lfi->mblim, lfi->lim,
+ lfi->hev_thr, 1);
+ s += 8;
+ lfl += 1;
+ mask_16x16 >>= 1;
+ mask_8x8 >>= 1;
+ mask_4x4 >>= 1;
+ mask_4x4_int >>= 1;
+ }
+}
+
static void filter_block_plane_non420(VP9_COMMON *cm,
struct macroblockd_plane *plane,
MODE_INFO **mi_8x8,
@@ -1008,7 +1116,6 @@
LOOP_FILTER_MASK *lfm) {
struct buf_2d *const dst = &plane->dst;
uint8_t* const dst0 = dst->buf;
- unsigned int mask_4x4_int_row[MI_BLOCK_SIZE] = {0};
int r, c;
if (!plane->plane_type) {
@@ -1017,23 +1124,27 @@
uint64_t mask_4x4 = lfm->left_y[TX_4X4];
uint64_t mask_4x4_int = lfm->int_4x4_y;
- // Vertical pass
- for (r = 0; r < MI_BLOCK_SIZE && mi_row + r < cm->mi_rows; r++) {
- mask_4x4_int_row[r] = mask_4x4_int & 0xff;
+ // Vertical pass: do 2 rows at one time
+ for (r = 0; r < MI_BLOCK_SIZE && mi_row + r < cm->mi_rows; r += 2) {
+ unsigned int mask_16x16_l = mask_16x16 & 0xffff;
+ unsigned int mask_8x8_l = mask_8x8 & 0xffff;
+ unsigned int mask_4x4_l = mask_4x4 & 0xffff;
+ unsigned int mask_4x4_int_l = mask_4x4_int & 0xffff;
// Disable filtering on the leftmost column
- filter_selectively_vert(dst->buf, dst->stride,
- mask_16x16 & 0xff,
- mask_8x8 & 0xff,
- mask_4x4 & 0xff,
- mask_4x4_int_row[r],
- &cm->lf_info, &lfm->lfl_y[r << 3]);
+ filter_selectively_vert_row2(plane->plane_type,
+ dst->buf, dst->stride,
+ mask_16x16_l,
+ mask_8x8_l,
+ mask_4x4_l,
+ mask_4x4_int_l,
+ &cm->lf_info, &lfm->lfl_y[r << 3]);
- dst->buf += 8 * dst->stride;
- mask_16x16 >>= 8;
- mask_8x8 >>= 8;
- mask_4x4 >>= 8;
- mask_4x4_int >>= 8;
+ dst->buf += 16 * dst->stride;
+ mask_16x16 >>= 16;
+ mask_8x8 >>= 16;
+ mask_4x4 >>= 16;
+ mask_4x4_int >>= 16;
}
// Horizontal pass
@@ -1041,6 +1152,7 @@
mask_16x16 = lfm->above_y[TX_16X16];
mask_8x8 = lfm->above_y[TX_8X8];
mask_4x4 = lfm->above_y[TX_4X4];
+ mask_4x4_int = lfm->int_4x4_y;
for (r = 0; r < MI_BLOCK_SIZE && mi_row + r < cm->mi_rows; r++) {
unsigned int mask_16x16_r;
@@ -1061,13 +1173,14 @@
mask_16x16_r,
mask_8x8_r,
mask_4x4_r,
- mask_4x4_int_row[r],
+ mask_4x4_int & 0xff,
&cm->lf_info, &lfm->lfl_y[r << 3]);
dst->buf += 8 * dst->stride;
mask_16x16 >>= 8;
mask_8x8 >>= 8;
mask_4x4 >>= 8;
+ mask_4x4_int >>= 8;
}
} else {
uint16_t mask_16x16 = lfm->left_uv[TX_16X16];
@@ -1075,27 +1188,37 @@
uint16_t mask_4x4 = lfm->left_uv[TX_4X4];
uint16_t mask_4x4_int = lfm->int_4x4_uv;
- // Vertical pass
- for (r = 0; r < MI_BLOCK_SIZE && mi_row + r < cm->mi_rows; r += 2) {
+ // Vertical pass: do 2 rows at one time
+ for (r = 0; r < MI_BLOCK_SIZE && mi_row + r < cm->mi_rows; r += 4) {
if (plane->plane_type == 1) {
- for (c = 0; c < (MI_BLOCK_SIZE >> 1); c++)
+ for (c = 0; c < (MI_BLOCK_SIZE >> 1); c++) {
lfm->lfl_uv[(r << 1) + c] = lfm->lfl_y[(r << 3) + (c << 1)];
+ lfm->lfl_uv[((r + 2) << 1) + c] = lfm->lfl_y[((r + 2) << 3) +
+ (c << 1)];
+ }
}
- mask_4x4_int_row[r] = mask_4x4_int & 0xf;
- // Disable filtering on the leftmost column
- filter_selectively_vert(dst->buf, dst->stride,
- mask_16x16 & 0xf,
- mask_8x8 & 0xf,
- mask_4x4 & 0xf,
- mask_4x4_int_row[r],
- &cm->lf_info, &lfm->lfl_uv[r << 1]);
+ {
+ unsigned int mask_16x16_l = mask_16x16 & 0xff;
+ unsigned int mask_8x8_l = mask_8x8 & 0xff;
+ unsigned int mask_4x4_l = mask_4x4 & 0xff;
+ unsigned int mask_4x4_int_l = mask_4x4_int & 0xff;
- dst->buf += 8 * dst->stride;
- mask_16x16 >>= 4;
- mask_8x8 >>= 4;
- mask_4x4 >>= 4;
- mask_4x4_int >>= 4;
+ // Disable filtering on the leftmost column
+ filter_selectively_vert_row2(plane->plane_type,
+ dst->buf, dst->stride,
+ mask_16x16_l,
+ mask_8x8_l,
+ mask_4x4_l,
+ mask_4x4_int_l,
+ &cm->lf_info, &lfm->lfl_uv[r << 1]);
+
+ dst->buf += 16 * dst->stride;
+ mask_16x16 >>= 8;
+ mask_8x8 >>= 8;
+ mask_4x4 >>= 8;
+ mask_4x4_int >>= 8;
+ }
}
// Horizontal pass
@@ -1103,11 +1226,12 @@
mask_16x16 = lfm->above_uv[TX_16X16];
mask_8x8 = lfm->above_uv[TX_8X8];
mask_4x4 = lfm->above_uv[TX_4X4];
+ mask_4x4_int = lfm->int_4x4_uv;
for (r = 0; r < MI_BLOCK_SIZE && mi_row + r < cm->mi_rows; r += 2) {
const int skip_border_4x4_r = mi_row + r == cm->mi_rows - 1;
const unsigned int mask_4x4_int_r = skip_border_4x4_r ?
- 0 : (mask_4x4_int_row[r]);
+ 0 : (mask_4x4_int & 0xf);
unsigned int mask_16x16_r;
unsigned int mask_8x8_r;
unsigned int mask_4x4_r;
@@ -1133,6 +1257,7 @@
mask_16x16 >>= 4;
mask_8x8 >>= 4;
mask_4x4 >>= 4;
+ mask_4x4_int >>= 4;
}
}
}
diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h
index 452dd6b..cda68a2 100644
--- a/vp9/common/vp9_onyx.h
+++ b/vp9/common/vp9_onyx.h
@@ -64,6 +64,12 @@
FRAMEFLAGS_ALTREF = 4,
} FRAMETYPE_FLAGS;
+ typedef enum {
+ NO_AQ = 0,
+ VARIANCE_AQ = 1,
+ AQ_MODES_COUNT // This should always be the last member of the enum
+ } AQ_MODES;
+
typedef struct {
int version; // 4 versions of bitstream defined:
// 0 - best quality/slowest decode,
@@ -128,6 +134,7 @@
int best_allowed_q;
int cq_level;
int lossless;
+ int aq_mode; // Adaptive Quantization mode
// two pass datarate control
int two_pass_vbrbias; // two pass datarate control tweaks
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index 3add81b..aa17b85 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -106,9 +106,10 @@
BLOCK_SIZE bsize, int pred_w, int pred_h,
int mi_x, int mi_y) {
struct macroblockd_plane *const pd = &xd->plane[plane];
- const int bwl = b_width_log2(bsize) - pd->subsampling_x;
+ const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
+ const int bwl = b_width_log2(plane_bsize);
const int bw = 4 << bwl;
- const int bh = plane_block_height(bsize, pd);
+ const int bh = 4 * num_4x4_blocks_high_lookup[plane_bsize];
const int x = 4 * (block & ((1 << bwl) - 1));
const int y = 4 * (block >> bwl);
const MODE_INFO *mi = xd->mi_8x8[0];
diff --git a/vp9/common/x86/vp9_subpixel_8t_ssse3.asm b/vp9/common/x86/vp9_subpixel_8t_ssse3.asm
index dbc17ec..634fa77 100644
--- a/vp9/common/x86/vp9_subpixel_8t_ssse3.asm
+++ b/vp9/common/x86/vp9_subpixel_8t_ssse3.asm
@@ -158,10 +158,13 @@
pmaddubsw xmm6, k6k7
paddsw xmm0, xmm6
- paddsw xmm0, xmm2
+ movdqa xmm1, xmm2
+ pmaxsw xmm2, xmm4
+ pminsw xmm4, xmm1
paddsw xmm0, xmm4
- paddsw xmm0, krd
+ paddsw xmm0, xmm2
+ paddsw xmm0, krd
psraw xmm0, 7
packuswb xmm0, xmm0
@@ -243,10 +246,13 @@
pmaddubsw xmm6, k6k7
paddsw xmm0, xmm6
- paddsw xmm0, xmm2
+ movdqa xmm1, xmm2
+ pmaxsw xmm2, xmm4
+ pminsw xmm4, xmm1
paddsw xmm0, xmm4
- paddsw xmm0, krd
+ paddsw xmm0, xmm2
+ paddsw xmm0, krd
psraw xmm0, 7
packuswb xmm0, xmm0
%if %1
@@ -635,9 +641,13 @@
pmaddubsw %3, k4k5
pmaddubsw %4, k6k7
- paddsw %1, %2
paddsw %1, %4
+ movdqa %4, %2
+ pmaxsw %2, %3
+ pminsw %3, %4
paddsw %1, %3
+ paddsw %1, %2
+
paddsw %1, krd
psraw %1, 7
packuswb %1, %1
@@ -783,12 +793,19 @@
pmaddubsw xmm6, k4k5
pmaddubsw xmm7, k6k7
- paddsw xmm0, xmm1
paddsw xmm0, xmm3
+ movdqa xmm3, xmm1
+ pmaxsw xmm1, xmm2
+ pminsw xmm2, xmm3
paddsw xmm0, xmm2
- paddsw xmm4, xmm5
+ paddsw xmm0, xmm1
+
paddsw xmm4, xmm7
+ movdqa xmm7, xmm5
+ pmaxsw xmm5, xmm6
+ pminsw xmm6, xmm7
paddsw xmm4, xmm6
+ paddsw xmm4, xmm5
paddsw xmm0, krd
paddsw xmm4, krd
@@ -839,6 +856,7 @@
HORIZx4 0
add rsp, 16 * 3
+ pop rsp
; begin epilog
pop rdi
pop rsi
@@ -952,6 +970,7 @@
HORIZx4 1
add rsp, 16 * 3
+ pop rsp
; begin epilog
pop rdi
pop rsi
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index dbcae76..916cb42 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -159,7 +159,7 @@
int i;
for (i = 0; i < n; ++i)
if (vp9_read(r, NMV_UPDATE_PROB))
- p[i] = (vp9_read_literal(r, 7) << 1) | 1;
+ p[i] = (vp9_read_literal(r, 7) << 1) | 1;
}
static void read_mv_probs(nmv_context *ctx, int allow_hp, vp9_reader *r) {
@@ -178,7 +178,7 @@
for (i = 0; i < 2; ++i) {
nmv_component *const comp_ctx = &ctx->comps[i];
for (j = 0; j < CLASS0_SIZE; ++j)
- update_mv_probs(comp_ctx->class0_fp[j], 3, r);
+ update_mv_probs(comp_ctx->class0_fp[j], MV_FP_SIZE - 1, r);
update_mv_probs(comp_ctx->fp, 3, r);
}
@@ -241,7 +241,8 @@
}
static void inverse_transform_block(MACROBLOCKD* xd, int plane, int block,
- TX_SIZE tx_size, uint8_t *dst, int stride) {
+ TX_SIZE tx_size, uint8_t *dst, int stride,
+ uint8_t *token_cache) {
struct macroblockd_plane *const pd = &xd->plane[plane];
const int eob = pd->eobs[block];
if (eob > 0) {
@@ -274,13 +275,20 @@
if (eob == 1) {
vpx_memset(dqcoeff, 0, 2 * sizeof(dqcoeff[0]));
+ vpx_memset(token_cache, 0, 2 * sizeof(token_cache[0]));
} else {
- if (tx_type == DCT_DCT && tx_size <= TX_16X16 && eob <= 10)
+ if (tx_type == DCT_DCT && tx_size <= TX_16X16 && eob <= 10) {
vpx_memset(dqcoeff, 0, 4 * (4 << tx_size) * sizeof(dqcoeff[0]));
- else if (tx_size == TX_32X32 && eob <= 34)
+ vpx_memset(token_cache, 0,
+ 4 * (4 << tx_size) * sizeof(token_cache[0]));
+ } else if (tx_size == TX_32X32 && eob <= 34) {
vpx_memset(dqcoeff, 0, 256 * sizeof(dqcoeff[0]));
- else
+ vpx_memset(token_cache, 0, 256 * sizeof(token_cache[0]));
+ } else {
vpx_memset(dqcoeff, 0, (16 << (tx_size << 1)) * sizeof(dqcoeff[0]));
+ vpx_memset(token_cache, 0,
+ (16 << (tx_size << 1)) * sizeof(token_cache[0]));
+ }
}
}
}
@@ -310,7 +318,7 @@
dst = &pd->dst.buf[4 * y * pd->dst.stride + 4 * x];
if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0)
- extend_for_intra(xd, plane_bsize, plane, block, tx_size);
+ extend_for_intra(xd, plane_bsize, plane, x, y);
vp9_predict_intra_block(xd, block >> (tx_size << 1),
b_width_log2(plane_bsize), tx_size, mode,
@@ -319,7 +327,8 @@
if (!mi->mbmi.skip_coeff) {
vp9_decode_block_tokens(cm, xd, plane, block, plane_bsize, x, y, tx_size,
args->r, args->token_cache);
- inverse_transform_block(xd, plane, block, tx_size, dst, pd->dst.stride);
+ inverse_transform_block(xd, plane, block, tx_size, dst, pd->dst.stride,
+ args->token_cache);
}
}
@@ -345,7 +354,7 @@
args->r, args->token_cache);
inverse_transform_block(xd, plane, block, tx_size,
&pd->dst.buf[4 * y * pd->dst.stride + 4 * x],
- pd->dst.stride);
+ pd->dst.stride, args->token_cache);
}
static void set_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd,
@@ -946,6 +955,7 @@
pd[i].dqcoeff = tile_data->dqcoeff[i];
pd[i].eobs = tile_data->eobs[i];
vpx_memset(xd->plane[i].dqcoeff, 0, 64 * 64 * sizeof(int16_t));
+ vpx_memset(tile_data->token_cache, 0, sizeof(tile_data->token_cache));
}
}
diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c
index 75e7e40..f6219c5 100644
--- a/vp9/decoder/vp9_detokenize.c
+++ b/vp9/decoder/vp9_detokenize.c
@@ -81,6 +81,7 @@
INCREMENT_COUNT(token); \
token_cache[scan[c]] = vp9_pt_energy_class[token]; \
++c; \
+ pt = get_coef_context(nb, token_cache, c); \
dqv = dq[1]; \
continue; \
}
@@ -118,31 +119,24 @@
while (c < seg_eob) {
int val;
- if (c)
- pt = get_coef_context(nb, token_cache, c);
band = *band_translate++;
prob = coef_probs[band][pt];
if (!cm->frame_parallel_decoding_mode)
++eob_branch_count[band][pt];
if (!vp9_read(r, prob[EOB_CONTEXT_NODE]))
break;
- goto DECODE_ZERO;
-
- SKIP_START:
- if (c >= seg_eob)
- break;
- if (c)
- pt = get_coef_context(nb, token_cache, c);
- band = *band_translate++;
- prob = coef_probs[band][pt];
DECODE_ZERO:
if (!vp9_read(r, prob[ZERO_CONTEXT_NODE])) {
INCREMENT_COUNT(ZERO_TOKEN);
- token_cache[scan[c]] = vp9_pt_energy_class[ZERO_TOKEN];
- dqv = dq[1]; \
+ dqv = dq[1];
++c;
- goto SKIP_START;
+ if (c >= seg_eob)
+ break;
+ pt = get_coef_context(nb, token_cache, c);
+ band = *band_translate++;
+ prob = coef_probs[band][pt];
+ goto DECODE_ZERO;
}
// ONE_CONTEXT_NODE_0_
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 9bd0123..e8ec61e 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -239,18 +239,8 @@
const struct vp9_token *const a = &vp9_coef_encodings[t];
const vp9_extra_bit *const b = &vp9_extra_bits[t];
int i = 0;
- const vp9_prob *pp;
int v = a->value;
int n = a->len;
- vp9_prob probs[ENTROPY_NODES];
-
- if (t >= TWO_TOKEN) {
- vp9_model_to_full_probs(p->context_tree, probs);
- pp = probs;
- } else {
- pp = p->context_tree;
- }
- assert(pp != 0);
/* skip one or two nodes */
if (p->skip_eob_node) {
@@ -258,11 +248,24 @@
i = 2 * p->skip_eob_node;
}
- do {
- const int bb = (v >> --n) & 1;
- vp9_write(w, bb, pp[i >> 1]);
- i = vp9_coef_tree[i + bb];
- } while (n);
+ // TODO(jbb): expanding this can lead to big gains. It allows
+ // much better branch prediction and would enable us to avoid numerous
+ // lookups and compares.
+
+ // If we have a token that's in the constrained set, the coefficient tree
+ // is split into two treed writes. The first treed write takes care of the
+ // unconstrained nodes. The second treed write takes care of the
+ // constrained nodes.
+ if (t >= TWO_TOKEN && t < DCT_EOB_TOKEN) {
+ int len = UNCONSTRAINED_NODES - p->skip_eob_node;
+ int bits = v >> (n - len);
+ treed_write(w, vp9_coef_tree, p->context_tree, bits, len, i);
+ treed_write(w, vp9_coef_con_tree,
+ vp9_pareto8_full[p->context_tree[PIVOT_NODE] - 1], v, n - len,
+ 0);
+ } else {
+ treed_write(w, vp9_coef_tree, p->context_tree, v, n, i);
+ }
if (b->base_val) {
const int e = p->extra, l = b->len;
@@ -299,7 +302,7 @@
static void write_segment_id(vp9_writer *w, const struct segmentation *seg,
int segment_id) {
if (seg->enabled && seg->update_map)
- treed_write(w, vp9_segment_tree, seg->tree_probs, segment_id, 3);
+ treed_write(w, vp9_segment_tree, seg->tree_probs, segment_id, 3, 0);
}
// This function encodes the reference frame
@@ -674,12 +677,6 @@
}
}
-static void build_coeff_contexts(VP9_COMP *cpi) {
- TX_SIZE t;
- for (t = TX_4X4; t <= TX_32X32; t++)
- build_tree_distribution(cpi, t);
-}
-
static void update_coef_probs_common(vp9_writer* const bc, VP9_COMP *cpi,
TX_SIZE tx_size) {
vp9_coeff_probs_model *new_frame_coef_probs = cpi->frame_coef_probs[tx_size];
@@ -853,25 +850,17 @@
}
}
-static void update_coef_probs(VP9_COMP* const cpi, vp9_writer* const bc) {
+static void update_coef_probs(VP9_COMP* cpi, vp9_writer* w) {
const TX_MODE tx_mode = cpi->common.tx_mode;
-
+ const TX_SIZE max_tx_size = tx_mode_to_biggest_tx_size[tx_mode];
+ TX_SIZE tx_size;
vp9_clear_system_state();
- // Build the cofficient contexts based on counts collected in encode loop
- build_coeff_contexts(cpi);
+ for (tx_size = TX_4X4; tx_size <= TX_32X32; ++tx_size)
+ build_tree_distribution(cpi, tx_size);
- update_coef_probs_common(bc, cpi, TX_4X4);
-
- // do not do this if not even allowed
- if (tx_mode > ONLY_4X4)
- update_coef_probs_common(bc, cpi, TX_8X8);
-
- if (tx_mode > ALLOW_8X8)
- update_coef_probs_common(bc, cpi, TX_16X16);
-
- if (tx_mode > ALLOW_16X16)
- update_coef_probs_common(bc, cpi, TX_32X32);
+ for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
+ update_coef_probs_common(w, cpi, tx_size);
}
static void encode_loopfilter(struct loopfilter *lf,
@@ -1446,53 +1435,3 @@
*size = data - dest;
}
-#ifdef ENTROPY_STATS
-static void print_tree_update_for_type(FILE *f,
- vp9_coeff_stats *tree_update_hist,
- int block_types, const char *header) {
- int i, j, k, l, m;
-
- fprintf(f, "const vp9_coeff_prob %s = {\n", header);
- for (i = 0; i < block_types; i++) {
- fprintf(f, " { \n");
- for (j = 0; j < REF_TYPES; j++) {
- fprintf(f, " { \n");
- for (k = 0; k < COEF_BANDS; k++) {
- fprintf(f, " {\n");
- for (l = 0; l < PREV_COEF_CONTEXTS; l++) {
- fprintf(f, " {");
- for (m = 0; m < ENTROPY_NODES; m++) {
- fprintf(f, "%3d, ",
- get_binary_prob(tree_update_hist[i][j][k][l][m][0],
- tree_update_hist[i][j][k][l][m][1]));
- }
- fprintf(f, "},\n");
- }
- fprintf(f, "},\n");
- }
- fprintf(f, " },\n");
- }
- fprintf(f, " },\n");
- }
- fprintf(f, "};\n");
-}
-
-void print_tree_update_probs() {
- FILE *f = fopen("coefupdprob.h", "w");
- fprintf(f, "\n/* Update probabilities for token entropy tree. */\n\n");
-
- print_tree_update_for_type(f, tree_update_hist[TX_4X4], BLOCK_TYPES,
- "vp9_coef_update_probs_4x4[BLOCK_TYPES]");
- print_tree_update_for_type(f, tree_update_hist[TX_8X8], BLOCK_TYPES,
- "vp9_coef_update_probs_8x8[BLOCK_TYPES]");
- print_tree_update_for_type(f, tree_update_hist[TX_16X16], BLOCK_TYPES,
- "vp9_coef_update_probs_16x16[BLOCK_TYPES]");
- print_tree_update_for_type(f, tree_update_hist[TX_32X32], BLOCK_TYPES,
- "vp9_coef_update_probs_32x32[BLOCK_TYPES]");
-
- fclose(f);
- f = fopen("treeupdate.bin", "wb");
- fwrite(tree_update_hist, sizeof(tree_update_hist), 1, f);
- fclose(f);
-}
-#endif
diff --git a/vp9/encoder/vp9_dct.c b/vp9/encoder/vp9_dct.c
index 065992a..0f4a6bb 100644
--- a/vp9/encoder/vp9_dct.c
+++ b/vp9/encoder/vp9_dct.c
@@ -20,6 +20,12 @@
#include "vp9/encoder/vp9_dct.h"
+static INLINE int fdct_round_shift(int input) {
+ int rv = ROUND_POWER_OF_TWO(input, DCT_CONST_BITS);
+ assert(INT16_MIN <= rv && rv <= INT16_MAX);
+ return rv;
+}
+
static void fdct4(const int16_t *input, int16_t *output) {
int16_t step[4];
int temp1, temp2;
@@ -31,12 +37,12 @@
temp1 = (step[0] + step[1]) * cospi_16_64;
temp2 = (step[0] - step[1]) * cospi_16_64;
- output[0] = dct_const_round_shift(temp1);
- output[2] = dct_const_round_shift(temp2);
+ output[0] = fdct_round_shift(temp1);
+ output[2] = fdct_round_shift(temp2);
temp1 = step[2] * cospi_24_64 + step[3] * cospi_8_64;
temp2 = -step[2] * cospi_8_64 + step[3] * cospi_24_64;
- output[1] = dct_const_round_shift(temp1);
- output[3] = dct_const_round_shift(temp2);
+ output[1] = fdct_round_shift(temp1);
+ output[3] = fdct_round_shift(temp2);
}
void vp9_fdct4x4_c(const int16_t *input, int16_t *output, int stride) {
@@ -80,12 +86,12 @@
step[3] = input[0] - input[3];
temp1 = (step[0] + step[1]) * cospi_16_64;
temp2 = (step[0] - step[1]) * cospi_16_64;
- out[0] = dct_const_round_shift(temp1);
- out[2] = dct_const_round_shift(temp2);
+ out[0] = fdct_round_shift(temp1);
+ out[2] = fdct_round_shift(temp2);
temp1 = step[2] * cospi_24_64 + step[3] * cospi_8_64;
temp2 = -step[2] * cospi_8_64 + step[3] * cospi_24_64;
- out[1] = dct_const_round_shift(temp1);
- out[3] = dct_const_round_shift(temp2);
+ out[1] = fdct_round_shift(temp1);
+ out[3] = fdct_round_shift(temp2);
// Do next column (which is a transposed row in second/horizontal pass)
in++;
out += 4;
@@ -138,10 +144,10 @@
s3 = x2 - x0 + x3;
// 1-D transform scaling factor is sqrt(2).
- output[0] = dct_const_round_shift(s0);
- output[1] = dct_const_round_shift(s1);
- output[2] = dct_const_round_shift(s2);
- output[3] = dct_const_round_shift(s3);
+ output[0] = fdct_round_shift(s0);
+ output[1] = fdct_round_shift(s1);
+ output[2] = fdct_round_shift(s2);
+ output[3] = fdct_round_shift(s3);
}
static const transform_2d FHT_4[] = {
@@ -204,16 +210,16 @@
t1 = (x0 - x1) * cospi_16_64;
t2 = x2 * cospi_24_64 + x3 * cospi_8_64;
t3 = -x2 * cospi_8_64 + x3 * cospi_24_64;
- output[0] = dct_const_round_shift(t0);
- output[2] = dct_const_round_shift(t2);
- output[4] = dct_const_round_shift(t1);
- output[6] = dct_const_round_shift(t3);
+ output[0] = fdct_round_shift(t0);
+ output[2] = fdct_round_shift(t2);
+ output[4] = fdct_round_shift(t1);
+ output[6] = fdct_round_shift(t3);
// Stage 2
t0 = (s6 - s5) * cospi_16_64;
t1 = (s6 + s5) * cospi_16_64;
- t2 = dct_const_round_shift(t0);
- t3 = dct_const_round_shift(t1);
+ t2 = fdct_round_shift(t0);
+ t3 = fdct_round_shift(t1);
// Stage 3
x0 = s4 + t2;
@@ -226,10 +232,10 @@
t1 = x1 * cospi_12_64 + x2 * cospi_20_64;
t2 = x2 * cospi_12_64 + x1 * -cospi_20_64;
t3 = x3 * cospi_28_64 + x0 * -cospi_4_64;
- output[1] = dct_const_round_shift(t0);
- output[3] = dct_const_round_shift(t2);
- output[5] = dct_const_round_shift(t1);
- output[7] = dct_const_round_shift(t3);
+ output[1] = fdct_round_shift(t0);
+ output[3] = fdct_round_shift(t2);
+ output[5] = fdct_round_shift(t1);
+ output[7] = fdct_round_shift(t3);
}
void vp9_fdct8x8_c(const int16_t *input, int16_t *final_output, int stride) {
@@ -264,16 +270,16 @@
t1 = (x0 - x1) * cospi_16_64;
t2 = x2 * cospi_24_64 + x3 * cospi_8_64;
t3 = -x2 * cospi_8_64 + x3 * cospi_24_64;
- output[0 * 8] = dct_const_round_shift(t0);
- output[2 * 8] = dct_const_round_shift(t2);
- output[4 * 8] = dct_const_round_shift(t1);
- output[6 * 8] = dct_const_round_shift(t3);
+ output[0 * 8] = fdct_round_shift(t0);
+ output[2 * 8] = fdct_round_shift(t2);
+ output[4 * 8] = fdct_round_shift(t1);
+ output[6 * 8] = fdct_round_shift(t3);
// Stage 2
t0 = (s6 - s5) * cospi_16_64;
t1 = (s6 + s5) * cospi_16_64;
- t2 = dct_const_round_shift(t0);
- t3 = dct_const_round_shift(t1);
+ t2 = fdct_round_shift(t0);
+ t3 = fdct_round_shift(t1);
// Stage 3
x0 = s4 + t2;
@@ -286,10 +292,10 @@
t1 = x1 * cospi_12_64 + x2 * cospi_20_64;
t2 = x2 * cospi_12_64 + x1 * -cospi_20_64;
t3 = x3 * cospi_28_64 + x0 * -cospi_4_64;
- output[1 * 8] = dct_const_round_shift(t0);
- output[3 * 8] = dct_const_round_shift(t2);
- output[5 * 8] = dct_const_round_shift(t1);
- output[7 * 8] = dct_const_round_shift(t3);
+ output[1 * 8] = fdct_round_shift(t0);
+ output[3 * 8] = fdct_round_shift(t2);
+ output[5 * 8] = fdct_round_shift(t1);
+ output[7 * 8] = fdct_round_shift(t3);
input++;
output++;
}
@@ -388,16 +394,16 @@
t1 = (x0 - x1) * cospi_16_64;
t2 = x3 * cospi_8_64 + x2 * cospi_24_64;
t3 = x3 * cospi_24_64 - x2 * cospi_8_64;
- out[0] = dct_const_round_shift(t0);
- out[4] = dct_const_round_shift(t2);
- out[8] = dct_const_round_shift(t1);
- out[12] = dct_const_round_shift(t3);
+ out[0] = fdct_round_shift(t0);
+ out[4] = fdct_round_shift(t2);
+ out[8] = fdct_round_shift(t1);
+ out[12] = fdct_round_shift(t3);
// Stage 2
t0 = (s6 - s5) * cospi_16_64;
t1 = (s6 + s5) * cospi_16_64;
- t2 = dct_const_round_shift(t0);
- t3 = dct_const_round_shift(t1);
+ t2 = fdct_round_shift(t0);
+ t3 = fdct_round_shift(t1);
// Stage 3
x0 = s4 + t2;
@@ -410,22 +416,22 @@
t1 = x1 * cospi_12_64 + x2 * cospi_20_64;
t2 = x2 * cospi_12_64 + x1 * -cospi_20_64;
t3 = x3 * cospi_28_64 + x0 * -cospi_4_64;
- out[2] = dct_const_round_shift(t0);
- out[6] = dct_const_round_shift(t2);
- out[10] = dct_const_round_shift(t1);
- out[14] = dct_const_round_shift(t3);
+ out[2] = fdct_round_shift(t0);
+ out[6] = fdct_round_shift(t2);
+ out[10] = fdct_round_shift(t1);
+ out[14] = fdct_round_shift(t3);
}
// Work on the next eight values; step1 -> odd_results
{
// step 2
temp1 = (step1[5] - step1[2]) * cospi_16_64;
temp2 = (step1[4] - step1[3]) * cospi_16_64;
- step2[2] = dct_const_round_shift(temp1);
- step2[3] = dct_const_round_shift(temp2);
+ step2[2] = fdct_round_shift(temp1);
+ step2[3] = fdct_round_shift(temp2);
temp1 = (step1[4] + step1[3]) * cospi_16_64;
temp2 = (step1[5] + step1[2]) * cospi_16_64;
- step2[4] = dct_const_round_shift(temp1);
- step2[5] = dct_const_round_shift(temp2);
+ step2[4] = fdct_round_shift(temp1);
+ step2[5] = fdct_round_shift(temp2);
// step 3
step3[0] = step1[0] + step2[3];
step3[1] = step1[1] + step2[2];
@@ -438,12 +444,12 @@
// step 4
temp1 = step3[1] * -cospi_8_64 + step3[6] * cospi_24_64;
temp2 = step3[2] * -cospi_24_64 - step3[5] * cospi_8_64;
- step2[1] = dct_const_round_shift(temp1);
- step2[2] = dct_const_round_shift(temp2);
+ step2[1] = fdct_round_shift(temp1);
+ step2[2] = fdct_round_shift(temp2);
temp1 = step3[2] * -cospi_8_64 + step3[5] * cospi_24_64;
temp2 = step3[1] * cospi_24_64 + step3[6] * cospi_8_64;
- step2[5] = dct_const_round_shift(temp1);
- step2[6] = dct_const_round_shift(temp2);
+ step2[5] = fdct_round_shift(temp1);
+ step2[6] = fdct_round_shift(temp2);
// step 5
step1[0] = step3[0] + step2[1];
step1[1] = step3[0] - step2[1];
@@ -456,20 +462,20 @@
// step 6
temp1 = step1[0] * cospi_30_64 + step1[7] * cospi_2_64;
temp2 = step1[1] * cospi_14_64 + step1[6] * cospi_18_64;
- out[1] = dct_const_round_shift(temp1);
- out[9] = dct_const_round_shift(temp2);
+ out[1] = fdct_round_shift(temp1);
+ out[9] = fdct_round_shift(temp2);
temp1 = step1[2] * cospi_22_64 + step1[5] * cospi_10_64;
temp2 = step1[3] * cospi_6_64 + step1[4] * cospi_26_64;
- out[5] = dct_const_round_shift(temp1);
- out[13] = dct_const_round_shift(temp2);
+ out[5] = fdct_round_shift(temp1);
+ out[13] = fdct_round_shift(temp2);
temp1 = step1[3] * -cospi_26_64 + step1[4] * cospi_6_64;
temp2 = step1[2] * -cospi_10_64 + step1[5] * cospi_22_64;
- out[3] = dct_const_round_shift(temp1);
- out[11] = dct_const_round_shift(temp2);
+ out[3] = fdct_round_shift(temp1);
+ out[11] = fdct_round_shift(temp2);
temp1 = step1[1] * -cospi_18_64 + step1[6] * cospi_14_64;
temp2 = step1[0] * -cospi_2_64 + step1[7] * cospi_30_64;
- out[7] = dct_const_round_shift(temp1);
- out[15] = dct_const_round_shift(temp2);
+ out[7] = fdct_round_shift(temp1);
+ out[15] = fdct_round_shift(temp2);
}
// Do next column (which is a transposed row in second/horizontal pass)
in++;
@@ -503,14 +509,14 @@
s6 = cospi_26_64 * x6 + cospi_6_64 * x7;
s7 = cospi_6_64 * x6 - cospi_26_64 * x7;
- x0 = dct_const_round_shift(s0 + s4);
- x1 = dct_const_round_shift(s1 + s5);
- x2 = dct_const_round_shift(s2 + s6);
- x3 = dct_const_round_shift(s3 + s7);
- x4 = dct_const_round_shift(s0 - s4);
- x5 = dct_const_round_shift(s1 - s5);
- x6 = dct_const_round_shift(s2 - s6);
- x7 = dct_const_round_shift(s3 - s7);
+ x0 = fdct_round_shift(s0 + s4);
+ x1 = fdct_round_shift(s1 + s5);
+ x2 = fdct_round_shift(s2 + s6);
+ x3 = fdct_round_shift(s3 + s7);
+ x4 = fdct_round_shift(s0 - s4);
+ x5 = fdct_round_shift(s1 - s5);
+ x6 = fdct_round_shift(s2 - s6);
+ x7 = fdct_round_shift(s3 - s7);
// stage 2
s0 = x0;
@@ -526,10 +532,10 @@
x1 = s1 + s3;
x2 = s0 - s2;
x3 = s1 - s3;
- x4 = dct_const_round_shift(s4 + s6);
- x5 = dct_const_round_shift(s5 + s7);
- x6 = dct_const_round_shift(s4 - s6);
- x7 = dct_const_round_shift(s5 - s7);
+ x4 = fdct_round_shift(s4 + s6);
+ x5 = fdct_round_shift(s5 + s7);
+ x6 = fdct_round_shift(s4 - s6);
+ x7 = fdct_round_shift(s5 - s7);
// stage 3
s2 = cospi_16_64 * (x2 + x3);
@@ -537,10 +543,10 @@
s6 = cospi_16_64 * (x6 + x7);
s7 = cospi_16_64 * (x6 - x7);
- x2 = dct_const_round_shift(s2);
- x3 = dct_const_round_shift(s3);
- x6 = dct_const_round_shift(s6);
- x7 = dct_const_round_shift(s7);
+ x2 = fdct_round_shift(s2);
+ x3 = fdct_round_shift(s3);
+ x6 = fdct_round_shift(s6);
+ x7 = fdct_round_shift(s7);
output[0] = x0;
output[1] = - x4;
@@ -693,16 +699,16 @@
t1 = (x0 - x1) * cospi_16_64;
t2 = x3 * cospi_8_64 + x2 * cospi_24_64;
t3 = x3 * cospi_24_64 - x2 * cospi_8_64;
- out[0] = dct_const_round_shift(t0);
- out[4] = dct_const_round_shift(t2);
- out[8] = dct_const_round_shift(t1);
- out[12] = dct_const_round_shift(t3);
+ out[0] = fdct_round_shift(t0);
+ out[4] = fdct_round_shift(t2);
+ out[8] = fdct_round_shift(t1);
+ out[12] = fdct_round_shift(t3);
// Stage 2
t0 = (s6 - s5) * cospi_16_64;
t1 = (s6 + s5) * cospi_16_64;
- t2 = dct_const_round_shift(t0);
- t3 = dct_const_round_shift(t1);
+ t2 = fdct_round_shift(t0);
+ t3 = fdct_round_shift(t1);
// Stage 3
x0 = s4 + t2;
@@ -715,21 +721,21 @@
t1 = x1 * cospi_12_64 + x2 * cospi_20_64;
t2 = x2 * cospi_12_64 + x1 * -cospi_20_64;
t3 = x3 * cospi_28_64 + x0 * -cospi_4_64;
- out[2] = dct_const_round_shift(t0);
- out[6] = dct_const_round_shift(t2);
- out[10] = dct_const_round_shift(t1);
- out[14] = dct_const_round_shift(t3);
+ out[2] = fdct_round_shift(t0);
+ out[6] = fdct_round_shift(t2);
+ out[10] = fdct_round_shift(t1);
+ out[14] = fdct_round_shift(t3);
}
// step 2
temp1 = (step1[5] - step1[2]) * cospi_16_64;
temp2 = (step1[4] - step1[3]) * cospi_16_64;
- step2[2] = dct_const_round_shift(temp1);
- step2[3] = dct_const_round_shift(temp2);
+ step2[2] = fdct_round_shift(temp1);
+ step2[3] = fdct_round_shift(temp2);
temp1 = (step1[4] + step1[3]) * cospi_16_64;
temp2 = (step1[5] + step1[2]) * cospi_16_64;
- step2[4] = dct_const_round_shift(temp1);
- step2[5] = dct_const_round_shift(temp2);
+ step2[4] = fdct_round_shift(temp1);
+ step2[5] = fdct_round_shift(temp2);
// step 3
step3[0] = step1[0] + step2[3];
@@ -744,12 +750,12 @@
// step 4
temp1 = step3[1] * -cospi_8_64 + step3[6] * cospi_24_64;
temp2 = step3[2] * -cospi_24_64 - step3[5] * cospi_8_64;
- step2[1] = dct_const_round_shift(temp1);
- step2[2] = dct_const_round_shift(temp2);
+ step2[1] = fdct_round_shift(temp1);
+ step2[2] = fdct_round_shift(temp2);
temp1 = step3[2] * -cospi_8_64 + step3[5] * cospi_24_64;
temp2 = step3[1] * cospi_24_64 + step3[6] * cospi_8_64;
- step2[5] = dct_const_round_shift(temp1);
- step2[6] = dct_const_round_shift(temp2);
+ step2[5] = fdct_round_shift(temp1);
+ step2[6] = fdct_round_shift(temp2);
// step 5
step1[0] = step3[0] + step2[1];
@@ -764,23 +770,23 @@
// step 6
temp1 = step1[0] * cospi_30_64 + step1[7] * cospi_2_64;
temp2 = step1[1] * cospi_14_64 + step1[6] * cospi_18_64;
- out[1] = dct_const_round_shift(temp1);
- out[9] = dct_const_round_shift(temp2);
+ out[1] = fdct_round_shift(temp1);
+ out[9] = fdct_round_shift(temp2);
temp1 = step1[2] * cospi_22_64 + step1[5] * cospi_10_64;
temp2 = step1[3] * cospi_6_64 + step1[4] * cospi_26_64;
- out[5] = dct_const_round_shift(temp1);
- out[13] = dct_const_round_shift(temp2);
+ out[5] = fdct_round_shift(temp1);
+ out[13] = fdct_round_shift(temp2);
temp1 = step1[3] * -cospi_26_64 + step1[4] * cospi_6_64;
temp2 = step1[2] * -cospi_10_64 + step1[5] * cospi_22_64;
- out[3] = dct_const_round_shift(temp1);
- out[11] = dct_const_round_shift(temp2);
+ out[3] = fdct_round_shift(temp1);
+ out[11] = fdct_round_shift(temp2);
temp1 = step1[1] * -cospi_18_64 + step1[6] * cospi_14_64;
temp2 = step1[0] * -cospi_2_64 + step1[7] * cospi_30_64;
- out[7] = dct_const_round_shift(temp1);
- out[15] = dct_const_round_shift(temp2);
+ out[7] = fdct_round_shift(temp1);
+ out[15] = fdct_round_shift(temp2);
}
static void fadst16(const int16_t *input, int16_t *output) {
@@ -821,22 +827,22 @@
s14 = x14 * cospi_29_64 + x15 * cospi_3_64;
s15 = x14 * cospi_3_64 - x15 * cospi_29_64;
- x0 = dct_const_round_shift(s0 + s8);
- x1 = dct_const_round_shift(s1 + s9);
- x2 = dct_const_round_shift(s2 + s10);
- x3 = dct_const_round_shift(s3 + s11);
- x4 = dct_const_round_shift(s4 + s12);
- x5 = dct_const_round_shift(s5 + s13);
- x6 = dct_const_round_shift(s6 + s14);
- x7 = dct_const_round_shift(s7 + s15);
- x8 = dct_const_round_shift(s0 - s8);
- x9 = dct_const_round_shift(s1 - s9);
- x10 = dct_const_round_shift(s2 - s10);
- x11 = dct_const_round_shift(s3 - s11);
- x12 = dct_const_round_shift(s4 - s12);
- x13 = dct_const_round_shift(s5 - s13);
- x14 = dct_const_round_shift(s6 - s14);
- x15 = dct_const_round_shift(s7 - s15);
+ x0 = fdct_round_shift(s0 + s8);
+ x1 = fdct_round_shift(s1 + s9);
+ x2 = fdct_round_shift(s2 + s10);
+ x3 = fdct_round_shift(s3 + s11);
+ x4 = fdct_round_shift(s4 + s12);
+ x5 = fdct_round_shift(s5 + s13);
+ x6 = fdct_round_shift(s6 + s14);
+ x7 = fdct_round_shift(s7 + s15);
+ x8 = fdct_round_shift(s0 - s8);
+ x9 = fdct_round_shift(s1 - s9);
+ x10 = fdct_round_shift(s2 - s10);
+ x11 = fdct_round_shift(s3 - s11);
+ x12 = fdct_round_shift(s4 - s12);
+ x13 = fdct_round_shift(s5 - s13);
+ x14 = fdct_round_shift(s6 - s14);
+ x15 = fdct_round_shift(s7 - s15);
// stage 2
s0 = x0;
@@ -864,14 +870,14 @@
x5 = s1 - s5;
x6 = s2 - s6;
x7 = s3 - s7;
- x8 = dct_const_round_shift(s8 + s12);
- x9 = dct_const_round_shift(s9 + s13);
- x10 = dct_const_round_shift(s10 + s14);
- x11 = dct_const_round_shift(s11 + s15);
- x12 = dct_const_round_shift(s8 - s12);
- x13 = dct_const_round_shift(s9 - s13);
- x14 = dct_const_round_shift(s10 - s14);
- x15 = dct_const_round_shift(s11 - s15);
+ x8 = fdct_round_shift(s8 + s12);
+ x9 = fdct_round_shift(s9 + s13);
+ x10 = fdct_round_shift(s10 + s14);
+ x11 = fdct_round_shift(s11 + s15);
+ x12 = fdct_round_shift(s8 - s12);
+ x13 = fdct_round_shift(s9 - s13);
+ x14 = fdct_round_shift(s10 - s14);
+ x15 = fdct_round_shift(s11 - s15);
// stage 3
s0 = x0;
@@ -895,18 +901,18 @@
x1 = s1 + s3;
x2 = s0 - s2;
x3 = s1 - s3;
- x4 = dct_const_round_shift(s4 + s6);
- x5 = dct_const_round_shift(s5 + s7);
- x6 = dct_const_round_shift(s4 - s6);
- x7 = dct_const_round_shift(s5 - s7);
+ x4 = fdct_round_shift(s4 + s6);
+ x5 = fdct_round_shift(s5 + s7);
+ x6 = fdct_round_shift(s4 - s6);
+ x7 = fdct_round_shift(s5 - s7);
x8 = s8 + s10;
x9 = s9 + s11;
x10 = s8 - s10;
x11 = s9 - s11;
- x12 = dct_const_round_shift(s12 + s14);
- x13 = dct_const_round_shift(s13 + s15);
- x14 = dct_const_round_shift(s12 - s14);
- x15 = dct_const_round_shift(s13 - s15);
+ x12 = fdct_round_shift(s12 + s14);
+ x13 = fdct_round_shift(s13 + s15);
+ x14 = fdct_round_shift(s12 - s14);
+ x15 = fdct_round_shift(s13 - s15);
// stage 4
s2 = (- cospi_16_64) * (x2 + x3);
@@ -918,14 +924,14 @@
s14 = (- cospi_16_64) * (x14 + x15);
s15 = cospi_16_64 * (x14 - x15);
- x2 = dct_const_round_shift(s2);
- x3 = dct_const_round_shift(s3);
- x6 = dct_const_round_shift(s6);
- x7 = dct_const_round_shift(s7);
- x10 = dct_const_round_shift(s10);
- x11 = dct_const_round_shift(s11);
- x14 = dct_const_round_shift(s14);
- x15 = dct_const_round_shift(s15);
+ x2 = fdct_round_shift(s2);
+ x3 = fdct_round_shift(s3);
+ x6 = fdct_round_shift(s6);
+ x7 = fdct_round_shift(s7);
+ x10 = fdct_round_shift(s10);
+ x11 = fdct_round_shift(s11);
+ x14 = fdct_round_shift(s14);
+ x15 = fdct_round_shift(s15);
output[0] = x0;
output[1] = - x8;
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index c056bff..2a85dee 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -408,7 +408,7 @@
&& (xd->mb_to_bottom_edge >> (3 + MI_SIZE_LOG2)) + mi_height > y)
xd->mi_8x8[x_idx + y * mis] = mi_addr;
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_mb_init_quantizer(cpi, x);
}
@@ -557,7 +557,7 @@
/* segment ID */
if (seg->enabled) {
- if (!cpi->sf.variance_adaptive_quantization) {
+ if (!cpi->oxcf.aq_mode == VARIANCE_AQ) {
uint8_t *map = seg->update_map ? cpi->segmentation_map
: cm->last_frame_seg_map;
mbmi->segment_id = vp9_get_segment_id(cm, map, bsize, mi_row, mi_col);
@@ -634,7 +634,7 @@
x->source_variance = get_sby_perpixel_variance(cpi, x, bsize);
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
int energy;
if (bsize <= BLOCK_16X16) {
energy = x->mb_energy;
@@ -650,7 +650,7 @@
if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
vp9_activity_masking(cpi, x);
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_clear_system_state(); // __asm emms;
x->rdmult = round(x->rdmult * rdmult_ratio);
}
@@ -669,7 +669,7 @@
totaldist, bsize, ctx, best_rd);
}
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
x->rdmult = orig_rdmult;
if (*totalrate != INT_MAX) {
vp9_clear_system_state(); // __asm emms;
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index 0e1523b..22ab26d 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -63,13 +63,12 @@
static void subtract_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
struct macroblock_plane *const p = &x->plane[plane];
- const MACROBLOCKD *const xd = &x->e_mbd;
- const struct macroblockd_plane *const pd = &xd->plane[plane];
- const int bw = plane_block_width(bsize, pd);
- const int bh = plane_block_height(bsize, pd);
+ const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
+ const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
+ const int bw = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
+ const int bh = 4 * num_4x4_blocks_high_lookup[plane_bsize];
- vp9_subtract_block(bh, bw, p->src_diff, bw,
- p->src.buf, p->src.stride,
+ vp9_subtract_block(bh, bw, p->src_diff, bw, p->src.buf, p->src.stride,
pd->dst.buf, pd->dst.stride);
}
@@ -167,7 +166,7 @@
/* Now set up a Viterbi trellis to evaluate alternative roundings. */
rdmult = mb->rdmult * err_mult;
- if (mb->e_mbd.mi_8x8[0]->mbmi.ref_frame[0] == INTRA_FRAME)
+ if (!is_inter_block(&mb->e_mbd.mi_8x8[0]->mbmi))
rdmult = (rdmult * 9) >> 4;
rddiv = mb->rddiv;
/* Initialize the sentinel node of the trellis. */
@@ -551,15 +550,19 @@
const int16_t *scan, *iscan;
TX_TYPE tx_type;
MB_PREDICTION_MODE mode;
- const int bwl = b_width_log2(plane_bsize), bw = 1 << bwl;
- const int twl = bwl - tx_size, twmask = (1 << twl) - 1;
- int xoff, yoff;
+ const int bwl = b_width_log2(plane_bsize);
+ const int diff_stride = 4 * (1 << bwl);
uint8_t *src, *dst;
int16_t *src_diff;
uint16_t *eob = &pd->eobs[block];
+ int i, j;
+ txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
+ dst = &pd->dst.buf[4 * (j * pd->dst.stride + i)];
+ src = &p->src.buf[4 * (j * p->src.stride + i)];
+ src_diff = &p->src_diff[4 * (j * diff_stride + i)];
if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0)
- extend_for_intra(xd, plane_bsize, plane, block, tx_size);
+ extend_for_intra(xd, plane_bsize, plane, i, j);
// if (x->optimize)
// vp9_optimize_b(plane, block, plane_bsize, tx_size, x, args->ctx);
@@ -570,21 +573,16 @@
iscan = vp9_default_iscan_32x32;
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
block >>= 6;
- xoff = 32 * (block & twmask);
- yoff = 32 * (block >> twl);
- dst = pd->dst.buf + yoff * pd->dst.stride + xoff;
vp9_predict_intra_block(xd, block, bwl, TX_32X32, mode,
dst, pd->dst.stride, dst, pd->dst.stride);
if (!x->skip_recode) {
- src = p->src.buf + yoff * p->src.stride + xoff;
- src_diff = p->src_diff + 4 * bw * yoff + xoff;
- vp9_subtract_block(32, 32, src_diff, bw * 4,
+ vp9_subtract_block(32, 32, src_diff, diff_stride,
src, p->src.stride, dst, pd->dst.stride);
if (x->use_lp32x32fdct)
- vp9_fdct32x32_rd(src_diff, coeff, bw * 4);
+ vp9_fdct32x32_rd(src_diff, coeff, diff_stride);
else
- vp9_fdct32x32(src_diff, coeff, bw * 4);
+ vp9_fdct32x32(src_diff, coeff, diff_stride);
vp9_quantize_b_32x32(coeff, 1024, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, p->zbin_extra, eob, scan, iscan);
@@ -598,17 +596,12 @@
iscan = get_iscan_16x16(tx_type);
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
block >>= 4;
- xoff = 16 * (block & twmask);
- yoff = 16 * (block >> twl);
- dst = pd->dst.buf + yoff * pd->dst.stride + xoff;
vp9_predict_intra_block(xd, block, bwl, TX_16X16, mode,
dst, pd->dst.stride, dst, pd->dst.stride);
if (!x->skip_recode) {
- src = p->src.buf + yoff * p->src.stride + xoff;
- src_diff = p->src_diff + 4 * bw * yoff + xoff;
- vp9_subtract_block(16, 16, src_diff, bw * 4,
+ vp9_subtract_block(16, 16, src_diff, diff_stride,
src, p->src.stride, dst, pd->dst.stride);
- vp9_fht16x16(tx_type, src_diff, coeff, bw * 4);
+ vp9_fht16x16(tx_type, src_diff, coeff, diff_stride);
vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, p->zbin_extra, eob, scan, iscan);
@@ -622,17 +615,12 @@
iscan = get_iscan_8x8(tx_type);
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
block >>= 2;
- xoff = 8 * (block & twmask);
- yoff = 8 * (block >> twl);
- dst = pd->dst.buf + yoff * pd->dst.stride + xoff;
vp9_predict_intra_block(xd, block, bwl, TX_8X8, mode,
dst, pd->dst.stride, dst, pd->dst.stride);
if (!x->skip_recode) {
- src = p->src.buf + yoff * p->src.stride + xoff;
- src_diff = p->src_diff + 4 * bw * yoff + xoff;
- vp9_subtract_block(8, 8, src_diff, bw * 4,
+ vp9_subtract_block(8, 8, src_diff, diff_stride,
src, p->src.stride, dst, pd->dst.stride);
- vp9_fht8x8(tx_type, src_diff, coeff, bw * 4);
+ vp9_fht8x8(tx_type, src_diff, coeff, diff_stride);
vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff,
pd->dequant, p->zbin_extra, eob, scan, iscan);
@@ -649,21 +637,16 @@
else
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
- xoff = 4 * (block & twmask);
- yoff = 4 * (block >> twl);
- dst = pd->dst.buf + yoff * pd->dst.stride + xoff;
vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode,
dst, pd->dst.stride, dst, pd->dst.stride);
if (!x->skip_recode) {
- src = p->src.buf + yoff * p->src.stride + xoff;
- src_diff = p->src_diff + 4 * bw * yoff + xoff;
- vp9_subtract_block(4, 4, src_diff, bw * 4,
+ vp9_subtract_block(4, 4, src_diff, diff_stride,
src, p->src.stride, dst, pd->dst.stride);
if (tx_type != DCT_DCT)
- vp9_short_fht4x4(src_diff, coeff, bw * 4, tx_type);
+ vp9_short_fht4x4(src_diff, coeff, diff_stride, tx_type);
else
- x->fwd_txm4x4(src_diff, coeff, bw * 4);
+ x->fwd_txm4x4(src_diff, coeff, diff_stride);
vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round, p->quant,
p->quant_shift, qcoeff, dqcoeff,
pd->dequant, p->zbin_extra, eob, scan, iscan);
diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c
index bb9baff..cc4e347 100644
--- a/vp9/encoder/vp9_encodemv.c
+++ b/vp9/encoder/vp9_encodemv.c
@@ -68,7 +68,7 @@
int i, v;
int sign_cost[2], class_cost[MV_CLASSES], class0_cost[CLASS0_SIZE];
int bits_cost[MV_OFFSET_BITS][2];
- int class0_fp_cost[CLASS0_SIZE][4], fp_cost[4];
+ int class0_fp_cost[CLASS0_SIZE][MV_FP_SIZE], fp_cost[MV_FP_SIZE];
int class0_hp_cost[2], hp_cost[2];
sign_cost[0] = vp9_cost_zero(mvcomp->sign);
@@ -145,8 +145,8 @@
unsigned int (*branch_ct_classes)[MV_CLASSES - 1][2],
unsigned int (*branch_ct_class0)[CLASS0_SIZE - 1][2],
unsigned int (*branch_ct_bits)[MV_OFFSET_BITS][2],
- unsigned int (*branch_ct_class0_fp)[CLASS0_SIZE][4 - 1][2],
- unsigned int (*branch_ct_fp)[4 - 1][2],
+ unsigned int (*branch_ct_class0_fp)[CLASS0_SIZE][MV_FP_SIZE - 1][2],
+ unsigned int (*branch_ct_fp)[MV_FP_SIZE - 1][2],
unsigned int (*branch_ct_class0_hp)[2],
unsigned int (*branch_ct_hp)[2]) {
int i, j, k;
@@ -194,8 +194,8 @@
unsigned int branch_ct_classes[2][MV_CLASSES - 1][2];
unsigned int branch_ct_class0[2][CLASS0_SIZE - 1][2];
unsigned int branch_ct_bits[2][MV_OFFSET_BITS][2];
- unsigned int branch_ct_class0_fp[2][CLASS0_SIZE][4 - 1][2];
- unsigned int branch_ct_fp[2][4 - 1][2];
+ unsigned int branch_ct_class0_fp[2][CLASS0_SIZE][MV_FP_SIZE - 1][2];
+ unsigned int branch_ct_fp[2][MV_FP_SIZE - 1][2];
unsigned int branch_ct_class0_hp[2][2];
unsigned int branch_ct_hp[2][2];
nmv_context *mvc = &cpi->common.fc.nmvc;
@@ -227,12 +227,12 @@
for (i = 0; i < 2; ++i) {
for (j = 0; j < CLASS0_SIZE; ++j) {
int k;
- for (k = 0; k < 3; ++k)
+ for (k = 0; k < MV_FP_SIZE - 1; ++k)
update_mv(bc, branch_ct_class0_fp[i][j][k],
&mvc->comps[i].class0_fp[j][k], NMV_UPDATE_PROB);
}
- for (j = 0; j < 3; ++j)
+ for (j = 0; j < MV_FP_SIZE - 1; ++j)
update_mv(bc, branch_ct_fp[i][j], &mvc->comps[i].fp[j], NMV_UPDATE_PROB);
}
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index d80ecb1..df28410 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -599,14 +599,14 @@
num_8x8_blocks_wide_lookup[xd->mi_8x8[0]->mbmi.sb_type],
cm->mi_rows, cm->mi_cols);
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
int energy = vp9_block_energy(cpi, x, xd->mi_8x8[0]->mbmi.sb_type);
error_weight = vp9_vaq_inv_q_ratio(energy);
}
// do intra 16x16 prediction
this_error = vp9_encode_intra(x, use_dc_pred);
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_clear_system_state(); // __asm emms;
this_error *= error_weight;
}
@@ -644,7 +644,7 @@
first_pass_motion_search(cpi, x, &best_ref_mv,
&mv.as_mv, lst_yv12,
&motion_error, recon_yoffset);
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_clear_system_state(); // __asm emms;
motion_error *= error_weight;
}
@@ -655,7 +655,7 @@
tmp_err = INT_MAX;
first_pass_motion_search(cpi, x, &zero_ref_mv, &tmp_mv.as_mv,
lst_yv12, &tmp_err, recon_yoffset);
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_clear_system_state(); // __asm emms;
tmp_err *= error_weight;
}
@@ -675,7 +675,7 @@
first_pass_motion_search(cpi, x, &zero_ref_mv,
&tmp_mv.as_mv, gld_yv12,
&gf_motion_error, recon_yoffset);
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_clear_system_state(); // __asm emms;
gf_motion_error *= error_weight;
}
@@ -966,19 +966,19 @@
// (now uses the actual quantizer) but has not been tuned.
static void adjust_maxq_qrange(VP9_COMP *cpi) {
int i;
- // Set the max corresponding to cpi->avg_q * 2.0
- double q = cpi->avg_q * 2.0;
- cpi->twopass.maxq_max_limit = cpi->worst_quality;
- for (i = cpi->best_quality; i <= cpi->worst_quality; i++) {
+ // Set the max corresponding to cpi->rc.avg_q * 2.0
+ double q = cpi->rc.avg_q * 2.0;
+ cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
+ for (i = cpi->rc.best_quality; i <= cpi->rc.worst_quality; i++) {
cpi->twopass.maxq_max_limit = i;
if (vp9_convert_qindex_to_q(i) >= q)
break;
}
- // Set the min corresponding to cpi->avg_q * 0.5
- q = cpi->avg_q * 0.5;
- cpi->twopass.maxq_min_limit = cpi->best_quality;
- for (i = cpi->worst_quality; i >= cpi->best_quality; i--) {
+ // Set the min corresponding to cpi->rc.avg_q * 0.5
+ q = cpi->rc.avg_q * 0.5;
+ cpi->twopass.maxq_min_limit = cpi->rc.best_quality;
+ for (i = cpi->rc.worst_quality; i >= cpi->rc.best_quality; i--) {
cpi->twopass.maxq_min_limit = i;
if (vp9_convert_qindex_to_q(i) <= q)
break;
@@ -1017,10 +1017,10 @@
// Calculate a corrective factor based on a rolling ratio of bits spent
// vs target bits
- if (cpi->rolling_target_bits > 0 &&
- cpi->active_worst_quality < cpi->worst_quality) {
- double rolling_ratio = (double)cpi->rolling_actual_bits /
- (double)cpi->rolling_target_bits;
+ if (cpi->rc.rolling_target_bits > 0 &&
+ cpi->rc.active_worst_quality < cpi->rc.worst_quality) {
+ double rolling_ratio = (double)cpi->rc.rolling_actual_bits /
+ (double)cpi->rc.rolling_target_bits;
if (rolling_ratio < 0.95)
cpi->twopass.est_max_qcorrection_factor -= 0.005;
@@ -1066,8 +1066,8 @@
// average q observed in clip for non kf/gf/arf frames
// Give average a chance to settle though.
// PGW TODO.. This code is broken for the extended Q range
- if (cpi->ni_frames > ((int)cpi->twopass.total_stats.count >> 8) &&
- cpi->ni_frames > 25)
+ if (cpi->rc.ni_frames > ((int)cpi->twopass.total_stats.count >> 8) &&
+ cpi->rc.ni_frames > 25)
adjust_maxq_qrange(cpi);
return q;
@@ -1146,10 +1146,10 @@
// Clip value to range "best allowed to (worst allowed - 1)"
q = select_cq_level(q);
- if (q >= cpi->worst_quality)
- q = cpi->worst_quality - 1;
- if (q < cpi->best_quality)
- q = cpi->best_quality;
+ if (q >= cpi->rc.worst_quality)
+ q = cpi->rc.worst_quality - 1;
+ if (q < cpi->rc.best_quality)
+ q = cpi->rc.best_quality;
return q;
}
@@ -1599,13 +1599,13 @@
if (cpi->twopass.frames_to_key <= (FIXED_ARF_GROUP_SIZE + 8)) {
// Setup a GF group close to the keyframe.
cpi->source_alt_ref_pending = 0;
- cpi->baseline_gf_interval = cpi->twopass.frames_to_key;
- schedule_frames(cpi, 0, (cpi->baseline_gf_interval - 1), 2, 0, 0);
+ cpi->rc.baseline_gf_interval = cpi->twopass.frames_to_key;
+ schedule_frames(cpi, 0, (cpi->rc.baseline_gf_interval - 1), 2, 0, 0);
} else {
// Setup a fixed period ARF group.
cpi->source_alt_ref_pending = 1;
- cpi->baseline_gf_interval = FIXED_ARF_GROUP_SIZE;
- schedule_frames(cpi, 0, -(cpi->baseline_gf_interval - 1), 2, 1, 0);
+ cpi->rc.baseline_gf_interval = FIXED_ARF_GROUP_SIZE;
+ schedule_frames(cpi, 0, -(cpi->rc.baseline_gf_interval - 1), 2, 1, 0);
}
// Replace level indicator of -1 with correct level.
@@ -1702,10 +1702,10 @@
// At high Q when there are few bits to spare we are better with a longer
// interval to spread the cost of the GF.
active_max_gf_interval =
- 12 + ((int)vp9_convert_qindex_to_q(cpi->active_worst_quality) >> 5);
+ 12 + ((int)vp9_convert_qindex_to_q(cpi->rc.active_worst_quality) >> 5);
- if (active_max_gf_interval > cpi->max_gf_interval)
- active_max_gf_interval = cpi->max_gf_interval;
+ if (active_max_gf_interval > cpi->rc.max_gf_interval)
+ active_max_gf_interval = cpi->rc.max_gf_interval;
i = 0;
while (((i < cpi->twopass.static_scene_max_gf_interval) ||
@@ -1799,7 +1799,7 @@
}
// Set the interval until the next gf or arf.
- cpi->baseline_gf_interval = i;
+ cpi->rc.baseline_gf_interval = i;
#if CONFIG_MULTIPLE_ARF
if (cpi->multi_arf_enabled) {
@@ -1825,24 +1825,25 @@
(mv_in_out_accumulator > -2.0)) &&
(boost_score > 100)) {
// Alternative boost calculation for alt ref
- cpi->gfu_boost = calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost,
+ cpi->rc.gfu_boost = calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost,
&b_boost);
cpi->source_alt_ref_pending = 1;
#if CONFIG_MULTIPLE_ARF
// Set the ARF schedule.
if (cpi->multi_arf_enabled) {
- schedule_frames(cpi, 0, -(cpi->baseline_gf_interval - 1), 2, 1, 0);
+ schedule_frames(cpi, 0, -(cpi->rc.baseline_gf_interval - 1), 2, 1, 0);
}
#endif
} else {
- cpi->gfu_boost = (int)boost_score;
+ cpi->rc.gfu_boost = (int)boost_score;
cpi->source_alt_ref_pending = 0;
#if CONFIG_MULTIPLE_ARF
// Set the GF schedule.
if (cpi->multi_arf_enabled) {
- schedule_frames(cpi, 0, cpi->baseline_gf_interval - 1, 2, 0, 0);
- assert(cpi->new_frame_coding_order_period == cpi->baseline_gf_interval);
+ schedule_frames(cpi, 0, cpi->rc.baseline_gf_interval - 1, 2, 0, 0);
+ assert(cpi->new_frame_coding_order_period ==
+ cpi->rc.baseline_gf_interval);
}
#endif
}
@@ -1915,8 +1916,9 @@
// Clip cpi->twopass.gf_group_bits based on user supplied data rate
// variability limit (cpi->oxcf.two_pass_vbrmax_section)
if (cpi->twopass.gf_group_bits >
- (int64_t)max_bits * cpi->baseline_gf_interval)
- cpi->twopass.gf_group_bits = (int64_t)max_bits * cpi->baseline_gf_interval;
+ (int64_t)max_bits * cpi->rc.baseline_gf_interval)
+ cpi->twopass.gf_group_bits =
+ (int64_t)max_bits * cpi->rc.baseline_gf_interval;
// Reset the file position
reset_fpf_position(cpi, start_pos);
@@ -1929,19 +1931,18 @@
i <= (cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME);
++i) {
int allocation_chunks;
- int q = cpi->oxcf.fixed_q < 0 ? cpi->last_q[INTER_FRAME]
- : cpi->oxcf.fixed_q;
+ int q = cpi->rc.last_q[INTER_FRAME];
int gf_bits;
- int boost = (cpi->gfu_boost * vp9_gfboost_qadjust(q)) / 100;
+ int boost = (cpi->rc.gfu_boost * vp9_gfboost_qadjust(q)) / 100;
// Set max and minimum boost and hence minimum allocation
- boost = clamp(boost, 125, (cpi->baseline_gf_interval + 1) * 200);
+ boost = clamp(boost, 125, (cpi->rc.baseline_gf_interval + 1) * 200);
if (cpi->source_alt_ref_pending && i == 0)
- allocation_chunks = ((cpi->baseline_gf_interval + 1) * 100) + boost;
+ allocation_chunks = ((cpi->rc.baseline_gf_interval + 1) * 100) + boost;
else
- allocation_chunks = (cpi->baseline_gf_interval * 100) + (boost - 100);
+ allocation_chunks = (cpi->rc.baseline_gf_interval * 100) + (boost - 100);
// Prevent overflow
if (boost > 1023) {
@@ -1958,10 +1959,10 @@
// If the frame that is to be boosted is simpler than the average for
// the gf/arf group then use an alternative calculation
// based on the error score of the frame itself
- if (mod_frame_err < gf_group_err / (double)cpi->baseline_gf_interval) {
+ if (mod_frame_err < gf_group_err / (double)cpi->rc.baseline_gf_interval) {
double alt_gf_grp_bits =
(double)cpi->twopass.kf_group_bits *
- (mod_frame_err * (double)cpi->baseline_gf_interval) /
+ (mod_frame_err * (double)cpi->rc.baseline_gf_interval) /
DOUBLE_DIVIDE_CHECK(cpi->twopass.kf_group_error_left);
int alt_gf_bits = (int)((double)boost * (alt_gf_grp_bits /
@@ -1986,7 +1987,7 @@
gf_bits = 0;
// Add in minimum for a frame
- gf_bits += cpi->min_frame_bandwidth;
+ gf_bits += cpi->rc.min_frame_bandwidth;
if (i == 0) {
cpi->twopass.gf_bits = gf_bits;
@@ -1994,7 +1995,7 @@
if (i == 1 || (!cpi->source_alt_ref_pending
&& (cpi->common.frame_type != KEY_FRAME))) {
// Per frame bit target for this frame
- cpi->per_frame_bandwidth = gf_bits;
+ cpi->rc.per_frame_bandwidth = gf_bits;
}
}
@@ -2017,7 +2018,7 @@
cpi->twopass.gf_group_error_left = (int64_t)gf_group_err;
cpi->twopass.gf_group_bits -= cpi->twopass.gf_bits
- - cpi->min_frame_bandwidth;
+ - cpi->rc.min_frame_bandwidth;
if (cpi->twopass.gf_group_bits < 0)
cpi->twopass.gf_group_bits = 0;
@@ -2025,8 +2026,9 @@
// This condition could fail if there are two kfs very close together
// despite (MIN_GF_INTERVAL) and would cause a divide by 0 in the
// calculation of alt_extra_bits.
- if (cpi->baseline_gf_interval >= 3) {
- const int boost = cpi->source_alt_ref_pending ? b_boost : cpi->gfu_boost;
+ if (cpi->rc.baseline_gf_interval >= 3) {
+ const int boost = cpi->source_alt_ref_pending ?
+ b_boost : cpi->rc.gfu_boost;
if (boost >= 150) {
int alt_extra_bits;
@@ -2045,7 +2047,7 @@
zero_stats(§ionstats);
reset_fpf_position(cpi, start_pos);
- for (i = 0; i < cpi->baseline_gf_interval; i++) {
+ for (i = 0; i < cpi->rc.baseline_gf_interval; i++) {
input_stats(cpi, &next_frame);
accumulate_stats(§ionstats, &next_frame);
}
@@ -2102,10 +2104,10 @@
cpi->twopass.gf_group_bits = 0;
// Add in the minimum number of bits that is set aside for every frame.
- target_frame_size += cpi->min_frame_bandwidth;
+ target_frame_size += cpi->rc.min_frame_bandwidth;
// Per frame bit target for this frame.
- cpi->per_frame_bandwidth = target_frame_size;
+ cpi->rc.per_frame_bandwidth = target_frame_size;
}
// Make a damped adjustment to the active max q.
@@ -2145,7 +2147,7 @@
vp9_clear_system_state();
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
- cpi->active_worst_quality = cpi->oxcf.cq_level;
+ cpi->rc.active_worst_quality = cpi->oxcf.cq_level;
} else {
// Special case code for first frame.
if (cpi->common.current_video_frame == 0) {
@@ -2169,15 +2171,15 @@
*/
// guess at maxq needed in 2nd pass
- cpi->twopass.maxq_max_limit = cpi->worst_quality;
- cpi->twopass.maxq_min_limit = cpi->best_quality;
+ cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
+ cpi->twopass.maxq_min_limit = cpi->rc.best_quality;
tmp_q = estimate_max_q(cpi, &cpi->twopass.total_left_stats,
section_target_bandwidth);
- cpi->active_worst_quality = tmp_q;
- cpi->ni_av_qi = tmp_q;
- cpi->avg_q = vp9_convert_qindex_to_q(tmp_q);
+ cpi->rc.active_worst_quality = tmp_q;
+ cpi->rc.ni_av_qi = tmp_q;
+ cpi->rc.avg_q = vp9_convert_qindex_to_q(tmp_q);
// Limit the maxq value returned subsequently.
// This increases the risk of overspend or underspend if the initial
@@ -2193,7 +2195,7 @@
// few surplus bits or get beneath the target rate.
else if ((cpi->common.current_video_frame <
(((unsigned int)cpi->twopass.total_stats.count * 255) >> 8)) &&
- ((cpi->common.current_video_frame + cpi->baseline_gf_interval) <
+ ((cpi->common.current_video_frame + cpi->rc.baseline_gf_interval) <
(unsigned int)cpi->twopass.total_stats.count)) {
int section_target_bandwidth =
(int)(cpi->twopass.bits_left / frames_left);
@@ -2206,8 +2208,8 @@
section_target_bandwidth);
// Make a damped adjustment to active max Q
- cpi->active_worst_quality =
- adjust_active_maxq(cpi->active_worst_quality, tmp_q);
+ cpi->rc.active_worst_quality =
+ adjust_active_maxq(cpi->rc.active_worst_quality, tmp_q);
}
}
vp9_zero(this_frame);
@@ -2225,7 +2227,7 @@
}
// Is this a GF / ARF (Note that a KF is always also a GF)
- if (cpi->frames_till_gf_update_due == 0) {
+ if (cpi->rc.frames_till_gf_update_due == 0) {
// Define next gf group and assign bits to it
this_frame_copy = this_frame;
@@ -2259,10 +2261,10 @@
if (cpi->source_alt_ref_pending && (cpi->common.frame_type != KEY_FRAME)) {
// Assign a standard frames worth of bits from those allocated
// to the GF group
- int bak = cpi->per_frame_bandwidth;
+ int bak = cpi->rc.per_frame_bandwidth;
this_frame_copy = this_frame;
assign_std_frame_bits(cpi, &this_frame_copy);
- cpi->per_frame_bandwidth = bak;
+ cpi->rc.per_frame_bandwidth = bak;
}
} else {
// Otherwise this is an ordinary frame
@@ -2283,7 +2285,7 @@
}
// Set nominal per second bandwidth for this frame
- cpi->target_bandwidth = (int)(cpi->per_frame_bandwidth
+ cpi->target_bandwidth = (int)(cpi->rc.per_frame_bandwidth
* cpi->output_framerate);
if (cpi->target_bandwidth < 0)
cpi->target_bandwidth = 0;
@@ -2416,7 +2418,7 @@
cpi->source_alt_ref_active = 0;
// Kf is always a gf so clear frames till next gf counter
- cpi->frames_till_gf_update_due = 0;
+ cpi->rc.frames_till_gf_update_due = 0;
cpi->twopass.frames_to_key = 1;
@@ -2579,7 +2581,7 @@
}
// For the first few frames collect data to decide kf boost.
- if (i <= (cpi->max_gf_interval * 2)) {
+ if (i <= (cpi->rc.max_gf_interval * 2)) {
if (next_frame.intra_error > cpi->twopass.kf_intra_err_min)
r = (IIKFACTOR2 * next_frame.intra_error /
DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
@@ -2637,7 +2639,7 @@
// Make a note of baseline boost and the zero motion
// accumulator value for use elsewhere.
- cpi->kf_boost = kf_boost;
+ cpi->rc.kf_boost = kf_boost;
cpi->kf_zeromotion_pct = (int)(zero_motion_accumulator * 100.0);
// We do three calculations for kf size.
@@ -2707,10 +2709,10 @@
cpi->twopass.kf_group_bits -= cpi->twopass.kf_bits;
// Add in the minimum frame allowance
- cpi->twopass.kf_bits += cpi->min_frame_bandwidth;
+ cpi->twopass.kf_bits += cpi->rc.min_frame_bandwidth;
// Peer frame bit target for this frame
- cpi->per_frame_bandwidth = cpi->twopass.kf_bits;
+ cpi->rc.per_frame_bandwidth = cpi->twopass.kf_bits;
// Convert to a per second bitrate
cpi->target_bandwidth = (int)(cpi->twopass.kf_bits *
cpi->output_framerate);
diff --git a/vp9/encoder/vp9_mbgraph.c b/vp9/encoder/vp9_mbgraph.c
index 9870738..544f130 100644
--- a/vp9/encoder/vp9_mbgraph.c
+++ b/vp9/encoder/vp9_mbgraph.c
@@ -323,8 +323,8 @@
1));
// We are not interested in results beyond the alt ref itself.
- if (n_frames > cpi->frames_till_gf_update_due)
- n_frames = cpi->frames_till_gf_update_due;
+ if (n_frames > cpi->rc.frames_till_gf_update_due)
+ n_frames = cpi->rc.frames_till_gf_update_due;
// defer cost to reference frames
for (i = n_frames - 1; i >= 0; i--) {
@@ -396,7 +396,7 @@
// we need to look ahead beyond where the ARF transitions into
// being a GF - so exit if we don't look ahead beyond that
- if (n_frames <= cpi->frames_till_gf_update_due)
+ if (n_frames <= cpi->rc.frames_till_gf_update_due)
return;
if (n_frames > (int)cpi->frames_till_alt_ref_frame)
n_frames = cpi->frames_till_alt_ref_frame;
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index dd4705d..585f799 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -37,9 +37,6 @@
#include "vpx_ports/vpx_timer.h"
-
-extern void print_tree_update_probs();
-
static void set_default_lf_deltas(struct loopfilter *lf);
#define DEFAULT_INTERP_FILTER SWITCHABLE
@@ -112,15 +109,6 @@
extern void vp9_init_quantizer(VP9_COMP *cpi);
-// Tables relating active max Q to active min Q
-static int kf_low_motion_minq[QINDEX_RANGE];
-static int kf_high_motion_minq[QINDEX_RANGE];
-static int gf_low_motion_minq[QINDEX_RANGE];
-static int gf_high_motion_minq[QINDEX_RANGE];
-static int inter_minq[QINDEX_RANGE];
-static int afq_low_motion_minq[QINDEX_RANGE];
-static int afq_high_motion_minq[QINDEX_RANGE];
-
static INLINE void Scale2Ratio(int mode, int *hr, int *hs) {
switch (mode) {
case NORMAL:
@@ -147,96 +135,6 @@
}
}
-// Functions to compute the active minq lookup table entries based on a
-// formulaic approach to facilitate easier adjustment of the Q tables.
-// The formulae were derived from computing a 3rd order polynomial best
-// fit to the original data (after plotting real maxq vs minq (not q index))
-static int calculate_minq_index(double maxq,
- double x3, double x2, double x1, double c) {
- int i;
- const double minqtarget = MIN(((x3 * maxq + x2) * maxq + x1) * maxq + c,
- maxq);
-
- // Special case handling to deal with the step from q2.0
- // down to lossless mode represented by q 1.0.
- if (minqtarget <= 2.0)
- return 0;
-
- for (i = 0; i < QINDEX_RANGE; i++) {
- if (minqtarget <= vp9_convert_qindex_to_q(i))
- return i;
- }
-
- return QINDEX_RANGE - 1;
-}
-
-static void init_minq_luts(void) {
- int i;
-
- for (i = 0; i < QINDEX_RANGE; i++) {
- const double maxq = vp9_convert_qindex_to_q(i);
-
-
- kf_low_motion_minq[i] = calculate_minq_index(maxq,
- 0.000001,
- -0.0004,
- 0.15,
- 0.0);
- kf_high_motion_minq[i] = calculate_minq_index(maxq,
- 0.000002,
- -0.0012,
- 0.5,
- 0.0);
-
- gf_low_motion_minq[i] = calculate_minq_index(maxq,
- 0.0000015,
- -0.0009,
- 0.32,
- 0.0);
- gf_high_motion_minq[i] = calculate_minq_index(maxq,
- 0.0000021,
- -0.00125,
- 0.50,
- 0.0);
- inter_minq[i] = calculate_minq_index(maxq,
- 0.00000271,
- -0.00113,
- 0.75,
- 0.0);
- afq_low_motion_minq[i] = calculate_minq_index(maxq,
- 0.0000015,
- -0.0009,
- 0.33,
- 0.0);
- afq_high_motion_minq[i] = calculate_minq_index(maxq,
- 0.0000021,
- -0.00125,
- 0.55,
- 0.0);
- }
-}
-
-static int get_active_quality(int q,
- int gfu_boost,
- int low,
- int high,
- int *low_motion_minq,
- int *high_motion_minq) {
- int active_best_quality;
- if (gfu_boost > high) {
- active_best_quality = low_motion_minq[q];
- } else if (gfu_boost < low) {
- active_best_quality = high_motion_minq[q];
- } else {
- const int gap = high - low;
- const int offset = high - gfu_boost;
- const int qdiff = high_motion_minq[q] - low_motion_minq[q];
- const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap;
- active_best_quality = low_motion_minq[q] + adjustment;
- }
- return active_best_quality;
-}
-
static void set_mvcost(VP9_COMP *cpi) {
MACROBLOCK *const mb = &cpi->mb;
if (cpi->common.allow_high_precision_mv) {
@@ -256,7 +154,7 @@
vp9_tokenize_initialize();
vp9_init_quant_tables();
vp9_init_me_luts();
- init_minq_luts();
+ vp9_init_minq_luts();
// init_base_skip_probs();
init_done = 1;
}
@@ -325,18 +223,18 @@
// target q value
int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget) {
int i;
- int start_index = cpi->worst_quality;
- int target_index = cpi->worst_quality;
+ int start_index = cpi->rc.worst_quality;
+ int target_index = cpi->rc.worst_quality;
// Convert the average q value to an index.
- for (i = cpi->best_quality; i < cpi->worst_quality; i++) {
+ for (i = cpi->rc.best_quality; i < cpi->rc.worst_quality; i++) {
start_index = i;
if (vp9_convert_qindex_to_q(i) >= qstart)
break;
}
// Convert the q target to an index
- for (i = cpi->best_quality; i < cpi->worst_quality; i++) {
+ for (i = cpi->rc.best_quality; i < cpi->rc.worst_quality; i++) {
target_index = i;
if (vp9_convert_qindex_to_q(i) >= qtarget)
break;
@@ -349,7 +247,7 @@
VP9_COMMON *cm = &cpi->common;
struct segmentation *seg = &cm->seg;
- int high_q = (int)(cpi->avg_q > 48.0);
+ int high_q = (int)(cpi->rc.avg_q > 48.0);
int qi_delta;
// Disable and clear down for KF
@@ -387,7 +285,8 @@
seg->update_map = 1;
seg->update_data = 1;
- qi_delta = vp9_compute_qdelta(cpi, cpi->avg_q, (cpi->avg_q * 0.875));
+ qi_delta = vp9_compute_qdelta(
+ cpi, cpi->rc.avg_q, (cpi->rc.avg_q * 0.875));
vp9_set_segdata(seg, 1, SEG_LVL_ALT_Q, (qi_delta - 2));
vp9_set_segdata(seg, 1, SEG_LVL_ALT_LF, -2);
@@ -401,15 +300,15 @@
// All other frames if segmentation has been enabled
// First normal frame in a valid gf or alt ref group
- if (cpi->frames_since_golden == 0) {
+ if (cpi->rc.frames_since_golden == 0) {
// Set up segment features for normal frames in an arf group
if (cpi->source_alt_ref_active) {
seg->update_map = 0;
seg->update_data = 1;
seg->abs_delta = SEGMENT_DELTADATA;
- qi_delta = vp9_compute_qdelta(cpi, cpi->avg_q,
- (cpi->avg_q * 1.125));
+ qi_delta = vp9_compute_qdelta(cpi, cpi->rc.avg_q,
+ (cpi->rc.avg_q * 1.125));
vp9_set_segdata(seg, 1, SEG_LVL_ALT_Q, (qi_delta + 2));
vp9_enable_segfeature(seg, 1, SEG_LVL_ALT_Q);
@@ -467,69 +366,6 @@
}
}
-#ifdef ENTROPY_STATS
-void vp9_update_mode_context_stats(VP9_COMP *cpi) {
- VP9_COMMON *cm = &cpi->common;
- int i, j;
- unsigned int (*inter_mode_counts)[INTER_MODES - 1][2] =
- cm->fc.inter_mode_counts;
- int64_t (*mv_ref_stats)[INTER_MODES - 1][2] = cpi->mv_ref_stats;
- FILE *f;
-
- // Read the past stats counters
- f = fopen("mode_context.bin", "rb");
- if (!f) {
- vpx_memset(cpi->mv_ref_stats, 0, sizeof(cpi->mv_ref_stats));
- } else {
- fread(cpi->mv_ref_stats, sizeof(cpi->mv_ref_stats), 1, f);
- fclose(f);
- }
-
- // Add in the values for this frame
- for (i = 0; i < INTER_MODE_CONTEXTS; i++) {
- for (j = 0; j < INTER_MODES - 1; j++) {
- mv_ref_stats[i][j][0] += (int64_t)inter_mode_counts[i][j][0];
- mv_ref_stats[i][j][1] += (int64_t)inter_mode_counts[i][j][1];
- }
- }
-
- // Write back the accumulated stats
- f = fopen("mode_context.bin", "wb");
- fwrite(cpi->mv_ref_stats, sizeof(cpi->mv_ref_stats), 1, f);
- fclose(f);
-}
-
-void print_mode_context(VP9_COMP *cpi) {
- FILE *f = fopen("vp9_modecont.c", "a");
- int i, j;
-
- fprintf(f, "#include \"vp9_entropy.h\"\n");
- fprintf(
- f,
- "const int inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1] =");
- fprintf(f, "{\n");
- for (j = 0; j < INTER_MODE_CONTEXTS; j++) {
- fprintf(f, " {/* %d */ ", j);
- fprintf(f, " ");
- for (i = 0; i < INTER_MODES - 1; i++) {
- int this_prob;
- int64_t count = cpi->mv_ref_stats[j][i][0] + cpi->mv_ref_stats[j][i][1];
- if (count)
- this_prob = ((cpi->mv_ref_stats[j][i][0] * 256) + (count >> 1)) / count;
- else
- this_prob = 128;
-
- // context probs
- fprintf(f, "%5d, ", this_prob);
- }
- fprintf(f, " },\n");
- }
-
- fprintf(f, "};\n");
- fclose(f);
-}
-#endif // ENTROPY_STATS
-
// DEBUG: Print out the segment id of each MB in the current frame.
static void print_seg_map(VP9_COMP *cpi) {
VP9_COMMON *cm = &cpi->common;
@@ -764,8 +600,6 @@
sf->static_segmentation = 0;
#endif
- sf->variance_adaptive_quantization = 0;
-
switch (mode) {
case 0: // This is the best quality mode.
break;
@@ -1127,33 +961,34 @@
cpi->oxcf.framerate = framerate;
cpi->output_framerate = cpi->oxcf.framerate;
- cpi->per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth
- / cpi->output_framerate);
- cpi->av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth
- / cpi->output_framerate);
- cpi->min_frame_bandwidth = (int)(cpi->av_per_frame_bandwidth *
- cpi->oxcf.two_pass_vbrmin_section / 100);
+ cpi->rc.per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth
+ / cpi->output_framerate);
+ cpi->rc.av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth
+ / cpi->output_framerate);
+ cpi->rc.min_frame_bandwidth = (int)(cpi->rc.av_per_frame_bandwidth *
+ cpi->oxcf.two_pass_vbrmin_section / 100);
- cpi->min_frame_bandwidth = MAX(cpi->min_frame_bandwidth, FRAME_OVERHEAD_BITS);
+ cpi->rc.min_frame_bandwidth = MAX(cpi->rc.min_frame_bandwidth,
+ FRAME_OVERHEAD_BITS);
// Set Maximum gf/arf interval
- cpi->max_gf_interval = 16;
+ cpi->rc.max_gf_interval = 16;
// Extended interval for genuinely static scenes
cpi->twopass.static_scene_max_gf_interval = cpi->key_frame_frequency >> 1;
// Special conditions when alt ref frame enabled in lagged compress mode
if (cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames) {
- if (cpi->max_gf_interval > cpi->oxcf.lag_in_frames - 1)
- cpi->max_gf_interval = cpi->oxcf.lag_in_frames - 1;
+ if (cpi->rc.max_gf_interval > cpi->oxcf.lag_in_frames - 1)
+ cpi->rc.max_gf_interval = cpi->oxcf.lag_in_frames - 1;
if (cpi->twopass.static_scene_max_gf_interval > cpi->oxcf.lag_in_frames - 1)
cpi->twopass.static_scene_max_gf_interval = cpi->oxcf.lag_in_frames - 1;
}
- if (cpi->max_gf_interval > cpi->twopass.static_scene_max_gf_interval)
- cpi->max_gf_interval = cpi->twopass.static_scene_max_gf_interval;
+ if (cpi->rc.max_gf_interval > cpi->twopass.static_scene_max_gf_interval)
+ cpi->rc.max_gf_interval = cpi->twopass.static_scene_max_gf_interval;
}
static int64_t rescale(int val, int64_t num, int denom) {
@@ -1194,21 +1029,21 @@
vp9_change_config(ptr, oxcf);
// Initialize active best and worst q and average q values.
- cpi->active_worst_quality = cpi->oxcf.worst_allowed_q;
- cpi->active_best_quality = cpi->oxcf.best_allowed_q;
- cpi->avg_frame_qindex = cpi->oxcf.worst_allowed_q;
+ cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q;
+ cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q;
+ cpi->rc.avg_frame_qindex = cpi->oxcf.worst_allowed_q;
// Initialise the starting buffer levels
- cpi->buffer_level = cpi->oxcf.starting_buffer_level;
- cpi->bits_off_target = cpi->oxcf.starting_buffer_level;
+ cpi->rc.buffer_level = cpi->oxcf.starting_buffer_level;
+ cpi->rc.bits_off_target = cpi->oxcf.starting_buffer_level;
- cpi->rolling_target_bits = cpi->av_per_frame_bandwidth;
- cpi->rolling_actual_bits = cpi->av_per_frame_bandwidth;
- cpi->long_rolling_target_bits = cpi->av_per_frame_bandwidth;
- cpi->long_rolling_actual_bits = cpi->av_per_frame_bandwidth;
+ cpi->rc.rolling_target_bits = cpi->rc.av_per_frame_bandwidth;
+ cpi->rc.rolling_actual_bits = cpi->rc.av_per_frame_bandwidth;
+ cpi->rc.long_rolling_target_bits = cpi->rc.av_per_frame_bandwidth;
+ cpi->rc.long_rolling_actual_bits = cpi->rc.av_per_frame_bandwidth;
- cpi->total_actual_bits = 0;
- cpi->total_target_vs_actual = 0;
+ cpi->rc.total_actual_bits = 0;
+ cpi->rc.total_target_vs_actual = 0;
cpi->static_mb_pct = 0;
@@ -1272,7 +1107,7 @@
cpi->oxcf.lossless = oxcf->lossless;
cpi->mb.e_mbd.itxm_add = cpi->oxcf.lossless ? vp9_iwht4x4_add
: vp9_idct4x4_add;
- cpi->baseline_gf_interval = DEFAULT_GF_INTERVAL;
+ cpi->rc.baseline_gf_interval = DEFAULT_GF_INTERVAL;
cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
@@ -1327,20 +1162,18 @@
vp9_new_framerate(cpi, cpi->oxcf.framerate);
// Set absolute upper and lower quality limits
- cpi->worst_quality = cpi->oxcf.worst_allowed_q;
- cpi->best_quality = cpi->oxcf.best_allowed_q;
+ cpi->rc.worst_quality = cpi->oxcf.worst_allowed_q;
+ cpi->rc.best_quality = cpi->oxcf.best_allowed_q;
// active values should only be modified if out of new range
- cpi->active_worst_quality = clamp(cpi->active_worst_quality,
+ cpi->rc.active_worst_quality = clamp(cpi->rc.active_worst_quality,
cpi->oxcf.best_allowed_q,
cpi->oxcf.worst_allowed_q);
- cpi->active_best_quality = clamp(cpi->active_best_quality,
+ cpi->rc.active_best_quality = clamp(cpi->rc.active_best_quality,
cpi->oxcf.best_allowed_q,
cpi->oxcf.worst_allowed_q);
- cpi->buffered_mode = cpi->oxcf.optimal_buffer_level > 0;
-
cpi->cq_target_quality = cpi->oxcf.cq_level;
cm->mcomp_filter_type = DEFAULT_INTERP_FILTER;
@@ -1365,9 +1198,9 @@
update_frame_size(cpi);
if (cpi->oxcf.fixed_q >= 0) {
- cpi->last_q[0] = cpi->oxcf.fixed_q;
- cpi->last_q[1] = cpi->oxcf.fixed_q;
- cpi->last_boosted_qindex = cpi->oxcf.fixed_q;
+ cpi->rc.last_q[0] = cpi->oxcf.fixed_q;
+ cpi->rc.last_q[1] = cpi->oxcf.fixed_q;
+ cpi->rc.last_boosted_qindex = cpi->oxcf.fixed_q;
}
cpi->speed = cpi->oxcf.cpu_used;
@@ -1595,16 +1428,12 @@
init_pick_mode_context(cpi);
cm->current_video_frame = 0;
- cpi->kf_overspend_bits = 0;
- cpi->kf_bitrate_adjustment = 0;
- cpi->frames_till_gf_update_due = 0;
- cpi->gf_overspend_bits = 0;
- cpi->non_gf_bitrate_adjustment = 0;
+ cpi->rc.frames_till_gf_update_due = 0;
// Set reference frame sign bias for ALTREF frame to 1 (for now)
cm->ref_frame_sign_bias[ALTREF_FRAME] = 1;
- cpi->baseline_gf_interval = DEFAULT_GF_INTERVAL;
+ cpi->rc.baseline_gf_interval = DEFAULT_GF_INTERVAL;
cpi->gold_is_last = 0;
cpi->alt_is_last = 0;
@@ -1704,19 +1533,18 @@
cpi->first_time_stamp_ever = INT64_MAX;
- cpi->frames_till_gf_update_due = 0;
- cpi->key_frame_count = 1;
+ cpi->rc.frames_till_gf_update_due = 0;
+ cpi->rc.key_frame_count = 1;
- cpi->ni_av_qi = cpi->oxcf.worst_allowed_q;
- cpi->ni_tot_qi = 0;
- cpi->ni_frames = 0;
- cpi->tot_q = 0.0;
- cpi->avg_q = vp9_convert_qindex_to_q(cpi->oxcf.worst_allowed_q);
- cpi->total_byte_count = 0;
+ cpi->rc.ni_av_qi = cpi->oxcf.worst_allowed_q;
+ cpi->rc.ni_tot_qi = 0;
+ cpi->rc.ni_frames = 0;
+ cpi->rc.tot_q = 0.0;
+ cpi->rc.avg_q = vp9_convert_qindex_to_q(cpi->oxcf.worst_allowed_q);
- cpi->rate_correction_factor = 1.0;
- cpi->key_frame_rate_correction_factor = 1.0;
- cpi->gf_rate_correction_factor = 1.0;
+ cpi->rc.rate_correction_factor = 1.0;
+ cpi->rc.key_frame_rate_correction_factor = 1.0;
+ cpi->rc.gf_rate_correction_factor = 1.0;
cpi->twopass.est_max_qcorrection_factor = 1.0;
cal_nmvjointsadcost(cpi->mb.nmvjointsadcost);
@@ -1733,7 +1561,7 @@
cal_nmvsadcosts_hp(cpi->mb.nmvsadcost_hp);
for (i = 0; i < KEY_FRAME_CONTEXT; i++)
- cpi->prior_key_frame_distance[i] = (int)cpi->output_framerate;
+ cpi->rc.prior_key_frame_distance[i] = (int)cpi->output_framerate;
#ifdef OUTPUT_YUV_SRC
yuv_file = fopen("bd.yuv", "ab");
@@ -1904,14 +1732,6 @@
vp9_end_second_pass(cpi);
}
-#ifdef ENTROPY_STATS
- if (cpi->pass != 1) {
- print_context_counters();
- print_tree_update_probs();
- print_mode_context(cpi);
- }
-#endif
-
#ifdef MODE_STATS
if (cpi->pass != 1) {
write_tx_count_stats();
@@ -2391,7 +2211,7 @@
static void update_alt_ref_frame_stats(VP9_COMP *cpi) {
// this frame refreshes means next frames don't unless specified by user
- cpi->frames_since_golden = 0;
+ cpi->rc.frames_since_golden = 0;
#if CONFIG_MULTIPLE_ARF
if (!cpi->multi_arf_enabled)
@@ -2407,7 +2227,7 @@
if (cpi->refresh_golden_frame) {
// this frame refreshes means next frames don't unless specified by user
cpi->refresh_golden_frame = 0;
- cpi->frames_since_golden = 0;
+ cpi->rc.frames_since_golden = 0;
// ******** Fixed Q test code only ************
// If we are going to use the ALT reference for the next group of frames
@@ -2415,12 +2235,12 @@
if (cpi->oxcf.fixed_q >= 0 &&
cpi->oxcf.play_alternate && !cpi->refresh_alt_ref_frame) {
cpi->source_alt_ref_pending = 1;
- cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+ cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
// TODO(ivan): For SVC encoder, GF automatic update is disabled by using
// a large GF_interval.
if (cpi->use_svc) {
- cpi->frames_till_gf_update_due = INT_MAX;
+ cpi->rc.frames_till_gf_update_due = INT_MAX;
}
}
@@ -2428,18 +2248,18 @@
cpi->source_alt_ref_active = 0;
// Decrement count down till next gf
- if (cpi->frames_till_gf_update_due > 0)
- cpi->frames_till_gf_update_due--;
+ if (cpi->rc.frames_till_gf_update_due > 0)
+ cpi->rc.frames_till_gf_update_due--;
} else if (!cpi->refresh_alt_ref_frame) {
// Decrement count down till next gf
- if (cpi->frames_till_gf_update_due > 0)
- cpi->frames_till_gf_update_due--;
+ if (cpi->rc.frames_till_gf_update_due > 0)
+ cpi->rc.frames_till_gf_update_due--;
if (cpi->frames_till_alt_ref_frame)
cpi->frames_till_alt_ref_frame--;
- cpi->frames_since_golden++;
+ cpi->rc.frames_since_golden++;
}
}
@@ -2549,21 +2369,22 @@
cpi->refresh_golden_frame ||
cpi->refresh_alt_ref_frame))) {
// General over and under shoot tests
- if (((cpi->projected_frame_size > high_limit) && (q < maxq)) ||
- ((cpi->projected_frame_size < low_limit) && (q > minq))) {
+ if (((cpi->rc.projected_frame_size > high_limit) && (q < maxq)) ||
+ ((cpi->rc.projected_frame_size < low_limit) && (q > minq))) {
force_recode = 1;
} else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
// Deal with frame undershoot and whether or not we are
// below the automatically set cq level.
if (q > cpi->cq_target_quality &&
- cpi->projected_frame_size < ((cpi->this_frame_target * 7) >> 3)) {
+ cpi->rc.projected_frame_size <
+ ((cpi->rc.this_frame_target * 7) >> 3)) {
force_recode = 1;
} else if (q > cpi->oxcf.cq_level &&
- cpi->projected_frame_size < cpi->min_frame_bandwidth &&
- cpi->active_best_quality > cpi->oxcf.cq_level) {
+ cpi->rc.projected_frame_size < cpi->rc.min_frame_bandwidth &&
+ cpi->rc.active_best_quality > cpi->oxcf.cq_level) {
// Severe undershoot and between auto and user cq level
force_recode = 1;
- cpi->active_best_quality = cpi->oxcf.cq_level;
+ cpi->rc.active_best_quality = cpi->oxcf.cq_level;
}
}
}
@@ -2730,25 +2551,26 @@
"%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
"%6d %6d %5d %5d %5d %8.2f %10d %10.3f"
"%10.3f %8d %10d %10d %10d\n",
- cpi->common.current_video_frame, cpi->this_frame_target,
- cpi->projected_frame_size, 0,
- (cpi->projected_frame_size - cpi->this_frame_target),
- (int)cpi->total_target_vs_actual,
- (int)(cpi->oxcf.starting_buffer_level - cpi->bits_off_target),
- (int)cpi->total_actual_bits, cm->base_qindex,
+ cpi->common.current_video_frame, cpi->rc.this_frame_target,
+ cpi->rc.projected_frame_size, 0,
+ (cpi->rc.projected_frame_size - cpi->rc.this_frame_target),
+ (int)cpi->rc.total_target_vs_actual,
+ (int)(cpi->oxcf.starting_buffer_level - cpi->rc.bits_off_target),
+ (int)cpi->rc.total_actual_bits, cm->base_qindex,
vp9_convert_qindex_to_q(cm->base_qindex),
(double)vp9_dc_quant(cm->base_qindex, 0) / 4.0,
- vp9_convert_qindex_to_q(cpi->active_best_quality),
- vp9_convert_qindex_to_q(cpi->active_worst_quality), cpi->avg_q,
- vp9_convert_qindex_to_q(cpi->ni_av_qi),
+ vp9_convert_qindex_to_q(cpi->rc.active_best_quality),
+ vp9_convert_qindex_to_q(cpi->rc.active_worst_quality), cpi->rc.avg_q,
+ vp9_convert_qindex_to_q(cpi->rc.ni_av_qi),
vp9_convert_qindex_to_q(cpi->cq_target_quality),
cpi->refresh_last_frame, cpi->refresh_golden_frame,
- cpi->refresh_alt_ref_frame, cm->frame_type, cpi->gfu_boost,
+ cpi->refresh_alt_ref_frame, cm->frame_type, cpi->rc.gfu_boost,
cpi->twopass.est_max_qcorrection_factor, (int)cpi->twopass.bits_left,
cpi->twopass.total_left_stats.coded_error,
(double)cpi->twopass.bits_left /
(1 + cpi->twopass.total_left_stats.coded_error),
- cpi->tot_recode_hits, recon_err, cpi->kf_boost, cpi->kf_zeromotion_pct);
+ cpi->tot_recode_hits, recon_err, cpi->rc.kf_boost,
+ cpi->kf_zeromotion_pct);
fclose(f);
@@ -2772,194 +2594,212 @@
}
#endif
-static int pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
- int * bottom_index, int * top_index) {
- // Set an active best quality and if necessary active worst quality
- int q = cpi->active_worst_quality;
+static void encode_with_recode_loop(VP9_COMP *cpi,
+ unsigned long *size,
+ uint8_t *dest,
+ int q,
+ int bottom_index,
+ int top_index,
+ int frame_over_shoot_limit,
+ int frame_under_shoot_limit) {
VP9_COMMON *const cm = &cpi->common;
+ int loop_count = 0;
+ int loop = 0;
+ int overshoot_seen = 0;
+ int undershoot_seen = 0;
+ int active_worst_qchanged = 0;
+ int q_low = bottom_index, q_high = top_index;
+ do {
+ vp9_clear_system_state(); // __asm emms;
- if (frame_is_intra_only(cm)) {
-#if !CONFIG_MULTIPLE_ARF
- // Handle the special case for key frames forced when we have75 reached
- // the maximum key frame interval. Here force the Q to a range
- // based on the ambient Q to reduce the risk of popping.
- if (cpi->this_key_frame_forced) {
- int delta_qindex;
- int qindex = cpi->last_boosted_qindex;
- double last_boosted_q = vp9_convert_qindex_to_q(qindex);
+ vp9_set_quantizer(cpi, q);
- delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q,
- (last_boosted_q * 0.75));
-
- cpi->active_best_quality = MAX(qindex + delta_qindex,
- cpi->best_quality);
- } else {
- int high = 5000;
- int low = 400;
- double q_adj_factor = 1.0;
- double q_val;
-
- // Baseline value derived from cpi->active_worst_quality and kf boost
- cpi->active_best_quality = get_active_quality(q, cpi->kf_boost,
- low, high,
- kf_low_motion_minq,
- kf_high_motion_minq);
-
- // Allow somewhat lower kf minq with small image formats.
- if ((cm->width * cm->height) <= (352 * 288)) {
- q_adj_factor -= 0.25;
- }
-
- // Make a further adjustment based on the kf zero motion measure.
- q_adj_factor += 0.05 - (0.001 * (double)cpi->kf_zeromotion_pct);
-
- // Convert the adjustment factor to a qindex delta
- // on active_best_quality.
- q_val = vp9_convert_qindex_to_q(cpi->active_best_quality);
- cpi->active_best_quality +=
- vp9_compute_qdelta(cpi, q_val, (q_val * q_adj_factor));
- }
-#else
- double current_q;
- // Force the KF quantizer to be 30% of the active_worst_quality.
- current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality);
- cpi->active_best_quality = cpi->active_worst_quality
- + vp9_compute_qdelta(cpi, current_q, current_q * 0.3);
-#endif
- } else if (!cpi->is_src_frame_alt_ref &&
- (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
- int high = 2000;
- int low = 400;
-
- // Use the lower of cpi->active_worst_quality and recent
- // average Q as basis for GF/ARF best Q limit unless last frame was
- // a key frame.
- if (cpi->frames_since_key > 1 &&
- cpi->avg_frame_qindex < cpi->active_worst_quality) {
- q = cpi->avg_frame_qindex;
- }
- // For constrained quality dont allow Q less than the cq level
- if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
- if (q < cpi->cq_target_quality)
- q = cpi->cq_target_quality;
- if (cpi->frames_since_key > 1) {
- cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost,
- low, high,
- afq_low_motion_minq,
- afq_high_motion_minq);
+ if (loop_count == 0) {
+ // Set up entropy context depending on frame type. The decoder mandates
+ // the use of the default context, index 0, for keyframes and inter
+ // frames where the error_resilient_mode or intra_only flag is set. For
+ // other inter-frames the encoder currently uses only two contexts;
+ // context 1 for ALTREF frames and context 0 for the others.
+ if (cm->frame_type == KEY_FRAME) {
+ vp9_setup_key_frame(cpi);
} else {
- cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost,
- low, high,
- gf_low_motion_minq,
- gf_high_motion_minq);
- }
- // Constrained quality use slightly lower active best.
- cpi->active_best_quality = cpi->active_best_quality * 15 / 16;
-
- } else if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
- if (!cpi->refresh_alt_ref_frame) {
- cpi->active_best_quality = cpi->cq_target_quality;
- } else {
- if (cpi->frames_since_key > 1) {
- cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost,
- low, high,
- afq_low_motion_minq,
- afq_high_motion_minq);
- } else {
- cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost,
- low, high,
- gf_low_motion_minq,
- gf_high_motion_minq);
+ if (!cm->intra_only && !cm->error_resilient_mode) {
+ cpi->common.frame_context_idx = cpi->refresh_alt_ref_frame;
}
+ vp9_setup_inter_frame(cpi);
}
- } else {
- cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost,
- low, high,
- gf_low_motion_minq,
- gf_high_motion_minq);
}
- } else {
+
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
+ vp9_vaq_frame_setup(cpi);
+ }
+
+ // transform / motion compensation build reconstruction frame
+
+ vp9_encode_frame(cpi);
+
+ // Update the skip mb flag probabilities based on the distribution
+ // seen in the last encoder iteration.
+ // update_base_skip_probs(cpi);
+
+ vp9_clear_system_state(); // __asm emms;
+
+ // Dummy pack of the bitstream using up to date stats to get an
+ // accurate estimate of output frame size to determine if we need
+ // to recode.
+ vp9_save_coding_context(cpi);
+ cpi->dummy_packing = 1;
+ vp9_pack_bitstream(cpi, dest, size);
+ cpi->rc.projected_frame_size = (*size) << 3;
+ vp9_restore_coding_context(cpi);
+
+ if (frame_over_shoot_limit == 0)
+ frame_over_shoot_limit = 1;
+ active_worst_qchanged = 0;
+
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
- cpi->active_best_quality = cpi->cq_target_quality;
+ loop = 0;
} else {
- cpi->active_best_quality = inter_minq[q];
- // 1-pass: for now, use the average Q for the active_best, if its lower
- // than active_worst.
- if (cpi->pass == 0 && (cpi->avg_frame_qindex < q))
- cpi->active_best_quality = inter_minq[cpi->avg_frame_qindex];
+ // Special case handling for forced key frames
+ if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
+ int last_q = q;
+ int kf_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm));
- // For the constrained quality mode we don't want
- // q to fall below the cq level.
- if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
- (cpi->active_best_quality < cpi->cq_target_quality)) {
- // If we are strongly undershooting the target rate in the last
- // frames then use the user passed in cq value not the auto
- // cq value.
- if (cpi->rolling_actual_bits < cpi->min_frame_bandwidth)
- cpi->active_best_quality = cpi->oxcf.cq_level;
- else
- cpi->active_best_quality = cpi->cq_target_quality;
+ int high_err_target = cpi->ambient_err;
+ int low_err_target = cpi->ambient_err >> 1;
+
+ // Prevent possible divide by zero error below for perfect KF
+ kf_err += !kf_err;
+
+ // The key frame is not good enough or we can afford
+ // to make it better without undue risk of popping.
+ if ((kf_err > high_err_target &&
+ cpi->rc.projected_frame_size <= frame_over_shoot_limit) ||
+ (kf_err > low_err_target &&
+ cpi->rc.projected_frame_size <= frame_under_shoot_limit)) {
+ // Lower q_high
+ q_high = q > q_low ? q - 1 : q_low;
+
+ // Adjust Q
+ q = (q * high_err_target) / kf_err;
+ q = MIN(q, (q_high + q_low) >> 1);
+ } else if (kf_err < low_err_target &&
+ cpi->rc.projected_frame_size >= frame_under_shoot_limit) {
+ // The key frame is much better than the previous frame
+ // Raise q_low
+ q_low = q < q_high ? q + 1 : q_high;
+
+ // Adjust Q
+ q = (q * low_err_target) / kf_err;
+ q = MIN(q, (q_high + q_low + 1) >> 1);
+ }
+
+ // Clamp Q to upper and lower limits:
+ q = clamp(q, q_low, q_high);
+
+ loop = q != last_q;
+ } else if (recode_loop_test(
+ cpi, frame_over_shoot_limit, frame_under_shoot_limit,
+ q, top_index, bottom_index)) {
+ // Is the projected frame size out of range and are we allowed
+ // to attempt to recode.
+ int last_q = q;
+ int retries = 0;
+
+ // Frame size out of permitted range:
+ // Update correction factor & compute new Q to try...
+
+ // Frame is too large
+ if (cpi->rc.projected_frame_size > cpi->rc.this_frame_target) {
+ // Raise Qlow as to at least the current value
+ q_low = q < q_high ? q + 1 : q_high;
+
+ if (undershoot_seen || loop_count > 1) {
+ // Update rate_correction_factor unless
+ // cpi->rc.active_worst_quality has changed.
+ if (!active_worst_qchanged)
+ vp9_update_rate_correction_factors(cpi, 1);
+
+ q = (q_high + q_low + 1) / 2;
+ } else {
+ // Update rate_correction_factor unless
+ // cpi->rc.active_worst_quality has changed.
+ if (!active_worst_qchanged)
+ vp9_update_rate_correction_factors(cpi, 0);
+
+ q = vp9_regulate_q(cpi, cpi->rc.this_frame_target);
+
+ while (q < q_low && retries < 10) {
+ vp9_update_rate_correction_factors(cpi, 0);
+ q = vp9_regulate_q(cpi, cpi->rc.this_frame_target);
+ retries++;
+ }
+ }
+
+ overshoot_seen = 1;
+ } else {
+ // Frame is too small
+ q_high = q > q_low ? q - 1 : q_low;
+
+ if (overshoot_seen || loop_count > 1) {
+ // Update rate_correction_factor unless
+ // cpi->rc.active_worst_quality has changed.
+ if (!active_worst_qchanged)
+ vp9_update_rate_correction_factors(cpi, 1);
+
+ q = (q_high + q_low) / 2;
+ } else {
+ // Update rate_correction_factor unless
+ // cpi->rc.active_worst_quality has changed.
+ if (!active_worst_qchanged)
+ vp9_update_rate_correction_factors(cpi, 0);
+
+ q = vp9_regulate_q(cpi, cpi->rc.this_frame_target);
+
+ // Special case reset for qlow for constrained quality.
+ // This should only trigger where there is very substantial
+ // undershoot on a frame and the auto cq level is above
+ // the user passsed in value.
+ if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY && q < q_low) {
+ q_low = q;
+ }
+
+ while (q > q_high && retries < 10) {
+ vp9_update_rate_correction_factors(cpi, 0);
+ q = vp9_regulate_q(cpi, cpi->rc.this_frame_target);
+ retries++;
+ }
+ }
+
+ undershoot_seen = 1;
+ }
+
+ // Clamp Q to upper and lower limits:
+ q = clamp(q, q_low, q_high);
+
+ loop = q != last_q;
+ } else {
+ loop = 0;
}
}
- }
- // Clip the active best and worst quality values to limits
- if (cpi->active_worst_quality > cpi->worst_quality)
- cpi->active_worst_quality = cpi->worst_quality;
+ if (cpi->is_src_frame_alt_ref)
+ loop = 0;
- if (cpi->active_best_quality < cpi->best_quality)
- cpi->active_best_quality = cpi->best_quality;
+ if (loop) {
+ loop_count++;
- if (cpi->active_best_quality > cpi->worst_quality)
- cpi->active_best_quality = cpi->worst_quality;
-
- if (cpi->active_worst_quality < cpi->active_best_quality)
- cpi->active_worst_quality = cpi->active_best_quality;
-
- // Limit Q range for the adaptive loop.
- if (cm->frame_type == KEY_FRAME && !cpi->this_key_frame_forced) {
- *top_index =
- (cpi->active_worst_quality + cpi->active_best_quality * 3) / 4;
- // If this is the first (key) frame in 1-pass, active best is the user
- // best-allowed, and leave the top_index to active_worst.
- if (cpi->pass == 0 && cpi->common.current_video_frame == 0) {
- cpi->active_best_quality = cpi->oxcf.best_allowed_q;
- *top_index = cpi->oxcf.worst_allowed_q;
+#if CONFIG_INTERNAL_STATS
+ cpi->tot_recode_hits++;
+#endif
}
- } else if (!cpi->is_src_frame_alt_ref &&
- (cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) &&
- (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
- *top_index =
- (cpi->active_worst_quality + cpi->active_best_quality) / 2;
- } else {
- *top_index = cpi->active_worst_quality;
- }
- *bottom_index = cpi->active_best_quality;
-
- if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
- q = cpi->active_best_quality;
- // Special case code to try and match quality with forced key frames
- } else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
- q = cpi->last_boosted_qindex;
- } else {
- // Determine initial Q to try.
- if (cpi->pass == 0) {
- // 1-pass: for now, use per-frame-bw for target size of frame, scaled
- // by |x| for key frame.
- int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1;
- q = vp9_regulate_q(cpi, scale * cpi->av_per_frame_bandwidth);
- } else {
- q = vp9_regulate_q(cpi, cpi->this_frame_target);
- }
- if (q > *top_index)
- q = *top_index;
- }
-
- return q;
+ } while (loop);
+ cpi->rc.active_worst_qchanged = active_worst_qchanged;
}
+
static void encode_frame_to_data_rate(VP9_COMP *cpi,
unsigned long *size,
- unsigned char *dest,
+ uint8_t *dest,
unsigned int *frame_flags) {
VP9_COMMON *const cm = &cpi->common;
TX_SIZE t;
@@ -2967,18 +2807,8 @@
int frame_over_shoot_limit;
int frame_under_shoot_limit;
- int loop = 0;
- int loop_count;
-
- int q_low;
- int q_high;
-
int top_index;
int bottom_index;
- int active_worst_qchanged = 0;
-
- int overshoot_seen = 0;
- int undershoot_seen = 0;
SPEED_FEATURES *const sf = &cpi->sf;
unsigned int max_mv_def = MIN(cpi->common.width, cpi->common.height);
@@ -3001,7 +2831,7 @@
// pass function that sets the target bandwidth so we must set it here.
if (cpi->refresh_alt_ref_frame) {
// Set a per frame bit target for the alt ref frame.
- cpi->per_frame_bandwidth = cpi->twopass.gf_bits;
+ cpi->rc.per_frame_bandwidth = cpi->twopass.gf_bits;
// Set a per second target bitrate.
cpi->target_bandwidth = (int)(cpi->twopass.gf_bits * cpi->output_framerate);
}
@@ -3094,10 +2924,7 @@
vp9_clear_system_state();
- q = pick_q_and_adjust_q_bounds(cpi, &bottom_index, &top_index);
-
- q_high = top_index;
- q_low = bottom_index;
+ q = vp9_pick_q_and_adjust_q_bounds(cpi, &bottom_index, &top_index);
vp9_compute_frame_size_bounds(cpi, &frame_under_shoot_limit,
&frame_over_shoot_limit);
@@ -3107,24 +2934,22 @@
if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) {
double new_q;
- double current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality);
+ double current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality);
int level = cpi->this_frame_weight;
assert(level >= 0);
// Set quantizer steps at 10% increments.
new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
- q = cpi->active_worst_quality + vp9_compute_qdelta(cpi, current_q, new_q);
+ q = cpi->rc.active_worst_quality +
+ vp9_compute_qdelta(cpi, current_q, new_q);
bottom_index = q;
top_index = q;
- q_low = q;
- q_high = q;
printf("frame:%d q:%d\n", cm->current_video_frame, q);
}
#endif
- loop_count = 0;
vp9_zero(cpi->rd_tx_select_threshes);
if (!frame_is_intra_only(cm)) {
@@ -3135,10 +2960,8 @@
}
#if CONFIG_VP9_POSTPROC
-
if (cpi->oxcf.noise_sensitivity > 0) {
int l = 0;
-
switch (cpi->oxcf.noise_sensitivity) {
case 1:
l = 20;
@@ -3157,201 +2980,22 @@
l = 150;
break;
}
-
vp9_denoise(cpi->Source, cpi->Source, l);
}
-
#endif
#ifdef OUTPUT_YUV_SRC
vp9_write_yuv_frame(cpi->Source);
#endif
- do {
- vp9_clear_system_state(); // __asm emms;
-
- vp9_set_quantizer(cpi, q);
-
- if (loop_count == 0) {
- // Set up entropy context depending on frame type. The decoder mandates
- // the use of the default context, index 0, for keyframes and inter
- // frames where the error_resilient_mode or intra_only flag is set. For
- // other inter-frames the encoder currently uses only two contexts;
- // context 1 for ALTREF frames and context 0 for the others.
- if (cm->frame_type == KEY_FRAME) {
- vp9_setup_key_frame(cpi);
- } else {
- if (!cm->intra_only && !cm->error_resilient_mode) {
- cpi->common.frame_context_idx = cpi->refresh_alt_ref_frame;
- }
- vp9_setup_inter_frame(cpi);
- }
- }
-
- if (cpi->sf.variance_adaptive_quantization) {
- vp9_vaq_frame_setup(cpi);
- }
-
- // transform / motion compensation build reconstruction frame
-
- vp9_encode_frame(cpi);
-
- // Update the skip mb flag probabilities based on the distribution
- // seen in the last encoder iteration.
- // update_base_skip_probs(cpi);
-
- vp9_clear_system_state(); // __asm emms;
-
- // Dummy pack of the bitstream using up to date stats to get an
- // accurate estimate of output frame size to determine if we need
- // to recode.
- vp9_save_coding_context(cpi);
- cpi->dummy_packing = 1;
- vp9_pack_bitstream(cpi, dest, size);
- cpi->projected_frame_size = (*size) << 3;
- vp9_restore_coding_context(cpi);
-
- if (frame_over_shoot_limit == 0)
- frame_over_shoot_limit = 1;
- active_worst_qchanged = 0;
-
- if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
- loop = 0;
- } else {
- // Special case handling for forced key frames
- if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
- int last_q = q;
- int kf_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm));
-
- int high_err_target = cpi->ambient_err;
- int low_err_target = cpi->ambient_err >> 1;
-
- // Prevent possible divide by zero error below for perfect KF
- kf_err += !kf_err;
-
- // The key frame is not good enough or we can afford
- // to make it better without undue risk of popping.
- if ((kf_err > high_err_target &&
- cpi->projected_frame_size <= frame_over_shoot_limit) ||
- (kf_err > low_err_target &&
- cpi->projected_frame_size <= frame_under_shoot_limit)) {
- // Lower q_high
- q_high = q > q_low ? q - 1 : q_low;
-
- // Adjust Q
- q = (q * high_err_target) / kf_err;
- q = MIN(q, (q_high + q_low) >> 1);
- } else if (kf_err < low_err_target &&
- cpi->projected_frame_size >= frame_under_shoot_limit) {
- // The key frame is much better than the previous frame
- // Raise q_low
- q_low = q < q_high ? q + 1 : q_high;
-
- // Adjust Q
- q = (q * low_err_target) / kf_err;
- q = MIN(q, (q_high + q_low + 1) >> 1);
- }
-
- // Clamp Q to upper and lower limits:
- q = clamp(q, q_low, q_high);
-
- loop = q != last_q;
- } else if (recode_loop_test(
- cpi, frame_over_shoot_limit, frame_under_shoot_limit,
- q, top_index, bottom_index)) {
- // Is the projected frame size out of range and are we allowed
- // to attempt to recode.
- int last_q = q;
- int retries = 0;
-
- // Frame size out of permitted range:
- // Update correction factor & compute new Q to try...
-
- // Frame is too large
- if (cpi->projected_frame_size > cpi->this_frame_target) {
- // Raise Qlow as to at least the current value
- q_low = q < q_high ? q + 1 : q_high;
-
- if (undershoot_seen || loop_count > 1) {
- // Update rate_correction_factor unless
- // cpi->active_worst_quality has changed.
- if (!active_worst_qchanged)
- vp9_update_rate_correction_factors(cpi, 1);
-
- q = (q_high + q_low + 1) / 2;
- } else {
- // Update rate_correction_factor unless
- // cpi->active_worst_quality has changed.
- if (!active_worst_qchanged)
- vp9_update_rate_correction_factors(cpi, 0);
-
- q = vp9_regulate_q(cpi, cpi->this_frame_target);
-
- while (q < q_low && retries < 10) {
- vp9_update_rate_correction_factors(cpi, 0);
- q = vp9_regulate_q(cpi, cpi->this_frame_target);
- retries++;
- }
- }
-
- overshoot_seen = 1;
- } else {
- // Frame is too small
- q_high = q > q_low ? q - 1 : q_low;
-
- if (overshoot_seen || loop_count > 1) {
- // Update rate_correction_factor unless
- // cpi->active_worst_quality has changed.
- if (!active_worst_qchanged)
- vp9_update_rate_correction_factors(cpi, 1);
-
- q = (q_high + q_low) / 2;
- } else {
- // Update rate_correction_factor unless
- // cpi->active_worst_quality has changed.
- if (!active_worst_qchanged)
- vp9_update_rate_correction_factors(cpi, 0);
-
- q = vp9_regulate_q(cpi, cpi->this_frame_target);
-
- // Special case reset for qlow for constrained quality.
- // This should only trigger where there is very substantial
- // undershoot on a frame and the auto cq level is above
- // the user passsed in value.
- if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY && q < q_low) {
- q_low = q;
- }
-
- while (q > q_high && retries < 10) {
- vp9_update_rate_correction_factors(cpi, 0);
- q = vp9_regulate_q(cpi, cpi->this_frame_target);
- retries++;
- }
- }
-
- undershoot_seen = 1;
- }
-
- // Clamp Q to upper and lower limits:
- q = clamp(q, q_low, q_high);
-
- loop = q != last_q;
- } else {
- loop = 0;
- }
- }
-
- if (cpi->is_src_frame_alt_ref)
- loop = 0;
-
- if (loop) {
- loop_count++;
-
-#if CONFIG_INTERNAL_STATS
- cpi->tot_recode_hits++;
-#endif
- }
- } while (loop);
+ encode_with_recode_loop(cpi,
+ size,
+ dest,
+ q,
+ bottom_index,
+ top_index,
+ frame_over_shoot_limit,
+ frame_under_shoot_limit);
// Special case code to reduce pulsing when key frames are forced at a
// fixed interval. Note the reconstruction error if it is the frame before
@@ -3431,28 +3075,27 @@
cm->last_frame_type = cm->frame_type;
// Update rate control heuristics
- cpi->total_byte_count += (*size);
- cpi->projected_frame_size = (*size) << 3;
+ cpi->rc.projected_frame_size = (*size) << 3;
// Post encode loop adjustment of Q prediction.
- if (!active_worst_qchanged)
+ if (!cpi->rc.active_worst_qchanged)
vp9_update_rate_correction_factors(cpi, (cpi->sf.recode_loop ||
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) ? 2 : 0);
- cpi->last_q[cm->frame_type] = cm->base_qindex;
+ cpi->rc.last_q[cm->frame_type] = cm->base_qindex;
// Keep record of last boosted (KF/KF/ARF) Q value.
// If the current frame is coded at a lower Q then we also update it.
// If all mbs in this group are skipped only update if the Q value is
// better than that already stored.
// This is used to help set quality in forced key frames to reduce popping
- if ((cm->base_qindex < cpi->last_boosted_qindex) ||
+ if ((cm->base_qindex < cpi->rc.last_boosted_qindex) ||
((cpi->static_mb_pct < 100) &&
((cm->frame_type == KEY_FRAME) ||
cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !cpi->is_src_frame_alt_ref)))) {
- cpi->last_boosted_qindex = cm->base_qindex;
+ cpi->rc.last_boosted_qindex = cm->base_qindex;
}
if (cm->frame_type == KEY_FRAME) {
@@ -3461,7 +3104,7 @@
// Keep a record of ambient average Q.
if (cm->frame_type != KEY_FRAME)
- cpi->avg_frame_qindex = (2 + 3 * cpi->avg_frame_qindex +
+ cpi->rc.avg_frame_qindex = (2 + 3 * cpi->rc.avg_frame_qindex +
cm->base_qindex) >> 2;
// Keep a record from which we can calculate the average Q excluding GF
@@ -3469,61 +3112,64 @@
if (cm->frame_type != KEY_FRAME &&
!cpi->refresh_golden_frame &&
!cpi->refresh_alt_ref_frame) {
- cpi->ni_frames++;
- cpi->tot_q += vp9_convert_qindex_to_q(q);
- cpi->avg_q = cpi->tot_q / (double)cpi->ni_frames;
+ cpi->rc.ni_frames++;
+ cpi->rc.tot_q += vp9_convert_qindex_to_q(q);
+ cpi->rc.avg_q = cpi->rc.tot_q / (double)cpi->rc.ni_frames;
// Calculate the average Q for normal inter frames (not key or GFU frames).
- cpi->ni_tot_qi += q;
- cpi->ni_av_qi = cpi->ni_tot_qi / cpi->ni_frames;
+ cpi->rc.ni_tot_qi += q;
+ cpi->rc.ni_av_qi = cpi->rc.ni_tot_qi / cpi->rc.ni_frames;
}
// Update the buffer level variable.
// Non-viewable frames are a special case and are treated as pure overhead.
if (!cm->show_frame)
- cpi->bits_off_target -= cpi->projected_frame_size;
+ cpi->rc.bits_off_target -= cpi->rc.projected_frame_size;
else
- cpi->bits_off_target += cpi->av_per_frame_bandwidth -
- cpi->projected_frame_size;
+ cpi->rc.bits_off_target += cpi->rc.av_per_frame_bandwidth -
+ cpi->rc.projected_frame_size;
// Clip the buffer level at the maximum buffer size
- if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size)
- cpi->bits_off_target = cpi->oxcf.maximum_buffer_size;
+ if (cpi->rc.bits_off_target > cpi->oxcf.maximum_buffer_size)
+ cpi->rc.bits_off_target = cpi->oxcf.maximum_buffer_size;
// Rolling monitors of whether we are over or underspending used to help
// regulate min and Max Q in two pass.
if (cm->frame_type != KEY_FRAME) {
- cpi->rolling_target_bits =
- ((cpi->rolling_target_bits * 3) + cpi->this_frame_target + 2) / 4;
- cpi->rolling_actual_bits =
- ((cpi->rolling_actual_bits * 3) + cpi->projected_frame_size + 2) / 4;
- cpi->long_rolling_target_bits =
- ((cpi->long_rolling_target_bits * 31) + cpi->this_frame_target + 16) / 32;
- cpi->long_rolling_actual_bits =
- ((cpi->long_rolling_actual_bits * 31) +
- cpi->projected_frame_size + 16) / 32;
+ cpi->rc.rolling_target_bits =
+ ((cpi->rc.rolling_target_bits * 3) +
+ cpi->rc.this_frame_target + 2) / 4;
+ cpi->rc.rolling_actual_bits =
+ ((cpi->rc.rolling_actual_bits * 3) +
+ cpi->rc.projected_frame_size + 2) / 4;
+ cpi->rc.long_rolling_target_bits =
+ ((cpi->rc.long_rolling_target_bits * 31) +
+ cpi->rc.this_frame_target + 16) / 32;
+ cpi->rc.long_rolling_actual_bits =
+ ((cpi->rc.long_rolling_actual_bits * 31) +
+ cpi->rc.projected_frame_size + 16) / 32;
}
// Actual bits spent
- cpi->total_actual_bits += cpi->projected_frame_size;
+ cpi->rc.total_actual_bits += cpi->rc.projected_frame_size;
// Debug stats
- cpi->total_target_vs_actual += (cpi->this_frame_target -
- cpi->projected_frame_size);
+ cpi->rc.total_target_vs_actual += (cpi->rc.this_frame_target -
+ cpi->rc.projected_frame_size);
- cpi->buffer_level = cpi->bits_off_target;
+ cpi->rc.buffer_level = cpi->rc.bits_off_target;
#ifndef DISABLE_RC_LONG_TERM_MEM
// Update bits left to the kf and gf groups to account for overshoot or
// undershoot on these frames
if (cm->frame_type == KEY_FRAME) {
- cpi->twopass.kf_group_bits += cpi->this_frame_target -
- cpi->projected_frame_size;
+ cpi->twopass.kf_group_bits += cpi->rc.this_frame_target -
+ cpi->rc.projected_frame_size;
cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0);
} else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) {
- cpi->twopass.gf_group_bits += cpi->this_frame_target -
- cpi->projected_frame_size;
+ cpi->twopass.gf_group_bits += cpi->rc.this_frame_target -
+ cpi->rc.projected_frame_size;
cpi->twopass.gf_group_bits = MAX(cpi->twopass.gf_group_bits, 0);
}
@@ -3658,7 +3304,7 @@
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
// vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt");
#ifdef DISABLE_RC_LONG_TERM_MEM
- cpi->twopass.bits_left -= cpi->this_frame_target;
+ cpi->twopass.bits_left -= cpi->rc.this_frame_target;
#else
cpi->twopass.bits_left -= 8 * *size;
#endif
@@ -3763,7 +3409,7 @@
- cpi->next_frame_in_order;
else
#endif
- frames_to_arf = cpi->frames_till_gf_update_due;
+ frames_to_arf = cpi->rc.frames_till_gf_update_due;
assert(frames_to_arf < cpi->twopass.frames_to_key);
@@ -3778,7 +3424,7 @@
// Produce the filtered ARF frame.
// TODO(agrange) merge these two functions.
configure_arnr_filter(cpi, cm->current_video_frame + frames_to_arf,
- cpi->gfu_boost);
+ cpi->rc.gfu_boost);
vp9_temporal_filter_prepare(cpi, frames_to_arf);
vp9_extend_frame_borders(&cpi->alt_ref_buffer,
cm->subsampling_x, cm->subsampling_y);
@@ -3975,7 +3621,7 @@
vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm);
- if (cpi->sf.variance_adaptive_quantization) {
+ if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
vp9_vaq_init();
}
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 9e80212..8fa6385 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -248,7 +248,6 @@
int auto_mv_step_size;
int optimize_coefficients;
int static_segmentation;
- int variance_adaptive_quantization;
int comp_inter_joint_search_thresh;
int adaptive_rd_thresh;
int skip_encode_sb;
@@ -290,6 +289,59 @@
int use_fast_coef_updates; // 0: 2-loop, 1: 1-loop, 2: 1-loop reduced
} SPEED_FEATURES;
+typedef struct {
+ // Rate targetting variables
+ int this_frame_target;
+ int projected_frame_size;
+ int last_q[2]; // Separate values for Intra/Inter
+ int last_boosted_qindex; // Last boosted GF/KF/ARF q
+
+ int gfu_boost;
+ int last_boost;
+ int kf_boost;
+
+ double rate_correction_factor;
+ double key_frame_rate_correction_factor;
+ double gf_rate_correction_factor;
+
+ unsigned int frames_since_golden;
+ int frames_till_gf_update_due; // Count down till next GF
+
+ int max_gf_interval;
+ int baseline_gf_interval;
+
+ int64_t key_frame_count;
+ int prior_key_frame_distance[KEY_FRAME_CONTEXT];
+ int per_frame_bandwidth; // Current section per frame bandwidth target
+ int av_per_frame_bandwidth; // Average frame size target for clip
+ int min_frame_bandwidth; // Minimum allocation used for any frame
+
+ int ni_av_qi;
+ int ni_tot_qi;
+ int ni_frames;
+ int avg_frame_qindex;
+ double tot_q;
+ double avg_q;
+
+ int buffer_level;
+ int 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 active_worst_qchanged;
+} RATE_CONTROL;
+
typedef struct VP9_COMP {
DECLARE_ALIGNED(16, int16_t, y_quant[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, y_quant_shift[QINDEX_RANGE][8]);
@@ -399,71 +451,17 @@
CODING_CONTEXT coding_context;
- // Rate targetting variables
- int this_frame_target;
- int projected_frame_size;
- int last_q[2]; // Separate values for Intra/Inter
- int last_boosted_qindex; // Last boosted GF/KF/ARF q
-
- double rate_correction_factor;
- double key_frame_rate_correction_factor;
- double gf_rate_correction_factor;
-
- unsigned int frames_since_golden;
- int frames_till_gf_update_due; // Count down till next GF
-
- int gf_overspend_bits; // cumulative bits overspent because of GF boost
-
- int non_gf_bitrate_adjustment; // Following GF to recover extra bits spent
-
- int kf_overspend_bits; // Bits spent on key frames to be recovered on inters
- int kf_bitrate_adjustment; // number of bits to recover on each inter frame.
- int max_gf_interval;
- int baseline_gf_interval;
+ int zbin_mode_boost;
+ int zbin_mode_boost_enabled;
int active_arnr_frames; // <= cpi->oxcf.arnr_max_frames
int active_arnr_strength; // <= cpi->oxcf.arnr_max_strength
- int64_t key_frame_count;
- int prior_key_frame_distance[KEY_FRAME_CONTEXT];
- int per_frame_bandwidth; // Current section per frame bandwidth target
- int av_per_frame_bandwidth; // Average frame size target for clip
- int min_frame_bandwidth; // Minimum allocation used for any frame
- 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;
- double tot_q;
- double avg_q;
-
- int zbin_mode_boost;
- int zbin_mode_boost_enabled;
-
- int64_t total_byte_count;
-
- int buffered_mode;
-
- int buffer_level;
- int 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;
+ RATE_CONTROL rc;
int cq_target_quality;
@@ -477,9 +475,6 @@
vp9_coeff_probs_model frame_coef_probs[TX_SIZES][BLOCK_TYPES];
vp9_coeff_stats frame_branch_ct[TX_SIZES][BLOCK_TYPES];
- int gfu_boost;
- int last_boost;
- int kf_boost;
int kf_zeromotion_pct;
int gf_zeromotion_pct;
@@ -503,7 +498,6 @@
int speed;
int compressor_speed;
- int auto_worst_q;
int cpu_used;
int pass;
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 0aa3a68..1293e86 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -35,6 +35,84 @@
static const unsigned int prior_key_frame_weight[KEY_FRAME_CONTEXT] =
{ 1, 2, 3, 4, 5 };
+// Tables relating active max Q to active min Q
+static int kf_low_motion_minq[QINDEX_RANGE];
+static int kf_high_motion_minq[QINDEX_RANGE];
+static int gf_low_motion_minq[QINDEX_RANGE];
+static int gf_high_motion_minq[QINDEX_RANGE];
+static int inter_minq[QINDEX_RANGE];
+static int afq_low_motion_minq[QINDEX_RANGE];
+static int afq_high_motion_minq[QINDEX_RANGE];
+
+// Functions to compute the active minq lookup table entries based on a
+// formulaic approach to facilitate easier adjustment of the Q tables.
+// The formulae were derived from computing a 3rd order polynomial best
+// fit to the original data (after plotting real maxq vs minq (not q index))
+static int calculate_minq_index(double maxq,
+ double x3, double x2, double x1, double c) {
+ int i;
+ const double minqtarget = MIN(((x3 * maxq + x2) * maxq + x1) * maxq + c,
+ maxq);
+
+ // Special case handling to deal with the step from q2.0
+ // down to lossless mode represented by q 1.0.
+ if (minqtarget <= 2.0)
+ return 0;
+
+ for (i = 0; i < QINDEX_RANGE; i++) {
+ if (minqtarget <= vp9_convert_qindex_to_q(i))
+ return i;
+ }
+
+ return QINDEX_RANGE - 1;
+}
+
+void vp9_init_minq_luts(void) {
+ int i;
+
+ for (i = 0; i < QINDEX_RANGE; i++) {
+ const double maxq = vp9_convert_qindex_to_q(i);
+
+
+ kf_low_motion_minq[i] = calculate_minq_index(maxq,
+ 0.000001,
+ -0.0004,
+ 0.15,
+ 0.0);
+ kf_high_motion_minq[i] = calculate_minq_index(maxq,
+ 0.000002,
+ -0.0012,
+ 0.5,
+ 0.0);
+
+ gf_low_motion_minq[i] = calculate_minq_index(maxq,
+ 0.0000015,
+ -0.0009,
+ 0.32,
+ 0.0);
+ gf_high_motion_minq[i] = calculate_minq_index(maxq,
+ 0.0000021,
+ -0.00125,
+ 0.50,
+ 0.0);
+ inter_minq[i] = calculate_minq_index(maxq,
+ 0.00000271,
+ -0.00113,
+ 0.75,
+ 0.0);
+ afq_low_motion_minq[i] = calculate_minq_index(maxq,
+ 0.0000015,
+ -0.0009,
+ 0.33,
+ 0.0);
+ afq_high_motion_minq[i] = calculate_minq_index(maxq,
+ 0.0000021,
+ -0.00125,
+ 0.55,
+ 0.0);
+ }
+}
+
// These functions use formulaic calculations to make playing with the
// quantizer tables easier. If necessary they can be replaced by lookup
// tables if and when things settle down in the experimental bitstream
@@ -118,7 +196,7 @@
vp9_setup_past_independence(cm);
// interval before next GF
- cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+ cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
/* All buffers are implicitly updated on key frames. */
cpi->refresh_golden_frame = 1;
cpi->refresh_alt_ref_frame = 1;
@@ -153,17 +231,17 @@
vp9_clear_system_state(); // __asm emms;
// New Two pass RC
- target = cpi->per_frame_bandwidth;
+ target = cpi->rc.per_frame_bandwidth;
if (cpi->oxcf.rc_max_intra_bitrate_pct) {
- int max_rate = cpi->per_frame_bandwidth
+ int max_rate = cpi->rc.per_frame_bandwidth
* cpi->oxcf.rc_max_intra_bitrate_pct / 100;
if (target > max_rate)
target = max_rate;
}
- cpi->this_frame_target = target;
+ cpi->rc.this_frame_target = target;
}
@@ -174,21 +252,21 @@
// so we just use the interval determined in the two pass code.
static void calc_gf_params(VP9_COMP *cpi) {
// Set the gf interval
- cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+ cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
}
static void calc_pframe_target_size(VP9_COMP *cpi) {
- const int min_frame_target = MAX(cpi->min_frame_bandwidth,
- cpi->av_per_frame_bandwidth >> 5);
+ const int min_frame_target = MAX(cpi->rc.min_frame_bandwidth,
+ cpi->rc.av_per_frame_bandwidth >> 5);
if (cpi->refresh_alt_ref_frame) {
// Special alt reference frame case
// Per frame bit target for the alt ref frame
- cpi->per_frame_bandwidth = cpi->twopass.gf_bits;
- cpi->this_frame_target = cpi->per_frame_bandwidth;
+ cpi->rc.per_frame_bandwidth = cpi->twopass.gf_bits;
+ cpi->rc.this_frame_target = cpi->rc.per_frame_bandwidth;
} else {
// Normal frames (gf,and inter)
- cpi->this_frame_target = cpi->per_frame_bandwidth;
+ cpi->rc.this_frame_target = cpi->rc.per_frame_bandwidth;
}
// Check that the total sum of adjustments is not above the maximum allowed.
@@ -197,41 +275,26 @@
// not capable of recovering all the extra bits we have spent in the KF or GF,
// then the remainder will have to be recovered over a longer time span via
// other buffer / rate control mechanisms.
- if (cpi->this_frame_target < min_frame_target)
- cpi->this_frame_target = min_frame_target;
-
- if (!cpi->refresh_alt_ref_frame)
- // Note the baseline target data rate for this inter frame.
- cpi->inter_frame_target = cpi->this_frame_target;
+ if (cpi->rc.this_frame_target < min_frame_target)
+ cpi->rc.this_frame_target = min_frame_target;
// Adjust target frame size for Golden Frames:
- if (cpi->frames_till_gf_update_due == 0) {
- const int q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME]
- : cpi->oxcf.fixed_q;
-
+ if (cpi->rc.frames_till_gf_update_due == 0) {
cpi->refresh_golden_frame = 1;
-
calc_gf_params(cpi);
-
// If we are using alternate ref instead of gf then do not apply the boost
// It will instead be applied to the altref update
// Jims modified boost
if (!cpi->source_alt_ref_active) {
- if (cpi->oxcf.fixed_q < 0) {
- // The spend on the GF is defined in the two pass code
- // for two pass encodes
- cpi->this_frame_target = cpi->per_frame_bandwidth;
- } else {
- cpi->this_frame_target =
- (estimate_bits_at_q(1, q, cpi->common.MBs, 1.0)
- * cpi->last_boost) / 100;
- }
+ // The spend on the GF is defined in the two pass code
+ // for two pass encodes
+ cpi->rc.this_frame_target = cpi->rc.per_frame_bandwidth;
} else {
// If there is an active ARF at this location use the minimum
// bits on this frame even if it is a constructed arf.
// The active maximum quantizer insures that an appropriate
// number of bits will be spent if needed for constructed ARFs.
- cpi->this_frame_target = 0;
+ cpi->rc.this_frame_target = 0;
}
}
}
@@ -249,12 +312,12 @@
vp9_clear_system_state(); // __asm emms;
if (cpi->common.frame_type == KEY_FRAME) {
- rate_correction_factor = cpi->key_frame_rate_correction_factor;
+ rate_correction_factor = cpi->rc.key_frame_rate_correction_factor;
} else {
if (cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame)
- rate_correction_factor = cpi->gf_rate_correction_factor;
+ rate_correction_factor = cpi->rc.gf_rate_correction_factor;
else
- rate_correction_factor = cpi->rate_correction_factor;
+ rate_correction_factor = cpi->rc.rate_correction_factor;
}
// Work out how big we would have expected the frame to be at this Q given
@@ -267,7 +330,7 @@
// Work out a size correction factor.
if (projected_size_based_on_q > 0)
correction_factor =
- (100 * cpi->projected_frame_size) / projected_size_based_on_q;
+ (100 * cpi->rc.projected_frame_size) / projected_size_based_on_q;
// More heavily damped adjustment used if we have been oscillating either side
// of target.
@@ -284,7 +347,7 @@
break;
}
- // if ( (correction_factor > 102) && (Q < cpi->active_worst_quality) )
+ // if ( (correction_factor > 102) && (Q < cpi->rc.active_worst_quality) )
if (correction_factor > 102) {
// We are not already at the worst allowable quality
correction_factor =
@@ -308,18 +371,18 @@
}
if (cpi->common.frame_type == KEY_FRAME) {
- cpi->key_frame_rate_correction_factor = rate_correction_factor;
+ cpi->rc.key_frame_rate_correction_factor = rate_correction_factor;
} else {
if (cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame)
- cpi->gf_rate_correction_factor = rate_correction_factor;
+ cpi->rc.gf_rate_correction_factor = rate_correction_factor;
else
- cpi->rate_correction_factor = rate_correction_factor;
+ cpi->rc.rate_correction_factor = rate_correction_factor;
}
}
int vp9_regulate_q(VP9_COMP *cpi, int target_bits_per_frame) {
- int q = cpi->active_worst_quality;
+ int q = cpi->rc.active_worst_quality;
int i;
int last_error = INT_MAX;
@@ -329,12 +392,12 @@
// Select the appropriate correction factor based upon type of frame.
if (cpi->common.frame_type == KEY_FRAME) {
- correction_factor = cpi->key_frame_rate_correction_factor;
+ correction_factor = cpi->rc.key_frame_rate_correction_factor;
} else {
if (cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame)
- correction_factor = cpi->gf_rate_correction_factor;
+ correction_factor = cpi->rc.gf_rate_correction_factor;
else
- correction_factor = cpi->rate_correction_factor;
+ correction_factor = cpi->rc.rate_correction_factor;
}
// Calculate required scaling factor based on target frame size and size of
@@ -347,7 +410,7 @@
target_bits_per_mb =
(target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;
- i = cpi->active_best_quality;
+ i = cpi->rc.active_best_quality;
do {
bits_per_mb_at_this_q = (int)vp9_bits_per_mb(cpi->common.frame_type, i,
@@ -363,7 +426,214 @@
} else {
last_error = bits_per_mb_at_this_q - target_bits_per_mb;
}
- } while (++i <= cpi->active_worst_quality);
+ } while (++i <= cpi->rc.active_worst_quality);
+
+ return q;
+}
+
+static int get_active_quality(int q,
+ int gfu_boost,
+ int low,
+ int high,
+ int *low_motion_minq,
+ int *high_motion_minq) {
+ int active_best_quality;
+ if (gfu_boost > high) {
+ active_best_quality = low_motion_minq[q];
+ } else if (gfu_boost < low) {
+ active_best_quality = high_motion_minq[q];
+ } else {
+ const int gap = high - low;
+ const int offset = high - gfu_boost;
+ const int qdiff = high_motion_minq[q] - low_motion_minq[q];
+ const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap;
+ active_best_quality = low_motion_minq[q] + adjustment;
+ }
+ return active_best_quality;
+}
+
+int vp9_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
+ int * bottom_index, int * top_index) {
+ // Set an active best quality and if necessary active worst quality
+ int q = cpi->rc.active_worst_quality;
+ VP9_COMMON *const cm = &cpi->common;
+
+ if (frame_is_intra_only(cm)) {
+#if !CONFIG_MULTIPLE_ARF
+ // Handle the special case for key frames forced when we have75 reached
+ // the maximum key frame interval. Here force the Q to a range
+ // based on the ambient Q to reduce the risk of popping.
+ if (cpi->this_key_frame_forced) {
+ int delta_qindex;
+ int qindex = cpi->rc.last_boosted_qindex;
+ double last_boosted_q = vp9_convert_qindex_to_q(qindex);
+
+ delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q,
+ (last_boosted_q * 0.75));
+
+ cpi->rc.active_best_quality = MAX(qindex + delta_qindex,
+ cpi->rc.best_quality);
+ } else {
+ int high = 5000;
+ int low = 400;
+ double q_adj_factor = 1.0;
+ double q_val;
+
+ // Baseline value derived from cpi->active_worst_quality and kf boost
+ cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.kf_boost,
+ low, high,
+ kf_low_motion_minq,
+ kf_high_motion_minq);
+
+ // Allow somewhat lower kf minq with small image formats.
+ if ((cm->width * cm->height) <= (352 * 288)) {
+ q_adj_factor -= 0.25;
+ }
+
+ // Make a further adjustment based on the kf zero motion measure.
+ q_adj_factor += 0.05 - (0.001 * (double)cpi->kf_zeromotion_pct);
+
+ // Convert the adjustment factor to a qindex delta
+ // on active_best_quality.
+ q_val = vp9_convert_qindex_to_q(cpi->rc.active_best_quality);
+ cpi->rc.active_best_quality +=
+ vp9_compute_qdelta(cpi, q_val, (q_val * q_adj_factor));
+ }
+#else
+ double current_q;
+ // Force the KF quantizer to be 30% of the active_worst_quality.
+ current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality);
+ cpi->rc.active_best_quality = cpi->rc.active_worst_quality
+ + vp9_compute_qdelta(cpi, current_q, current_q * 0.3);
+#endif
+ } else if (!cpi->is_src_frame_alt_ref &&
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ int high = 2000;
+ int low = 400;
+
+ // Use the lower of cpi->rc.active_worst_quality and recent
+ // average Q as basis for GF/ARF best Q limit unless last frame was
+ // a key frame.
+ if (cpi->frames_since_key > 1 &&
+ cpi->rc.avg_frame_qindex < cpi->rc.active_worst_quality) {
+ q = cpi->rc.avg_frame_qindex;
+ }
+ // For constrained quality dont allow Q less than the cq level
+ if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
+ if (q < cpi->cq_target_quality)
+ q = cpi->cq_target_quality;
+ if (cpi->frames_since_key > 1) {
+ cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+ low, high,
+ afq_low_motion_minq,
+ afq_high_motion_minq);
+ } else {
+ cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+ low, high,
+ gf_low_motion_minq,
+ gf_high_motion_minq);
+ }
+ // Constrained quality use slightly lower active best.
+ cpi->rc.active_best_quality = cpi->rc.active_best_quality * 15 / 16;
+
+ } else if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
+ if (!cpi->refresh_alt_ref_frame) {
+ cpi->rc.active_best_quality = cpi->cq_target_quality;
+ } else {
+ if (cpi->frames_since_key > 1) {
+ cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+ low, high,
+ afq_low_motion_minq,
+ afq_high_motion_minq);
+ } else {
+ cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+ low, high,
+ gf_low_motion_minq,
+ gf_high_motion_minq);
+ }
+ }
+ } else {
+ cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+ low, high,
+ gf_low_motion_minq,
+ gf_high_motion_minq);
+ }
+ } else {
+ if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
+ cpi->rc.active_best_quality = cpi->cq_target_quality;
+ } else {
+ cpi->rc.active_best_quality = inter_minq[q];
+ // 1-pass: for now, use the average Q for the active_best, if its lower
+ // than active_worst.
+ if (cpi->pass == 0 && (cpi->rc.avg_frame_qindex < q))
+ cpi->rc.active_best_quality = inter_minq[cpi->rc.avg_frame_qindex];
+
+ // For the constrained quality mode we don't want
+ // q to fall below the cq level.
+ if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+ (cpi->rc.active_best_quality < cpi->cq_target_quality)) {
+ // If we are strongly undershooting the target rate in the last
+ // frames then use the user passed in cq value not the auto
+ // cq value.
+ if (cpi->rc.rolling_actual_bits < cpi->rc.min_frame_bandwidth)
+ cpi->rc.active_best_quality = cpi->oxcf.cq_level;
+ else
+ cpi->rc.active_best_quality = cpi->cq_target_quality;
+ }
+ }
+ }
+
+ // Clip the active best and worst quality values to limits
+ if (cpi->rc.active_worst_quality > cpi->rc.worst_quality)
+ cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+
+ if (cpi->rc.active_best_quality < cpi->rc.best_quality)
+ cpi->rc.active_best_quality = cpi->rc.best_quality;
+
+ if (cpi->rc.active_best_quality > cpi->rc.worst_quality)
+ cpi->rc.active_best_quality = cpi->rc.worst_quality;
+
+ if (cpi->rc.active_worst_quality < cpi->rc.active_best_quality)
+ cpi->rc.active_worst_quality = cpi->rc.active_best_quality;
+
+ // Limit Q range for the adaptive loop.
+ if (cm->frame_type == KEY_FRAME && !cpi->this_key_frame_forced) {
+ *top_index =
+ (cpi->rc.active_worst_quality + cpi->rc.active_best_quality * 3) / 4;
+ // If this is the first (key) frame in 1-pass, active best is the user
+ // best-allowed, and leave the top_index to active_worst.
+ if (cpi->pass == 0 && cpi->common.current_video_frame == 0) {
+ cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q;
+ *top_index = cpi->oxcf.worst_allowed_q;
+ }
+ } else if (!cpi->is_src_frame_alt_ref &&
+ (cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) &&
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+ *top_index =
+ (cpi->rc.active_worst_quality + cpi->rc.active_best_quality) / 2;
+ } else {
+ *top_index = cpi->rc.active_worst_quality;
+ }
+ *bottom_index = cpi->rc.active_best_quality;
+
+ if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
+ q = cpi->rc.active_best_quality;
+ // Special case code to try and match quality with forced key frames
+ } else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
+ q = cpi->rc.last_boosted_qindex;
+ } else {
+ // Determine initial Q to try.
+ if (cpi->pass == 0) {
+ // 1-pass: for now, use per-frame-bw for target size of frame, scaled
+ // by |x| for key frame.
+ int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1;
+ q = vp9_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth);
+ } else {
+ q = vp9_regulate_q(cpi, cpi->rc.this_frame_target);
+ }
+ if (q > *top_index)
+ q = *top_index;
+ }
return q;
}
@@ -378,7 +648,7 @@
/* First key frame at start of sequence is a special case. We have no
* frequency data.
*/
- if (cpi->key_frame_count == 1) {
+ if (cpi->rc.key_frame_count == 1) {
/* Assume a default of 1 kf every 2 seconds, or the max kf interval,
* whichever is smaller.
*/
@@ -388,7 +658,7 @@
if (cpi->oxcf.auto_key && av_key_frame_frequency > key_freq)
av_key_frame_frequency = cpi->oxcf.key_freq;
- cpi->prior_key_frame_distance[KEY_FRAME_CONTEXT - 1]
+ cpi->rc.prior_key_frame_distance[KEY_FRAME_CONTEXT - 1]
= av_key_frame_frequency;
} else {
unsigned int total_weight = 0;
@@ -400,13 +670,13 @@
*/
for (i = 0; i < KEY_FRAME_CONTEXT; i++) {
if (i < KEY_FRAME_CONTEXT - 1)
- cpi->prior_key_frame_distance[i]
- = cpi->prior_key_frame_distance[i + 1];
+ cpi->rc.prior_key_frame_distance[i]
+ = cpi->rc.prior_key_frame_distance[i + 1];
else
- cpi->prior_key_frame_distance[i] = last_kf_interval;
+ cpi->rc.prior_key_frame_distance[i] = last_kf_interval;
av_key_frame_frequency += prior_key_frame_weight[i]
- * cpi->prior_key_frame_distance[i];
+ * cpi->rc.prior_key_frame_distance[i];
total_weight += prior_key_frame_weight[i];
}
@@ -421,33 +691,32 @@
vp9_clear_system_state();
cpi->frames_since_key = 0;
- cpi->key_frame_count++;
+ cpi->rc.key_frame_count++;
}
void vp9_compute_frame_size_bounds(VP9_COMP *cpi, int *frame_under_shoot_limit,
int *frame_over_shoot_limit) {
// Set-up bounds on acceptable frame size:
- if (cpi->oxcf.fixed_q >= 0) {
- // Fixed Q scenario: frame size never outranges target (there is no target!)
+ if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
*frame_under_shoot_limit = 0;
*frame_over_shoot_limit = INT_MAX;
} else {
if (cpi->common.frame_type == KEY_FRAME) {
- *frame_over_shoot_limit = cpi->this_frame_target * 9 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
+ *frame_over_shoot_limit = cpi->rc.this_frame_target * 9 / 8;
+ *frame_under_shoot_limit = cpi->rc.this_frame_target * 7 / 8;
} else {
if (cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) {
- *frame_over_shoot_limit = cpi->this_frame_target * 9 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
+ *frame_over_shoot_limit = cpi->rc.this_frame_target * 9 / 8;
+ *frame_under_shoot_limit = cpi->rc.this_frame_target * 7 / 8;
} else {
// Stron overshoot limit for constrained quality
if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
- *frame_over_shoot_limit = cpi->this_frame_target * 11 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 2 / 8;
+ *frame_over_shoot_limit = cpi->rc.this_frame_target * 11 / 8;
+ *frame_under_shoot_limit = cpi->rc.this_frame_target * 2 / 8;
} else {
- *frame_over_shoot_limit = cpi->this_frame_target * 11 / 8;
- *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
+ *frame_over_shoot_limit = cpi->rc.this_frame_target * 11 / 8;
+ *frame_under_shoot_limit = cpi->rc.this_frame_target * 5 / 8;
}
}
}
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index ddda713..57dcd3f 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -27,6 +27,8 @@
int *frame_under_shoot_limit,
int *frame_over_shoot_limit);
+void vp9_init_minq_luts(void);
+
// return of 0 means drop frame
int vp9_pick_frame_size(VP9_COMP *cpi);
@@ -35,5 +37,7 @@
int vp9_bits_per_mb(FRAME_TYPE frame_type, int qindex,
double correction_factor);
void vp9_setup_inter_frame(VP9_COMP *cpi);
+int vp9_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
+ int * bottom_index, int * top_index);
#endif // VP9_ENCODER_VP9_RATECTRL_H_
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 5d37f83..8905225 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -567,8 +567,7 @@
&this_sse) >> shift;
args->sse = this_sse >> shift;
- if (x->skip_encode &&
- xd->mi_8x8[0]->mbmi.ref_frame[0] == INTRA_FRAME) {
+ if (x->skip_encode && !is_inter_block(&xd->mi_8x8[0]->mbmi)) {
// TODO(jingning): tune the model to better capture the distortion.
int64_t p = (pd->dequant[1] * pd->dequant[1] *
(1 << ss_txfrm_size)) >> (shift + 2);
@@ -1549,9 +1548,9 @@
struct macroblockd_plane *const pd = &xd->plane[0];
struct macroblock_plane *const p = &x->plane[0];
MODE_INFO *const mi = xd->mi_8x8[0];
- const BLOCK_SIZE bsize = mi->mbmi.sb_type;
- const int width = plane_block_width(bsize, pd);
- const int height = plane_block_height(bsize, pd);
+ const BLOCK_SIZE plane_bsize = get_plane_block_size(mi->mbmi.sb_type, pd);
+ const int width = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
+ const int height = 4 * num_4x4_blocks_high_lookup[plane_bsize];
int idx, idy;
const uint8_t *const src = &p->src.buf[raster_block_offset(BLOCK_8X8, i,
@@ -3754,7 +3753,7 @@
assert((cm->mcomp_filter_type == SWITCHABLE) ||
(cm->mcomp_filter_type == best_mbmode.interp_filter) ||
- (best_mbmode.ref_frame[0] == INTRA_FRAME));
+ !is_inter_block(&best_mbmode));
// Updating rd_thresh_freq_fact[] here means that the different
// partition/block sizes are handled independently based on the best
@@ -4325,8 +4324,8 @@
}
// Keep record of best inter rd with single reference
- if (xd->mi_8x8[0]->mbmi.ref_frame[0] > INTRA_FRAME &&
- xd->mi_8x8[0]->mbmi.ref_frame[1] == NONE &&
+ if (is_inter_block(&xd->mi_8x8[0]->mbmi) &&
+ !has_second_ref(&xd->mi_8x8[0]->mbmi) &&
!mode_excluded &&
this_rd < best_inter_rd) {
best_inter_rd = this_rd;
@@ -4489,7 +4488,7 @@
assert((cm->mcomp_filter_type == SWITCHABLE) ||
(cm->mcomp_filter_type == best_mbmode.interp_filter) ||
- (best_mbmode.ref_frame[0] == INTRA_FRAME));
+ !is_inter_block(&best_mbmode));
// Updating rd_thresh_freq_fact[] here means that the different
// partition/block sizes are handled independently based on the best
@@ -4515,7 +4514,7 @@
// macroblock modes
*mbmi = best_mbmode;
x->skip |= best_skip2;
- if (best_mbmode.ref_frame[0] == INTRA_FRAME) {
+ if (!is_inter_block(&best_mbmode)) {
for (i = 0; i < 4; i++)
xd->mi_8x8[0]->bmi[i].as_mode = best_bmodes[i].as_mode;
} else {
diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c
index 3bffb12..6d4075e 100644
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -469,7 +469,7 @@
// cases where the filter extends beyond the end of clip.
// Note: this_frame->frame has been updated in the loop
// so it now points at the ARF frame.
- half_gf_int = cpi->baseline_gf_interval >> 1;
+ half_gf_int = cpi->rc.baseline_gf_interval >> 1;
frames_after_arf = (int)(cpi->twopass.total_stats.count - this_frame - 1);
switch (cpi->oxcf.arnr_type) {
@@ -507,7 +507,7 @@
cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd;
// Adjust the strength based on active max q
- q = ((int)vp9_convert_qindex_to_q(cpi->active_worst_quality) >> 1);
+ q = ((int)vp9_convert_qindex_to_q(cpi->rc.active_worst_quality) >> 1);
if (q > 8) {
cpi->active_arnr_strength = cpi->oxcf.arnr_strength;
} else {
diff --git a/vp9/encoder/vp9_treewriter.h b/vp9/encoder/vp9_treewriter.h
index 41d1bfb..c9bf4da 100644
--- a/vp9/encoder/vp9_treewriter.h
+++ b/vp9/encoder/vp9_treewriter.h
@@ -35,9 +35,8 @@
static INLINE void treed_write(vp9_writer *w,
vp9_tree tree, const vp9_prob *probs,
- int bits, int len) {
- vp9_tree_index i = 0;
-
+ int bits, int len,
+ vp9_tree_index i) {
do {
const int bit = (bits >> --len) & 1;
vp9_write(w, bit, probs[i >> 1]);
@@ -48,7 +47,7 @@
static INLINE void write_token(vp9_writer *w, vp9_tree tree,
const vp9_prob *probs,
const struct vp9_token *token) {
- treed_write(w, tree, probs, token->value, token->len);
+ treed_write(w, tree, probs, token->value, token->len, 0);
}
static INLINE int treed_cost(vp9_tree tree, const vp9_prob *probs,
diff --git a/vp9/encoder/x86/vp9_dct_sse2.c b/vp9/encoder/x86/vp9_dct_sse2.c
index fefca66..65431bd 100644
--- a/vp9/encoder/x86/vp9_dct_sse2.c
+++ b/vp9/encoder/x86/vp9_dct_sse2.c
@@ -26,24 +26,25 @@
// by constructing the 32 bit constant corresponding to that pair.
const __m128i k__cospi_p16_p16 = _mm_set1_epi16(cospi_16_64);
const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
- const __m128i k__cospi_p24_p08 = pair_set_epi16(cospi_24_64, cospi_8_64);
- const __m128i k__cospi_m08_p24 = pair_set_epi16(-cospi_8_64, cospi_24_64);
+ const __m128i k__cospi_p08_p24 = pair_set_epi16(cospi_8_64, cospi_24_64);
+ const __m128i k__cospi_p24_m08 = pair_set_epi16(cospi_24_64, -cospi_8_64);
const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING);
const __m128i k__nonzero_bias_a = _mm_setr_epi16(0, 1, 1, 1, 1, 1, 1, 1);
const __m128i k__nonzero_bias_b = _mm_setr_epi16(1, 0, 0, 0, 0, 0, 0, 0);
const __m128i kOne = _mm_set1_epi16(1);
- __m128i in0, in1, in2, in3;
+ __m128i in0, in1;
// Load inputs.
{
in0 = _mm_loadl_epi64((const __m128i *)(input + 0 * stride));
- in1 = _mm_loadl_epi64((const __m128i *)(input + 1 * stride));
- in2 = _mm_loadl_epi64((const __m128i *)(input + 2 * stride));
- in3 = _mm_loadl_epi64((const __m128i *)(input + 3 * stride));
+ in0 = _mm_unpacklo_epi64(in0, _mm_loadl_epi64((const __m128i *)
+ (input + 1 * stride)));
+ in1 = _mm_loadl_epi64((const __m128i *)(input + 2 * stride));
+ in1 = _mm_unpacklo_epi64(_mm_loadl_epi64((const __m128i *)
+ (input + 3 * stride)), in1);
+
// x = x << 4
in0 = _mm_slli_epi16(in0, 4);
in1 = _mm_slli_epi16(in1, 4);
- in2 = _mm_slli_epi16(in2, 4);
- in3 = _mm_slli_epi16(in3, 4);
// if (i == 0 && input[0]) input[0] += 1;
{
// The mask will only contain wether the first value is zero, all
@@ -60,18 +61,18 @@
// Do the two transform/transpose passes
for (pass = 0; pass < 2; ++pass) {
// Transform 1/2: Add/substract
- const __m128i r0 = _mm_add_epi16(in0, in3);
- const __m128i r1 = _mm_add_epi16(in1, in2);
- const __m128i r2 = _mm_sub_epi16(in1, in2);
- const __m128i r3 = _mm_sub_epi16(in0, in3);
+ const __m128i r0 = _mm_add_epi16(in0, in1);
+ const __m128i r1 = _mm_sub_epi16(in0, in1);
+ const __m128i r2 = _mm_unpacklo_epi64(r0, r1);
+ const __m128i r3 = _mm_unpackhi_epi64(r0, r1);
// Transform 1/2: Interleave to do the multiply by constants which gets us
// into 32 bits.
- const __m128i t0 = _mm_unpacklo_epi16(r0, r1);
- const __m128i t2 = _mm_unpacklo_epi16(r2, r3);
+ const __m128i t0 = _mm_unpacklo_epi16(r2, r3);
+ const __m128i t2 = _mm_unpackhi_epi16(r2, r3);
const __m128i u0 = _mm_madd_epi16(t0, k__cospi_p16_p16);
const __m128i u2 = _mm_madd_epi16(t0, k__cospi_p16_m16);
- const __m128i u4 = _mm_madd_epi16(t2, k__cospi_p24_p08);
- const __m128i u6 = _mm_madd_epi16(t2, k__cospi_m08_p24);
+ const __m128i u4 = _mm_madd_epi16(t2, k__cospi_p08_p24);
+ const __m128i u6 = _mm_madd_epi16(t2, k__cospi_p24_m08);
const __m128i v0 = _mm_add_epi32(u0, k__DCT_CONST_ROUNDING);
const __m128i v2 = _mm_add_epi32(u2, k__DCT_CONST_ROUNDING);
const __m128i v4 = _mm_add_epi32(u4, k__DCT_CONST_ROUNDING);
@@ -90,24 +91,21 @@
// 00 10 01 11 02 12 03 13
// 20 30 21 31 22 32 23 33
in0 = _mm_unpacklo_epi32(tr0_0, tr0_1);
- in2 = _mm_unpackhi_epi32(tr0_0, tr0_1);
+ in1 = _mm_unpackhi_epi32(tr0_0, tr0_1);
+ in1 = _mm_shuffle_epi32(in1, 0x4E);
// 00 10 20 30 01 11 21 31 in0 contains 0 followed by 1
- // 02 12 22 32 03 13 23 33 in2 contains 2 followed by 3
- if (0 == pass) {
- // Extract values in the high part for second pass as transform code
- // only uses the first four values.
- in1 = _mm_unpackhi_epi64(in0, in0);
- in3 = _mm_unpackhi_epi64(in2, in2);
- } else {
- // Post-condition output and store it (v + 1) >> 2, taking advantage
- // of the fact 1/3 are stored just after 0/2.
- __m128i out01 = _mm_add_epi16(in0, kOne);
- __m128i out23 = _mm_add_epi16(in2, kOne);
- out01 = _mm_srai_epi16(out01, 2);
- out23 = _mm_srai_epi16(out23, 2);
- _mm_storeu_si128((__m128i *)(output + 0 * 4), out01);
- _mm_storeu_si128((__m128i *)(output + 2 * 4), out23);
- }
+ // 02 12 22 32 03 13 23 33 in1 contains 2 followed by 3
+ }
+ in1 = _mm_shuffle_epi32(in1, 0x4E);
+ // Post-condition output and store it (v + 1) >> 2, taking advantage
+ // of the fact 1/3 are stored just after 0/2.
+ {
+ __m128i out01 = _mm_add_epi16(in0, kOne);
+ __m128i out23 = _mm_add_epi16(in1, kOne);
+ out01 = _mm_srai_epi16(out01, 2);
+ out23 = _mm_srai_epi16(out23, 2);
+ _mm_storeu_si128((__m128i *)(output + 0 * 4), out01);
+ _mm_storeu_si128((__m128i *)(output + 2 * 4), out23);
}
}
diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk
index c566765..6e4a498 100644
--- a/vp9/vp9_common.mk
+++ b/vp9/vp9_common.mk
@@ -124,6 +124,7 @@
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_convolve8_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_convolve8_avg_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_loopfilter_neon$(ASM)
+#VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_loopfilter_16_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_dc_only_idct_add_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct4x4_1_add_neon$(ASM)
VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_short_idct4x4_add_neon$(ASM)
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 1942039..9a23ebd 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -38,6 +38,7 @@
unsigned int rc_max_intra_bitrate_pct;
unsigned int lossless;
unsigned int frame_parallel_decoding_mode;
+ unsigned int aq_mode;
};
struct extraconfig_map {
@@ -66,6 +67,7 @@
0, /* rc_max_intra_bitrate_pct */
0, /* lossless */
0, /* frame_parallel_decoding_mode */
+ 0, /* aq_mode */
}
}
};
@@ -157,6 +159,7 @@
RANGE_CHECK_HI(cfg, rc_max_quantizer, 0);
RANGE_CHECK_HI(cfg, rc_min_quantizer, 0);
}
+ RANGE_CHECK(vp8_cfg, aq_mode, 0, AQ_MODES_COUNT - 1);
RANGE_CHECK_HI(cfg, g_threads, 64);
RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
@@ -335,6 +338,8 @@
oxcf->error_resilient_mode = cfg.g_error_resilient;
oxcf->frame_parallel_decoding_mode = vp8_cfg.frame_parallel_decoding_mode;
+ oxcf->aq_mode = vp8_cfg.aq_mode;
+
oxcf->ss_number_layers = cfg.ss_number_layers;
/*
printf("Current VP9 Settings: \n");
@@ -445,6 +450,7 @@
MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT, xcfg.rc_max_intra_bitrate_pct);
MAP(VP9E_SET_LOSSLESS, xcfg.lossless);
MAP(VP9E_SET_FRAME_PARALLEL_DECODING, xcfg.frame_parallel_decoding_mode);
+ MAP(VP9E_SET_AQ_MODE, xcfg.aq_mode);
}
res = validate_config(ctx, &ctx->cfg, &xcfg);
@@ -1071,6 +1077,7 @@
{VP8E_SET_MAX_INTRA_BITRATE_PCT, set_param},
{VP9E_SET_LOSSLESS, set_param},
{VP9E_SET_FRAME_PARALLEL_DECODING, set_param},
+ {VP9E_SET_AQ_MODE, set_param},
{VP9_GET_REFERENCE, get_reference},
{VP9E_SET_SVC, vp9e_set_svc},
{VP9E_SET_SVC_PARAMETERS, vp9e_set_svc_parameters},
diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h
index 433cc0d..c0424f1 100644
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -193,6 +193,7 @@
VP9E_SET_TILE_COLUMNS,
VP9E_SET_TILE_ROWS,
VP9E_SET_FRAME_PARALLEL_DECODING,
+ VP9E_SET_AQ_MODE,
VP9E_SET_SVC,
VP9E_SET_SVC_PARAMETERS
@@ -343,6 +344,8 @@
VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PARALLEL_DECODING, unsigned int)
+VPX_CTRL_USE_TYPE(VP9E_SET_AQ_MODE, unsigned int)
+
/*! @} - end defgroup vp8_encoder */
#ifdef __cplusplus
} // extern "C"
diff --git a/vpx_ports/x86.h b/vpx_ports/x86.h
index 2990583..e5e97e7 100644
--- a/vpx_ports/x86.h
+++ b/vpx_ports/x86.h
@@ -35,51 +35,53 @@
#if defined(__GNUC__) && __GNUC__ || defined(__ANDROID__)
#if ARCH_X86_64
-#define cpuid(func,ax,bx,cx,dx)\
+#define cpuid(func, func2, ax, bx, cx, dx)\
__asm__ __volatile__ (\
"cpuid \n\t" \
: "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \
- : "a" (func));
+ : "a" (func), "c" (func2));
#else
-#define cpuid(func,ax,bx,cx,dx)\
+#define cpuid(func, func2, ax, bx, cx, dx)\
__asm__ __volatile__ (\
"mov %%ebx, %%edi \n\t" \
"cpuid \n\t" \
"xchg %%edi, %%ebx \n\t" \
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
- : "a" (func));
+ : "a" (func), "c" (func2));
#endif
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* end __GNUC__ or __ANDROID__*/
#if ARCH_X86_64
-#define cpuid(func,ax,bx,cx,dx)\
+#define cpuid(func, func2, ax, bx, cx, dx)\
asm volatile (\
"xchg %rsi, %rbx \n\t" \
"cpuid \n\t" \
"movl %ebx, %edi \n\t" \
"xchg %rsi, %rbx \n\t" \
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
- : "a" (func));
+ : "a" (func), "c" (func2));
#else
-#define cpuid(func,ax,bx,cx,dx)\
+#define cpuid(func, func2, ax, bx, cx, dx)\
asm volatile (\
"pushl %ebx \n\t" \
"cpuid \n\t" \
"movl %ebx, %edi \n\t" \
"popl %ebx \n\t" \
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
- : "a" (func));
+ : "a" (func), "c" (func2));
#endif
#else /* end __SUNPRO__ */
#if ARCH_X86_64
-void __cpuid(int CPUInfo[4], int info_type);
-#pragma intrinsic(__cpuid)
-#define cpuid(func,a,b,c,d) do{\
+void __cpuidex(int CPUInfo[4], int info_type, int ecxvalue);
+#pragma intrinsic(__cpuidex)
+#define cpuid(func, func2, a, b, c, d) do {\
int regs[4];\
- __cpuid(regs,func); a=regs[0]; b=regs[1]; c=regs[2]; d=regs[3];\
+ __cpuidex(regs, func, func2); \
+ a = regs[0]; b = regs[1]; c = regs[2]; d = regs[3];\
} while(0)
#else
-#define cpuid(func,a,b,c,d)\
+#define cpuid(func, func2, a, b, c, d)\
__asm mov eax, func\
+ __asm mov ecx, func2\
__asm cpuid\
__asm mov a, eax\
__asm mov b, ebx\
@@ -120,13 +122,13 @@
mask = strtol(env, NULL, 0);
/* Ensure that the CPUID instruction supports extended features */
- cpuid(0, reg_eax, reg_ebx, reg_ecx, reg_edx);
+ cpuid(0, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
if (reg_eax < 1)
return 0;
/* Get the standard feature flags */
- cpuid(1, reg_eax, reg_ebx, reg_ecx, reg_edx);
+ cpuid(1, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
if (reg_edx & BIT(23)) flags |= HAS_MMX;
@@ -142,6 +144,11 @@
if (reg_ecx & BIT(28)) flags |= HAS_AVX;
+ /* Get the leaf 7 feature flags. Needed to check for AVX2 support */
+ reg_eax = 7;
+ reg_ecx = 0;
+ cpuid(7, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
+
if (reg_ebx & BIT(5)) flags |= HAS_AVX2;
return flags & mask;
diff --git a/vpx_ports/x86_cpuid.c b/vpx_ports/x86_cpuid.c
index fe86cfc..02d382c 100644
--- a/vpx_ports/x86_cpuid.c
+++ b/vpx_ports/x86_cpuid.c
@@ -38,7 +38,7 @@
int i;
/* Get the Vendor String from the CPU */
- cpuid(0, reg_eax, vs[0], vs[2], vs[1]);
+ cpuid(0, 0, reg_eax, vs[0], vs[2], vs[1]);
for (i = 0; i < VPX_CPU_LAST; i++) {
if (strncmp((const char *)vs, cpuid_vendor_list[i].vendor_string, 12) == 0)
diff --git a/vpxenc.c b/vpxenc.c
index 377e38b..c35493f 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -8,6 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#include "./vpxenc.h"
#include "./vpx_config.h"
#include <assert.h>
@@ -214,11 +215,7 @@
"Show encoder parameters");
static const arg_def_t psnrarg = ARG_DEF(NULL, "psnr", 0,
"Show PSNR in status line");
-enum TestDecodeFatality {
- TEST_DECODE_OFF,
- TEST_DECODE_FATAL,
- TEST_DECODE_WARN,
-};
+
static const struct arg_enum_list test_decode_enum[] = {
{"off", TEST_DECODE_OFF},
{"fatal", TEST_DECODE_FATAL},
@@ -238,11 +235,16 @@
"Show quantizer histogram (n-buckets)");
static const arg_def_t rate_hist_n = ARG_DEF(NULL, "rate-hist", 1,
"Show rate histogram (n-buckets)");
+static const arg_def_t disable_warnings =
+ ARG_DEF(NULL, "disable-warnings", 0,
+ "Disable warnings about potentially incorrect encode settings.");
+
static const arg_def_t *main_args[] = {
&debugmode,
&outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &skip,
&deadline, &best_dl, &good_dl, &rt_dl,
- &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n,
+ &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n,
+ &rate_hist_n, &disable_warnings,
NULL
};
@@ -380,6 +382,9 @@
#if CONFIG_VP9_ENCODER
static const arg_def_t frame_parallel_decoding = ARG_DEF(
NULL, "frame-parallel", 1, "Enable frame parallel decodability features");
+static const arg_def_t aq_mode = ARG_DEF(
+ NULL, "aq-mode", 1,
+ "Adaptive quantization mode (0: disabled (by default), 1: variance based)");
#endif
#if CONFIG_VP8_ENCODER
@@ -404,7 +409,7 @@
&cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
&tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
&tune_ssim, &cq_level, &max_intra_rate_pct, &lossless,
- &frame_parallel_decoding,
+ &frame_parallel_decoding, &aq_mode,
NULL
};
static const int vp9_arg_ctrl_map[] = {
@@ -413,7 +418,7 @@
VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS,
VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
- VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING,
+ VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE,
0
};
#endif
@@ -853,29 +858,6 @@
NELEMENTS(vp9_arg_ctrl_map))
#endif
-/* Configuration elements common to all streams */
-struct global_config {
- const struct codec_item *codec;
- int passes;
- int pass;
- int usage;
- int deadline;
- int use_i420;
- int quiet;
- int verbose;
- int limit;
- int skip_frames;
- int show_psnr;
- enum TestDecodeFatality test_decode;
- int have_framerate;
- struct vpx_rational framerate;
- int out_part;
- int debug;
- int show_q_hist_buckets;
- int show_rate_hist_buckets;
-};
-
-
/* Per-stream configuration */
struct stream_config {
struct vpx_codec_enc_cfg cfg;
@@ -928,7 +910,7 @@
}
-static void parse_global_config(struct global_config *global, char **argv) {
+static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
char **argi, **argj;
struct arg arg;
@@ -1079,7 +1061,7 @@
y4m_input_close(&input->y4m);
}
-static struct stream_state *new_stream(struct global_config *global,
+static struct stream_state *new_stream(struct VpxEncoderConfig *global,
struct stream_state *prev) {
struct stream_state *stream;
@@ -1128,7 +1110,7 @@
}
-static int parse_stream_params(struct global_config *global,
+static int parse_stream_params(struct VpxEncoderConfig *global,
struct stream_state *stream,
char **argv) {
char **argi, **argj;
@@ -1274,14 +1256,13 @@
}
-#define FOREACH_STREAM(func)\
- do\
- {\
- struct stream_state *stream;\
- \
- for(stream = streams; stream; stream = stream->next)\
- func;\
- }while(0)
+#define FOREACH_STREAM(func) \
+ do { \
+ struct stream_state *stream; \
+ for(stream = streams; stream; stream = stream->next) { \
+ func; \
+ } \
+ } while (0)
static void validate_stream_config(struct stream_state *stream) {
@@ -1333,8 +1314,8 @@
}
-static void set_default_kf_interval(struct stream_state *stream,
- struct global_config *global) {
+static void set_default_kf_interval(struct stream_state *stream,
+ struct VpxEncoderConfig *global) {
/* Use a max keyframe interval of 5 seconds, if none was
* specified on the command line.
*/
@@ -1346,8 +1327,8 @@
}
-static void show_stream_config(struct stream_state *stream,
- struct global_config *global,
+static void show_stream_config(struct stream_state *stream,
+ struct VpxEncoderConfig *global,
struct VpxInputContext *input) {
#define SHOW(field) \
@@ -1397,7 +1378,7 @@
static void open_output_file(struct stream_state *stream,
- struct global_config *global) {
+ struct VpxEncoderConfig *global) {
const char *fn = stream->config.out_fn;
stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout);
@@ -1437,9 +1418,9 @@
}
-static void setup_pass(struct stream_state *stream,
- struct global_config *global,
- int pass) {
+static void setup_pass(struct stream_state *stream,
+ struct VpxEncoderConfig *global,
+ int pass) {
if (stream->config.stats_fn) {
if (!stats_open_file(&stream->stats, stream->config.stats_fn,
pass))
@@ -1461,8 +1442,8 @@
}
-static void initialize_encoder(struct stream_state *stream,
- struct global_config *global) {
+static void initialize_encoder(struct stream_state *stream,
+ struct VpxEncoderConfig *global) {
int i;
int flags = 0;
@@ -1496,10 +1477,10 @@
}
-static void encode_frame(struct stream_state *stream,
- struct global_config *global,
- struct vpx_image *img,
- unsigned int frames_in) {
+static void encode_frame(struct stream_state *stream,
+ struct VpxEncoderConfig *global,
+ struct vpx_image *img,
+ unsigned int frames_in) {
vpx_codec_pts_t frame_start, next_frame_start;
struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
struct vpx_usec_timer timer;
@@ -1554,9 +1535,9 @@
}
-static void get_cx_data(struct stream_state *stream,
- struct global_config *global,
- int *got_data) {
+static void get_cx_data(struct stream_state *stream,
+ struct VpxEncoderConfig *global,
+ int *got_data) {
const vpx_codec_cx_pkt_t *pkt;
const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
vpx_codec_iter_t iter = NULL;
@@ -1748,18 +1729,44 @@
}
}
-int main(int argc, const char **argv_) {
- int pass;
- vpx_image_t raw;
- int frame_avail, got_data;
+int continue_prompt() {
+ int c;
+ fprintf(stderr, "Continue? (y to continue) ");
+ c = getchar();
+ return c == 'y';
+}
- struct VpxInputContext input = {0};
- struct global_config global;
- struct stream_state *streams = NULL;
- char **argv, **argi;
- uint64_t cx_time = 0;
- int stream_cnt = 0;
- int res = 0;
+void check_quantizer(struct VpxEncoderConfig* config, int min_q, int max_q) {
+ int check_failed = 0;
+
+ if (config->disable_warnings)
+ return;
+
+ if (min_q == max_q || abs(max_q - min_q) < 8) {
+ check_failed = 1;
+ }
+
+ if (check_failed) {
+ warn("Bad quantizer values. Quantizer values must not be equal, and "
+ "should differ by at least 8.");
+
+ if (!continue_prompt())
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc, const char **argv_) {
+ int pass;
+ vpx_image_t raw;
+ int frame_avail, got_data;
+
+ struct VpxInputContext input = {0};
+ struct VpxEncoderConfig global;
+ struct stream_state *streams = NULL;
+ char **argv, **argi;
+ uint64_t cx_time = 0;
+ int stream_cnt = 0;
+ int res = 0;
exec_name = argv_[0];
@@ -1779,6 +1786,7 @@
argv = argv_dup(argc - 1, argv_ + 1);
parse_global_config(&global, argv);
+
{
/* Now parse each stream's parameters. Using a local scope here
* due to the use of 'stream' as loop variable in FOREACH_STREAM
@@ -1799,6 +1807,10 @@
if (argi[0][0] == '-' && argi[0][1])
die("Error: Unrecognized option %s\n", *argi);
+ FOREACH_STREAM(
+ check_quantizer(&global,
+ stream->config.cfg.rc_min_quantizer,
+ stream->config.cfg.rc_max_quantizer););
/* Handle non-option arguments */
input.filename = argv[0];
diff --git a/vpxenc.h b/vpxenc.h
new file mode 100644
index 0000000..5cb3f85
--- /dev/null
+++ b/vpxenc.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013 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 VPXENC_H_
+#define VPXENC_H_
+
+#include "vpx/vpx_encoder.h"
+
+enum TestDecodeFatality {
+ TEST_DECODE_OFF,
+ TEST_DECODE_FATAL,
+ TEST_DECODE_WARN,
+};
+
+/* Configuration elements common to all streams. */
+struct VpxEncoderConfig {
+ const struct codec_item *codec;
+ int passes;
+ int pass;
+ int usage;
+ int deadline;
+ int use_i420;
+ int quiet;
+ int verbose;
+ int limit;
+ int skip_frames;
+ int show_psnr;
+ enum TestDecodeFatality test_decode;
+ int have_framerate;
+ struct vpx_rational framerate;
+ int out_part;
+ int debug;
+ int show_q_hist_buckets;
+ int show_rate_hist_buckets;
+ int disable_warnings;
+ int disable_warning_prompt;
+};
+
+#endif // VPXENC_H_