1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2012 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 /* MFQE: Multiframe Quality Enhancement
12*fb1b10abSAndroid Build Coastguard Worker * In rate limited situations keyframes may cause significant visual artifacts
13*fb1b10abSAndroid Build Coastguard Worker * commonly referred to as "popping." This file implements a postproccesing
14*fb1b10abSAndroid Build Coastguard Worker * algorithm which blends data from the preceeding frame when there is no
15*fb1b10abSAndroid Build Coastguard Worker * motion and the q from the previous frame is lower which indicates that it is
16*fb1b10abSAndroid Build Coastguard Worker * higher quality.
17*fb1b10abSAndroid Build Coastguard Worker */
18*fb1b10abSAndroid Build Coastguard Worker
19*fb1b10abSAndroid Build Coastguard Worker #include "./vp8_rtcd.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/common.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/postproc.h"
23*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/variance.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "vpx_scale/yv12config.h"
26*fb1b10abSAndroid Build Coastguard Worker
27*fb1b10abSAndroid Build Coastguard Worker #include <limits.h>
28*fb1b10abSAndroid Build Coastguard Worker #include <stdlib.h>
29*fb1b10abSAndroid Build Coastguard Worker
filter_by_weight(unsigned char * src,int src_stride,unsigned char * dst,int dst_stride,int block_size,int src_weight)30*fb1b10abSAndroid Build Coastguard Worker static void filter_by_weight(unsigned char *src, int src_stride,
31*fb1b10abSAndroid Build Coastguard Worker unsigned char *dst, int dst_stride, int block_size,
32*fb1b10abSAndroid Build Coastguard Worker int src_weight) {
33*fb1b10abSAndroid Build Coastguard Worker int dst_weight = (1 << MFQE_PRECISION) - src_weight;
34*fb1b10abSAndroid Build Coastguard Worker int rounding_bit = 1 << (MFQE_PRECISION - 1);
35*fb1b10abSAndroid Build Coastguard Worker int r, c;
36*fb1b10abSAndroid Build Coastguard Worker
37*fb1b10abSAndroid Build Coastguard Worker for (r = 0; r < block_size; ++r) {
38*fb1b10abSAndroid Build Coastguard Worker for (c = 0; c < block_size; ++c) {
39*fb1b10abSAndroid Build Coastguard Worker dst[c] = (src[c] * src_weight + dst[c] * dst_weight + rounding_bit) >>
40*fb1b10abSAndroid Build Coastguard Worker MFQE_PRECISION;
41*fb1b10abSAndroid Build Coastguard Worker }
42*fb1b10abSAndroid Build Coastguard Worker src += src_stride;
43*fb1b10abSAndroid Build Coastguard Worker dst += dst_stride;
44*fb1b10abSAndroid Build Coastguard Worker }
45*fb1b10abSAndroid Build Coastguard Worker }
46*fb1b10abSAndroid Build Coastguard Worker
vp8_filter_by_weight16x16_c(unsigned char * src,int src_stride,unsigned char * dst,int dst_stride,int src_weight)47*fb1b10abSAndroid Build Coastguard Worker void vp8_filter_by_weight16x16_c(unsigned char *src, int src_stride,
48*fb1b10abSAndroid Build Coastguard Worker unsigned char *dst, int dst_stride,
49*fb1b10abSAndroid Build Coastguard Worker int src_weight) {
50*fb1b10abSAndroid Build Coastguard Worker filter_by_weight(src, src_stride, dst, dst_stride, 16, src_weight);
51*fb1b10abSAndroid Build Coastguard Worker }
52*fb1b10abSAndroid Build Coastguard Worker
vp8_filter_by_weight8x8_c(unsigned char * src,int src_stride,unsigned char * dst,int dst_stride,int src_weight)53*fb1b10abSAndroid Build Coastguard Worker void vp8_filter_by_weight8x8_c(unsigned char *src, int src_stride,
54*fb1b10abSAndroid Build Coastguard Worker unsigned char *dst, int dst_stride,
55*fb1b10abSAndroid Build Coastguard Worker int src_weight) {
56*fb1b10abSAndroid Build Coastguard Worker filter_by_weight(src, src_stride, dst, dst_stride, 8, src_weight);
57*fb1b10abSAndroid Build Coastguard Worker }
58*fb1b10abSAndroid Build Coastguard Worker
vp8_filter_by_weight4x4_c(unsigned char * src,int src_stride,unsigned char * dst,int dst_stride,int src_weight)59*fb1b10abSAndroid Build Coastguard Worker void vp8_filter_by_weight4x4_c(unsigned char *src, int src_stride,
60*fb1b10abSAndroid Build Coastguard Worker unsigned char *dst, int dst_stride,
61*fb1b10abSAndroid Build Coastguard Worker int src_weight) {
62*fb1b10abSAndroid Build Coastguard Worker filter_by_weight(src, src_stride, dst, dst_stride, 4, src_weight);
63*fb1b10abSAndroid Build Coastguard Worker }
64*fb1b10abSAndroid Build Coastguard Worker
apply_ifactor(unsigned char * y_src,int y_src_stride,unsigned char * y_dst,int y_dst_stride,unsigned char * u_src,unsigned char * v_src,int uv_src_stride,unsigned char * u_dst,unsigned char * v_dst,int uv_dst_stride,int block_size,int src_weight)65*fb1b10abSAndroid Build Coastguard Worker static void apply_ifactor(unsigned char *y_src, int y_src_stride,
66*fb1b10abSAndroid Build Coastguard Worker unsigned char *y_dst, int y_dst_stride,
67*fb1b10abSAndroid Build Coastguard Worker unsigned char *u_src, unsigned char *v_src,
68*fb1b10abSAndroid Build Coastguard Worker int uv_src_stride, unsigned char *u_dst,
69*fb1b10abSAndroid Build Coastguard Worker unsigned char *v_dst, int uv_dst_stride,
70*fb1b10abSAndroid Build Coastguard Worker int block_size, int src_weight) {
71*fb1b10abSAndroid Build Coastguard Worker if (block_size == 16) {
72*fb1b10abSAndroid Build Coastguard Worker vp8_filter_by_weight16x16(y_src, y_src_stride, y_dst, y_dst_stride,
73*fb1b10abSAndroid Build Coastguard Worker src_weight);
74*fb1b10abSAndroid Build Coastguard Worker vp8_filter_by_weight8x8(u_src, uv_src_stride, u_dst, uv_dst_stride,
75*fb1b10abSAndroid Build Coastguard Worker src_weight);
76*fb1b10abSAndroid Build Coastguard Worker vp8_filter_by_weight8x8(v_src, uv_src_stride, v_dst, uv_dst_stride,
77*fb1b10abSAndroid Build Coastguard Worker src_weight);
78*fb1b10abSAndroid Build Coastguard Worker } else {
79*fb1b10abSAndroid Build Coastguard Worker vp8_filter_by_weight8x8(y_src, y_src_stride, y_dst, y_dst_stride,
80*fb1b10abSAndroid Build Coastguard Worker src_weight);
81*fb1b10abSAndroid Build Coastguard Worker vp8_filter_by_weight4x4(u_src, uv_src_stride, u_dst, uv_dst_stride,
82*fb1b10abSAndroid Build Coastguard Worker src_weight);
83*fb1b10abSAndroid Build Coastguard Worker vp8_filter_by_weight4x4(v_src, uv_src_stride, v_dst, uv_dst_stride,
84*fb1b10abSAndroid Build Coastguard Worker src_weight);
85*fb1b10abSAndroid Build Coastguard Worker }
86*fb1b10abSAndroid Build Coastguard Worker }
87*fb1b10abSAndroid Build Coastguard Worker
int_sqrt(unsigned int x)88*fb1b10abSAndroid Build Coastguard Worker static unsigned int int_sqrt(unsigned int x) {
89*fb1b10abSAndroid Build Coastguard Worker unsigned int y = x;
90*fb1b10abSAndroid Build Coastguard Worker unsigned int guess;
91*fb1b10abSAndroid Build Coastguard Worker int p = 1;
92*fb1b10abSAndroid Build Coastguard Worker while (y >>= 1) p++;
93*fb1b10abSAndroid Build Coastguard Worker p >>= 1;
94*fb1b10abSAndroid Build Coastguard Worker
95*fb1b10abSAndroid Build Coastguard Worker guess = 0;
96*fb1b10abSAndroid Build Coastguard Worker while (p >= 0) {
97*fb1b10abSAndroid Build Coastguard Worker guess |= (1 << p);
98*fb1b10abSAndroid Build Coastguard Worker if (x < guess * guess) guess -= (1 << p);
99*fb1b10abSAndroid Build Coastguard Worker p--;
100*fb1b10abSAndroid Build Coastguard Worker }
101*fb1b10abSAndroid Build Coastguard Worker /* choose between guess or guess+1 */
102*fb1b10abSAndroid Build Coastguard Worker return guess + (guess * guess + guess + 1 <= x);
103*fb1b10abSAndroid Build Coastguard Worker }
104*fb1b10abSAndroid Build Coastguard Worker
105*fb1b10abSAndroid Build Coastguard Worker #define USE_SSD
multiframe_quality_enhance_block(int blksize,int qcurr,int qprev,unsigned char * y,unsigned char * u,unsigned char * v,int y_stride,int uv_stride,unsigned char * yd,unsigned char * ud,unsigned char * vd,int yd_stride,int uvd_stride)106*fb1b10abSAndroid Build Coastguard Worker static void multiframe_quality_enhance_block(
107*fb1b10abSAndroid Build Coastguard Worker int blksize, /* Currently only values supported are 16, 8 */
108*fb1b10abSAndroid Build Coastguard Worker int qcurr, int qprev, unsigned char *y, unsigned char *u, unsigned char *v,
109*fb1b10abSAndroid Build Coastguard Worker int y_stride, int uv_stride, unsigned char *yd, unsigned char *ud,
110*fb1b10abSAndroid Build Coastguard Worker unsigned char *vd, int yd_stride, int uvd_stride) {
111*fb1b10abSAndroid Build Coastguard Worker static const unsigned char VP8_ZEROS[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
112*fb1b10abSAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0 };
113*fb1b10abSAndroid Build Coastguard Worker int uvblksize = blksize >> 1;
114*fb1b10abSAndroid Build Coastguard Worker int qdiff = qcurr - qprev;
115*fb1b10abSAndroid Build Coastguard Worker
116*fb1b10abSAndroid Build Coastguard Worker int i;
117*fb1b10abSAndroid Build Coastguard Worker unsigned char *up;
118*fb1b10abSAndroid Build Coastguard Worker unsigned char *udp;
119*fb1b10abSAndroid Build Coastguard Worker unsigned char *vp;
120*fb1b10abSAndroid Build Coastguard Worker unsigned char *vdp;
121*fb1b10abSAndroid Build Coastguard Worker
122*fb1b10abSAndroid Build Coastguard Worker unsigned int act, actd, sad, usad, vsad, sse, thr, thrsq, actrisk;
123*fb1b10abSAndroid Build Coastguard Worker
124*fb1b10abSAndroid Build Coastguard Worker if (blksize == 16) {
125*fb1b10abSAndroid Build Coastguard Worker actd = (vpx_variance16x16(yd, yd_stride, VP8_ZEROS, 0, &sse) + 128) >> 8;
126*fb1b10abSAndroid Build Coastguard Worker act = (vpx_variance16x16(y, y_stride, VP8_ZEROS, 0, &sse) + 128) >> 8;
127*fb1b10abSAndroid Build Coastguard Worker #ifdef USE_SSD
128*fb1b10abSAndroid Build Coastguard Worker vpx_variance16x16(y, y_stride, yd, yd_stride, &sse);
129*fb1b10abSAndroid Build Coastguard Worker sad = (sse + 128) >> 8;
130*fb1b10abSAndroid Build Coastguard Worker vpx_variance8x8(u, uv_stride, ud, uvd_stride, &sse);
131*fb1b10abSAndroid Build Coastguard Worker usad = (sse + 32) >> 6;
132*fb1b10abSAndroid Build Coastguard Worker vpx_variance8x8(v, uv_stride, vd, uvd_stride, &sse);
133*fb1b10abSAndroid Build Coastguard Worker vsad = (sse + 32) >> 6;
134*fb1b10abSAndroid Build Coastguard Worker #else
135*fb1b10abSAndroid Build Coastguard Worker sad = (vpx_sad16x16(y, y_stride, yd, yd_stride) + 128) >> 8;
136*fb1b10abSAndroid Build Coastguard Worker usad = (vpx_sad8x8(u, uv_stride, ud, uvd_stride) + 32) >> 6;
137*fb1b10abSAndroid Build Coastguard Worker vsad = (vpx_sad8x8(v, uv_stride, vd, uvd_stride) + 32) >> 6;
138*fb1b10abSAndroid Build Coastguard Worker #endif
139*fb1b10abSAndroid Build Coastguard Worker } else {
140*fb1b10abSAndroid Build Coastguard Worker actd = (vpx_variance8x8(yd, yd_stride, VP8_ZEROS, 0, &sse) + 32) >> 6;
141*fb1b10abSAndroid Build Coastguard Worker act = (vpx_variance8x8(y, y_stride, VP8_ZEROS, 0, &sse) + 32) >> 6;
142*fb1b10abSAndroid Build Coastguard Worker #ifdef USE_SSD
143*fb1b10abSAndroid Build Coastguard Worker vpx_variance8x8(y, y_stride, yd, yd_stride, &sse);
144*fb1b10abSAndroid Build Coastguard Worker sad = (sse + 32) >> 6;
145*fb1b10abSAndroid Build Coastguard Worker vpx_variance4x4(u, uv_stride, ud, uvd_stride, &sse);
146*fb1b10abSAndroid Build Coastguard Worker usad = (sse + 8) >> 4;
147*fb1b10abSAndroid Build Coastguard Worker vpx_variance4x4(v, uv_stride, vd, uvd_stride, &sse);
148*fb1b10abSAndroid Build Coastguard Worker vsad = (sse + 8) >> 4;
149*fb1b10abSAndroid Build Coastguard Worker #else
150*fb1b10abSAndroid Build Coastguard Worker sad = (vpx_sad8x8(y, y_stride, yd, yd_stride) + 32) >> 6;
151*fb1b10abSAndroid Build Coastguard Worker usad = (vpx_sad4x4(u, uv_stride, ud, uvd_stride) + 8) >> 4;
152*fb1b10abSAndroid Build Coastguard Worker vsad = (vpx_sad4x4(v, uv_stride, vd, uvd_stride) + 8) >> 4;
153*fb1b10abSAndroid Build Coastguard Worker #endif
154*fb1b10abSAndroid Build Coastguard Worker }
155*fb1b10abSAndroid Build Coastguard Worker
156*fb1b10abSAndroid Build Coastguard Worker actrisk = (actd > act * 5);
157*fb1b10abSAndroid Build Coastguard Worker
158*fb1b10abSAndroid Build Coastguard Worker /* thr = qdiff/16 + log2(act) + log4(qprev) */
159*fb1b10abSAndroid Build Coastguard Worker thr = (qdiff >> 4);
160*fb1b10abSAndroid Build Coastguard Worker while (actd >>= 1) thr++;
161*fb1b10abSAndroid Build Coastguard Worker while (qprev >>= 2) thr++;
162*fb1b10abSAndroid Build Coastguard Worker
163*fb1b10abSAndroid Build Coastguard Worker #ifdef USE_SSD
164*fb1b10abSAndroid Build Coastguard Worker thrsq = thr * thr;
165*fb1b10abSAndroid Build Coastguard Worker if (sad < thrsq &&
166*fb1b10abSAndroid Build Coastguard Worker /* additional checks for color mismatch and excessive addition of
167*fb1b10abSAndroid Build Coastguard Worker * high-frequencies */
168*fb1b10abSAndroid Build Coastguard Worker 4 * usad < thrsq && 4 * vsad < thrsq && !actrisk)
169*fb1b10abSAndroid Build Coastguard Worker #else
170*fb1b10abSAndroid Build Coastguard Worker if (sad < thr &&
171*fb1b10abSAndroid Build Coastguard Worker /* additional checks for color mismatch and excessive addition of
172*fb1b10abSAndroid Build Coastguard Worker * high-frequencies */
173*fb1b10abSAndroid Build Coastguard Worker 2 * usad < thr && 2 * vsad < thr && !actrisk)
174*fb1b10abSAndroid Build Coastguard Worker #endif
175*fb1b10abSAndroid Build Coastguard Worker {
176*fb1b10abSAndroid Build Coastguard Worker int ifactor;
177*fb1b10abSAndroid Build Coastguard Worker #ifdef USE_SSD
178*fb1b10abSAndroid Build Coastguard Worker /* TODO: optimize this later to not need sqr root */
179*fb1b10abSAndroid Build Coastguard Worker sad = int_sqrt(sad);
180*fb1b10abSAndroid Build Coastguard Worker #endif
181*fb1b10abSAndroid Build Coastguard Worker ifactor = (sad << MFQE_PRECISION) / thr;
182*fb1b10abSAndroid Build Coastguard Worker ifactor >>= (qdiff >> 5);
183*fb1b10abSAndroid Build Coastguard Worker
184*fb1b10abSAndroid Build Coastguard Worker if (ifactor) {
185*fb1b10abSAndroid Build Coastguard Worker apply_ifactor(y, y_stride, yd, yd_stride, u, v, uv_stride, ud, vd,
186*fb1b10abSAndroid Build Coastguard Worker uvd_stride, blksize, ifactor);
187*fb1b10abSAndroid Build Coastguard Worker }
188*fb1b10abSAndroid Build Coastguard Worker } else { /* else implicitly copy from previous frame */
189*fb1b10abSAndroid Build Coastguard Worker if (blksize == 16) {
190*fb1b10abSAndroid Build Coastguard Worker vp8_copy_mem16x16(y, y_stride, yd, yd_stride);
191*fb1b10abSAndroid Build Coastguard Worker vp8_copy_mem8x8(u, uv_stride, ud, uvd_stride);
192*fb1b10abSAndroid Build Coastguard Worker vp8_copy_mem8x8(v, uv_stride, vd, uvd_stride);
193*fb1b10abSAndroid Build Coastguard Worker } else {
194*fb1b10abSAndroid Build Coastguard Worker vp8_copy_mem8x8(y, y_stride, yd, yd_stride);
195*fb1b10abSAndroid Build Coastguard Worker for (up = u, udp = ud, i = 0; i < uvblksize;
196*fb1b10abSAndroid Build Coastguard Worker ++i, up += uv_stride, udp += uvd_stride) {
197*fb1b10abSAndroid Build Coastguard Worker memcpy(udp, up, uvblksize);
198*fb1b10abSAndroid Build Coastguard Worker }
199*fb1b10abSAndroid Build Coastguard Worker for (vp = v, vdp = vd, i = 0; i < uvblksize;
200*fb1b10abSAndroid Build Coastguard Worker ++i, vp += uv_stride, vdp += uvd_stride) {
201*fb1b10abSAndroid Build Coastguard Worker memcpy(vdp, vp, uvblksize);
202*fb1b10abSAndroid Build Coastguard Worker }
203*fb1b10abSAndroid Build Coastguard Worker }
204*fb1b10abSAndroid Build Coastguard Worker }
205*fb1b10abSAndroid Build Coastguard Worker }
206*fb1b10abSAndroid Build Coastguard Worker
qualify_inter_mb(const MODE_INFO * mode_info_context,int * map)207*fb1b10abSAndroid Build Coastguard Worker static int qualify_inter_mb(const MODE_INFO *mode_info_context, int *map) {
208*fb1b10abSAndroid Build Coastguard Worker if (mode_info_context->mbmi.mb_skip_coeff) {
209*fb1b10abSAndroid Build Coastguard Worker map[0] = map[1] = map[2] = map[3] = 1;
210*fb1b10abSAndroid Build Coastguard Worker } else if (mode_info_context->mbmi.mode == SPLITMV) {
211*fb1b10abSAndroid Build Coastguard Worker static int ndx[4][4] = {
212*fb1b10abSAndroid Build Coastguard Worker { 0, 1, 4, 5 }, { 2, 3, 6, 7 }, { 8, 9, 12, 13 }, { 10, 11, 14, 15 }
213*fb1b10abSAndroid Build Coastguard Worker };
214*fb1b10abSAndroid Build Coastguard Worker int i, j;
215*fb1b10abSAndroid Build Coastguard Worker vp8_zero(*map);
216*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 4; ++i) {
217*fb1b10abSAndroid Build Coastguard Worker map[i] = 1;
218*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 4 && map[j]; ++j) {
219*fb1b10abSAndroid Build Coastguard Worker map[i] &= (mode_info_context->bmi[ndx[i][j]].mv.as_mv.row <= 2 &&
220*fb1b10abSAndroid Build Coastguard Worker mode_info_context->bmi[ndx[i][j]].mv.as_mv.col <= 2);
221*fb1b10abSAndroid Build Coastguard Worker }
222*fb1b10abSAndroid Build Coastguard Worker }
223*fb1b10abSAndroid Build Coastguard Worker } else {
224*fb1b10abSAndroid Build Coastguard Worker map[0] = map[1] = map[2] = map[3] =
225*fb1b10abSAndroid Build Coastguard Worker (mode_info_context->mbmi.mode > B_PRED &&
226*fb1b10abSAndroid Build Coastguard Worker abs(mode_info_context->mbmi.mv.as_mv.row) <= 2 &&
227*fb1b10abSAndroid Build Coastguard Worker abs(mode_info_context->mbmi.mv.as_mv.col) <= 2);
228*fb1b10abSAndroid Build Coastguard Worker }
229*fb1b10abSAndroid Build Coastguard Worker return (map[0] + map[1] + map[2] + map[3]);
230*fb1b10abSAndroid Build Coastguard Worker }
231*fb1b10abSAndroid Build Coastguard Worker
vp8_multiframe_quality_enhance(VP8_COMMON * cm)232*fb1b10abSAndroid Build Coastguard Worker void vp8_multiframe_quality_enhance(VP8_COMMON *cm) {
233*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *show = cm->frame_to_show;
234*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *dest = &cm->post_proc_buffer;
235*fb1b10abSAndroid Build Coastguard Worker
236*fb1b10abSAndroid Build Coastguard Worker FRAME_TYPE frame_type = cm->frame_type;
237*fb1b10abSAndroid Build Coastguard Worker /* Point at base of Mb MODE_INFO list has motion vectors etc */
238*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *mode_info_context = cm->mi;
239*fb1b10abSAndroid Build Coastguard Worker int mb_row;
240*fb1b10abSAndroid Build Coastguard Worker int mb_col;
241*fb1b10abSAndroid Build Coastguard Worker int totmap, map[4];
242*fb1b10abSAndroid Build Coastguard Worker int qcurr = cm->base_qindex;
243*fb1b10abSAndroid Build Coastguard Worker int qprev = cm->postproc_state.last_base_qindex;
244*fb1b10abSAndroid Build Coastguard Worker
245*fb1b10abSAndroid Build Coastguard Worker unsigned char *y_ptr, *u_ptr, *v_ptr;
246*fb1b10abSAndroid Build Coastguard Worker unsigned char *yd_ptr, *ud_ptr, *vd_ptr;
247*fb1b10abSAndroid Build Coastguard Worker
248*fb1b10abSAndroid Build Coastguard Worker /* Set up the buffer pointers */
249*fb1b10abSAndroid Build Coastguard Worker y_ptr = show->y_buffer;
250*fb1b10abSAndroid Build Coastguard Worker u_ptr = show->u_buffer;
251*fb1b10abSAndroid Build Coastguard Worker v_ptr = show->v_buffer;
252*fb1b10abSAndroid Build Coastguard Worker yd_ptr = dest->y_buffer;
253*fb1b10abSAndroid Build Coastguard Worker ud_ptr = dest->u_buffer;
254*fb1b10abSAndroid Build Coastguard Worker vd_ptr = dest->v_buffer;
255*fb1b10abSAndroid Build Coastguard Worker
256*fb1b10abSAndroid Build Coastguard Worker /* postprocess each macro block */
257*fb1b10abSAndroid Build Coastguard Worker for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
258*fb1b10abSAndroid Build Coastguard Worker for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
259*fb1b10abSAndroid Build Coastguard Worker /* if motion is high there will likely be no benefit */
260*fb1b10abSAndroid Build Coastguard Worker if (frame_type == INTER_FRAME) {
261*fb1b10abSAndroid Build Coastguard Worker totmap = qualify_inter_mb(mode_info_context, map);
262*fb1b10abSAndroid Build Coastguard Worker } else {
263*fb1b10abSAndroid Build Coastguard Worker totmap = (frame_type == KEY_FRAME ? 4 : 0);
264*fb1b10abSAndroid Build Coastguard Worker }
265*fb1b10abSAndroid Build Coastguard Worker if (totmap) {
266*fb1b10abSAndroid Build Coastguard Worker if (totmap < 4) {
267*fb1b10abSAndroid Build Coastguard Worker int i, j;
268*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 2; ++i) {
269*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 2; ++j) {
270*fb1b10abSAndroid Build Coastguard Worker if (map[i * 2 + j]) {
271*fb1b10abSAndroid Build Coastguard Worker multiframe_quality_enhance_block(
272*fb1b10abSAndroid Build Coastguard Worker 8, qcurr, qprev, y_ptr + 8 * (i * show->y_stride + j),
273*fb1b10abSAndroid Build Coastguard Worker u_ptr + 4 * (i * show->uv_stride + j),
274*fb1b10abSAndroid Build Coastguard Worker v_ptr + 4 * (i * show->uv_stride + j), show->y_stride,
275*fb1b10abSAndroid Build Coastguard Worker show->uv_stride, yd_ptr + 8 * (i * dest->y_stride + j),
276*fb1b10abSAndroid Build Coastguard Worker ud_ptr + 4 * (i * dest->uv_stride + j),
277*fb1b10abSAndroid Build Coastguard Worker vd_ptr + 4 * (i * dest->uv_stride + j), dest->y_stride,
278*fb1b10abSAndroid Build Coastguard Worker dest->uv_stride);
279*fb1b10abSAndroid Build Coastguard Worker } else {
280*fb1b10abSAndroid Build Coastguard Worker /* copy a 8x8 block */
281*fb1b10abSAndroid Build Coastguard Worker int k;
282*fb1b10abSAndroid Build Coastguard Worker unsigned char *up = u_ptr + 4 * (i * show->uv_stride + j);
283*fb1b10abSAndroid Build Coastguard Worker unsigned char *udp = ud_ptr + 4 * (i * dest->uv_stride + j);
284*fb1b10abSAndroid Build Coastguard Worker unsigned char *vp = v_ptr + 4 * (i * show->uv_stride + j);
285*fb1b10abSAndroid Build Coastguard Worker unsigned char *vdp = vd_ptr + 4 * (i * dest->uv_stride + j);
286*fb1b10abSAndroid Build Coastguard Worker vp8_copy_mem8x8(
287*fb1b10abSAndroid Build Coastguard Worker y_ptr + 8 * (i * show->y_stride + j), show->y_stride,
288*fb1b10abSAndroid Build Coastguard Worker yd_ptr + 8 * (i * dest->y_stride + j), dest->y_stride);
289*fb1b10abSAndroid Build Coastguard Worker for (k = 0; k < 4; ++k, up += show->uv_stride,
290*fb1b10abSAndroid Build Coastguard Worker udp += dest->uv_stride, vp += show->uv_stride,
291*fb1b10abSAndroid Build Coastguard Worker vdp += dest->uv_stride) {
292*fb1b10abSAndroid Build Coastguard Worker memcpy(udp, up, 4);
293*fb1b10abSAndroid Build Coastguard Worker memcpy(vdp, vp, 4);
294*fb1b10abSAndroid Build Coastguard Worker }
295*fb1b10abSAndroid Build Coastguard Worker }
296*fb1b10abSAndroid Build Coastguard Worker }
297*fb1b10abSAndroid Build Coastguard Worker }
298*fb1b10abSAndroid Build Coastguard Worker } else { /* totmap = 4 */
299*fb1b10abSAndroid Build Coastguard Worker multiframe_quality_enhance_block(
300*fb1b10abSAndroid Build Coastguard Worker 16, qcurr, qprev, y_ptr, u_ptr, v_ptr, show->y_stride,
301*fb1b10abSAndroid Build Coastguard Worker show->uv_stride, yd_ptr, ud_ptr, vd_ptr, dest->y_stride,
302*fb1b10abSAndroid Build Coastguard Worker dest->uv_stride);
303*fb1b10abSAndroid Build Coastguard Worker }
304*fb1b10abSAndroid Build Coastguard Worker } else {
305*fb1b10abSAndroid Build Coastguard Worker vp8_copy_mem16x16(y_ptr, show->y_stride, yd_ptr, dest->y_stride);
306*fb1b10abSAndroid Build Coastguard Worker vp8_copy_mem8x8(u_ptr, show->uv_stride, ud_ptr, dest->uv_stride);
307*fb1b10abSAndroid Build Coastguard Worker vp8_copy_mem8x8(v_ptr, show->uv_stride, vd_ptr, dest->uv_stride);
308*fb1b10abSAndroid Build Coastguard Worker }
309*fb1b10abSAndroid Build Coastguard Worker y_ptr += 16;
310*fb1b10abSAndroid Build Coastguard Worker u_ptr += 8;
311*fb1b10abSAndroid Build Coastguard Worker v_ptr += 8;
312*fb1b10abSAndroid Build Coastguard Worker yd_ptr += 16;
313*fb1b10abSAndroid Build Coastguard Worker ud_ptr += 8;
314*fb1b10abSAndroid Build Coastguard Worker vd_ptr += 8;
315*fb1b10abSAndroid Build Coastguard Worker mode_info_context++; /* step to next MB */
316*fb1b10abSAndroid Build Coastguard Worker }
317*fb1b10abSAndroid Build Coastguard Worker
318*fb1b10abSAndroid Build Coastguard Worker y_ptr += show->y_stride * 16 - 16 * cm->mb_cols;
319*fb1b10abSAndroid Build Coastguard Worker u_ptr += show->uv_stride * 8 - 8 * cm->mb_cols;
320*fb1b10abSAndroid Build Coastguard Worker v_ptr += show->uv_stride * 8 - 8 * cm->mb_cols;
321*fb1b10abSAndroid Build Coastguard Worker yd_ptr += dest->y_stride * 16 - 16 * cm->mb_cols;
322*fb1b10abSAndroid Build Coastguard Worker ud_ptr += dest->uv_stride * 8 - 8 * cm->mb_cols;
323*fb1b10abSAndroid Build Coastguard Worker vd_ptr += dest->uv_stride * 8 - 8 * cm->mb_cols;
324*fb1b10abSAndroid Build Coastguard Worker
325*fb1b10abSAndroid Build Coastguard Worker mode_info_context++; /* Skip border mb */
326*fb1b10abSAndroid Build Coastguard Worker }
327*fb1b10abSAndroid Build Coastguard Worker }
328