diff options
31 files changed, 899 insertions, 423 deletions
diff --git a/test/convolve_test.cc b/test/convolve_test.cc index 6e5002fe9..93d3b01c2 100644 --- a/test/convolve_test.cc +++ b/test/convolve_test.cc @@ -211,7 +211,7 @@ class ConvolveTest : public PARAMS(int, int, const ConvolveFunctions*) { virtual void SetUp() { UUT_ = GET_PARAM(2); - /* Set up guard blocks for an inner block cetered in the outer block */ + /* Set up guard blocks for an inner block centered in the outer block */ for (int i = 0; i < kOutputBufferSize; ++i) { if (IsIndexInBorder(i)) output_[i] = 255; @@ -546,4 +546,26 @@ INSTANTIATE_TEST_CASE_P(SSSE3, ConvolveTest, ::testing::Values( make_tuple(32, 64, &convolve8_ssse3), make_tuple(64, 64, &convolve8_ssse3))); #endif + +#if HAVE_NEON +const ConvolveFunctions convolve8_neon( + vp9_convolve8_horiz_neon, vp9_convolve8_avg_horiz_c, + vp9_convolve8_vert_neon, vp9_convolve8_avg_vert_c, + vp9_convolve8_c, vp9_convolve8_avg_c); + +INSTANTIATE_TEST_CASE_P(NEON, ConvolveTest, ::testing::Values( + make_tuple(4, 4, &convolve8_neon), + make_tuple(8, 4, &convolve8_neon), + make_tuple(4, 8, &convolve8_neon), + make_tuple(8, 8, &convolve8_neon), + make_tuple(16, 8, &convolve8_neon), + make_tuple(8, 16, &convolve8_neon), + make_tuple(16, 16, &convolve8_neon), + make_tuple(32, 16, &convolve8_neon), + make_tuple(16, 32, &convolve8_neon), + make_tuple(32, 32, &convolve8_neon), + make_tuple(64, 32, &convolve8_neon), + make_tuple(32, 64, &convolve8_neon), + make_tuple(64, 64, &convolve8_neon))); +#endif } // namespace diff --git a/vp9/common/arm/neon/vp9_convolve8_neon.asm b/vp9/common/arm/neon/vp9_convolve8_neon.asm new file mode 100644 index 000000000..842c73c90 --- /dev/null +++ b/vp9/common/arm/neon/vp9_convolve8_neon.asm @@ -0,0 +1,250 @@ +; +; 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. +; + + + ; These functions are only valid when: + ; x_step_q4 == 16 + ; w%4 == 0 + ; h%4 == 0 + ; taps == 8 + ; VP9_FILTER_WEIGHT == 128 + ; VP9_FILTER_SHIFT == 7 + + EXPORT |vp9_convolve8_horiz_neon| + EXPORT |vp9_convolve8_vert_neon| + IMPORT |vp9_convolve8_horiz_c| + IMPORT |vp9_convolve8_vert_c| + ARM + REQUIRE8 + PRESERVE8 + + AREA ||.text||, CODE, READONLY, ALIGN=2 + + ; Multiply and accumulate by q0 + MACRO + MULTIPLY_BY_Q0 $dst, $src0, $src1, $src2, $src3, $src4, $src5, $src6, $src7 + vmull.s16 $dst, $src0, d0[0] + vmlal.s16 $dst, $src1, d0[1] + vmlal.s16 $dst, $src2, d0[2] + vmlal.s16 $dst, $src3, d0[3] + vmlal.s16 $dst, $src4, d1[0] + vmlal.s16 $dst, $src5, d1[1] + vmlal.s16 $dst, $src6, d1[2] + vmlal.s16 $dst, $src7, d1[3] + MEND + +; r0 const uint8_t *src +; r1 int src_stride +; r2 uint8_t *dst +; r3 int dst_stride +; sp[]const int16_t *filter_x +; sp[]int x_step_q4 +; sp[]const int16_t *filter_y ; unused +; sp[]int y_step_q4 ; unused +; sp[]int w +; sp[]int h + +|vp9_convolve8_horiz_neon| PROC + push {r4-r10, lr} + + sub r0, r0, #3 ; adjust for taps + + ldr r4, [sp, #36] ; x_step_q4 + ldr r5, [sp, #32] ; filter_x + cmp r4, #16 + bne call_horiz_c_convolve ; x_step_q4 != 16 + + ldr r6, [sp, #48] ; w + ldr r7, [sp, #52] ; h + + vld1.s16 {q0}, [r5] ; filter_x + + add r8, r1, r1, lsl #1 ; src_stride * 3 + add r8, r8, #4 ; src_stride * 3 + 4 + rsb r8, r8, #0 ; reset for src + + add r4, r3, r3, lsl #1 ; dst_stride * 3 + sub r4, r4, #4 ; dst_stride * 3 - 4 + rsb r4, r4, #0 ; reset for dst + + sub r9, r1, #8 ; post increment for src load + + rsb r1, r6, r1, lsl #2 ; reset src for outer loop + rsb r12, r6, r3, lsl #2 ; reset dst for outer loop + + mov r10, r6 ; w loop counter + +loop_horiz + vld4.u8 {d24[0], d25[0], d26[0], d27[0]}, [r0]! + vld4.u8 {d24[4], d25[4], d26[4], d27[4]}, [r0]! + vld3.u8 {d28[0], d29[0], d30[0]}, [r0], r9 + + vld4.u8 {d24[1], d25[1], d26[1], d27[1]}, [r0]! + vld4.u8 {d24[5], d25[5], d26[5], d27[5]}, [r0]! + vld3.u8 {d28[1], d29[1], d30[1]}, [r0], r9 + + vld4.u8 {d24[2], d25[2], d26[2], d27[2]}, [r0]! + vld4.u8 {d24[6], d25[6], d26[6], d27[6]}, [r0]! + vld3.u8 {d28[2], d29[2], d30[2]}, [r0], r9 + + vld4.u8 {d24[3], d25[3], d26[3], d27[3]}, [r0]! + vld4.u8 {d24[7], d25[7], d26[7], d27[7]}, [r0]! + vld3.u8 {d28[3], d29[3], d30[3]}, [r0], r8 + + ; extract to s16 + vmovl.u8 q8, d24 + vmovl.u8 q9, d25 + vmovl.u8 q10, d26 + vmovl.u8 q11, d27 + vtrn.32 d28, d29 ; only the first half is populated + vmovl.u8 q12, d28 + vmovl.u8 q13, d30 + + ; src[] * filter_x + MULTIPLY_BY_Q0 q1, d16, d18, d20, d22, d17, d19, d21, d23 + MULTIPLY_BY_Q0 q2, d18, d20, d22, d17, d19, d21, d23, d24 + MULTIPLY_BY_Q0 q14, d20, d22, d17, d19, d21, d23, d24, d25 + MULTIPLY_BY_Q0 q15, d22, d17, d19, d21, d23, d24, d25, d26 + + ; += 64 >> 7 + vqrshrun.s32 d2, q1, #7 + vqrshrun.s32 d3, q2, #7 + vqrshrun.s32 d4, q14, #7 + vqrshrun.s32 d5, q15, #7 + + ; saturate + vqshrn.u16 d2, q1, #0 + vqshrn.u16 d3, q2, #0 + + ; transpose + vtrn.16 d2, d3 + vtrn.32 d2, d3 + vtrn.8 d2, d3 + + vst1.u32 {d2[0]}, [r2], r3 + vst1.u32 {d3[0]}, [r2], r3 + vst1.u32 {d2[1]}, [r2], r3 + vst1.u32 {d3[1]}, [r2], r4 + + subs r6, r6, #4 ; w -= 4 + bgt loop_horiz + + ; outer loop + mov r6, r10 ; restore w counter + add r0, r0, r1 ; src += src_stride * 4 - w + add r2, r2, r12 ; dst += dst_stride * 4 - w + subs r7, r7, #4 ; h -= 4 + bgt loop_horiz + + pop {r4-r10, pc} + +call_horiz_c_convolve + pop {r4-r10, lr} + add r0, r0, #3 ; un-adjust for taps + b vp9_convolve8_horiz_c + + + ENDP + +|vp9_convolve8_vert_neon| PROC + push {r4-r10, lr} + + ; adjust for taps + sub r0, r0, r1 + sub r0, r0, r1, lsl #1 + + ldr r6, [sp, #44] ; y_step_q4 + ldr r7, [sp, #40] ; filter_y + cmp r6, #16 + bne call_vert_c_convolve ; y_step_q4 != 16 + + ldr r8, [sp, #48] ; w + ldr r9, [sp, #52] ; h + + vld1.s16 {q0}, [r7] ; filter_y + + mov r5, r1, lsl #1 ; src_stride * 2 + add r5, r5, r1, lsl #3 ; src_stride * 10 + sub r5, r5, #4 ; src_stride * 10 + 4 + rsb r5, r5, #0 ; reset for src + + add r6, r3, r3, lsl #1 ; dst_stride * 3 + sub r6, r6, #4 ; dst_stride * 3 - 4 + rsb r6, r6, #0 ; reset for dst + + rsb r7, r8, r1, lsl #2 ; reset src for outer loop + rsb r12, r8, r3, lsl #2 ; reset dst for outer loop + + mov r10, r8 ; w loop counter + +loop_vert + ; always process a 4x4 block at a time + vld1.u32 {d16[0]}, [r0], r1 + vld1.u32 {d16[1]}, [r0], r1 + vld1.u32 {d18[0]}, [r0], r1 + vld1.u32 {d18[1]}, [r0], r1 + vld1.u32 {d20[0]}, [r0], r1 + vld1.u32 {d20[1]}, [r0], r1 + vld1.u32 {d22[0]}, [r0], r1 + vld1.u32 {d22[1]}, [r0], r1 + vld1.u32 {d24[0]}, [r0], r1 + vld1.u32 {d24[1]}, [r0], r1 + vld1.u32 {d26[0]}, [r0], r5 + + ; extract to s16 + vmovl.u8 q8, d16 + vmovl.u8 q9, d18 + vmovl.u8 q10, d20 + vmovl.u8 q11, d22 + vmovl.u8 q12, d24 + vmovl.u8 q13, d26 + + ; src[] * filter_y + MULTIPLY_BY_Q0 q1, d16, d17, d18, d19, d20, d21, d22, d23 + MULTIPLY_BY_Q0 q2, d17, d18, d19, d20, d21, d22, d23, d24 + MULTIPLY_BY_Q0 q14, d18, d19, d20, d21, d22, d23, d24, d25 + MULTIPLY_BY_Q0 q15, d19, d20, d21, d22, d23, d24, d25, d26 + + ; += 64 >> 7 + vqrshrun.s32 d2, q1, #7 + vqrshrun.s32 d3, q2, #7 + vqrshrun.s32 d4, q14, #7 + vqrshrun.s32 d5, q15, #7 + + ; saturate + vqshrn.u16 d2, q1, #0 + vqshrn.u16 d3, q2, #0 + + vst1.u32 {d2[0]}, [r2], r3 + vst1.u32 {d2[1]}, [r2], r3 + vst1.u32 {d3[0]}, [r2], r3 + vst1.u32 {d3[1]}, [r2], r6 + + subs r8, r8, #4 ; w -= 4 + bgt loop_vert + + ; outer loop + mov r8, r10 ; restore w counter + add r0, r0, r7 ; src += 4 * src_stride - w + add r2, r2, r12 ; dst += 4 * dst_stride - w + subs r9, r9, #4 ; h -= 4 + bgt loop_vert + + pop {r4-r10, pc} + +call_vert_c_convolve + pop {r4-r10, lr} + ; un-adjust for taps + add r0, r0, r1 + add r0, r0, r1, lsl #1 + b vp9_convolve8_vert_c + + ENDP + END diff --git a/vp9/common/arm/neon/vp9_dc_only_idct_add_neon.asm b/vp9/common/arm/neon/vp9_dc_only_idct_add_neon.asm new file mode 100644 index 000000000..60a0d98c5 --- /dev/null +++ b/vp9/common/arm/neon/vp9_dc_only_idct_add_neon.asm @@ -0,0 +1,69 @@ +; +; Copyright (c) 2013 The WebM project authors. All Rights Reserved. +; +; Use of this source code is governed by a BSD-style license and patent +; grant that can be found in the LICENSE file in the root of the source +; tree. All contributing project authors may be found in the AUTHORS +; file in the root of the source tree. +; + + + EXPORT |vp9_dc_only_idct_add_neon| + ARM + REQUIRE8 + PRESERVE8 + + AREA ||.text||, CODE, READONLY, ALIGN=2 + +;void vp9_dc_only_idct_add_neon(int input_dc, uint8_t *pred_ptr, +; uint8_t *dst_ptr, int pitch, int stride) +; +; r0 int input_dc +; r1 uint8_t *pred_ptr +; r2 uint8_t *dst_ptr +; r3 int pitch +; sp int stride + +|vp9_dc_only_idct_add_neon| PROC + + ; generate cospi_16_64 = 11585 + mov r12, #0x2d00 + add r12, #0x41 + + ; dct_const_round_shift(input_dc * cospi_16_64) + mul r0, r0, r12 ; input_dc * cospi_16_64 + add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1)) + asr r0, r0, #14 ; >> DCT_CONST_BITS + + ; dct_const_round_shift(out * cospi_16_64) + mul r0, r0, r12 ; out * cospi_16_64 + add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1)) + asr r0, r0, #14 ; >> DCT_CONST_BITS + + ; ROUND_POWER_OF_TWO(out, 4) + add r0, r0, #8 ; + (1 <<((4) - 1)) + asr r0, r0, #4 ; >> 4 + + vdup.16 q0, r0; ; duplicate a1 + ldr r12, [sp] ; load stride + + vld1.32 {d2[0]}, [r1], r3 + vld1.32 {d2[1]}, [r1], r3 + vld1.32 {d4[0]}, [r1], r3 + vld1.32 {d4[1]}, [r1] + + vaddw.u8 q1, q0, d2 ; a1 + pred_ptr[c] + vaddw.u8 q2, q0, d4 + + vqmovun.s16 d2, q1 ; clip_pixel + vqmovun.s16 d4, q2 + + vst1.32 {d2[0]}, [r2], r12 + vst1.32 {d2[1]}, [r2], r12 + vst1.32 {d4[0]}, [r2], r12 + vst1.32 {d4[1]}, [r2] + + bx lr + ENDP ; |vp9_dc_only_idct_add_neon| + + END diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h index 385dcc1d1..e67250b0f 100644 --- a/vp9/common/vp9_blockd.h +++ b/vp9/common/vp9_blockd.h @@ -13,18 +13,19 @@ #define VP9_COMMON_VP9_BLOCKD_H_ #include "./vpx_config.h" + +#include "vpx_ports/mem.h" #include "vpx_scale/yv12config.h" + +#include "vp9/common/vp9_common.h" +#include "vp9/common/vp9_common_data.h" #include "vp9/common/vp9_convolve.h" +#include "vp9/common/vp9_enums.h" #include "vp9/common/vp9_mv.h" +#include "vp9/common/vp9_seg_common.h" #include "vp9/common/vp9_treecoder.h" -#include "vpx_ports/mem.h" -#include "vp9/common/vp9_common.h" -#include "vp9/common/vp9_enums.h" -#include "vp9/common/vp9_common_data.h" #define BLOCK_SIZE_GROUPS 4 -#define MAX_MB_SEGMENTS 8 -#define MB_SEG_TREE_PROBS (MAX_MB_SEGMENTS-1) #define PREDICTION_PROBS 3 @@ -34,8 +35,6 @@ #define MAX_MODE_LF_DELTAS 2 /* Segment Feature Masks */ -#define SEGMENT_DELTADATA 0 -#define SEGMENT_ABSDATA 1 #define MAX_MV_REF_CANDIDATES 2 #define INTRA_INTER_CONTEXTS 4 @@ -94,15 +93,6 @@ static INLINE int is_inter_mode(MB_PREDICTION_MODE mode) { // Segment level features. typedef enum { - SEG_LVL_ALT_Q = 0, // Use alternate Quantizer .... - SEG_LVL_ALT_LF = 1, // Use alternate loop filter value... - SEG_LVL_REF_FRAME = 2, // Optional Segment reference frame - SEG_LVL_SKIP = 3, // Optional Segment (0,0) + skip mode - SEG_LVL_MAX = 4 // Number of MB level features supported -} SEG_LVL_FEATURES; - -// Segment level features. -typedef enum { TX_4X4 = 0, // 4x4 dct transform TX_8X8 = 1, // 8x8 dct transform TX_16X16 = 2, // 16x16 dct transform @@ -253,32 +243,12 @@ typedef struct macroblockd { int left_available; int right_available; + struct segmentation seg; + // partition contexts PARTITION_CONTEXT *above_seg_context; PARTITION_CONTEXT *left_seg_context; - /* 0 (disable) 1 (enable) segmentation */ - unsigned char segmentation_enabled; - - /* 0 (do not update) 1 (update) the macroblock segmentation map. */ - unsigned char update_mb_segmentation_map; - - /* 0 (do not update) 1 (update) the macroblock segmentation feature data. */ - unsigned char update_mb_segmentation_data; - - /* 0 (do not update) 1 (update) the macroblock segmentation feature data. */ - unsigned char mb_segment_abs_delta; - - /* Per frame flags that define which MB level features (such as quantizer or loop filter level) */ - /* are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO */ - - // Probability Tree used to code Segment number - vp9_prob mb_segment_tree_probs[MB_SEG_TREE_PROBS]; - - // Segment features - int16_t segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX]; - unsigned int segment_feature_mask[MAX_MB_SEGMENTS]; - /* mode_based Loop filter adjustment */ unsigned char mode_ref_lf_delta_enabled; unsigned char mode_ref_lf_delta_update; diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c index 1cdf1380d..0b5f2ea46 100644 --- a/vp9/common/vp9_entropymode.c +++ b/vp9/common/vp9_entropymode.c @@ -460,8 +460,8 @@ void vp9_setup_past_independence(VP9_COMMON *cm, MACROBLOCKD *xd) { // Reset the segment feature data to the default stats: // Features disabled, 0, with delta coding (Default state). int i; - vp9_clearall_segfeatures(xd); - xd->mb_segment_abs_delta = SEGMENT_DELTADATA; + vp9_clearall_segfeatures(&xd->seg); + xd->seg.abs_delta = SEGMENT_DELTADATA; if (cm->last_frame_seg_map) vpx_memset(cm->last_frame_seg_map, 0, (cm->mi_rows * cm->mi_cols)); diff --git a/vp9/common/vp9_entropymv.c b/vp9/common/vp9_entropymv.c index 50e8463f6..ed6af665e 100644 --- a/vp9/common/vp9_entropymv.c +++ b/vp9/common/vp9_entropymv.c @@ -56,7 +56,7 @@ const vp9_tree_index vp9_mv_fp_tree [2 * 4 - 2] = { }; struct vp9_token vp9_mv_fp_encodings[4]; -const nmv_context vp9_default_nmv_context = { +static const nmv_context default_nmv_context = { {32, 64, 96}, { { /* vert component */ @@ -360,5 +360,5 @@ void vp9_entropy_mv_init() { } void vp9_init_mv_probs(VP9_COMMON *cm) { - vpx_memcpy(&cm->fc.nmvc, &vp9_default_nmv_context, sizeof(nmv_context)); + cm->fc.nmvc = default_nmv_context; } diff --git a/vp9/common/vp9_entropymv.h b/vp9/common/vp9_entropymv.h index 15f9ada43..0df92d031 100644 --- a/vp9/common/vp9_entropymv.h +++ b/vp9/common/vp9_entropymv.h @@ -130,7 +130,6 @@ typedef struct { void vp9_inc_mv(const MV *mv, const MV *ref, nmv_context_counts *mvctx, int usehp); -extern const nmv_context vp9_default_nmv_context; void vp9_counts_process(nmv_context_counts *NMVcount, int usehp); diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c index 6dc622a96..37209a74b 100644 --- a/vp9/common/vp9_loopfilter.c +++ b/vp9/common/vp9_loopfilter.c @@ -92,9 +92,9 @@ void vp9_loop_filter_frame_init(VP9_COMMON *cm, MACROBLOCKD *xd, int lvl_seg = default_filt_lvl, ref, mode, intra_lvl; // Set the baseline filter values for each segment - if (vp9_segfeature_active(xd, seg, SEG_LVL_ALT_LF)) { - const int data = vp9_get_segdata(xd, seg, SEG_LVL_ALT_LF); - lvl_seg = xd->mb_segment_abs_delta == SEGMENT_ABSDATA + if (vp9_segfeature_active(&xd->seg, seg, SEG_LVL_ALT_LF)) { + const int data = vp9_get_segdata(&xd->seg, seg, SEG_LVL_ALT_LF); + lvl_seg = xd->seg.abs_delta == SEGMENT_ABSDATA ? data : clamp(default_filt_lvl + data, 0, MAX_LOOP_FILTER); } diff --git a/vp9/common/vp9_loopfilter.h b/vp9/common/vp9_loopfilter.h index 2582979f5..52d3b2d63 100644 --- a/vp9/common/vp9_loopfilter.h +++ b/vp9/common/vp9_loopfilter.h @@ -13,7 +13,9 @@ #include "vpx_ports/mem.h" #include "vpx_config.h" + #include "vp9/common/vp9_blockd.h" +#include "vp9/common/vp9_seg_common.h" #define MAX_LOOP_FILTER 63 #define MAX_SHARPNESS 7 diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index 7094e711d..b7025cac7 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -247,10 +247,6 @@ typedef struct VP9Common { [VP9_INTRA_MODES - 1]; vp9_prob kf_uv_mode_prob[VP9_INTRA_MODES] [VP9_INTRA_MODES - 1]; - // Context probabilities when using predictive coding of segment id - vp9_prob segment_pred_probs[PREDICTION_PROBS]; - unsigned char temporal_update; - // Context probabilities for reference frame prediction int allow_comp_inter_inter; MV_REFERENCE_FRAME comp_fixed_ref; diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h index 3ec1ff780..21a7d809e 100644 --- a/vp9/common/vp9_pred_common.h +++ b/vp9/common/vp9_pred_common.h @@ -32,7 +32,7 @@ static INLINE unsigned char vp9_get_pred_context_seg_id(const VP9_COMMON *cm, static INLINE vp9_prob vp9_get_pred_prob_seg_id(const VP9_COMMON *cm, const MACROBLOCKD *xd) { const int pred_context = vp9_get_pred_context_seg_id(cm, xd); - return cm->segment_pred_probs[pred_context]; + return xd->seg.pred_probs[pred_context]; } static INLINE unsigned char vp9_get_pred_flag_seg_id( const MACROBLOCKD * const xd) { diff --git a/vp9/common/vp9_quant_common.c b/vp9/common/vp9_quant_common.c index 295c8e738..2b81c2e28 100644 --- a/vp9/common/vp9_quant_common.c +++ b/vp9/common/vp9_quant_common.c @@ -57,9 +57,9 @@ int16_t vp9_ac_quant(int qindex, int delta) { int vp9_get_qindex(MACROBLOCKD *xd, int segment_id, int base_qindex) { - if (vp9_segfeature_active(xd, segment_id, SEG_LVL_ALT_Q)) { - const int data = vp9_get_segdata(xd, segment_id, SEG_LVL_ALT_Q); - return xd->mb_segment_abs_delta == SEGMENT_ABSDATA ? + if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_ALT_Q)) { + const int data = vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_ALT_Q); + return xd->seg.abs_delta == SEGMENT_ABSDATA ? data : // Abs value clamp(base_qindex + data, 0, MAXQ); // Delta value } else { diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh index 56a2284b5..95cf3acb8 100644 --- a/vp9/common/vp9_rtcd_defs.sh +++ b/vp9/common/vp9_rtcd_defs.sh @@ -274,10 +274,10 @@ prototype void vp9_convolve8 "const uint8_t *src, ptrdiff_t src_stride, uint8_t specialize vp9_convolve8 ssse3 prototype void vp9_convolve8_horiz "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h" -specialize vp9_convolve8_horiz ssse3 +specialize vp9_convolve8_horiz ssse3 neon prototype void vp9_convolve8_vert "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h" -specialize vp9_convolve8_vert ssse3 +specialize vp9_convolve8_vert ssse3 neon prototype void vp9_convolve8_avg "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h" specialize vp9_convolve8_avg ssse3 @@ -325,7 +325,7 @@ prototype void vp9_short_idct10_32x32_add "int16_t *input, uint8_t *dest, int de specialize vp9_short_idct10_32x32_add prototype void vp9_short_iht4x4_add "int16_t *input, uint8_t *dest, int dest_stride, int tx_type" -specialize vp9_short_iht4x4_add +specialize vp9_short_iht4x4_add sse2 prototype void vp9_short_iht8x8_add "int16_t *input, uint8_t *dest, int dest_stride, int tx_type" specialize vp9_short_iht8x8_add @@ -338,7 +338,7 @@ specialize vp9_idct4_1d sse2 # dct and add prototype void vp9_dc_only_idct_add "int input_dc, uint8_t *pred_ptr, uint8_t *dst_ptr, int pitch, int stride" -specialize vp9_dc_only_idct_add sse2 +specialize vp9_dc_only_idct_add sse2 neon prototype void vp9_short_iwalsh4x4_1_add "int16_t *input, uint8_t *dest, int dest_stride" specialize vp9_short_iwalsh4x4_1_add diff --git a/vp9/common/vp9_seg_common.c b/vp9/common/vp9_seg_common.c index 9bf207251..9b13b5b5f 100644 --- a/vp9/common/vp9_seg_common.c +++ b/vp9/common/vp9_seg_common.c @@ -9,8 +9,11 @@ */ #include <assert.h> + #include "vp9/common/vp9_blockd.h" +#include "vp9/common/vp9_loopfilter.h" #include "vp9/common/vp9_seg_common.h" +#include "vp9/common/vp9_quant_common.h" static const int seg_feature_data_signed[SEG_LVL_MAX] = { 1, 1, 0, 0 }; @@ -22,25 +25,25 @@ static const int seg_feature_data_max[SEG_LVL_MAX] = { // the coding mechanism is still subject to change so these provide a // convenient single point of change. -int vp9_segfeature_active(const MACROBLOCKD *xd, int segment_id, +int vp9_segfeature_active(const struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id) { - return xd->segmentation_enabled && - (xd->segment_feature_mask[segment_id] & (1 << feature_id)); + return seg->enabled && + (seg->feature_mask[segment_id] & (1 << feature_id)); } -void vp9_clearall_segfeatures(MACROBLOCKD *xd) { - vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data)); - vpx_memset(xd->segment_feature_mask, 0, sizeof(xd->segment_feature_mask)); +void vp9_clearall_segfeatures(struct segmentation *seg) { + vpx_memset(seg->feature_data, 0, sizeof(seg->feature_data)); + vpx_memset(seg->feature_mask, 0, sizeof(seg->feature_mask)); } -void vp9_enable_segfeature(MACROBLOCKD *xd, int segment_id, +void vp9_enable_segfeature(struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id) { - xd->segment_feature_mask[segment_id] |= 1 << feature_id; + seg->feature_mask[segment_id] |= 1 << feature_id; } -void vp9_disable_segfeature(MACROBLOCKD *xd, int segment_id, +void vp9_disable_segfeature(struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id) { - xd->segment_feature_mask[segment_id] &= ~(1 << feature_id); + seg->feature_mask[segment_id] &= ~(1 << feature_id); } int vp9_seg_feature_data_max(SEG_LVL_FEATURES feature_id) { @@ -51,12 +54,12 @@ int vp9_is_segfeature_signed(SEG_LVL_FEATURES feature_id) { return seg_feature_data_signed[feature_id]; } -void vp9_clear_segdata(MACROBLOCKD *xd, int segment_id, +void vp9_clear_segdata(struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id) { - xd->segment_feature_data[segment_id][feature_id] = 0; + seg->feature_data[segment_id][feature_id] = 0; } -void vp9_set_segdata(MACROBLOCKD *xd, int segment_id, +void vp9_set_segdata(struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id, int seg_data) { assert(seg_data <= seg_feature_data_max[feature_id]); if (seg_data < 0) { @@ -64,12 +67,12 @@ void vp9_set_segdata(MACROBLOCKD *xd, int segment_id, assert(-seg_data <= seg_feature_data_max[feature_id]); } - xd->segment_feature_data[segment_id][feature_id] = seg_data; + seg->feature_data[segment_id][feature_id] = seg_data; } -int vp9_get_segdata(const MACROBLOCKD *xd, int segment_id, +int vp9_get_segdata(const struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id) { - return xd->segment_feature_data[segment_id][feature_id]; + return seg->feature_data[segment_id][feature_id]; } diff --git a/vp9/common/vp9_seg_common.h b/vp9/common/vp9_seg_common.h index 74ba03c3e..f072a518d 100644 --- a/vp9/common/vp9_seg_common.h +++ b/vp9/common/vp9_seg_common.h @@ -8,23 +8,54 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "vp9/common/vp9_onyxc_int.h" -#include "vp9/common/vp9_blockd.h" - #ifndef VP9_COMMON_VP9_SEG_COMMON_H_ #define VP9_COMMON_VP9_SEG_COMMON_H_ -int vp9_segfeature_active(const MACROBLOCKD *xd, +#include "vp9/common/vp9_treecoder.h" + +#define SEGMENT_DELTADATA 0 +#define SEGMENT_ABSDATA 1 + +#define MAX_MB_SEGMENTS 8 +#define MB_SEG_TREE_PROBS (MAX_MB_SEGMENTS-1) + +#define PREDICTION_PROBS 3 + +// Segment level features. +typedef enum { + SEG_LVL_ALT_Q = 0, // Use alternate Quantizer .... + SEG_LVL_ALT_LF = 1, // Use alternate loop filter value... + SEG_LVL_REF_FRAME = 2, // Optional Segment reference frame + SEG_LVL_SKIP = 3, // Optional Segment (0,0) + skip mode + SEG_LVL_MAX = 4 // Number of MB level features supported +} SEG_LVL_FEATURES; + + +struct segmentation { + uint8_t enabled; + uint8_t update_map; + uint8_t update_data; + uint8_t abs_delta; + uint8_t temporal_update; + + vp9_prob tree_probs[MB_SEG_TREE_PROBS]; + vp9_prob pred_probs[PREDICTION_PROBS]; + + int16_t feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX]; + unsigned int feature_mask[MAX_MB_SEGMENTS]; +}; + +int vp9_segfeature_active(const struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id); -void vp9_clearall_segfeatures(MACROBLOCKD *xd); +void vp9_clearall_segfeatures(struct segmentation *seg); -void vp9_enable_segfeature(MACROBLOCKD *xd, +void vp9_enable_segfeature(struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id); -void vp9_disable_segfeature(MACROBLOCKD *xd, +void vp9_disable_segfeature(struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id); @@ -32,16 +63,16 @@ int vp9_seg_feature_data_max(SEG_LVL_FEATURES feature_id); int vp9_is_segfeature_signed(SEG_LVL_FEATURES feature_id); -void vp9_clear_segdata(MACROBLOCKD *xd, +void vp9_clear_segdata(struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id); -void vp9_set_segdata(MACROBLOCKD *xd, +void vp9_set_segdata(struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id, int seg_data); -int vp9_get_segdata(const MACROBLOCKD *xd, +int vp9_get_segdata(const struct segmentation *seg, int segment_id, SEG_LVL_FEATURES feature_id); diff --git a/vp9/common/x86/vp9_asm_stubs.c b/vp9/common/x86/vp9_asm_stubs.c index 98fc4dc83..3f1c19828 100644 --- a/vp9/common/x86/vp9_asm_stubs.c +++ b/vp9/common/x86/vp9_asm_stubs.c @@ -126,6 +126,7 @@ void vp9_convolve8_horiz_ssse3(const uint8_t *src, ptrdiff_t src_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h) { + /* Ensure the filter can be compressed to int16_t. */ if (x_step_q4 == 16 && filter_x[3] != 128) { while (w >= 16) { vp9_filter_block1d16_h8_ssse3(src, src_stride, diff --git a/vp9/common/x86/vp9_idct_intrin_sse2.c b/vp9/common/x86/vp9_idct_intrin_sse2.c index 599dcff93..4495b15ed 100644 --- a/vp9/common/x86/vp9_idct_intrin_sse2.c +++ b/vp9/common/x86/vp9_idct_intrin_sse2.c @@ -241,6 +241,155 @@ void vp9_idct4_1d_sse2(int16_t *input, int16_t *output) { _mm_storel_epi64((__m128i *)output, in); } +static INLINE void transpose_4x4(__m128i *res) { + const __m128i tr0_0 = _mm_unpacklo_epi16(res[0], res[1]); + const __m128i tr0_1 = _mm_unpacklo_epi16(res[2], res[3]); + res[0] = _mm_unpacklo_epi32(tr0_0, tr0_1); + res[2] = _mm_unpackhi_epi32(tr0_0, tr0_1); + + res[1] = _mm_unpackhi_epi64(res[0], res[0]); + res[3] = _mm_unpackhi_epi64(res[2], res[2]); +} + +void idct4_1d_sse2(__m128i *in) { + const __m128i k__cospi_p16_p16 = pair_set_epi16(cospi_16_64, cospi_16_64); + const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64); + const __m128i k__cospi_p24_m08 = pair_set_epi16(cospi_24_64, -cospi_8_64); + const __m128i k__cospi_p08_p24 = pair_set_epi16(cospi_8_64, cospi_24_64); + const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING); + __m128i u[8], v[8]; + + transpose_4x4(in); + // stage 1 + u[0] = _mm_unpacklo_epi16(in[0], in[2]); + u[1] = _mm_unpacklo_epi16(in[1], in[3]); + v[0] = _mm_madd_epi16(u[0], k__cospi_p16_p16); + v[1] = _mm_madd_epi16(u[0], k__cospi_p16_m16); + v[2] = _mm_madd_epi16(u[1], k__cospi_p24_m08); + v[3] = _mm_madd_epi16(u[1], k__cospi_p08_p24); + + u[0] = _mm_add_epi32(v[0], k__DCT_CONST_ROUNDING); + u[1] = _mm_add_epi32(v[1], k__DCT_CONST_ROUNDING); + u[2] = _mm_add_epi32(v[2], k__DCT_CONST_ROUNDING); + u[3] = _mm_add_epi32(v[3], k__DCT_CONST_ROUNDING); + + v[0] = _mm_srai_epi32(u[0], DCT_CONST_BITS); + v[1] = _mm_srai_epi32(u[1], DCT_CONST_BITS); + v[2] = _mm_srai_epi32(u[2], DCT_CONST_BITS); + v[3] = _mm_srai_epi32(u[3], DCT_CONST_BITS); + + u[0] = _mm_packs_epi32(v[0], v[2]); + u[1] = _mm_packs_epi32(v[1], v[3]); + u[2] = _mm_unpackhi_epi64(u[0], u[0]); + u[3] = _mm_unpackhi_epi64(u[1], u[1]); + + // stage 2 + in[0] = _mm_add_epi16(u[0], u[3]); + in[1] = _mm_add_epi16(u[1], u[2]); + in[2] = _mm_sub_epi16(u[1], u[2]); + in[3] = _mm_sub_epi16(u[0], u[3]); +} + +void iadst4_1d_sse2(__m128i *in) { + const __m128i k__sinpi_p01_p04 = pair_set_epi16(sinpi_1_9, sinpi_4_9); + const __m128i k__sinpi_p03_p02 = pair_set_epi16(sinpi_3_9, sinpi_2_9); + const __m128i k__sinpi_p02_m01 = pair_set_epi16(sinpi_2_9, -sinpi_1_9); + const __m128i k__sinpi_p03_m04 = pair_set_epi16(sinpi_3_9, -sinpi_4_9); + const __m128i k__sinpi_p03_p03 = _mm_set1_epi16(sinpi_3_9); + const __m128i kZero = _mm_set1_epi16(0); + const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING); + __m128i u[8], v[8], in7; + + transpose_4x4(in); + in7 = _mm_add_epi16(in[0], in[3]); + in7 = _mm_sub_epi16(in7, in[2]); + + u[0] = _mm_unpacklo_epi16(in[0], in[2]); + u[1] = _mm_unpacklo_epi16(in[1], in[3]); + u[2] = _mm_unpacklo_epi16(in7, kZero); + u[3] = _mm_unpacklo_epi16(in[1], kZero); + + v[0] = _mm_madd_epi16(u[0], k__sinpi_p01_p04); // s0 + s3 + v[1] = _mm_madd_epi16(u[1], k__sinpi_p03_p02); // s2 + s5 + v[2] = _mm_madd_epi16(u[2], k__sinpi_p03_p03); // x2 + v[3] = _mm_madd_epi16(u[0], k__sinpi_p02_m01); // s1 - s4 + v[4] = _mm_madd_epi16(u[1], k__sinpi_p03_m04); // s2 - s6 + v[5] = _mm_madd_epi16(u[3], k__sinpi_p03_p03); // s2 + + u[0] = _mm_add_epi32(v[0], v[1]); + u[1] = _mm_add_epi32(v[3], v[4]); + u[2] = v[2]; + u[3] = _mm_add_epi32(u[0], u[1]); + u[4] = _mm_slli_epi32(v[5], 2); + u[5] = _mm_add_epi32(u[3], v[5]); + u[6] = _mm_sub_epi32(u[5], u[4]); + + v[0] = _mm_add_epi32(u[0], k__DCT_CONST_ROUNDING); + v[1] = _mm_add_epi32(u[1], k__DCT_CONST_ROUNDING); + v[2] = _mm_add_epi32(u[2], k__DCT_CONST_ROUNDING); + v[3] = _mm_add_epi32(u[6], k__DCT_CONST_ROUNDING); + + u[0] = _mm_srai_epi32(v[0], DCT_CONST_BITS); + u[1] = _mm_srai_epi32(v[1], DCT_CONST_BITS); + u[2] = _mm_srai_epi32(v[2], DCT_CONST_BITS); + u[3] = _mm_srai_epi32(v[3], DCT_CONST_BITS); + + in[0] = _mm_packs_epi32(u[0], u[2]); + in[1] = _mm_packs_epi32(u[1], u[3]); + in[2] = _mm_unpackhi_epi64(in[0], in[0]); + in[3] = _mm_unpackhi_epi64(in[1], in[1]); +} + +void vp9_short_iht4x4_add_sse2(int16_t *input, uint8_t *dest, int stride, + int tx_type) { + __m128i in[4]; + const __m128i zero = _mm_setzero_si128(); + const __m128i eight = _mm_set1_epi16(8); + + in[0] = _mm_loadl_epi64((__m128i *)input); + in[1] = _mm_loadl_epi64((__m128i *)(input + 4)); + in[2] = _mm_loadl_epi64((__m128i *)(input + 8)); + in[3] = _mm_loadl_epi64((__m128i *)(input + 12)); + + switch (tx_type) { + case 0: // DCT_DCT + idct4_1d_sse2(in); + idct4_1d_sse2(in); + break; + case 1: // ADST_DCT + idct4_1d_sse2(in); + iadst4_1d_sse2(in); + break; + case 2: // DCT_ADST + iadst4_1d_sse2(in); + idct4_1d_sse2(in); + break; + case 3: // ADST_ADST + iadst4_1d_sse2(in); + iadst4_1d_sse2(in); + break; + default: + assert(0); + break; + } + + // Final round and shift + in[0] = _mm_add_epi16(in[0], eight); + in[1] = _mm_add_epi16(in[1], eight); + in[2] = _mm_add_epi16(in[2], eight); + in[3] = _mm_add_epi16(in[3], eight); + + in[0] = _mm_srai_epi16(in[0], 4); + in[1] = _mm_srai_epi16(in[1], 4); + in[2] = _mm_srai_epi16(in[2], 4); + in[3] = _mm_srai_epi16(in[3], 4); + + RECON_AND_STORE4X4(dest, in[0]); + RECON_AND_STORE4X4(dest, in[1]); + RECON_AND_STORE4X4(dest, in[2]); + RECON_AND_STORE4X4(dest, in[3]); +} + #define TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7, \ out0, out1, out2, out3, out4, out5, out6, out7) \ { \ diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index 369505c2f..3fc62c365 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -44,8 +44,8 @@ static MB_PREDICTION_MODE read_inter_mode(vp9_reader *r, const vp9_prob *p) { return (MB_PREDICTION_MODE)treed_read(r, vp9_sb_mv_ref_tree, p); } -static int read_segment_id(vp9_reader *r, MACROBLOCKD *xd) { - return treed_read(r, vp9_segment_tree, xd->mb_segment_tree_probs); +static int read_segment_id(vp9_reader *r, const struct segmentation *seg) { + return treed_read(r, vp9_segment_tree, seg->tree_probs); } static TX_SIZE read_selected_txfm_size(VP9_COMMON *cm, MACROBLOCKD *xd, @@ -105,13 +105,13 @@ static void set_segment_id(VP9_COMMON *cm, BLOCK_SIZE_TYPE bsize, static int read_intra_segment_id(VP9D_COMP *pbi, int mi_row, int mi_col, vp9_reader *r) { - VP9_COMMON *const cm = &pbi->common; MACROBLOCKD *const xd = &pbi->mb; + struct segmentation *const seg = &xd->seg; const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type; - if (xd->segmentation_enabled && xd->update_mb_segmentation_map) { - const int segment_id = read_segment_id(r, xd); - set_segment_id(cm, bsize, mi_row, mi_col, segment_id); + if (seg->enabled && seg->update_map) { + const int segment_id = read_segment_id(r, seg); + set_segment_id(&pbi->common, bsize, mi_row, mi_col, segment_id); return segment_id; } else { return 0; @@ -121,7 +121,7 @@ static int read_intra_segment_id(VP9D_COMP *pbi, int mi_row, int mi_col, static uint8_t read_skip_coeff(VP9D_COMP *pbi, int segment_id, vp9_reader *r) { VP9_COMMON *const cm = &pbi->common; MACROBLOCKD *const xd = &pbi->mb; - int skip_coeff = vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP); + int skip_coeff = vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP); if (!skip_coeff) { const uint8_t ctx = vp9_get_pred_context_mbskip(cm, xd); skip_coeff = vp9_read(r, vp9_get_pred_prob_mbskip(cm, xd)); @@ -290,8 +290,8 @@ static void read_ref_frame(VP9D_COMP *pbi, vp9_reader *r, MACROBLOCKD *const xd = &pbi->mb; FRAME_CONTEXT *const fc = &cm->fc; - if (vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME)) { - ref_frame[0] = vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME); + if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME)) { + ref_frame[0] = vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_REF_FRAME); ref_frame[1] = NONE; } else { const int comp_ctx = vp9_get_pred_context_comp_inter_inter(cm, xd); @@ -366,26 +366,28 @@ static int read_inter_segment_id(VP9D_COMP *pbi, int mi_row, int mi_col, vp9_reader *r) { VP9_COMMON *const cm = &pbi->common; MACROBLOCKD *const xd = &pbi->mb; + struct segmentation *const seg = &xd->seg; const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type; int pred_segment_id; int segment_id; - if (!xd->segmentation_enabled) + if (!seg->enabled) return 0; // Default for disabled segmentation pred_segment_id = vp9_get_segment_id(cm, cm->last_frame_seg_map, - bsize, mi_row, mi_col); - if (!xd->update_mb_segmentation_map) + bsize, mi_row, mi_col); + if (!seg->update_map) return pred_segment_id; - if (cm->temporal_update) { + + if (seg->temporal_update) { const vp9_prob pred_prob = vp9_get_pred_prob_seg_id(cm, xd); const int pred_flag = vp9_read(r, pred_prob); vp9_set_pred_flag_seg_id(xd, bsize, pred_flag); segment_id = pred_flag ? pred_segment_id - : read_segment_id(r, xd); + : read_segment_id(r, seg); } else { - segment_id = read_segment_id(r, xd); + segment_id = read_segment_id(r, seg); } set_segment_id(cm, bsize, mi_row, mi_col, segment_id); return segment_id; @@ -455,14 +457,14 @@ static MV_REFERENCE_FRAME read_reference_frame(VP9D_COMP *pbi, int segment_id, MACROBLOCKD *const xd = &pbi->mb; MV_REFERENCE_FRAME ref; - if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME)) { + if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME)) { const int ctx = vp9_get_pred_context_intra_inter(cm, xd); ref = (MV_REFERENCE_FRAME) vp9_read(r, vp9_get_pred_prob_intra_inter(cm, xd)); cm->fc.intra_inter_count[ctx][ref != INTRA_FRAME]++; } else { - ref = (MV_REFERENCE_FRAME) - vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME) != INTRA_FRAME; + ref = (MV_REFERENCE_FRAME) vp9_get_segdata(&xd->seg, segment_id, + SEG_LVL_REF_FRAME) != INTRA_FRAME; } return ref; } @@ -515,7 +517,7 @@ static void read_inter_mode_info(VP9D_COMP *pbi, MODE_INFO *mi, mv_ref_p = cm->fc.inter_mode_probs[mbmi->mb_mode_context[ref0]]; - if (vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP)) { + if (vp9_segfeature_active(&xd->seg, mbmi->segment_id, SEG_LVL_SKIP)) { mbmi->mode = ZEROMV; } else if (bsize >= BLOCK_SIZE_SB8X8) { mbmi->mode = read_inter_mode(r, mv_ref_p); diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 37bdad29d..48be06946 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -174,7 +174,7 @@ static int decode_tokens(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize, vp9_reader *r) { vp9_reset_sb_tokens_context(xd, bsize); return -1; } else { - if (xd->segmentation_enabled) + if (xd->seg.enabled) mb_init_dequantizer(&pbi->common, xd); // TODO(dkovalev) if (!vp9_reader_has_error(r)) @@ -395,55 +395,53 @@ static void read_coef_probs(FRAME_CONTEXT *fc, TXFM_MODE txfm_mode, read_coef_probs_common(fc, TX_32X32, r); } -static void setup_segmentation(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) { +static void setup_segmentation(struct segmentation *seg, + struct vp9_read_bit_buffer *rb) { int i, j; - VP9_COMMON *const cm = &pbi->common; - MACROBLOCKD *const xd = &pbi->mb; - - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 0; + seg->update_map = 0; + seg->update_data = 0; - xd->segmentation_enabled = vp9_rb_read_bit(rb); - if (!xd->segmentation_enabled) + seg->enabled = vp9_rb_read_bit(rb); + if (!seg->enabled) return; // Segmentation map update - xd->update_mb_segmentation_map = vp9_rb_read_bit(rb); - if (xd->update_mb_segmentation_map) { + seg->update_map = vp9_rb_read_bit(rb); + if (seg->update_map) { for (i = 0; i < MB_SEG_TREE_PROBS; i++) - xd->mb_segment_tree_probs[i] = vp9_rb_read_bit(rb) ? - vp9_rb_read_literal(rb, 8) : MAX_PROB; + seg->tree_probs[i] = vp9_rb_read_bit(rb) ? vp9_rb_read_literal(rb, 8) + : MAX_PROB; - cm->temporal_update = vp9_rb_read_bit(rb); - if (cm->temporal_update) { + seg->temporal_update = vp9_rb_read_bit(rb); + if (seg->temporal_update) { for (i = 0; i < PREDICTION_PROBS; i++) - cm->segment_pred_probs[i] = vp9_rb_read_bit(rb) ? - vp9_rb_read_literal(rb, 8) : MAX_PROB; + seg->pred_probs[i] = vp9_rb_read_bit(rb) ? vp9_rb_read_literal(rb, 8) + : MAX_PROB; } else { for (i = 0; i < PREDICTION_PROBS; i++) - cm->segment_pred_probs[i] = MAX_PROB; + seg->pred_probs[i] = MAX_PROB; } } // Segmentation data update - xd->update_mb_segmentation_data = vp9_rb_read_bit(rb); - if (xd->update_mb_segmentation_data) { - xd->mb_segment_abs_delta = vp9_rb_read_bit(rb); + seg->update_data = vp9_rb_read_bit(rb); + if (seg->update_data) { + seg->abs_delta = vp9_rb_read_bit(rb); - vp9_clearall_segfeatures(xd); + vp9_clearall_segfeatures(seg); for (i = 0; i < MAX_MB_SEGMENTS; i++) { for (j = 0; j < SEG_LVL_MAX; j++) { int data = 0; const int feature_enabled = vp9_rb_read_bit(rb); if (feature_enabled) { - vp9_enable_segfeature(xd, i, j); + vp9_enable_segfeature(seg, i, j); data = decode_unsigned_max(rb, vp9_seg_feature_data_max(j)); if (vp9_is_segfeature_signed(j)) data = vp9_rb_read_bit(rb) ? -data : data; } - vp9_set_segdata(xd, i, j, data); + vp9_set_segdata(seg, i, j, data); } } } @@ -902,7 +900,7 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, setup_loopfilter(pbi, rb); setup_quantization(pbi, rb); - setup_segmentation(pbi, rb); + setup_segmentation(&pbi->mb.seg, rb); setup_tile_info(cm, rb); diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c index 76889c477..3a4fae065 100644 --- a/vp9/decoder/vp9_detokenize.c +++ b/vp9/decoder/vp9_detokenize.c @@ -278,8 +278,8 @@ SKIP_START: return c; } -static int get_eob(MACROBLOCKD* const xd, int segment_id, int eob_max) { - return vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP) ? 0 : eob_max; +static int get_eob(struct segmentation *seg, int segment_id, int eob_max) { + return vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max; } struct decode_block_args { @@ -300,7 +300,7 @@ static void decode_block(int plane, int block, struct macroblockd_plane* pd = &xd->plane[plane]; const int segment_id = xd->mode_info_context->mbmi.segment_id; const TX_SIZE ss_tx_size = ss_txfrm_size / 2; - const int seg_eob = get_eob(xd, segment_id, 16 << ss_txfrm_size); + const int seg_eob = get_eob(&xd->seg, segment_id, 16 << ss_txfrm_size); const int off = block >> ss_txfrm_size; const int mod = bw - ss_tx_size - pd->subsampling_x; const int aoff = (off & ((1 << mod) - 1)) << ss_tx_size; diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 3a2990cf3..adeff102f 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -216,7 +216,7 @@ static void write_selected_txfm_size(const VP9_COMP *cpi, TX_SIZE tx_size, static int write_skip_coeff(const VP9_COMP *cpi, int segment_id, MODE_INFO *m, vp9_writer *w) { const MACROBLOCKD *const xd = &cpi->mb.e_mbd; - if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) { + if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)) { return 1; } else { const int skip_coeff = m->mbmi.mb_skip_coeff; @@ -348,18 +348,18 @@ static void pack_mb_tokens(vp9_writer* const bc, *tp = p; } -static void write_sb_mv_ref(vp9_writer *w, MB_PREDICTION_MODE m, +static void write_sb_mv_ref(vp9_writer *w, MB_PREDICTION_MODE mode, const vp9_prob *p) { - assert(NEARESTMV <= m && m <= NEWMV); + assert(is_inter_mode(mode)); write_token(w, vp9_sb_mv_ref_tree, p, - vp9_sb_mv_ref_encoding_array - NEARESTMV + m); + &vp9_sb_mv_ref_encoding_array[mode - NEARESTMV]); } -static void write_segment_id(vp9_writer *w, const MACROBLOCKD *xd, +static void write_segment_id(vp9_writer *w, const struct segmentation *seg, int segment_id) { - if (xd->segmentation_enabled && xd->update_mb_segmentation_map) - treed_write(w, vp9_segment_tree, xd->mb_segment_tree_probs, segment_id, 3); + if (seg->enabled && seg->update_map) + treed_write(w, vp9_segment_tree, seg->tree_probs, segment_id, 3); } // This function encodes the reference frame @@ -369,7 +369,7 @@ static void encode_ref_frame(VP9_COMP *cpi, vp9_writer *bc) { MACROBLOCKD *const xd = &x->e_mbd; MB_MODE_INFO *mi = &xd->mode_info_context->mbmi; const int segment_id = mi->segment_id; - int seg_ref_active = vp9_segfeature_active(xd, segment_id, + int seg_ref_active = vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME); // If segment level coding of this signal is disabled... // or the segment allows multiple reference frame options @@ -396,7 +396,7 @@ static void encode_ref_frame(VP9_COMP *cpi, vp9_writer *bc) { } } else { assert(mi->ref_frame[1] <= INTRA_FRAME); - assert(vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME) == + assert(vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_REF_FRAME) == mi->ref_frame[0]); } @@ -410,6 +410,7 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m, const nmv_context *nmvc = &pc->fc.nmvc; MACROBLOCK *const x = &cpi->mb; MACROBLOCKD *const xd = &x->e_mbd; + struct segmentation *seg = &xd->seg; MB_MODE_INFO *const mi = &m->mbmi; const MV_REFERENCE_FRAME rf = mi->ref_frame[0]; const MB_PREDICTION_MODE mode = mi->mode; @@ -423,33 +424,27 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m, active_section = 9; #endif - if (cpi->mb.e_mbd.update_mb_segmentation_map) { - // Is temporal coding of the segment map enabled - if (pc->temporal_update) { + if (seg->update_map) { + if (seg->temporal_update) { unsigned char prediction_flag = vp9_get_pred_flag_seg_id(xd); vp9_prob pred_prob = vp9_get_pred_prob_seg_id(pc, xd); - - // Code the segment id prediction flag for this mb vp9_write(bc, prediction_flag, pred_prob); - - // If the mb segment id wasn't predicted code explicitly if (!prediction_flag) - write_segment_id(bc, xd, mi->segment_id); + write_segment_id(bc, seg, mi->segment_id); } else { - // Normal unpredicted coding - write_segment_id(bc, xd, mi->segment_id); + write_segment_id(bc, seg, mi->segment_id); } } skip_coeff = write_skip_coeff(cpi, segment_id, m, bc); - if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME)) + if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) vp9_write(bc, rf != INTRA_FRAME, vp9_get_pred_prob_intra_inter(pc, xd)); if (mi->sb_type >= BLOCK_SIZE_SB8X8 && pc->txfm_mode == TX_MODE_SELECT && !(rf != INTRA_FRAME && - (skip_coeff || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) { + (skip_coeff || vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)))) { write_selected_txfm_size(cpi, mi->txfm_size, mi->sb_type, bc); } @@ -484,7 +479,7 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m, #endif // If segment skip is not enabled code the mode. - if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) { + if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { if (mi->sb_type >= BLOCK_SIZE_SB8X8) { write_sb_mv_ref(bc, mode, mv_ref_p); vp9_accum_mv_refs(&cpi->common, mode, mi->mb_mode_context[rf]); @@ -554,8 +549,8 @@ static void write_mb_modes_kf(const VP9_COMP *cpi, const int mis = c->mode_info_stride; const int segment_id = m->mbmi.segment_id; - if (xd->update_mb_segmentation_map) - write_segment_id(bc, xd, m->mbmi.segment_id); + if (xd->seg.update_map) + write_segment_id(bc, &xd->seg, m->mbmi.segment_id); write_skip_coeff(cpi, segment_id, m, bc); @@ -1002,23 +997,23 @@ static void encode_quantization(VP9_COMMON *cm, static void encode_segmentation(VP9_COMP *cpi, - struct vp9_write_bit_buffer *wb) { + struct vp9_write_bit_buffer *wb) { int i, j; - VP9_COMMON *const cm = &cpi->common; - MACROBLOCKD *const xd = &cpi->mb.e_mbd; - vp9_wb_write_bit(wb, xd->segmentation_enabled); - if (!xd->segmentation_enabled) + struct segmentation *seg = &cpi->mb.e_mbd.seg; + + vp9_wb_write_bit(wb, seg->enabled); + if (!seg->enabled) return; // Segmentation map - vp9_wb_write_bit(wb, xd->update_mb_segmentation_map); - if (xd->update_mb_segmentation_map) { + vp9_wb_write_bit(wb, seg->update_map); + if (seg->update_map) { // Select the coding strategy (temporal or spatial) vp9_choose_segmap_coding_method(cpi); // Write out probabilities used to decode unpredicted macro-block segments for (i = 0; i < MB_SEG_TREE_PROBS; i++) { - const int prob = xd->mb_segment_tree_probs[i]; + const int prob = seg->tree_probs[i]; const int update = prob != MAX_PROB; vp9_wb_write_bit(wb, update); if (update) @@ -1026,10 +1021,10 @@ static void encode_segmentation(VP9_COMP *cpi, } // Write out the chosen coding method. - vp9_wb_write_bit(wb, cm->temporal_update); - if (cm->temporal_update) { + vp9_wb_write_bit(wb, seg->temporal_update); + if (seg->temporal_update) { for (i = 0; i < PREDICTION_PROBS; i++) { - const int prob = cm->segment_pred_probs[i]; + const int prob = seg->pred_probs[i]; const int update = prob != MAX_PROB; vp9_wb_write_bit(wb, update); if (update) @@ -1039,16 +1034,16 @@ static void encode_segmentation(VP9_COMP *cpi, } // Segmentation data - vp9_wb_write_bit(wb, xd->update_mb_segmentation_data); - if (xd->update_mb_segmentation_data) { - vp9_wb_write_bit(wb, xd->mb_segment_abs_delta); + vp9_wb_write_bit(wb, seg->update_data); + if (seg->update_data) { + vp9_wb_write_bit(wb, seg->abs_delta); for (i = 0; i < MAX_MB_SEGMENTS; i++) { for (j = 0; j < SEG_LVL_MAX; j++) { - const int active = vp9_segfeature_active(xd, i, j); + const int active = vp9_segfeature_active(seg, i, j); vp9_wb_write_bit(wb, active); if (active) { - const int data = vp9_get_segdata(xd, i, j); + const int data = vp9_get_segdata(seg, i, j); const int data_max = vp9_seg_feature_data_max(j); if (vp9_is_segfeature_signed(j)) { @@ -1385,57 +1380,18 @@ static void write_uncompressed_header(VP9_COMP *cpi, write_tile_info(cm, wb); } -void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) { - int i, bytes_packed; - VP9_COMMON *const pc = &cpi->common; - vp9_writer header_bc; +static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) { + VP9_COMMON *const cm = &cpi->common; MACROBLOCKD *const xd = &cpi->mb.e_mbd; + FRAME_CONTEXT *const fc = &cm->fc; + vp9_writer header_bc; - uint8_t *cx_data = dest; - struct vp9_write_bit_buffer wb = {dest, 0}; - struct vp9_write_bit_buffer first_partition_size_wb; - - write_uncompressed_header(cpi, &wb); - first_partition_size_wb = wb; - vp9_wb_write_literal(&wb, 0, 16); // don't know in advance first part. size - - bytes_packed = vp9_rb_bytes_written(&wb); - cx_data += bytes_packed; - - vp9_compute_update_table(); - - vp9_start_encode(&header_bc, cx_data); + vp9_start_encode(&header_bc, data); -#ifdef ENTROPY_STATS - if (pc->frame_type == INTER_FRAME) - active_section = 0; + if (xd->lossless) + cm->txfm_mode = ONLY_4X4; else - active_section = 7; -#endif - - vp9_clear_system_state(); // __asm emms; - - vp9_copy(pc->fc.pre_coef_probs, pc->fc.coef_probs); - vp9_copy(pc->fc.pre_y_mode_prob, pc->fc.y_mode_prob); - vp9_copy(pc->fc.pre_uv_mode_prob, pc->fc.uv_mode_prob); - vp9_copy(pc->fc.pre_partition_prob, pc->fc.partition_prob[INTER_FRAME]); - pc->fc.pre_nmvc = pc->fc.nmvc; - vp9_copy(pc->fc.pre_switchable_interp_prob, pc->fc.switchable_interp_prob); - vp9_copy(pc->fc.pre_inter_mode_probs, pc->fc.inter_mode_probs); - vp9_copy(pc->fc.pre_intra_inter_prob, pc->fc.intra_inter_prob); - vp9_copy(pc->fc.pre_comp_inter_prob, pc->fc.comp_inter_prob); - vp9_copy(pc->fc.pre_comp_ref_prob, pc->fc.comp_ref_prob); - vp9_copy(pc->fc.pre_single_ref_prob, pc->fc.single_ref_prob); - vp9_copy(pc->fc.pre_tx_probs_8x8p, pc->fc.tx_probs_8x8p); - vp9_copy(pc->fc.pre_tx_probs_16x16p, pc->fc.tx_probs_16x16p); - vp9_copy(pc->fc.pre_tx_probs_32x32p, pc->fc.tx_probs_32x32p); - vp9_copy(pc->fc.pre_mbskip_probs, pc->fc.mbskip_probs); - - if (xd->lossless) { - pc->txfm_mode = ONLY_4X4; - } else { encode_txfm_probs(cpi, &header_bc); - } update_coef_probs(cpi, &header_bc); @@ -1445,80 +1401,123 @@ void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) { vp9_update_skip_probs(cpi, &header_bc); - if (pc->frame_type != KEY_FRAME) { + if (cm->frame_type != KEY_FRAME) { + int i; #ifdef ENTROPY_STATS active_section = 1; #endif - update_inter_mode_probs(pc, &header_bc); - vp9_zero(cpi->common.fc.inter_mode_counts); + update_inter_mode_probs(cm, &header_bc); + vp9_zero(fc->inter_mode_counts); - if (pc->mcomp_filter_type == SWITCHABLE) + if (cm->mcomp_filter_type == SWITCHABLE) update_switchable_interp_probs(cpi, &header_bc); for (i = 0; i < INTRA_INTER_CONTEXTS; i++) - vp9_cond_prob_diff_update(&header_bc, &pc->fc.intra_inter_prob[i], + vp9_cond_prob_diff_update(&header_bc, &fc->intra_inter_prob[i], VP9_MODE_UPDATE_PROB, cpi->intra_inter_count[i]); - if (pc->allow_comp_inter_inter) { + if (cm->allow_comp_inter_inter) { const int comp_pred_mode = cpi->common.comp_pred_mode; - const int use_compound_pred = (comp_pred_mode != SINGLE_PREDICTION_ONLY); - const int use_hybrid_pred = (comp_pred_mode == HYBRID_PREDICTION); + const int use_compound_pred = comp_pred_mode != SINGLE_PREDICTION_ONLY; + const int use_hybrid_pred = comp_pred_mode == HYBRID_PREDICTION; vp9_write_bit(&header_bc, use_compound_pred); if (use_compound_pred) { vp9_write_bit(&header_bc, use_hybrid_pred); - if (use_hybrid_pred) { + if (use_hybrid_pred) for (i = 0; i < COMP_INTER_CONTEXTS; i++) - vp9_cond_prob_diff_update(&header_bc, &pc->fc.comp_inter_prob[i], + vp9_cond_prob_diff_update(&header_bc, &fc->comp_inter_prob[i], VP9_MODE_UPDATE_PROB, cpi->comp_inter_count[i]); - } } } - if (pc->comp_pred_mode != COMP_PREDICTION_ONLY) { + if (cm->comp_pred_mode != COMP_PREDICTION_ONLY) { for (i = 0; i < REF_CONTEXTS; i++) { - vp9_cond_prob_diff_update(&header_bc, &pc->fc.single_ref_prob[i][0], + vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][0], VP9_MODE_UPDATE_PROB, cpi->single_ref_count[i][0]); - vp9_cond_prob_diff_update(&header_bc, &pc->fc.single_ref_prob[i][1], + vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][1], VP9_MODE_UPDATE_PROB, cpi->single_ref_count[i][1]); } } - if (pc->comp_pred_mode != SINGLE_PREDICTION_ONLY) { + if (cm->comp_pred_mode != SINGLE_PREDICTION_ONLY) for (i = 0; i < REF_CONTEXTS; i++) - vp9_cond_prob_diff_update(&header_bc, &pc->fc.comp_ref_prob[i], + vp9_cond_prob_diff_update(&header_bc, &fc->comp_ref_prob[i], VP9_MODE_UPDATE_PROB, cpi->comp_ref_count[i]); - } update_mbintra_mode_probs(cpi, &header_bc); for (i = 0; i < NUM_PARTITION_CONTEXTS; ++i) { - vp9_prob Pnew[PARTITION_TYPES - 1]; + vp9_prob pnew[PARTITION_TYPES - 1]; unsigned int bct[PARTITION_TYPES - 1][2]; update_mode(&header_bc, PARTITION_TYPES, vp9_partition_encodings, - vp9_partition_tree, Pnew, - pc->fc.partition_prob[pc->frame_type][i], bct, + vp9_partition_tree, pnew, + fc->partition_prob[cm->frame_type][i], bct, (unsigned int *)cpi->partition_count[i]); } vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc); } - vp9_stop_encode(&header_bc); + assert(header_bc.pos <= 0xffff); + return header_bc.pos; +} - // first partition size - assert(header_bc.pos <= 0xffff); - vp9_wb_write_literal(&first_partition_size_wb, header_bc.pos, 16); - *size = bytes_packed + header_bc.pos; - *size += encode_tiles(cpi, cx_data + header_bc.pos); +void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) { + FRAME_CONTEXT *const fc = &cpi->common.fc; + uint8_t *data = dest; + size_t first_part_size; + struct vp9_write_bit_buffer wb = {data, 0}; + struct vp9_write_bit_buffer saved_wb; + + write_uncompressed_header(cpi, &wb); + saved_wb = wb; + vp9_wb_write_literal(&wb, 0, 16); // don't know in advance first part. size + + data += vp9_rb_bytes_written(&wb); + + vp9_compute_update_table(); + +#ifdef ENTROPY_STATS + if (pc->frame_type == INTER_FRAME) + active_section = 0; + else + active_section = 7; +#endif + + vp9_clear_system_state(); // __asm emms; + + vp9_copy(fc->pre_coef_probs, fc->coef_probs); + vp9_copy(fc->pre_y_mode_prob, fc->y_mode_prob); + vp9_copy(fc->pre_uv_mode_prob, fc->uv_mode_prob); + vp9_copy(fc->pre_partition_prob, fc->partition_prob[INTER_FRAME]); + fc->pre_nmvc = fc->nmvc; + vp9_copy(fc->pre_switchable_interp_prob, fc->switchable_interp_prob); + vp9_copy(fc->pre_inter_mode_probs, fc->inter_mode_probs); + vp9_copy(fc->pre_intra_inter_prob, fc->intra_inter_prob); + vp9_copy(fc->pre_comp_inter_prob, fc->comp_inter_prob); + vp9_copy(fc->pre_comp_ref_prob, fc->comp_ref_prob); + vp9_copy(fc->pre_single_ref_prob, fc->single_ref_prob); + vp9_copy(fc->pre_tx_probs_8x8p, fc->tx_probs_8x8p); + vp9_copy(fc->pre_tx_probs_16x16p, fc->tx_probs_16x16p); + vp9_copy(fc->pre_tx_probs_32x32p, fc->tx_probs_32x32p); + vp9_copy(fc->pre_mbskip_probs, fc->mbskip_probs); + + first_part_size = write_compressed_header(cpi, data); + data += first_part_size; + vp9_wb_write_literal(&saved_wb, first_part_size, 16); + + data += encode_tiles(cpi, data); + + *size = data - dest; } #ifdef ENTROPY_STATS diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index adaf667c6..a3e116bbf 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -360,7 +360,7 @@ static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx, if (!output_enabled) return; - if (!vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP)) { + if (!vp9_segfeature_active(&xd->seg, mbmi->segment_id, SEG_LVL_SKIP)) { for (i = 0; i < NB_TXFM_MODES; i++) { cpi->rd_tx_select_diff[i] += ctx->txfm_rd_diff[i]; } @@ -512,16 +512,16 @@ static void set_offsets(VP9_COMP *cpi, int mi_row, int mi_col, x->rdmult = cpi->RDMULT; /* segment ID */ - if (xd->segmentation_enabled) { - uint8_t *map = xd->update_mb_segmentation_map ? cpi->segmentation_map - : cm->last_frame_seg_map; + if (xd->seg.enabled) { + uint8_t *map = xd->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); vp9_mb_init_quantizer(cpi, x); - if (xd->segmentation_enabled && cpi->seg0_cnt > 0 - && !vp9_segfeature_active(xd, 0, SEG_LVL_REF_FRAME) - && vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME)) { + if (xd->seg.enabled && cpi->seg0_cnt > 0 + && !vp9_segfeature_active(&xd->seg, 0, SEG_LVL_REF_FRAME) + && vp9_segfeature_active(&xd->seg, 1, SEG_LVL_REF_FRAME)) { cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt; } else { const int y = mb_row & ~3; @@ -541,11 +541,11 @@ static void set_offsets(VP9_COMP *cpi, int mi_row, int mi_col, } static void pick_sb_modes(VP9_COMP *cpi, int mi_row, int mi_col, - TOKENEXTRA **tp, int *totalrate, int64_t *totaldist, + int *totalrate, int64_t *totaldist, BLOCK_SIZE_TYPE bsize, PICK_MODE_CONTEXT *ctx) { - VP9_COMMON * const cm = &cpi->common; - MACROBLOCK * const x = &cpi->mb; - MACROBLOCKD * const xd = &x->e_mbd; + VP9_COMMON *const cm = &cpi->common; + MACROBLOCK *const x = &cpi->mb; + MACROBLOCKD *const xd = &x->e_mbd; x->rd_search = 1; @@ -558,14 +558,13 @@ static void pick_sb_modes(VP9_COMP *cpi, int mi_row, int mi_col, if (cpi->oxcf.tuning == VP8_TUNE_SSIM) vp9_activity_masking(cpi, x); - /* Find best coding mode & reconstruct the MB so it is available - * as a predictor for MBs that follow in the SB */ - if (cm->frame_type == KEY_FRAME) { + // Find best coding mode & reconstruct the MB so it is available + // as a predictor for MBs that follow in the SB + if (cm->frame_type == KEY_FRAME) vp9_rd_pick_intra_mode_sb(cpi, x, totalrate, totaldist, bsize, ctx); - } else { + else vp9_rd_pick_inter_mode_sb(cpi, x, mi_row, mi_col, totalrate, totaldist, bsize, ctx); - } } static void update_stats(VP9_COMP *cpi, int mi_row, int mi_col) { @@ -576,10 +575,8 @@ static void update_stats(VP9_COMP *cpi, int mi_row, int mi_col) { MB_MODE_INFO * const mbmi = &mi->mbmi; if (cm->frame_type != KEY_FRAME) { - int segment_id, seg_ref_active; - - segment_id = mbmi->segment_id; - seg_ref_active = vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME); + const int seg_ref_active = vp9_segfeature_active(&xd->seg, mbmi->segment_id, + SEG_LVL_REF_FRAME); if (!seg_ref_active) cpi->intra_inter_count[vp9_get_pred_context_intra_inter(cm, xd)][mbmi @@ -1232,7 +1229,7 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, mi_row + (ms >> 1) < cm->mi_rows && mi_col + (ms >> 1) < cm->mi_cols) { *(get_sb_partitioning(x, bsize)) = bsize; - pick_sb_modes(cpi, mi_row, mi_col, tp, &none_rate, &none_dist, bsize, + pick_sb_modes(cpi, mi_row, mi_col, &none_rate, &none_dist, bsize, get_block_context(x, bsize)); set_partition_seg_context(cm, xd, mi_row, mi_col); @@ -1247,7 +1244,7 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, switch (partition) { case PARTITION_NONE: - pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist, + pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist, bsize, get_block_context(x, bsize)); set_partition_seg_context(cm, xd, mi_row, mi_col); pl = partition_plane_context(xd, bsize); @@ -1255,7 +1252,7 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, break; case PARTITION_HORZ: *(get_sb_index(xd, subsize)) = 0; - pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist, + pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist, subsize, get_block_context(x, subsize)); if (bsize >= BLOCK_SIZE_SB8X8 && mi_row + (mh >> 1) < cm->mi_rows) { int rt = 0; @@ -1263,7 +1260,7 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, update_state(cpi, get_block_context(x, subsize), subsize, 0); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize); *(get_sb_index(xd, subsize)) = 1; - pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, tp, &rt, &dt, subsize, + pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, &rt, &dt, subsize, get_block_context(x, subsize)); last_part_rate += rt; last_part_dist += dt; @@ -1274,7 +1271,7 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, break; case PARTITION_VERT: *(get_sb_index(xd, subsize)) = 0; - pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist, + pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist, subsize, get_block_context(x, subsize)); if (bsize >= BLOCK_SIZE_SB8X8 && mi_col + (ms >> 1) < cm->mi_cols) { int rt = 0; @@ -1282,7 +1279,7 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, update_state(cpi, get_block_context(x, subsize), subsize, 0); encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize); *(get_sb_index(xd, subsize)) = 1; - pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), tp, &rt, &dt, subsize, + pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), &rt, &dt, subsize, get_block_context(x, subsize)); last_part_rate += rt; last_part_dist += dt; @@ -1347,7 +1344,7 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); - pick_sb_modes(cpi, mi_row + y_idx, mi_col + x_idx, tp, &rt, &dt, + pick_sb_modes(cpi, mi_row + y_idx, mi_col + x_idx, &rt, &dt, split_subsize, get_block_context(x, split_subsize)); restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize); @@ -1478,7 +1475,7 @@ static void rd_pick_partition(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row, (mi_col + (ms >> 1) < cm->mi_cols)) { int r; int64_t d; - pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, bsize, + pick_sb_modes(cpi, mi_row, mi_col, &r, &d, bsize, get_block_context(x, bsize)); if (bsize >= BLOCK_SIZE_SB8X8) { set_partition_seg_context(cm, xd, mi_row, mi_col); @@ -1503,7 +1500,7 @@ static void rd_pick_partition(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row, int64_t d2, d = 0; subsize = get_subsize(bsize, PARTITION_HORZ); *(get_sb_index(xd, subsize)) = 0; - pick_sb_modes(cpi, mi_row, mi_col, tp, &r2, &d2, subsize, + pick_sb_modes(cpi, mi_row, mi_col, &r2, &d2, subsize, get_block_context(x, subsize)); if (mi_row + (ms >> 1) < cm->mi_rows) { @@ -1511,7 +1508,7 @@ static void rd_pick_partition(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row, encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize); *(get_sb_index(xd, subsize)) = 1; - pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, tp, &r, &d, subsize, + pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, &r, &d, subsize, get_block_context(x, subsize)); r2 += r; d2 += d; @@ -1535,7 +1532,7 @@ static void rd_pick_partition(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row, int64_t d2; subsize = get_subsize(bsize, PARTITION_VERT); *(get_sb_index(xd, subsize)) = 0; - pick_sb_modes(cpi, mi_row, mi_col, tp, &r2, &d2, subsize, + pick_sb_modes(cpi, mi_row, mi_col, &r2, &d2, subsize, get_block_context(x, subsize)); if (mi_col + (ms >> 1) < cm->mi_cols) { int r = 0; @@ -1544,7 +1541,7 @@ static void rd_pick_partition(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row, encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize); *(get_sb_index(xd, subsize)) = 1; - pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), tp, &r, &d, subsize, + pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), &r, &d, subsize, get_block_context(x, subsize)); r2 += r; d2 += d; @@ -1603,7 +1600,7 @@ static void rd_pick_reference_frame(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row, if ((mi_row + (ms >> 1) < cm->mi_rows) && (mi_col + (ms >> 1) < cm->mi_cols)) { cpi->set_ref_frame_mask = 1; - pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, BLOCK_SIZE_SB64X64, + pick_sb_modes(cpi, mi_row, mi_col, &r, &d, BLOCK_SIZE_SB64X64, get_block_context(x, BLOCK_SIZE_SB64X64)); set_partition_seg_context(cm, xd, mi_row, mi_col); pl = partition_plane_context(xd, BLOCK_SIZE_SB64X64); @@ -1886,7 +1883,7 @@ static int check_dual_ref_flags(VP9_COMP *cpi) { MACROBLOCKD *xd = &cpi->mb.e_mbd; int ref_flags = cpi->ref_frame_flags; - if (vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME)) { + if (vp9_segfeature_active(&xd->seg, 1, SEG_LVL_REF_FRAME)) { return 0; } else { return (!!(ref_flags & VP9_GOLD_FLAG) + !!(ref_flags & VP9_LAST_FLAG) @@ -1933,9 +1930,8 @@ static void reset_skip_txfm_size_b(VP9_COMP *cpi, MODE_INFO *mi, int mis, const int xmbs = MIN(bw, cm->mi_cols - mi_col); xd->mode_info_context = mi; - assert( - vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP) || - get_skip_flag(mi, mis, ymbs, xmbs)); + assert(vp9_segfeature_active(&xd->seg, mbmi->segment_id, SEG_LVL_SKIP) || + get_skip_flag(mi, mis, ymbs, xmbs)); set_txfm_flag(mi, mis, ymbs, xmbs, txfm_max); } } @@ -2371,10 +2367,11 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled, vp9_set_pred_flag_mbskip(xd, bsize, mi->mbmi.mb_skip_coeff); if (output_enabled) { - if (cm->txfm_mode == TX_MODE_SELECT && mbmi->sb_type >= BLOCK_SIZE_SB8X8 - && !(mbmi->ref_frame[0] != INTRA_FRAME - && (mbmi->mb_skip_coeff - || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) { + if (cm->txfm_mode == TX_MODE_SELECT && + mbmi->sb_type >= BLOCK_SIZE_SB8X8 && + !(mbmi->ref_frame[0] != INTRA_FRAME && + (mbmi->mb_skip_coeff || + vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)))) { const int context = vp9_get_pred_context_tx_size(cm, xd); if (bsize >= BLOCK_SIZE_SB32X32) { cm->fc.tx_count_32x32p[context][mbmi->txfm_size]++; diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 67d0c4c76..486686ad7 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -219,13 +219,13 @@ static void setup_features(VP9_COMP *cpi) { MACROBLOCKD *xd = &cpi->mb.e_mbd; // Set up default state for MB feature flags - xd->segmentation_enabled = 0; + xd->seg.enabled = 0; - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 0; - vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs)); + xd->seg.update_map = 0; + xd->seg.update_data = 0; + vpx_memset(xd->seg.tree_probs, 255, sizeof(xd->seg.tree_probs)); - vp9_clearall_segfeatures(xd); + vp9_clearall_segfeatures(&xd->seg); xd->mode_ref_lf_delta_enabled = 0; xd->mode_ref_lf_delta_update = 0; @@ -305,26 +305,26 @@ static void configure_static_seg_features(VP9_COMP *cpi) { if (cm->frame_type == KEY_FRAME) { // Clear down the global segmentation map vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols); - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 0; + xd->seg.update_map = 0; + xd->seg.update_data = 0; cpi->static_mb_pct = 0; // Disable segmentation vp9_disable_segmentation((VP9_PTR)cpi); // Clear down the segment features. - vp9_clearall_segfeatures(xd); + vp9_clearall_segfeatures(&xd->seg); } else if (cpi->refresh_alt_ref_frame) { // If this is an alt ref frame // Clear down the global segmentation map vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols); - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 0; + xd->seg.update_map = 0; + xd->seg.update_data = 0; cpi->static_mb_pct = 0; // Disable segmentation and individual segment features by default vp9_disable_segmentation((VP9_PTR)cpi); - vp9_clearall_segfeatures(xd); + vp9_clearall_segfeatures(&xd->seg); // Scan frames from current to arf frame. // This function re-enables segmentation if appropriate. @@ -332,45 +332,45 @@ static void configure_static_seg_features(VP9_COMP *cpi) { // If segmentation was enabled set those features needed for the // arf itself. - if (xd->segmentation_enabled) { - xd->update_mb_segmentation_map = 1; - xd->update_mb_segmentation_data = 1; + if (xd->seg.enabled) { + xd->seg.update_map = 1; + xd->seg.update_data = 1; qi_delta = compute_qdelta(cpi, cpi->avg_q, (cpi->avg_q * 0.875)); - vp9_set_segdata(xd, 1, SEG_LVL_ALT_Q, (qi_delta - 2)); - vp9_set_segdata(xd, 1, SEG_LVL_ALT_LF, -2); + vp9_set_segdata(&xd->seg, 1, SEG_LVL_ALT_Q, (qi_delta - 2)); + vp9_set_segdata(&xd->seg, 1, SEG_LVL_ALT_LF, -2); - vp9_enable_segfeature(xd, 1, SEG_LVL_ALT_Q); - vp9_enable_segfeature(xd, 1, SEG_LVL_ALT_LF); + vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_ALT_Q); + vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_ALT_LF); // Where relevant assume segment data is delta data - xd->mb_segment_abs_delta = SEGMENT_DELTADATA; + xd->seg.abs_delta = SEGMENT_DELTADATA; } - } else if (xd->segmentation_enabled) { + } else if (xd->seg.enabled) { // All other frames if segmentation has been enabled // First normal frame in a valid gf or alt ref group if (cpi->common.frames_since_golden == 0) { // Set up segment features for normal frames in an arf group if (cpi->source_alt_ref_active) { - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 1; - xd->mb_segment_abs_delta = SEGMENT_DELTADATA; + xd->seg.update_map = 0; + xd->seg.update_data = 1; + xd->seg.abs_delta = SEGMENT_DELTADATA; qi_delta = compute_qdelta(cpi, cpi->avg_q, (cpi->avg_q * 1.125)); - vp9_set_segdata(xd, 1, SEG_LVL_ALT_Q, (qi_delta + 2)); - vp9_enable_segfeature(xd, 1, SEG_LVL_ALT_Q); + vp9_set_segdata(&xd->seg, 1, SEG_LVL_ALT_Q, (qi_delta + 2)); + vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_ALT_Q); - vp9_set_segdata(xd, 1, SEG_LVL_ALT_LF, -2); - vp9_enable_segfeature(xd, 1, SEG_LVL_ALT_LF); + vp9_set_segdata(&xd->seg, 1, SEG_LVL_ALT_LF, -2); + vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_ALT_LF); // Segment coding disabled for compred testing if (high_q || (cpi->static_mb_pct == 100)) { - vp9_set_segdata(xd, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME); - vp9_enable_segfeature(xd, 1, SEG_LVL_REF_FRAME); - vp9_enable_segfeature(xd, 1, SEG_LVL_SKIP); + vp9_set_segdata(&xd->seg, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME); + vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_REF_FRAME); + vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_SKIP); } } else { // Disable segmentation and clear down features if alt ref @@ -380,10 +380,10 @@ static void configure_static_seg_features(VP9_COMP *cpi) { vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols); - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 0; + xd->seg.update_map = 0; + xd->seg.update_data = 0; - vp9_clearall_segfeatures(xd); + vp9_clearall_segfeatures(&xd->seg); } } else if (cpi->is_src_frame_alt_ref) { // Special case where we are coding over the top of a previous @@ -391,28 +391,28 @@ static void configure_static_seg_features(VP9_COMP *cpi) { // Segment coding disabled for compred testing // Enable ref frame features for segment 0 as well - vp9_enable_segfeature(xd, 0, SEG_LVL_REF_FRAME); - vp9_enable_segfeature(xd, 1, SEG_LVL_REF_FRAME); + vp9_enable_segfeature(&xd->seg, 0, SEG_LVL_REF_FRAME); + vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_REF_FRAME); // All mbs should use ALTREF_FRAME - vp9_clear_segdata(xd, 0, SEG_LVL_REF_FRAME); - vp9_set_segdata(xd, 0, SEG_LVL_REF_FRAME, ALTREF_FRAME); - vp9_clear_segdata(xd, 1, SEG_LVL_REF_FRAME); - vp9_set_segdata(xd, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME); + vp9_clear_segdata(&xd->seg, 0, SEG_LVL_REF_FRAME); + vp9_set_segdata(&xd->seg, 0, SEG_LVL_REF_FRAME, ALTREF_FRAME); + vp9_clear_segdata(&xd->seg, 1, SEG_LVL_REF_FRAME); + vp9_set_segdata(&xd->seg, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME); // Skip all MBs if high Q (0,0 mv and skip coeffs) if (high_q) { - vp9_enable_segfeature(xd, 0, SEG_LVL_SKIP); - vp9_enable_segfeature(xd, 1, SEG_LVL_SKIP); + vp9_enable_segfeature(&xd->seg, 0, SEG_LVL_SKIP); + vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_SKIP); } // Enable data udpate - xd->update_mb_segmentation_data = 1; + xd->seg.update_data = 1; } else { // All other frames. // No updates.. leave things as they are. - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 0; + xd->seg.update_map = 0; + xd->seg.update_data = 0; } } } @@ -2567,9 +2567,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, setup_features(cpi); // If segmentation is enabled force a map update for key frames - if (xd->segmentation_enabled) { - xd->update_mb_segmentation_map = 1; - xd->update_mb_segmentation_data = 1; + if (xd->seg.enabled) { + xd->seg.update_map = 1; + xd->seg.update_data = 1; } // The alternate reference frame cannot be active for a key frame @@ -3100,9 +3100,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cpi->dummy_packing = 0; vp9_pack_bitstream(cpi, dest, size); - if (xd->update_mb_segmentation_map) { + if (xd->seg.update_map) update_reference_segmentation_map(cpi); - } release_scaled_references(cpi); update_reference_frames(cpi); @@ -3408,8 +3407,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, } // Clear the one shot update flags for segmentation map and mode/ref loop filter deltas. - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 0; + xd->seg.update_map = 0; + xd->seg.update_data = 0; xd->mode_ref_lf_delta_update = 0; // keep track of the last coded dimensions @@ -3521,8 +3520,8 @@ static int frame_is_reference(const VP9_COMP *cpi) { cpi->refresh_alt_ref_frame || cm->refresh_frame_context || mb->mode_ref_lf_delta_update || - mb->update_mb_segmentation_map || - mb->update_mb_segmentation_data; + mb->seg.update_map || + mb->seg.update_data; } #if CONFIG_MULTIPLE_ARF @@ -3978,14 +3977,14 @@ int vp9_set_roimap(VP9_PTR comp, unsigned char *map, unsigned int rows, // Enable the loop and quant changes in the feature mask for (i = 0; i < MAX_MB_SEGMENTS; i++) { if (delta_q[i]) - vp9_enable_segfeature(xd, i, SEG_LVL_ALT_Q); + vp9_enable_segfeature(&xd->seg, i, SEG_LVL_ALT_Q); else - vp9_disable_segfeature(xd, i, SEG_LVL_ALT_Q); + vp9_disable_segfeature(&xd->seg, i, SEG_LVL_ALT_Q); if (delta_lf[i]) - vp9_enable_segfeature(xd, i, SEG_LVL_ALT_LF); + vp9_enable_segfeature(&xd->seg, i, SEG_LVL_ALT_LF); else - vp9_disable_segfeature(xd, i, SEG_LVL_ALT_LF); + vp9_disable_segfeature(&xd->seg, i, SEG_LVL_ALT_LF); } // Initialise the feature data structure diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c index 862923fd4..2d3d6bf9d 100644 --- a/vp9/encoder/vp9_quantize.c +++ b/vp9/encoder/vp9_quantize.c @@ -365,7 +365,7 @@ void vp9_mb_init_quantizer(VP9_COMP *cpi, MACROBLOCK *x) { x->e_mbd.plane[3].dequant = cpi->common.a_dequant[qindex]; #endif - x->skip_block = vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP); + x->skip_block = vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP); /* save this macroblock QIndex for vp9_update_zbin_extra() */ x->e_mbd.q_index = qindex; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 93f8bb56d..733932821 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -127,7 +127,7 @@ void vp9_save_coding_context(VP9_COMP *cpi) { vp9_copy(cc->uv_mode_prob, cm->fc.uv_mode_prob); vp9_copy(cc->partition_prob, cm->fc.partition_prob); - vp9_copy(cc->segment_pred_probs, cm->segment_pred_probs); + vp9_copy(cc->segment_pred_probs, xd->seg.pred_probs); vp9_copy(cc->intra_inter_prob, cm->fc.intra_inter_prob); vp9_copy(cc->comp_inter_prob, cm->fc.comp_inter_prob); @@ -167,7 +167,7 @@ void vp9_restore_coding_context(VP9_COMP *cpi) { vp9_copy(cm->fc.uv_mode_prob, cc->uv_mode_prob); vp9_copy(cm->fc.partition_prob, cc->partition_prob); - vp9_copy(cm->segment_pred_probs, cc->segment_pred_probs); + vp9_copy(xd->seg.pred_probs, cc->segment_pred_probs); vp9_copy(cm->fc.intra_inter_prob, cc->intra_inter_prob); vp9_copy(cm->fc.comp_inter_prob, cc->comp_inter_prob); diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index f42467969..03b35eb0f 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -644,7 +644,7 @@ static INLINE int cost_coeffs(VP9_COMMON *const cm, MACROBLOCK *mb, pt = combine_entropy_contexts(above_ec, left_ec); nb = vp9_get_coef_neighbors_handle(scan); - if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) + if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)) seg_eob = 0; /* sanity check to ensure that we do not have spurious non-zero q values */ @@ -769,20 +769,6 @@ static int rdcost_uv(VP9_COMMON *const cm, MACROBLOCK *x, return cost; } -static int block_error(int16_t *coeff, int16_t *dqcoeff, - int block_size, int shift) { - int i; - int64_t error = 0; - - for (i = 0; i < block_size; i++) { - int this_diff = coeff[i] - dqcoeff[i]; - error += (unsigned)this_diff * this_diff; - } - error >>= shift; - - return error > INT_MAX ? INT_MAX : (int)error; -} - static int block_error_sby(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize, int shift, int64_t *sse) { struct macroblockd_plane *p = &x->e_mbd.plane[0]; @@ -1556,19 +1542,19 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x, return best_rd; } -static int cost_mv_ref(VP9_COMP *cpi, - MB_PREDICTION_MODE m, - const int mode_context) { +static int cost_mv_ref(VP9_COMP *cpi, MB_PREDICTION_MODE mode, + int mode_context) { MACROBLOCK *const x = &cpi->mb; MACROBLOCKD *const xd = &x->e_mbd; - int segment_id = xd->mode_info_context->mbmi.segment_id; + const int segment_id = xd->mode_info_context->mbmi.segment_id; - // Dont account for mode here if segment skip is enabled. - if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) { - assert(NEARESTMV <= m && m <= NEWMV); - return x->inter_mode_cost[mode_context][m - NEARESTMV]; - } else + // Don't account for mode here if segment skip is enabled. + if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)) { + assert(is_inter_mode(mode)); + return x->inter_mode_cost[mode_context][mode - NEARESTMV]; + } else { return 0; + } } void vp9_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv) { @@ -2172,7 +2158,7 @@ static void estimate_ref_frame_costs(VP9_COMP *cpi, int segment_id, vp9_prob *comp_mode_p) { VP9_COMMON *const cm = &cpi->common; MACROBLOCKD *const xd = &cpi->mb.e_mbd; - int seg_ref_active = vp9_segfeature_active(xd, segment_id, + int seg_ref_active = vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME); if (seg_ref_active) { vpx_memset(ref_costs_single, 0, MAX_REF_FRAMES * sizeof(*ref_costs_single)); @@ -3189,7 +3175,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, // Do not allow compound prediction if the segment level reference // frame feature is in use as in this case there can only be one reference. if ((vp9_mode_order[mode_index].second_ref_frame > INTRA_FRAME) && - vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME)) + vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME)) continue; x->skip = 0; @@ -3271,9 +3257,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1], scale_factor); - mode_excluded = - mode_excluded ? - mode_excluded : cm->comp_pred_mode == SINGLE_PREDICTION_ONLY; + mode_excluded = mode_excluded + ? mode_excluded + : cm->comp_pred_mode == SINGLE_PREDICTION_ONLY; } else { // mbmi->ref_frame[1] = vp9_mode_order[mode_index].ref_frame[1]; if (ref_frame != INTRA_FRAME) { @@ -3293,18 +3279,20 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, // If the segment reference frame feature is enabled.... // then do nothing if the current ref frame is not allowed.. - if (vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) && - vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) { + if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME) && + vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_REF_FRAME) != + (int)ref_frame) { continue; // If the segment skip feature is enabled.... // then do nothing if the current mode is not allowed.. - } else if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP) && + } else if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP) && (this_mode != ZEROMV && ref_frame != INTRA_FRAME)) { continue; // Disable this drop out case if the ref frame // segment level feature is enabled for this segment. This is to // prevent the possibility that we end up unable to pick any mode. - } else if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME)) { + } else if (!vp9_segfeature_active(&xd->seg, segment_id, + SEG_LVL_REF_FRAME)) { // Only consider ZEROMV/ALTREF_FRAME for alt ref frame, // unless ARNR filtering is enabled in which case we want // an unfiltered alternative @@ -3579,10 +3567,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, // because there are no non zero coefficients and make any // necessary adjustment for rate. Ignore if skip is coded at // segment level as the cost wont have been added in. - int mb_skip_allowed; - // Is Mb level skip allowed (i.e. not coded at segment level). - mb_skip_allowed = !vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP); + const int mb_skip_allowed = !vp9_segfeature_active(&xd->seg, segment_id, + SEG_LVL_SKIP); if (skippable && bsize >= BLOCK_SIZE_SB8X8) { // Back out the coefficient coding costs @@ -3881,7 +3868,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, // This code forces Altref,0,0 and skip for the frame that overlays a // an alrtef unless Altref is filtered. However, this is unsafe if // segment level coding of ref frame is enabled for this segment. - if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) && + if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME) && cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0) && (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame[0] != ALTREF_FRAME) diff --git a/vp9/encoder/vp9_segmentation.c b/vp9/encoder/vp9_segmentation.c index fb2b23dbe..6a22df86c 100644 --- a/vp9/encoder/vp9_segmentation.c +++ b/vp9/encoder/vp9_segmentation.c @@ -18,14 +18,14 @@ void vp9_enable_segmentation(VP9_PTR ptr) { VP9_COMP *cpi = (VP9_COMP *)ptr; - cpi->mb.e_mbd.segmentation_enabled = 1; - cpi->mb.e_mbd.update_mb_segmentation_map = 1; - cpi->mb.e_mbd.update_mb_segmentation_data = 1; + cpi->mb.e_mbd.seg.enabled = 1; + cpi->mb.e_mbd.seg.update_map = 1; + cpi->mb.e_mbd.seg.update_data = 1; } void vp9_disable_segmentation(VP9_PTR ptr) { VP9_COMP *cpi = (VP9_COMP *)ptr; - cpi->mb.e_mbd.segmentation_enabled = 0; + cpi->mb.e_mbd.seg.enabled = 0; } void vp9_set_segmentation_map(VP9_PTR ptr, @@ -37,8 +37,8 @@ void vp9_set_segmentation_map(VP9_PTR ptr, (cpi->common.mi_rows * cpi->common.mi_cols)); // Signal that the map should be updated. - cpi->mb.e_mbd.update_mb_segmentation_map = 1; - cpi->mb.e_mbd.update_mb_segmentation_data = 1; + cpi->mb.e_mbd.seg.update_map = 1; + cpi->mb.e_mbd.seg.update_data = 1; } void vp9_set_segment_data(VP9_PTR ptr, @@ -46,10 +46,10 @@ void vp9_set_segment_data(VP9_PTR ptr, unsigned char abs_delta) { VP9_COMP *cpi = (VP9_COMP *)(ptr); - cpi->mb.e_mbd.mb_segment_abs_delta = abs_delta; + cpi->mb.e_mbd.seg.abs_delta = abs_delta; - vpx_memcpy(cpi->mb.e_mbd.segment_feature_data, feature_data, - sizeof(cpi->mb.e_mbd.segment_feature_data)); + vpx_memcpy(cpi->mb.e_mbd.seg.feature_data, feature_data, + sizeof(cpi->mb.e_mbd.seg.feature_data)); // TBD ?? Set the feature mask // vpx_memcpy(cpi->mb.e_mbd.segment_feature_mask, 0, @@ -232,8 +232,8 @@ void vp9_choose_segmap_coding_method(VP9_COMP *cpi) { // Set default state for the segment tree probabilities and the // temporal coding probabilities - vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs)); - vpx_memset(cm->segment_pred_probs, 255, sizeof(cm->segment_pred_probs)); + vpx_memset(xd->seg.tree_probs, 255, sizeof(xd->seg.tree_probs)); + vpx_memset(xd->seg.pred_probs, 255, sizeof(xd->seg.pred_probs)); vpx_memset(no_pred_segcounts, 0, sizeof(no_pred_segcounts)); vpx_memset(t_unpred_seg_counts, 0, sizeof(t_unpred_seg_counts)); @@ -283,11 +283,11 @@ void vp9_choose_segmap_coding_method(VP9_COMP *cpi) { // Now choose which coding method to use. if (t_pred_cost < no_pred_cost) { - cm->temporal_update = 1; - vpx_memcpy(xd->mb_segment_tree_probs, t_pred_tree, sizeof(t_pred_tree)); - vpx_memcpy(cm->segment_pred_probs, t_nopred_prob, sizeof(t_nopred_prob)); + xd->seg.temporal_update = 1; + vpx_memcpy(xd->seg.tree_probs, t_pred_tree, sizeof(t_pred_tree)); + vpx_memcpy(xd->seg.pred_probs, t_nopred_prob, sizeof(t_nopred_prob)); } else { - cm->temporal_update = 0; - vpx_memcpy(xd->mb_segment_tree_probs, no_pred_tree, sizeof(no_pred_tree)); + xd->seg.temporal_update = 0; + vpx_memcpy(xd->seg.tree_probs, no_pred_tree, sizeof(no_pred_tree)); } } diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c index c16bdff35..d526990df 100644 --- a/vp9/encoder/vp9_tokenize.c +++ b/vp9/encoder/vp9_tokenize.c @@ -180,7 +180,7 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE_TYPE bsize, pt = combine_entropy_contexts(above_ec, left_ec); nb = vp9_get_coef_neighbors_handle(scan); - if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) + if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)) seg_eob = 0; c = 0; @@ -274,12 +274,10 @@ void vp9_tokenize_sb(VP9_COMP *cpi, MB_MODE_INFO * const mbmi = &xd->mode_info_context->mbmi; TOKENEXTRA *t_backup = *t; const int mb_skip_context = vp9_get_pred_context_mbskip(cm, xd); - const int segment_id = mbmi->segment_id; - const int skip_inc = !vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP); + const int skip_inc = !vp9_segfeature_active(&xd->seg, mbmi->segment_id, + SEG_LVL_SKIP); const TX_SIZE txfm_size = mbmi->txfm_size; - struct tokenize_b_args arg = { - cpi, xd, t, txfm_size, dry_run - }; + struct tokenize_b_args arg = { cpi, xd, t, txfm_size, dry_run }; mbmi->mb_skip_coeff = vp9_sb_is_skippable(xd, bsize); diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk index ee744d541..2518ce148 100644 --- a/vp9/vp9_common.mk +++ b/vp9/vp9_common.mk @@ -88,6 +88,8 @@ endif VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_idct_intrin_sse2.c +VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_convolve8_neon$(ASM) VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_loopfilter_neon$(ASM) +VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_dc_only_idct_add_neon$(ASM) $(eval $(call rtcd_h_template,vp9_rtcd,vp9/common/vp9_rtcd_defs.sh)) diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index ea6946bd9..3bfb35813 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -212,26 +212,27 @@ static vpx_codec_err_t vp8_peek_si(const uint8_t *data, vpx_codec_stream_info_t *si) { vpx_codec_err_t res = VPX_CODEC_OK; - if (data + data_sz <= data) + if (data_sz <= 8) return VPX_CODEC_UNSUP_BITSTREAM; + + if (data + data_sz <= data) { res = VPX_CODEC_INVALID_PARAM; - else { - si->is_kf = 0; + } else { + const int frame_marker = (data[0] >> 6) & 0x3; + const int version = (data[0] >> 4) & 0x3; + if (frame_marker != 0x2) return VPX_CODEC_UNSUP_BITSTREAM; + if (version != 0) return VPX_CODEC_UNSUP_BITSTREAM; - if (data_sz >= 8 && (data[0] & 0xD8) == 0x80) { /* I-Frame */ + si->is_kf = !((data[0] >> 2) & 0x1); + if (si->is_kf) { const uint8_t *c = data + 1; - si->is_kf = 1; if (c[0] != SYNC_CODE_0 || c[1] != SYNC_CODE_1 || c[2] != SYNC_CODE_2) - res = VPX_CODEC_UNSUP_BITSTREAM; - - si->w = (c[3] << 8) | c[4]; - si->h = (c[5] << 8) | c[6]; + return VPX_CODEC_UNSUP_BITSTREAM; - // printf("w=%d, h=%d\n", si->w, si->h); - if (!(si->h | si->w)) - res = VPX_CODEC_UNSUP_BITSTREAM; - } else - res = VPX_CODEC_UNSUP_BITSTREAM; + c += 3; + si->w = (((c[0] & 0xf) << 12) | (c[1] << 4) | ((c[2] >> 4) & 0xf)) + 1; + si->h = (((c[2] & 0xf) << 12) | (c[3] << 4) | ((c[4] >> 4) & 0xf)) + 1; + } } return res; diff --git a/vpx/internal/vpx_codec_internal.h b/vpx/internal/vpx_codec_internal.h index d7bcd4620..0b057de4c 100644 --- a/vpx/internal/vpx_codec_internal.h +++ b/vpx/internal/vpx_codec_internal.h @@ -94,9 +94,10 @@ typedef vpx_codec_err_t (*vpx_codec_destroy_fn_t)(vpx_codec_alg_priv_t *ctx); /*!\brief parse stream info function pointer prototype * - * Performs high level parsing of the bitstream. This function is called by - * the generic vpx_codec_parse_stream() wrapper function, so plugins implementing - * this interface may trust the input parameters to be properly initialized. + * Performs high level parsing of the bitstream. This function is called by the + * generic vpx_codec_peek_stream_info() wrapper function, so plugins + * implementing this interface may trust the input parameters to be properly + * initialized. * * \param[in] data Pointer to a block of data to parse * \param[in] data_sz Size of the data buffer @@ -301,7 +302,7 @@ struct vpx_codec_iface { vpx_codec_set_mmap_fn_t set_mmap; /**< \copydoc ::vpx_codec_set_mmap_fn_t */ struct vpx_codec_dec_iface { vpx_codec_peek_si_fn_t peek_si; /**< \copydoc ::vpx_codec_peek_si_fn_t */ - vpx_codec_get_si_fn_t get_si; /**< \copydoc ::vpx_codec_peek_si_fn_t */ + vpx_codec_get_si_fn_t get_si; /**< \copydoc ::vpx_codec_get_si_fn_t */ vpx_codec_decode_fn_t decode; /**< \copydoc ::vpx_codec_decode_fn_t */ vpx_codec_get_frame_fn_t get_frame; /**< \copydoc ::vpx_codec_get_frame_fn_t */ } dec; |