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
20void 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)    \
33if(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)    \
41if(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
54void 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. */
218void 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