xref: /aosp_15_r20/external/libvpx/vp8/encoder/mr_dissim.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
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