1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2010 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 <limits.h>
12*fb1b10abSAndroid Build Coastguard Worker #include "vpx_config.h"
13*fb1b10abSAndroid Build Coastguard Worker #include "onyx_int.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "mr_dissim.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "rdopt.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/common.h"
19*fb1b10abSAndroid Build Coastguard Worker
vp8_cal_low_res_mb_cols(VP8_COMP * cpi)20*fb1b10abSAndroid Build Coastguard Worker void vp8_cal_low_res_mb_cols(VP8_COMP *cpi) {
21*fb1b10abSAndroid Build Coastguard Worker int low_res_w;
22*fb1b10abSAndroid Build Coastguard Worker
23*fb1b10abSAndroid Build Coastguard Worker /* Support arbitrary down-sampling factor */
24*fb1b10abSAndroid Build Coastguard Worker unsigned int iw = cpi->oxcf.Width * cpi->oxcf.mr_down_sampling_factor.den +
25*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_down_sampling_factor.num - 1;
26*fb1b10abSAndroid Build Coastguard Worker
27*fb1b10abSAndroid Build Coastguard Worker low_res_w = iw / cpi->oxcf.mr_down_sampling_factor.num;
28*fb1b10abSAndroid Build Coastguard Worker cpi->mr_low_res_mb_cols = ((low_res_w + 15) >> 4);
29*fb1b10abSAndroid Build Coastguard Worker }
30*fb1b10abSAndroid Build Coastguard Worker
31*fb1b10abSAndroid Build Coastguard Worker #define GET_MV(x) \
32*fb1b10abSAndroid Build Coastguard Worker if (x->mbmi.ref_frame != INTRA_FRAME) { \
33*fb1b10abSAndroid Build Coastguard Worker mvx[cnt] = x->mbmi.mv.as_mv.row; \
34*fb1b10abSAndroid Build Coastguard Worker mvy[cnt] = x->mbmi.mv.as_mv.col; \
35*fb1b10abSAndroid Build Coastguard Worker cnt++; \
36*fb1b10abSAndroid Build Coastguard Worker }
37*fb1b10abSAndroid Build Coastguard Worker
38*fb1b10abSAndroid Build Coastguard Worker #define GET_MV_SIGN(x) \
39*fb1b10abSAndroid Build Coastguard Worker if (x->mbmi.ref_frame != INTRA_FRAME) { \
40*fb1b10abSAndroid Build Coastguard Worker mvx[cnt] = x->mbmi.mv.as_mv.row; \
41*fb1b10abSAndroid Build Coastguard Worker mvy[cnt] = x->mbmi.mv.as_mv.col; \
42*fb1b10abSAndroid Build Coastguard Worker if (cm->ref_frame_sign_bias[x->mbmi.ref_frame] != \
43*fb1b10abSAndroid Build Coastguard Worker cm->ref_frame_sign_bias[tmp->mbmi.ref_frame]) { \
44*fb1b10abSAndroid Build Coastguard Worker mvx[cnt] *= -1; \
45*fb1b10abSAndroid Build Coastguard Worker mvy[cnt] *= -1; \
46*fb1b10abSAndroid Build Coastguard Worker } \
47*fb1b10abSAndroid Build Coastguard Worker cnt++; \
48*fb1b10abSAndroid Build Coastguard Worker }
49*fb1b10abSAndroid Build Coastguard Worker
vp8_cal_dissimilarity(VP8_COMP * cpi)50*fb1b10abSAndroid Build Coastguard Worker void vp8_cal_dissimilarity(VP8_COMP *cpi) {
51*fb1b10abSAndroid Build Coastguard Worker VP8_COMMON *cm = &cpi->common;
52*fb1b10abSAndroid Build Coastguard Worker
53*fb1b10abSAndroid Build Coastguard Worker /* Note: The first row & first column in mip are outside the frame, which
54*fb1b10abSAndroid Build Coastguard Worker * were initialized to all 0.(ref_frame, mode, mv...)
55*fb1b10abSAndroid Build Coastguard Worker * Their ref_frame = 0 means they won't be counted in the following
56*fb1b10abSAndroid Build Coastguard Worker * calculation.
57*fb1b10abSAndroid Build Coastguard Worker */
58*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.mr_total_resolutions > 1 &&
59*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) {
60*fb1b10abSAndroid Build Coastguard Worker /* Store info for show/no-show frames for supporting alt_ref.
61*fb1b10abSAndroid Build Coastguard Worker * If parent frame is alt_ref, child has one too.
62*fb1b10abSAndroid Build Coastguard Worker */
63*fb1b10abSAndroid Build Coastguard Worker LOWER_RES_FRAME_INFO *store_info =
64*fb1b10abSAndroid Build Coastguard Worker (LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info;
65*fb1b10abSAndroid Build Coastguard Worker
66*fb1b10abSAndroid Build Coastguard Worker store_info->frame_type = cm->frame_type;
67*fb1b10abSAndroid Build Coastguard Worker
68*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_type != KEY_FRAME) {
69*fb1b10abSAndroid Build Coastguard Worker int i;
70*fb1b10abSAndroid Build Coastguard Worker store_info->is_frame_dropped = 0;
71*fb1b10abSAndroid Build Coastguard Worker for (i = 1; i < MAX_REF_FRAMES; ++i)
72*fb1b10abSAndroid Build Coastguard Worker store_info->low_res_ref_frames[i] = cpi->current_ref_frames[i];
73*fb1b10abSAndroid Build Coastguard Worker }
74*fb1b10abSAndroid Build Coastguard Worker
75*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_type != KEY_FRAME) {
76*fb1b10abSAndroid Build Coastguard Worker int mb_row;
77*fb1b10abSAndroid Build Coastguard Worker int mb_col;
78*fb1b10abSAndroid Build Coastguard Worker /* Point to beginning of allocated MODE_INFO arrays. */
79*fb1b10abSAndroid Build Coastguard Worker MODE_INFO *tmp = cm->mip + cm->mode_info_stride;
80*fb1b10abSAndroid Build Coastguard Worker LOWER_RES_MB_INFO *store_mode_info = store_info->mb_info;
81*fb1b10abSAndroid Build Coastguard Worker
82*fb1b10abSAndroid Build Coastguard Worker for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
83*fb1b10abSAndroid Build Coastguard Worker tmp++;
84*fb1b10abSAndroid Build Coastguard Worker for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
85*fb1b10abSAndroid Build Coastguard Worker int dissim = INT_MAX;
86*fb1b10abSAndroid Build Coastguard Worker
87*fb1b10abSAndroid Build Coastguard Worker if (tmp->mbmi.ref_frame != INTRA_FRAME) {
88*fb1b10abSAndroid Build Coastguard Worker int mvx[8];
89*fb1b10abSAndroid Build Coastguard Worker int mvy[8];
90*fb1b10abSAndroid Build Coastguard Worker int mmvx;
91*fb1b10abSAndroid Build Coastguard Worker int mmvy;
92*fb1b10abSAndroid Build Coastguard Worker int cnt = 0;
93*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *here = tmp;
94*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *above = here - cm->mode_info_stride;
95*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *left = here - 1;
96*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *aboveleft = above - 1;
97*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *aboveright = NULL;
98*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *right = NULL;
99*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *belowleft = NULL;
100*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *below = NULL;
101*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *belowright = NULL;
102*fb1b10abSAndroid Build Coastguard Worker
103*fb1b10abSAndroid Build Coastguard Worker /* If alternate reference frame is used, we have to
104*fb1b10abSAndroid Build Coastguard Worker * check sign of MV. */
105*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.play_alternate) {
106*fb1b10abSAndroid Build Coastguard Worker /* Gather mv of neighboring MBs */
107*fb1b10abSAndroid Build Coastguard Worker GET_MV_SIGN(above)
108*fb1b10abSAndroid Build Coastguard Worker GET_MV_SIGN(left)
109*fb1b10abSAndroid Build Coastguard Worker GET_MV_SIGN(aboveleft)
110*fb1b10abSAndroid Build Coastguard Worker
111*fb1b10abSAndroid Build Coastguard Worker if (mb_col < (cm->mb_cols - 1)) {
112*fb1b10abSAndroid Build Coastguard Worker right = here + 1;
113*fb1b10abSAndroid Build Coastguard Worker aboveright = above + 1;
114*fb1b10abSAndroid Build Coastguard Worker GET_MV_SIGN(right)
115*fb1b10abSAndroid Build Coastguard Worker GET_MV_SIGN(aboveright)
116*fb1b10abSAndroid Build Coastguard Worker }
117*fb1b10abSAndroid Build Coastguard Worker
118*fb1b10abSAndroid Build Coastguard Worker if (mb_row < (cm->mb_rows - 1)) {
119*fb1b10abSAndroid Build Coastguard Worker below = here + cm->mode_info_stride;
120*fb1b10abSAndroid Build Coastguard Worker belowleft = below - 1;
121*fb1b10abSAndroid Build Coastguard Worker GET_MV_SIGN(below)
122*fb1b10abSAndroid Build Coastguard Worker GET_MV_SIGN(belowleft)
123*fb1b10abSAndroid Build Coastguard Worker }
124*fb1b10abSAndroid Build Coastguard Worker
125*fb1b10abSAndroid Build Coastguard Worker if (mb_col < (cm->mb_cols - 1) && mb_row < (cm->mb_rows - 1)) {
126*fb1b10abSAndroid Build Coastguard Worker belowright = below + 1;
127*fb1b10abSAndroid Build Coastguard Worker GET_MV_SIGN(belowright)
128*fb1b10abSAndroid Build Coastguard Worker }
129*fb1b10abSAndroid Build Coastguard Worker } else {
130*fb1b10abSAndroid Build Coastguard Worker /* No alt_ref and gather mv of neighboring MBs */
131*fb1b10abSAndroid Build Coastguard Worker GET_MV(above)
132*fb1b10abSAndroid Build Coastguard Worker GET_MV(left)
133*fb1b10abSAndroid Build Coastguard Worker GET_MV(aboveleft)
134*fb1b10abSAndroid Build Coastguard Worker
135*fb1b10abSAndroid Build Coastguard Worker if (mb_col < (cm->mb_cols - 1)) {
136*fb1b10abSAndroid Build Coastguard Worker right = here + 1;
137*fb1b10abSAndroid Build Coastguard Worker aboveright = above + 1;
138*fb1b10abSAndroid Build Coastguard Worker GET_MV(right)
139*fb1b10abSAndroid Build Coastguard Worker GET_MV(aboveright)
140*fb1b10abSAndroid Build Coastguard Worker }
141*fb1b10abSAndroid Build Coastguard Worker
142*fb1b10abSAndroid Build Coastguard Worker if (mb_row < (cm->mb_rows - 1)) {
143*fb1b10abSAndroid Build Coastguard Worker below = here + cm->mode_info_stride;
144*fb1b10abSAndroid Build Coastguard Worker belowleft = below - 1;
145*fb1b10abSAndroid Build Coastguard Worker GET_MV(below)
146*fb1b10abSAndroid Build Coastguard Worker GET_MV(belowleft)
147*fb1b10abSAndroid Build Coastguard Worker }
148*fb1b10abSAndroid Build Coastguard Worker
149*fb1b10abSAndroid Build Coastguard Worker if (mb_col < (cm->mb_cols - 1) && mb_row < (cm->mb_rows - 1)) {
150*fb1b10abSAndroid Build Coastguard Worker belowright = below + 1;
151*fb1b10abSAndroid Build Coastguard Worker GET_MV(belowright)
152*fb1b10abSAndroid Build Coastguard Worker }
153*fb1b10abSAndroid Build Coastguard Worker }
154*fb1b10abSAndroid Build Coastguard Worker
155*fb1b10abSAndroid Build Coastguard Worker if (cnt > 0) {
156*fb1b10abSAndroid Build Coastguard Worker int max_mvx = mvx[0];
157*fb1b10abSAndroid Build Coastguard Worker int min_mvx = mvx[0];
158*fb1b10abSAndroid Build Coastguard Worker int max_mvy = mvy[0];
159*fb1b10abSAndroid Build Coastguard Worker int min_mvy = mvy[0];
160*fb1b10abSAndroid Build Coastguard Worker int i;
161*fb1b10abSAndroid Build Coastguard Worker
162*fb1b10abSAndroid Build Coastguard Worker if (cnt > 1) {
163*fb1b10abSAndroid Build Coastguard Worker for (i = 1; i < cnt; ++i) {
164*fb1b10abSAndroid Build Coastguard Worker if (mvx[i] > max_mvx)
165*fb1b10abSAndroid Build Coastguard Worker max_mvx = mvx[i];
166*fb1b10abSAndroid Build Coastguard Worker else if (mvx[i] < min_mvx)
167*fb1b10abSAndroid Build Coastguard Worker min_mvx = mvx[i];
168*fb1b10abSAndroid Build Coastguard Worker if (mvy[i] > max_mvy)
169*fb1b10abSAndroid Build Coastguard Worker max_mvy = mvy[i];
170*fb1b10abSAndroid Build Coastguard Worker else if (mvy[i] < min_mvy)
171*fb1b10abSAndroid Build Coastguard Worker min_mvy = mvy[i];
172*fb1b10abSAndroid Build Coastguard Worker }
173*fb1b10abSAndroid Build Coastguard Worker }
174*fb1b10abSAndroid Build Coastguard Worker
175*fb1b10abSAndroid Build Coastguard Worker mmvx = VPXMAX(abs(min_mvx - here->mbmi.mv.as_mv.row),
176*fb1b10abSAndroid Build Coastguard Worker abs(max_mvx - here->mbmi.mv.as_mv.row));
177*fb1b10abSAndroid Build Coastguard Worker mmvy = VPXMAX(abs(min_mvy - here->mbmi.mv.as_mv.col),
178*fb1b10abSAndroid Build Coastguard Worker abs(max_mvy - here->mbmi.mv.as_mv.col));
179*fb1b10abSAndroid Build Coastguard Worker dissim = VPXMAX(mmvx, mmvy);
180*fb1b10abSAndroid Build Coastguard Worker }
181*fb1b10abSAndroid Build Coastguard Worker }
182*fb1b10abSAndroid Build Coastguard Worker
183*fb1b10abSAndroid Build Coastguard Worker /* Store mode info for next resolution encoding */
184*fb1b10abSAndroid Build Coastguard Worker store_mode_info->mode = tmp->mbmi.mode;
185*fb1b10abSAndroid Build Coastguard Worker store_mode_info->ref_frame = tmp->mbmi.ref_frame;
186*fb1b10abSAndroid Build Coastguard Worker store_mode_info->mv.as_int = tmp->mbmi.mv.as_int;
187*fb1b10abSAndroid Build Coastguard Worker store_mode_info->dissim = dissim;
188*fb1b10abSAndroid Build Coastguard Worker tmp++;
189*fb1b10abSAndroid Build Coastguard Worker store_mode_info++;
190*fb1b10abSAndroid Build Coastguard Worker }
191*fb1b10abSAndroid Build Coastguard Worker }
192*fb1b10abSAndroid Build Coastguard Worker }
193*fb1b10abSAndroid Build Coastguard Worker }
194*fb1b10abSAndroid Build Coastguard Worker }
195*fb1b10abSAndroid Build Coastguard Worker
196*fb1b10abSAndroid Build Coastguard Worker /* This function is called only when this frame is dropped at current
197*fb1b10abSAndroid Build Coastguard Worker resolution level. */
vp8_store_drop_frame_info(VP8_COMP * cpi)198*fb1b10abSAndroid Build Coastguard Worker void vp8_store_drop_frame_info(VP8_COMP *cpi) {
199*fb1b10abSAndroid Build Coastguard Worker /* If the frame is dropped in lower-resolution encoding, this information
200*fb1b10abSAndroid Build Coastguard Worker is passed to higher resolution level so that the encoder knows there
201*fb1b10abSAndroid Build Coastguard Worker is no mode & motion info available.
202*fb1b10abSAndroid Build Coastguard Worker */
203*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.mr_total_resolutions > 1 &&
204*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) {
205*fb1b10abSAndroid Build Coastguard Worker /* Store info for show/no-show frames for supporting alt_ref.
206*fb1b10abSAndroid Build Coastguard Worker * If parent frame is alt_ref, child has one too.
207*fb1b10abSAndroid Build Coastguard Worker */
208*fb1b10abSAndroid Build Coastguard Worker LOWER_RES_FRAME_INFO *store_info =
209*fb1b10abSAndroid Build Coastguard Worker (LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info;
210*fb1b10abSAndroid Build Coastguard Worker
211*fb1b10abSAndroid Build Coastguard Worker /* Set frame_type to be INTER_FRAME since we won't drop key frame. */
212*fb1b10abSAndroid Build Coastguard Worker store_info->frame_type = INTER_FRAME;
213*fb1b10abSAndroid Build Coastguard Worker store_info->is_frame_dropped = 1;
214*fb1b10abSAndroid Build Coastguard Worker }
215*fb1b10abSAndroid Build Coastguard Worker }
216