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