2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
13 #include "vpx_ports/mem.h"
15 #include "vp9/encoder/vp9_aq_variance.h"
17 #include "vp9/common/vp9_seg_common.h"
19 #include "vp9/encoder/vp9_ratectrl.h"
20 #include "vp9/encoder/vp9_rd.h"
21 #include "vp9/encoder/vp9_segmentation.h"
22 #include "vp9/common/vp9_systemdependent.h"
24 #define ENERGY_MIN (-4)
25 #define ENERGY_MAX (1)
26 #define ENERGY_SPAN (ENERGY_MAX - ENERGY_MIN + 1)
27 #define ENERGY_IN_BOUNDS(energy)\
28 assert((energy) >= ENERGY_MIN && (energy) <= ENERGY_MAX)
30 static const double rate_ratio
[MAX_SEGMENTS
] =
31 {2.5, 2.0, 1.5, 1.0, 0.75, 1.0, 1.0, 1.0};
32 static const int segment_id
[ENERGY_SPAN
] = {0, 1, 1, 2, 3, 4};
34 #define SEGMENT_ID(i) segment_id[(i) - ENERGY_MIN]
36 DECLARE_ALIGNED(16, static const uint8_t, vp9_64_zeros
[64]) = {0};
37 #if CONFIG_VP9_HIGHBITDEPTH
38 DECLARE_ALIGNED(16, static const uint16_t, vp9_highbd_64_zeros
[64]) = {0};
41 unsigned int vp9_vaq_segment_id(int energy
) {
42 ENERGY_IN_BOUNDS(energy
);
43 return SEGMENT_ID(energy
);
46 void vp9_vaq_frame_setup(VP9_COMP
*cpi
) {
47 VP9_COMMON
*cm
= &cpi
->common
;
48 struct segmentation
*seg
= &cm
->seg
;
51 if (cm
->frame_type
== KEY_FRAME
||
52 cpi
->refresh_alt_ref_frame
||
53 (cpi
->refresh_golden_frame
&& !cpi
->rc
.is_src_frame_alt_ref
)) {
54 vp9_enable_segmentation(seg
);
55 vp9_clearall_segfeatures(seg
);
57 seg
->abs_delta
= SEGMENT_DELTADATA
;
59 vp9_clear_system_state();
61 for (i
= 0; i
< MAX_SEGMENTS
; ++i
) {
63 vp9_compute_qdelta_by_rate(&cpi
->rc
, cm
->frame_type
, cm
->base_qindex
,
64 rate_ratio
[i
], cm
->bit_depth
);
66 // We don't allow qindex 0 in a segment if the base value is not 0.
67 // Q index 0 (lossless) implies 4x4 encoding only and in AQ mode a segment
68 // Q delta is sometimes applied without going back around the rd loop.
69 // This could lead to an illegal combination of partition size and q.
70 if ((cm
->base_qindex
!= 0) && ((cm
->base_qindex
+ qindex_delta
) == 0)) {
71 qindex_delta
= -cm
->base_qindex
+ 1;
74 // No need to enable SEG_LVL_ALT_Q for this segment.
75 if (rate_ratio
[i
] == 1.0) {
79 vp9_set_segdata(seg
, i
, SEG_LVL_ALT_Q
, qindex_delta
);
80 vp9_enable_segfeature(seg
, i
, SEG_LVL_ALT_Q
);
85 /* TODO(agrange, paulwilkins): The block_variance calls the unoptimized versions
86 * of variance() and highbd_8_variance(). It should not.
88 static void aq_variance(const uint8_t *a
, int a_stride
,
89 const uint8_t *b
, int b_stride
,
90 int w
, int h
, unsigned int *sse
, int *sum
) {
96 for (i
= 0; i
< h
; i
++) {
97 for (j
= 0; j
< w
; j
++) {
98 const int diff
= a
[j
] - b
[j
];
108 #if CONFIG_VP9_HIGHBITDEPTH
109 static void aq_highbd_variance64(const uint8_t *a8
, int a_stride
,
110 const uint8_t *b8
, int b_stride
,
111 int w
, int h
, uint64_t *sse
, uint64_t *sum
) {
114 uint16_t *a
= CONVERT_TO_SHORTPTR(a8
);
115 uint16_t *b
= CONVERT_TO_SHORTPTR(b8
);
119 for (i
= 0; i
< h
; i
++) {
120 for (j
= 0; j
< w
; j
++) {
121 const int diff
= a
[j
] - b
[j
];
130 static void aq_highbd_8_variance(const uint8_t *a8
, int a_stride
,
131 const uint8_t *b8
, int b_stride
,
132 int w
, int h
, unsigned int *sse
, int *sum
) {
133 uint64_t sse_long
= 0;
134 uint64_t sum_long
= 0;
135 aq_highbd_variance64(a8
, a_stride
, b8
, b_stride
, w
, h
, &sse_long
, &sum_long
);
136 *sse
= (unsigned int)sse_long
;
137 *sum
= (int)sum_long
;
139 #endif // CONFIG_VP9_HIGHBITDEPTH
141 static unsigned int block_variance(VP9_COMP
*cpi
, MACROBLOCK
*x
,
143 MACROBLOCKD
*xd
= &x
->e_mbd
;
144 unsigned int var
, sse
;
145 int right_overflow
= (xd
->mb_to_right_edge
< 0) ?
146 ((-xd
->mb_to_right_edge
) >> 3) : 0;
147 int bottom_overflow
= (xd
->mb_to_bottom_edge
< 0) ?
148 ((-xd
->mb_to_bottom_edge
) >> 3) : 0;
150 if (right_overflow
|| bottom_overflow
) {
151 const int bw
= 8 * num_8x8_blocks_wide_lookup
[bs
] - right_overflow
;
152 const int bh
= 8 * num_8x8_blocks_high_lookup
[bs
] - bottom_overflow
;
154 #if CONFIG_VP9_HIGHBITDEPTH
155 if (xd
->cur_buf
->flags
& YV12_FLAG_HIGHBITDEPTH
) {
156 aq_highbd_8_variance(x
->plane
[0].src
.buf
, x
->plane
[0].src
.stride
,
157 CONVERT_TO_BYTEPTR(vp9_highbd_64_zeros
), 0, bw
, bh
,
159 sse
>>= 2 * (xd
->bd
- 8);
160 avg
>>= (xd
->bd
- 8);
162 aq_variance(x
->plane
[0].src
.buf
, x
->plane
[0].src
.stride
,
163 vp9_64_zeros
, 0, bw
, bh
, &sse
, &avg
);
166 aq_variance(x
->plane
[0].src
.buf
, x
->plane
[0].src
.stride
,
167 vp9_64_zeros
, 0, bw
, bh
, &sse
, &avg
);
168 #endif // CONFIG_VP9_HIGHBITDEPTH
169 var
= sse
- (((int64_t)avg
* avg
) / (bw
* bh
));
170 return (256 * var
) / (bw
* bh
);
172 #if CONFIG_VP9_HIGHBITDEPTH
173 if (xd
->cur_buf
->flags
& YV12_FLAG_HIGHBITDEPTH
) {
174 var
= cpi
->fn_ptr
[bs
].vf(x
->plane
[0].src
.buf
,
175 x
->plane
[0].src
.stride
,
176 CONVERT_TO_BYTEPTR(vp9_highbd_64_zeros
),
179 var
= cpi
->fn_ptr
[bs
].vf(x
->plane
[0].src
.buf
,
180 x
->plane
[0].src
.stride
,
181 vp9_64_zeros
, 0, &sse
);
184 var
= cpi
->fn_ptr
[bs
].vf(x
->plane
[0].src
.buf
,
185 x
->plane
[0].src
.stride
,
186 vp9_64_zeros
, 0, &sse
);
187 #endif // CONFIG_VP9_HIGHBITDEPTH
188 return (256 * var
) >> num_pels_log2_lookup
[bs
];
192 double vp9_log_block_var(VP9_COMP
*cpi
, MACROBLOCK
*x
, BLOCK_SIZE bs
) {
193 unsigned int var
= block_variance(cpi
, x
, bs
);
194 vp9_clear_system_state();
195 return log(var
+ 1.0);
198 #define DEFAULT_E_MIDPOINT 10.0
199 int vp9_block_energy(VP9_COMP
*cpi
, MACROBLOCK
*x
, BLOCK_SIZE bs
) {
201 double energy_midpoint
;
202 vp9_clear_system_state();
204 (cpi
->oxcf
.pass
== 2) ? cpi
->twopass
.mb_av_energy
: DEFAULT_E_MIDPOINT
;
205 energy
= vp9_log_block_var(cpi
, x
, bs
) - energy_midpoint
;
206 return clamp((int)round(energy
), ENERGY_MIN
, ENERGY_MAX
);