1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
12*fb1b10abSAndroid Build Coastguard Worker #include "./vp9_rtcd.h"
13*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_scale_rtcd.h"
15*fb1b10abSAndroid Build Coastguard Worker
16*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_onyxc_int.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_postproc.h"
18*fb1b10abSAndroid Build Coastguard Worker
19*fb1b10abSAndroid Build Coastguard Worker // TODO(jackychen): Replace this function with SSE2 code. There is
20*fb1b10abSAndroid Build Coastguard Worker // one SSE2 implementation in vp8, so will consider how to share it
21*fb1b10abSAndroid Build Coastguard Worker // between vp8 and vp9.
filter_by_weight(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride,int block_size,int src_weight)22*fb1b10abSAndroid Build Coastguard Worker static void filter_by_weight(const uint8_t *src, int src_stride, uint8_t *dst,
23*fb1b10abSAndroid Build Coastguard Worker int dst_stride, int block_size, int src_weight) {
24*fb1b10abSAndroid Build Coastguard Worker const int dst_weight = (1 << MFQE_PRECISION) - src_weight;
25*fb1b10abSAndroid Build Coastguard Worker const int rounding_bit = 1 << (MFQE_PRECISION - 1);
26*fb1b10abSAndroid Build Coastguard Worker int r, c;
27*fb1b10abSAndroid Build Coastguard Worker
28*fb1b10abSAndroid Build Coastguard Worker for (r = 0; r < block_size; r++) {
29*fb1b10abSAndroid Build Coastguard Worker for (c = 0; c < block_size; c++) {
30*fb1b10abSAndroid Build Coastguard Worker dst[c] = (src[c] * src_weight + dst[c] * dst_weight + rounding_bit) >>
31*fb1b10abSAndroid Build Coastguard Worker MFQE_PRECISION;
32*fb1b10abSAndroid Build Coastguard Worker }
33*fb1b10abSAndroid Build Coastguard Worker src += src_stride;
34*fb1b10abSAndroid Build Coastguard Worker dst += dst_stride;
35*fb1b10abSAndroid Build Coastguard Worker }
36*fb1b10abSAndroid Build Coastguard Worker }
37*fb1b10abSAndroid Build Coastguard Worker
vp9_filter_by_weight8x8_c(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride,int src_weight)38*fb1b10abSAndroid Build Coastguard Worker void vp9_filter_by_weight8x8_c(const uint8_t *src, int src_stride, uint8_t *dst,
39*fb1b10abSAndroid Build Coastguard Worker int dst_stride, int src_weight) {
40*fb1b10abSAndroid Build Coastguard Worker filter_by_weight(src, src_stride, dst, dst_stride, 8, src_weight);
41*fb1b10abSAndroid Build Coastguard Worker }
42*fb1b10abSAndroid Build Coastguard Worker
vp9_filter_by_weight16x16_c(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride,int src_weight)43*fb1b10abSAndroid Build Coastguard Worker void vp9_filter_by_weight16x16_c(const uint8_t *src, int src_stride,
44*fb1b10abSAndroid Build Coastguard Worker uint8_t *dst, int dst_stride, int src_weight) {
45*fb1b10abSAndroid Build Coastguard Worker filter_by_weight(src, src_stride, dst, dst_stride, 16, src_weight);
46*fb1b10abSAndroid Build Coastguard Worker }
47*fb1b10abSAndroid Build Coastguard Worker
filter_by_weight32x32(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride,int weight)48*fb1b10abSAndroid Build Coastguard Worker static void filter_by_weight32x32(const uint8_t *src, int src_stride,
49*fb1b10abSAndroid Build Coastguard Worker uint8_t *dst, int dst_stride, int weight) {
50*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight16x16(src, src_stride, dst, dst_stride, weight);
51*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight16x16(src + 16, src_stride, dst + 16, dst_stride, weight);
52*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight16x16(src + src_stride * 16, src_stride,
53*fb1b10abSAndroid Build Coastguard Worker dst + dst_stride * 16, dst_stride, weight);
54*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight16x16(src + src_stride * 16 + 16, src_stride,
55*fb1b10abSAndroid Build Coastguard Worker dst + dst_stride * 16 + 16, dst_stride, weight);
56*fb1b10abSAndroid Build Coastguard Worker }
57*fb1b10abSAndroid Build Coastguard Worker
filter_by_weight64x64(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride,int weight)58*fb1b10abSAndroid Build Coastguard Worker static void filter_by_weight64x64(const uint8_t *src, int src_stride,
59*fb1b10abSAndroid Build Coastguard Worker uint8_t *dst, int dst_stride, int weight) {
60*fb1b10abSAndroid Build Coastguard Worker filter_by_weight32x32(src, src_stride, dst, dst_stride, weight);
61*fb1b10abSAndroid Build Coastguard Worker filter_by_weight32x32(src + 32, src_stride, dst + 32, dst_stride, weight);
62*fb1b10abSAndroid Build Coastguard Worker filter_by_weight32x32(src + src_stride * 32, src_stride,
63*fb1b10abSAndroid Build Coastguard Worker dst + dst_stride * 32, dst_stride, weight);
64*fb1b10abSAndroid Build Coastguard Worker filter_by_weight32x32(src + src_stride * 32 + 32, src_stride,
65*fb1b10abSAndroid Build Coastguard Worker dst + dst_stride * 32 + 32, dst_stride, weight);
66*fb1b10abSAndroid Build Coastguard Worker }
67*fb1b10abSAndroid Build Coastguard Worker
apply_ifactor(const uint8_t * y,int y_stride,uint8_t * yd,int yd_stride,const uint8_t * u,const uint8_t * v,int uv_stride,uint8_t * ud,uint8_t * vd,int uvd_stride,BLOCK_SIZE block_size,int weight)68*fb1b10abSAndroid Build Coastguard Worker static void apply_ifactor(const uint8_t *y, int y_stride, uint8_t *yd,
69*fb1b10abSAndroid Build Coastguard Worker int yd_stride, const uint8_t *u, const uint8_t *v,
70*fb1b10abSAndroid Build Coastguard Worker int uv_stride, uint8_t *ud, uint8_t *vd,
71*fb1b10abSAndroid Build Coastguard Worker int uvd_stride, BLOCK_SIZE block_size, int weight) {
72*fb1b10abSAndroid Build Coastguard Worker if (block_size == BLOCK_16X16) {
73*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight16x16(y, y_stride, yd, yd_stride, weight);
74*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight8x8(u, uv_stride, ud, uvd_stride, weight);
75*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight8x8(v, uv_stride, vd, uvd_stride, weight);
76*fb1b10abSAndroid Build Coastguard Worker } else if (block_size == BLOCK_32X32) {
77*fb1b10abSAndroid Build Coastguard Worker filter_by_weight32x32(y, y_stride, yd, yd_stride, weight);
78*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight16x16(u, uv_stride, ud, uvd_stride, weight);
79*fb1b10abSAndroid Build Coastguard Worker vp9_filter_by_weight16x16(v, uv_stride, vd, uvd_stride, weight);
80*fb1b10abSAndroid Build Coastguard Worker } else if (block_size == BLOCK_64X64) {
81*fb1b10abSAndroid Build Coastguard Worker filter_by_weight64x64(y, y_stride, yd, yd_stride, weight);
82*fb1b10abSAndroid Build Coastguard Worker filter_by_weight32x32(u, uv_stride, ud, uvd_stride, weight);
83*fb1b10abSAndroid Build Coastguard Worker filter_by_weight32x32(v, uv_stride, vd, uvd_stride, weight);
84*fb1b10abSAndroid Build Coastguard Worker }
85*fb1b10abSAndroid Build Coastguard Worker }
86*fb1b10abSAndroid Build Coastguard Worker
87*fb1b10abSAndroid Build Coastguard Worker // TODO(jackychen): Determine whether replace it with assembly code.
copy_mem8x8(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride)88*fb1b10abSAndroid Build Coastguard Worker static void copy_mem8x8(const uint8_t *src, int src_stride, uint8_t *dst,
89*fb1b10abSAndroid Build Coastguard Worker int dst_stride) {
90*fb1b10abSAndroid Build Coastguard Worker int r;
91*fb1b10abSAndroid Build Coastguard Worker for (r = 0; r < 8; r++) {
92*fb1b10abSAndroid Build Coastguard Worker memcpy(dst, src, 8);
93*fb1b10abSAndroid Build Coastguard Worker src += src_stride;
94*fb1b10abSAndroid Build Coastguard Worker dst += dst_stride;
95*fb1b10abSAndroid Build Coastguard Worker }
96*fb1b10abSAndroid Build Coastguard Worker }
97*fb1b10abSAndroid Build Coastguard Worker
copy_mem16x16(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride)98*fb1b10abSAndroid Build Coastguard Worker static void copy_mem16x16(const uint8_t *src, int src_stride, uint8_t *dst,
99*fb1b10abSAndroid Build Coastguard Worker int dst_stride) {
100*fb1b10abSAndroid Build Coastguard Worker int r;
101*fb1b10abSAndroid Build Coastguard Worker for (r = 0; r < 16; r++) {
102*fb1b10abSAndroid Build Coastguard Worker memcpy(dst, src, 16);
103*fb1b10abSAndroid Build Coastguard Worker src += src_stride;
104*fb1b10abSAndroid Build Coastguard Worker dst += dst_stride;
105*fb1b10abSAndroid Build Coastguard Worker }
106*fb1b10abSAndroid Build Coastguard Worker }
107*fb1b10abSAndroid Build Coastguard Worker
copy_mem32x32(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride)108*fb1b10abSAndroid Build Coastguard Worker static void copy_mem32x32(const uint8_t *src, int src_stride, uint8_t *dst,
109*fb1b10abSAndroid Build Coastguard Worker int dst_stride) {
110*fb1b10abSAndroid Build Coastguard Worker copy_mem16x16(src, src_stride, dst, dst_stride);
111*fb1b10abSAndroid Build Coastguard Worker copy_mem16x16(src + 16, src_stride, dst + 16, dst_stride);
112*fb1b10abSAndroid Build Coastguard Worker copy_mem16x16(src + src_stride * 16, src_stride, dst + dst_stride * 16,
113*fb1b10abSAndroid Build Coastguard Worker dst_stride);
114*fb1b10abSAndroid Build Coastguard Worker copy_mem16x16(src + src_stride * 16 + 16, src_stride,
115*fb1b10abSAndroid Build Coastguard Worker dst + dst_stride * 16 + 16, dst_stride);
116*fb1b10abSAndroid Build Coastguard Worker }
117*fb1b10abSAndroid Build Coastguard Worker
copy_mem64x64(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride)118*fb1b10abSAndroid Build Coastguard Worker static void copy_mem64x64(const uint8_t *src, int src_stride, uint8_t *dst,
119*fb1b10abSAndroid Build Coastguard Worker int dst_stride) {
120*fb1b10abSAndroid Build Coastguard Worker copy_mem32x32(src, src_stride, dst, dst_stride);
121*fb1b10abSAndroid Build Coastguard Worker copy_mem32x32(src + 32, src_stride, dst + 32, dst_stride);
122*fb1b10abSAndroid Build Coastguard Worker copy_mem32x32(src + src_stride * 32, src_stride, dst + src_stride * 32,
123*fb1b10abSAndroid Build Coastguard Worker dst_stride);
124*fb1b10abSAndroid Build Coastguard Worker copy_mem32x32(src + src_stride * 32 + 32, src_stride,
125*fb1b10abSAndroid Build Coastguard Worker dst + src_stride * 32 + 32, dst_stride);
126*fb1b10abSAndroid Build Coastguard Worker }
127*fb1b10abSAndroid Build Coastguard Worker
copy_block(const uint8_t * y,const uint8_t * u,const uint8_t * v,int y_stride,int uv_stride,uint8_t * yd,uint8_t * ud,uint8_t * vd,int yd_stride,int uvd_stride,BLOCK_SIZE bs)128*fb1b10abSAndroid Build Coastguard Worker static void copy_block(const uint8_t *y, const uint8_t *u, const uint8_t *v,
129*fb1b10abSAndroid Build Coastguard Worker int y_stride, int uv_stride, uint8_t *yd, uint8_t *ud,
130*fb1b10abSAndroid Build Coastguard Worker uint8_t *vd, int yd_stride, int uvd_stride,
131*fb1b10abSAndroid Build Coastguard Worker BLOCK_SIZE bs) {
132*fb1b10abSAndroid Build Coastguard Worker if (bs == BLOCK_16X16) {
133*fb1b10abSAndroid Build Coastguard Worker copy_mem16x16(y, y_stride, yd, yd_stride);
134*fb1b10abSAndroid Build Coastguard Worker copy_mem8x8(u, uv_stride, ud, uvd_stride);
135*fb1b10abSAndroid Build Coastguard Worker copy_mem8x8(v, uv_stride, vd, uvd_stride);
136*fb1b10abSAndroid Build Coastguard Worker } else if (bs == BLOCK_32X32) {
137*fb1b10abSAndroid Build Coastguard Worker copy_mem32x32(y, y_stride, yd, yd_stride);
138*fb1b10abSAndroid Build Coastguard Worker copy_mem16x16(u, uv_stride, ud, uvd_stride);
139*fb1b10abSAndroid Build Coastguard Worker copy_mem16x16(v, uv_stride, vd, uvd_stride);
140*fb1b10abSAndroid Build Coastguard Worker } else {
141*fb1b10abSAndroid Build Coastguard Worker copy_mem64x64(y, y_stride, yd, yd_stride);
142*fb1b10abSAndroid Build Coastguard Worker copy_mem32x32(u, uv_stride, ud, uvd_stride);
143*fb1b10abSAndroid Build Coastguard Worker copy_mem32x32(v, uv_stride, vd, uvd_stride);
144*fb1b10abSAndroid Build Coastguard Worker }
145*fb1b10abSAndroid Build Coastguard Worker }
146*fb1b10abSAndroid Build Coastguard Worker
get_thr(BLOCK_SIZE bs,int qdiff,int * sad_thr,int * vdiff_thr)147*fb1b10abSAndroid Build Coastguard Worker static void get_thr(BLOCK_SIZE bs, int qdiff, int *sad_thr, int *vdiff_thr) {
148*fb1b10abSAndroid Build Coastguard Worker const int adj = qdiff >> MFQE_PRECISION;
149*fb1b10abSAndroid Build Coastguard Worker if (bs == BLOCK_16X16) {
150*fb1b10abSAndroid Build Coastguard Worker *sad_thr = 7 + adj;
151*fb1b10abSAndroid Build Coastguard Worker } else if (bs == BLOCK_32X32) {
152*fb1b10abSAndroid Build Coastguard Worker *sad_thr = 6 + adj;
153*fb1b10abSAndroid Build Coastguard Worker } else { // BLOCK_64X64
154*fb1b10abSAndroid Build Coastguard Worker *sad_thr = 5 + adj;
155*fb1b10abSAndroid Build Coastguard Worker }
156*fb1b10abSAndroid Build Coastguard Worker *vdiff_thr = 125 + qdiff;
157*fb1b10abSAndroid Build Coastguard Worker }
158*fb1b10abSAndroid Build Coastguard Worker
mfqe_block(BLOCK_SIZE bs,const uint8_t * y,const uint8_t * u,const uint8_t * v,int y_stride,int uv_stride,uint8_t * yd,uint8_t * ud,uint8_t * vd,int yd_stride,int uvd_stride,int qdiff)159*fb1b10abSAndroid Build Coastguard Worker static void mfqe_block(BLOCK_SIZE bs, const uint8_t *y, const uint8_t *u,
160*fb1b10abSAndroid Build Coastguard Worker const uint8_t *v, int y_stride, int uv_stride,
161*fb1b10abSAndroid Build Coastguard Worker uint8_t *yd, uint8_t *ud, uint8_t *vd, int yd_stride,
162*fb1b10abSAndroid Build Coastguard Worker int uvd_stride, int qdiff) {
163*fb1b10abSAndroid Build Coastguard Worker int sad, sad_thr, vdiff, vdiff_thr;
164*fb1b10abSAndroid Build Coastguard Worker uint32_t sse;
165*fb1b10abSAndroid Build Coastguard Worker
166*fb1b10abSAndroid Build Coastguard Worker get_thr(bs, qdiff, &sad_thr, &vdiff_thr);
167*fb1b10abSAndroid Build Coastguard Worker
168*fb1b10abSAndroid Build Coastguard Worker if (bs == BLOCK_16X16) {
169*fb1b10abSAndroid Build Coastguard Worker vdiff = (vpx_variance16x16(y, y_stride, yd, yd_stride, &sse) + 128) >> 8;
170*fb1b10abSAndroid Build Coastguard Worker sad = (vpx_sad16x16(y, y_stride, yd, yd_stride) + 128) >> 8;
171*fb1b10abSAndroid Build Coastguard Worker } else if (bs == BLOCK_32X32) {
172*fb1b10abSAndroid Build Coastguard Worker vdiff = (vpx_variance32x32(y, y_stride, yd, yd_stride, &sse) + 512) >> 10;
173*fb1b10abSAndroid Build Coastguard Worker sad = (vpx_sad32x32(y, y_stride, yd, yd_stride) + 512) >> 10;
174*fb1b10abSAndroid Build Coastguard Worker } else /* if (bs == BLOCK_64X64) */ {
175*fb1b10abSAndroid Build Coastguard Worker vdiff = (vpx_variance64x64(y, y_stride, yd, yd_stride, &sse) + 2048) >> 12;
176*fb1b10abSAndroid Build Coastguard Worker sad = (vpx_sad64x64(y, y_stride, yd, yd_stride) + 2048) >> 12;
177*fb1b10abSAndroid Build Coastguard Worker }
178*fb1b10abSAndroid Build Coastguard Worker
179*fb1b10abSAndroid Build Coastguard Worker // vdiff > sad * 3 means vdiff should not be too small, otherwise,
180*fb1b10abSAndroid Build Coastguard Worker // it might be a lighting change in smooth area. When there is a
181*fb1b10abSAndroid Build Coastguard Worker // lighting change in smooth area, it is dangerous to do MFQE.
182*fb1b10abSAndroid Build Coastguard Worker if (sad > 1 && vdiff > sad * 3) {
183*fb1b10abSAndroid Build Coastguard Worker const int weight = 1 << MFQE_PRECISION;
184*fb1b10abSAndroid Build Coastguard Worker int ifactor = weight * sad * vdiff / (sad_thr * vdiff_thr);
185*fb1b10abSAndroid Build Coastguard Worker // When ifactor equals weight, no MFQE is done.
186*fb1b10abSAndroid Build Coastguard Worker if (ifactor > weight) {
187*fb1b10abSAndroid Build Coastguard Worker ifactor = weight;
188*fb1b10abSAndroid Build Coastguard Worker }
189*fb1b10abSAndroid Build Coastguard Worker apply_ifactor(y, y_stride, yd, yd_stride, u, v, uv_stride, ud, vd,
190*fb1b10abSAndroid Build Coastguard Worker uvd_stride, bs, ifactor);
191*fb1b10abSAndroid Build Coastguard Worker } else {
192*fb1b10abSAndroid Build Coastguard Worker // Copy the block from current frame (i.e., no mfqe is done).
193*fb1b10abSAndroid Build Coastguard Worker copy_block(y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride, uvd_stride,
194*fb1b10abSAndroid Build Coastguard Worker bs);
195*fb1b10abSAndroid Build Coastguard Worker }
196*fb1b10abSAndroid Build Coastguard Worker }
197*fb1b10abSAndroid Build Coastguard Worker
mfqe_decision(MODE_INFO * mi,BLOCK_SIZE cur_bs)198*fb1b10abSAndroid Build Coastguard Worker static int mfqe_decision(MODE_INFO *mi, BLOCK_SIZE cur_bs) {
199*fb1b10abSAndroid Build Coastguard Worker // Check the motion in current block(for inter frame),
200*fb1b10abSAndroid Build Coastguard Worker // or check the motion in the correlated block in last frame (for keyframe).
201*fb1b10abSAndroid Build Coastguard Worker const int mv_len_square = mi->mv[0].as_mv.row * mi->mv[0].as_mv.row +
202*fb1b10abSAndroid Build Coastguard Worker mi->mv[0].as_mv.col * mi->mv[0].as_mv.col;
203*fb1b10abSAndroid Build Coastguard Worker const int mv_threshold = 100;
204*fb1b10abSAndroid Build Coastguard Worker return mi->mode >= NEARESTMV && // Not an intra block
205*fb1b10abSAndroid Build Coastguard Worker cur_bs >= BLOCK_16X16 && mv_len_square <= mv_threshold;
206*fb1b10abSAndroid Build Coastguard Worker }
207*fb1b10abSAndroid Build Coastguard Worker
208*fb1b10abSAndroid Build Coastguard Worker // Process each partiton in a super block, recursively.
mfqe_partition(VP9_COMMON * cm,MODE_INFO * mi,BLOCK_SIZE bs,const uint8_t * y,const uint8_t * u,const uint8_t * v,int y_stride,int uv_stride,uint8_t * yd,uint8_t * ud,uint8_t * vd,int yd_stride,int uvd_stride)209*fb1b10abSAndroid Build Coastguard Worker static void mfqe_partition(VP9_COMMON *cm, MODE_INFO *mi, BLOCK_SIZE bs,
210*fb1b10abSAndroid Build Coastguard Worker const uint8_t *y, const uint8_t *u, const uint8_t *v,
211*fb1b10abSAndroid Build Coastguard Worker int y_stride, int uv_stride, uint8_t *yd,
212*fb1b10abSAndroid Build Coastguard Worker uint8_t *ud, uint8_t *vd, int yd_stride,
213*fb1b10abSAndroid Build Coastguard Worker int uvd_stride) {
214*fb1b10abSAndroid Build Coastguard Worker int mi_offset, y_offset, uv_offset;
215*fb1b10abSAndroid Build Coastguard Worker const BLOCK_SIZE cur_bs = mi->sb_type;
216*fb1b10abSAndroid Build Coastguard Worker const int qdiff = cm->base_qindex - cm->postproc_state.last_base_qindex;
217*fb1b10abSAndroid Build Coastguard Worker const int bsl = b_width_log2_lookup[bs];
218*fb1b10abSAndroid Build Coastguard Worker PARTITION_TYPE partition = partition_lookup[bsl][cur_bs];
219*fb1b10abSAndroid Build Coastguard Worker const BLOCK_SIZE subsize = get_subsize(bs, partition);
220*fb1b10abSAndroid Build Coastguard Worker BLOCK_SIZE mfqe_bs, bs_tmp;
221*fb1b10abSAndroid Build Coastguard Worker
222*fb1b10abSAndroid Build Coastguard Worker if (cur_bs < BLOCK_8X8) {
223*fb1b10abSAndroid Build Coastguard Worker // If there are blocks smaller than 8x8, it must be on the boundary.
224*fb1b10abSAndroid Build Coastguard Worker return;
225*fb1b10abSAndroid Build Coastguard Worker }
226*fb1b10abSAndroid Build Coastguard Worker // No MFQE on blocks smaller than 16x16
227*fb1b10abSAndroid Build Coastguard Worker if (bs == BLOCK_16X16) {
228*fb1b10abSAndroid Build Coastguard Worker partition = PARTITION_NONE;
229*fb1b10abSAndroid Build Coastguard Worker }
230*fb1b10abSAndroid Build Coastguard Worker if (bs == BLOCK_64X64) {
231*fb1b10abSAndroid Build Coastguard Worker mi_offset = 4;
232*fb1b10abSAndroid Build Coastguard Worker y_offset = 32;
233*fb1b10abSAndroid Build Coastguard Worker uv_offset = 16;
234*fb1b10abSAndroid Build Coastguard Worker } else {
235*fb1b10abSAndroid Build Coastguard Worker mi_offset = 2;
236*fb1b10abSAndroid Build Coastguard Worker y_offset = 16;
237*fb1b10abSAndroid Build Coastguard Worker uv_offset = 8;
238*fb1b10abSAndroid Build Coastguard Worker }
239*fb1b10abSAndroid Build Coastguard Worker switch (partition) {
240*fb1b10abSAndroid Build Coastguard Worker case PARTITION_HORZ:
241*fb1b10abSAndroid Build Coastguard Worker if (bs == BLOCK_64X64) {
242*fb1b10abSAndroid Build Coastguard Worker mfqe_bs = BLOCK_64X32;
243*fb1b10abSAndroid Build Coastguard Worker bs_tmp = BLOCK_32X32;
244*fb1b10abSAndroid Build Coastguard Worker } else {
245*fb1b10abSAndroid Build Coastguard Worker mfqe_bs = BLOCK_32X16;
246*fb1b10abSAndroid Build Coastguard Worker bs_tmp = BLOCK_16X16;
247*fb1b10abSAndroid Build Coastguard Worker }
248*fb1b10abSAndroid Build Coastguard Worker if (mfqe_decision(mi, mfqe_bs)) {
249*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on the first square partition.
250*fb1b10abSAndroid Build Coastguard Worker mfqe_block(bs_tmp, y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride,
251*fb1b10abSAndroid Build Coastguard Worker uvd_stride, qdiff);
252*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on the second square partition.
253*fb1b10abSAndroid Build Coastguard Worker mfqe_block(bs_tmp, y + y_offset, u + uv_offset, v + uv_offset, y_stride,
254*fb1b10abSAndroid Build Coastguard Worker uv_stride, yd + y_offset, ud + uv_offset, vd + uv_offset,
255*fb1b10abSAndroid Build Coastguard Worker yd_stride, uvd_stride, qdiff);
256*fb1b10abSAndroid Build Coastguard Worker }
257*fb1b10abSAndroid Build Coastguard Worker if (mfqe_decision(mi + mi_offset * cm->mi_stride, mfqe_bs)) {
258*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on the first square partition.
259*fb1b10abSAndroid Build Coastguard Worker mfqe_block(bs_tmp, y + y_offset * y_stride, u + uv_offset * uv_stride,
260*fb1b10abSAndroid Build Coastguard Worker v + uv_offset * uv_stride, y_stride, uv_stride,
261*fb1b10abSAndroid Build Coastguard Worker yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
262*fb1b10abSAndroid Build Coastguard Worker vd + uv_offset * uvd_stride, yd_stride, uvd_stride, qdiff);
263*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on the second square partition.
264*fb1b10abSAndroid Build Coastguard Worker mfqe_block(bs_tmp, y + y_offset * y_stride + y_offset,
265*fb1b10abSAndroid Build Coastguard Worker u + uv_offset * uv_stride + uv_offset,
266*fb1b10abSAndroid Build Coastguard Worker v + uv_offset * uv_stride + uv_offset, y_stride, uv_stride,
267*fb1b10abSAndroid Build Coastguard Worker yd + y_offset * yd_stride + y_offset,
268*fb1b10abSAndroid Build Coastguard Worker ud + uv_offset * uvd_stride + uv_offset,
269*fb1b10abSAndroid Build Coastguard Worker vd + uv_offset * uvd_stride + uv_offset, yd_stride,
270*fb1b10abSAndroid Build Coastguard Worker uvd_stride, qdiff);
271*fb1b10abSAndroid Build Coastguard Worker }
272*fb1b10abSAndroid Build Coastguard Worker break;
273*fb1b10abSAndroid Build Coastguard Worker case PARTITION_VERT:
274*fb1b10abSAndroid Build Coastguard Worker if (bs == BLOCK_64X64) {
275*fb1b10abSAndroid Build Coastguard Worker mfqe_bs = BLOCK_32X64;
276*fb1b10abSAndroid Build Coastguard Worker bs_tmp = BLOCK_32X32;
277*fb1b10abSAndroid Build Coastguard Worker } else {
278*fb1b10abSAndroid Build Coastguard Worker mfqe_bs = BLOCK_16X32;
279*fb1b10abSAndroid Build Coastguard Worker bs_tmp = BLOCK_16X16;
280*fb1b10abSAndroid Build Coastguard Worker }
281*fb1b10abSAndroid Build Coastguard Worker if (mfqe_decision(mi, mfqe_bs)) {
282*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on the first square partition.
283*fb1b10abSAndroid Build Coastguard Worker mfqe_block(bs_tmp, y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride,
284*fb1b10abSAndroid Build Coastguard Worker uvd_stride, qdiff);
285*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on the second square partition.
286*fb1b10abSAndroid Build Coastguard Worker mfqe_block(bs_tmp, y + y_offset * y_stride, u + uv_offset * uv_stride,
287*fb1b10abSAndroid Build Coastguard Worker v + uv_offset * uv_stride, y_stride, uv_stride,
288*fb1b10abSAndroid Build Coastguard Worker yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
289*fb1b10abSAndroid Build Coastguard Worker vd + uv_offset * uvd_stride, yd_stride, uvd_stride, qdiff);
290*fb1b10abSAndroid Build Coastguard Worker }
291*fb1b10abSAndroid Build Coastguard Worker if (mfqe_decision(mi + mi_offset, mfqe_bs)) {
292*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on the first square partition.
293*fb1b10abSAndroid Build Coastguard Worker mfqe_block(bs_tmp, y + y_offset, u + uv_offset, v + uv_offset, y_stride,
294*fb1b10abSAndroid Build Coastguard Worker uv_stride, yd + y_offset, ud + uv_offset, vd + uv_offset,
295*fb1b10abSAndroid Build Coastguard Worker yd_stride, uvd_stride, qdiff);
296*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on the second square partition.
297*fb1b10abSAndroid Build Coastguard Worker mfqe_block(bs_tmp, y + y_offset * y_stride + y_offset,
298*fb1b10abSAndroid Build Coastguard Worker u + uv_offset * uv_stride + uv_offset,
299*fb1b10abSAndroid Build Coastguard Worker v + uv_offset * uv_stride + uv_offset, y_stride, uv_stride,
300*fb1b10abSAndroid Build Coastguard Worker yd + y_offset * yd_stride + y_offset,
301*fb1b10abSAndroid Build Coastguard Worker ud + uv_offset * uvd_stride + uv_offset,
302*fb1b10abSAndroid Build Coastguard Worker vd + uv_offset * uvd_stride + uv_offset, yd_stride,
303*fb1b10abSAndroid Build Coastguard Worker uvd_stride, qdiff);
304*fb1b10abSAndroid Build Coastguard Worker }
305*fb1b10abSAndroid Build Coastguard Worker break;
306*fb1b10abSAndroid Build Coastguard Worker case PARTITION_NONE:
307*fb1b10abSAndroid Build Coastguard Worker if (mfqe_decision(mi, cur_bs)) {
308*fb1b10abSAndroid Build Coastguard Worker // Do mfqe on this partition.
309*fb1b10abSAndroid Build Coastguard Worker mfqe_block(cur_bs, y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride,
310*fb1b10abSAndroid Build Coastguard Worker uvd_stride, qdiff);
311*fb1b10abSAndroid Build Coastguard Worker } else {
312*fb1b10abSAndroid Build Coastguard Worker // Copy the block from current frame(i.e., no mfqe is done).
313*fb1b10abSAndroid Build Coastguard Worker copy_block(y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride,
314*fb1b10abSAndroid Build Coastguard Worker uvd_stride, bs);
315*fb1b10abSAndroid Build Coastguard Worker }
316*fb1b10abSAndroid Build Coastguard Worker break;
317*fb1b10abSAndroid Build Coastguard Worker case PARTITION_SPLIT:
318*fb1b10abSAndroid Build Coastguard Worker // Recursion on four square partitions, e.g. if bs is 64X64,
319*fb1b10abSAndroid Build Coastguard Worker // then look into four 32X32 blocks in it.
320*fb1b10abSAndroid Build Coastguard Worker mfqe_partition(cm, mi, subsize, y, u, v, y_stride, uv_stride, yd, ud, vd,
321*fb1b10abSAndroid Build Coastguard Worker yd_stride, uvd_stride);
322*fb1b10abSAndroid Build Coastguard Worker mfqe_partition(cm, mi + mi_offset, subsize, y + y_offset, u + uv_offset,
323*fb1b10abSAndroid Build Coastguard Worker v + uv_offset, y_stride, uv_stride, yd + y_offset,
324*fb1b10abSAndroid Build Coastguard Worker ud + uv_offset, vd + uv_offset, yd_stride, uvd_stride);
325*fb1b10abSAndroid Build Coastguard Worker mfqe_partition(cm, mi + mi_offset * cm->mi_stride, subsize,
326*fb1b10abSAndroid Build Coastguard Worker y + y_offset * y_stride, u + uv_offset * uv_stride,
327*fb1b10abSAndroid Build Coastguard Worker v + uv_offset * uv_stride, y_stride, uv_stride,
328*fb1b10abSAndroid Build Coastguard Worker yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
329*fb1b10abSAndroid Build Coastguard Worker vd + uv_offset * uvd_stride, yd_stride, uvd_stride);
330*fb1b10abSAndroid Build Coastguard Worker mfqe_partition(cm, mi + mi_offset * cm->mi_stride + mi_offset, subsize,
331*fb1b10abSAndroid Build Coastguard Worker y + y_offset * y_stride + y_offset,
332*fb1b10abSAndroid Build Coastguard Worker u + uv_offset * uv_stride + uv_offset,
333*fb1b10abSAndroid Build Coastguard Worker v + uv_offset * uv_stride + uv_offset, y_stride, uv_stride,
334*fb1b10abSAndroid Build Coastguard Worker yd + y_offset * yd_stride + y_offset,
335*fb1b10abSAndroid Build Coastguard Worker ud + uv_offset * uvd_stride + uv_offset,
336*fb1b10abSAndroid Build Coastguard Worker vd + uv_offset * uvd_stride + uv_offset, yd_stride,
337*fb1b10abSAndroid Build Coastguard Worker uvd_stride);
338*fb1b10abSAndroid Build Coastguard Worker break;
339*fb1b10abSAndroid Build Coastguard Worker default: assert(0);
340*fb1b10abSAndroid Build Coastguard Worker }
341*fb1b10abSAndroid Build Coastguard Worker }
342*fb1b10abSAndroid Build Coastguard Worker
vp9_mfqe(VP9_COMMON * cm)343*fb1b10abSAndroid Build Coastguard Worker void vp9_mfqe(VP9_COMMON *cm) {
344*fb1b10abSAndroid Build Coastguard Worker int mi_row, mi_col;
345*fb1b10abSAndroid Build Coastguard Worker // Current decoded frame.
346*fb1b10abSAndroid Build Coastguard Worker const YV12_BUFFER_CONFIG *show = cm->frame_to_show;
347*fb1b10abSAndroid Build Coastguard Worker // Last decoded frame and will store the MFQE result.
348*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *dest = &cm->post_proc_buffer;
349*fb1b10abSAndroid Build Coastguard Worker // Loop through each super block.
350*fb1b10abSAndroid Build Coastguard Worker for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MI_BLOCK_SIZE) {
351*fb1b10abSAndroid Build Coastguard Worker for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE) {
352*fb1b10abSAndroid Build Coastguard Worker MODE_INFO *mi;
353*fb1b10abSAndroid Build Coastguard Worker MODE_INFO *mi_local = cm->mi + (mi_row * cm->mi_stride + mi_col);
354*fb1b10abSAndroid Build Coastguard Worker // Motion Info in last frame.
355*fb1b10abSAndroid Build Coastguard Worker MODE_INFO *mi_prev =
356*fb1b10abSAndroid Build Coastguard Worker cm->postproc_state.prev_mi + (mi_row * cm->mi_stride + mi_col);
357*fb1b10abSAndroid Build Coastguard Worker const uint32_t y_stride = show->y_stride;
358*fb1b10abSAndroid Build Coastguard Worker const uint32_t uv_stride = show->uv_stride;
359*fb1b10abSAndroid Build Coastguard Worker const uint32_t yd_stride = dest->y_stride;
360*fb1b10abSAndroid Build Coastguard Worker const uint32_t uvd_stride = dest->uv_stride;
361*fb1b10abSAndroid Build Coastguard Worker const uint32_t row_offset_y = mi_row << 3;
362*fb1b10abSAndroid Build Coastguard Worker const uint32_t row_offset_uv = mi_row << 2;
363*fb1b10abSAndroid Build Coastguard Worker const uint32_t col_offset_y = mi_col << 3;
364*fb1b10abSAndroid Build Coastguard Worker const uint32_t col_offset_uv = mi_col << 2;
365*fb1b10abSAndroid Build Coastguard Worker const uint8_t *y =
366*fb1b10abSAndroid Build Coastguard Worker show->y_buffer + row_offset_y * y_stride + col_offset_y;
367*fb1b10abSAndroid Build Coastguard Worker const uint8_t *u =
368*fb1b10abSAndroid Build Coastguard Worker show->u_buffer + row_offset_uv * uv_stride + col_offset_uv;
369*fb1b10abSAndroid Build Coastguard Worker const uint8_t *v =
370*fb1b10abSAndroid Build Coastguard Worker show->v_buffer + row_offset_uv * uv_stride + col_offset_uv;
371*fb1b10abSAndroid Build Coastguard Worker uint8_t *yd = dest->y_buffer + row_offset_y * yd_stride + col_offset_y;
372*fb1b10abSAndroid Build Coastguard Worker uint8_t *ud = dest->u_buffer + row_offset_uv * uvd_stride + col_offset_uv;
373*fb1b10abSAndroid Build Coastguard Worker uint8_t *vd = dest->v_buffer + row_offset_uv * uvd_stride + col_offset_uv;
374*fb1b10abSAndroid Build Coastguard Worker if (frame_is_intra_only(cm)) {
375*fb1b10abSAndroid Build Coastguard Worker mi = mi_prev;
376*fb1b10abSAndroid Build Coastguard Worker } else {
377*fb1b10abSAndroid Build Coastguard Worker mi = mi_local;
378*fb1b10abSAndroid Build Coastguard Worker }
379*fb1b10abSAndroid Build Coastguard Worker mfqe_partition(cm, mi, BLOCK_64X64, y, u, v, y_stride, uv_stride, yd, ud,
380*fb1b10abSAndroid Build Coastguard Worker vd, yd_stride, uvd_stride);
381*fb1b10abSAndroid Build Coastguard Worker }
382*fb1b10abSAndroid Build Coastguard Worker }
383*fb1b10abSAndroid Build Coastguard Worker }
384