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