findnearmv.c 8.24 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  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.
John Koleszar's avatar
John Koleszar committed
9
10
11
12
13
 */


#include "findnearmv.h"

14
15
16
17
18
19
20
const unsigned char vp8_mbsplit_offset[4][16] = {
    { 0,  8,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
    { 0,  2,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
    { 0,  2,  8, 10,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0},
    { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15}
};

John Koleszar's avatar
John Koleszar committed
21
22
23
/* Predict motion vectors using those from already-decoded nearby blocks.
   Note that we only consider one 4x4 subblock from each candidate 16x16
   macroblock.   */
24
#if CONFIG_NEWNEAR
John Koleszar's avatar
John Koleszar committed
25
26
27
28
void vp8_find_near_mvs
(
    MACROBLOCKD *xd,
    const MODE_INFO *here,
29
    const MODE_INFO *lf_here,
Scott LaVarnway's avatar
Scott LaVarnway committed
30
31
32
    int_mv *nearest,
    int_mv *nearby,
    int_mv *best_mv,
John Koleszar's avatar
John Koleszar committed
33
34
35
36
37
38
39
40
    int cnt[4],
    int refframe,
    int *ref_frame_sign_bias
)
{
    const MODE_INFO *above = here - xd->mode_info_stride;
    const MODE_INFO *left = here - 1;
    const MODE_INFO *aboveleft = above - 1;
41
    const MODE_INFO *third = NULL;
John Koleszar's avatar
John Koleszar committed
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    int_mv            near_mvs[4];
    int_mv           *mv = near_mvs;
    int             *cntx = cnt;
    enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};

    /* Zero accumulators */
    mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
    cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;

    /* Process above */
    if (above->mbmi.ref_frame != INTRA_FRAME)
    {
        if (above->mbmi.mv.as_int)
        {
            (++mv)->as_int = above->mbmi.mv.as_int;
Yaowu Xu's avatar
Yaowu Xu committed
57
58
            mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame],
                refframe, mv, ref_frame_sign_bias);
John Koleszar's avatar
John Koleszar committed
59
60
            ++cntx;
        }
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
        *cntx += 2;
    }

    /* Process left */
    if (left->mbmi.ref_frame != INTRA_FRAME)
    {
        if (left->mbmi.mv.as_int)
        {
            int_mv this_mv;
            this_mv.as_int = left->mbmi.mv.as_int;
            mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame],
                refframe, &this_mv, ref_frame_sign_bias);

            if (this_mv.as_int != mv->as_int)
            {
                (++mv)->as_int = this_mv.as_int;
                ++cntx;
            }
            *cntx += 2;
        }
        else
            cnt[CNT_INTRA] += 2;
    }
    /* Process above left or the one frome last frame */
    if ( aboveleft->mbmi.ref_frame != INTRA_FRAME||
         (lf_here->mbmi.ref_frame==LAST_FRAME && refframe == LAST_FRAME))
    {
        if (aboveleft->mbmi.mv.as_int)
        {
            third = aboveleft;
        }
        else if(lf_here->mbmi.mv.as_int)
        {
            third = lf_here;
        }
        if(third)
        {
            int_mv this_mv;
            this_mv.as_int = third->mbmi.mv.as_int;
            mv_bias(ref_frame_sign_bias[third->mbmi.ref_frame],
                refframe, &this_mv, ref_frame_sign_bias);

            if (this_mv.as_int != mv->as_int)
            {
                (++mv)->as_int = this_mv.as_int;
                ++cntx;
            }
            *cntx += 1;
        }
        else
            cnt[CNT_INTRA] += 1;
    }

    /* If we have three distinct MV's ... */
    if (cnt[CNT_SPLITMV])
    {
        /* See if the third MV can be merged with NEAREST */
        if (mv->as_int == near_mvs[CNT_NEAREST].as_int)
            cnt[CNT_NEAREST] += 1;
    }

    cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
                        + (left->mbmi.mode == SPLITMV)) * 2
                        + (
#if CONFIG_NEWNEAR
                        lf_here->mbmi.mode == SPLITMV ||
#endif
                       aboveleft->mbmi.mode == SPLITMV);

    /* Swap near and nearest if necessary */
    if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
    {
        int tmp;
        tmp = cnt[CNT_NEAREST];
        cnt[CNT_NEAREST] = cnt[CNT_NEAR];
        cnt[CNT_NEAR] = tmp;
        tmp = near_mvs[CNT_NEAREST].as_int;
        near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
        near_mvs[CNT_NEAR].as_int = tmp;
    }

    /* Use near_mvs[0] to store the "best" MV */
    if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA])
        near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST];

    /* Set up return values */
    best_mv->as_int = near_mvs[0].as_int;
    nearest->as_int = near_mvs[CNT_NEAREST].as_int;
    nearby->as_int = near_mvs[CNT_NEAR].as_int;

    //TODO: move clamp outside findnearmv
    vp8_clamp_mv2(nearest, xd);
    vp8_clamp_mv2(nearby, xd);
    vp8_clamp_mv2(best_mv, xd);
}


#else
void vp8_find_near_mvs
(
    MACROBLOCKD *xd,
    const MODE_INFO *here,
    int_mv *nearest,
    int_mv *nearby,
    int_mv *best_mv,
    int cnt[4],
    int refframe,
    int *ref_frame_sign_bias
)
{
    const MODE_INFO *above = here - xd->mode_info_stride;
    const MODE_INFO *left = here - 1;
    const MODE_INFO *aboveleft = above - 1;
    int_mv            near_mvs[4];
    int_mv           *mv = near_mvs;
    int             *cntx = cnt;
Yaowu Xu's avatar
Yaowu Xu committed
177
    enum {CNT_ZEROMV, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};
John Koleszar's avatar
John Koleszar committed
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
    /* Zero accumulators */
    mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
    cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;

    /* Process above */
    if (above->mbmi.ref_frame != INTRA_FRAME)
    {
        if (above->mbmi.mv.as_int)
        {
            (++mv)->as_int = above->mbmi.mv.as_int;
            mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame],
                refframe, mv, ref_frame_sign_bias);
            ++cntx;
        }
John Koleszar's avatar
John Koleszar committed
193
194
195
196
197
198
199
200
201
202
203
        *cntx += 2;
    }

    /* Process left */
    if (left->mbmi.ref_frame != INTRA_FRAME)
    {
        if (left->mbmi.mv.as_int)
        {
            int_mv this_mv;

            this_mv.as_int = left->mbmi.mv.as_int;
Yaowu Xu's avatar
Yaowu Xu committed
204
205
            mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame],
                refframe, &this_mv, ref_frame_sign_bias);
John Koleszar's avatar
John Koleszar committed
206
207
208
209
210
211
212
213
214
215

            if (this_mv.as_int != mv->as_int)
            {
                (++mv)->as_int = this_mv.as_int;
                ++cntx;
            }

            *cntx += 2;
        }
        else
Yaowu Xu's avatar
Yaowu Xu committed
216
            cnt[CNT_ZEROMV] += 2;
John Koleszar's avatar
John Koleszar committed
217
218
219
220
221
222
223
224
225
    }
    /* Process above left */
    if (aboveleft->mbmi.ref_frame != INTRA_FRAME)
    {
        if (aboveleft->mbmi.mv.as_int)
        {
            int_mv this_mv;

            this_mv.as_int = aboveleft->mbmi.mv.as_int;
Yaowu Xu's avatar
Yaowu Xu committed
226
227
            mv_bias(ref_frame_sign_bias[aboveleft->mbmi.ref_frame],
                refframe, &this_mv, ref_frame_sign_bias);
John Koleszar's avatar
John Koleszar committed
228
229
230
231
232
233
234
235
236
237

            if (this_mv.as_int != mv->as_int)
            {
                (++mv)->as_int = this_mv.as_int;
                ++cntx;
            }

            *cntx += 1;
        }
        else
Yaowu Xu's avatar
Yaowu Xu committed
238
            cnt[CNT_ZEROMV] += 1;
John Koleszar's avatar
John Koleszar committed
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    }

    /* If we have three distinct MV's ... */
    if (cnt[CNT_SPLITMV])
    {
        /* See if above-left MV can be merged with NEAREST */
        if (mv->as_int == near_mvs[CNT_NEAREST].as_int)
            cnt[CNT_NEAREST] += 1;
    }

    cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
                        + (left->mbmi.mode == SPLITMV)) * 2
                       + (aboveleft->mbmi.mode == SPLITMV);

    /* Swap near and nearest if necessary */
    if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
    {
        int tmp;
        tmp = cnt[CNT_NEAREST];
        cnt[CNT_NEAREST] = cnt[CNT_NEAR];
        cnt[CNT_NEAR] = tmp;
        tmp = near_mvs[CNT_NEAREST].as_int;
        near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
        near_mvs[CNT_NEAR].as_int = tmp;
    }

    /* Use near_mvs[0] to store the "best" MV */
Yaowu Xu's avatar
Yaowu Xu committed
266
267
    if (cnt[CNT_NEAREST] >= cnt[CNT_ZEROMV])
        near_mvs[CNT_ZEROMV] = near_mvs[CNT_NEAREST];
John Koleszar's avatar
John Koleszar committed
268
269

    /* Set up return values */
Scott LaVarnway's avatar
Scott LaVarnway committed
270
271
272
273
274
275
276
277
    best_mv->as_int = near_mvs[0].as_int;
    nearest->as_int = near_mvs[CNT_NEAREST].as_int;
    nearby->as_int = near_mvs[CNT_NEAR].as_int;

    //TODO: move clamp outside findnearmv
    vp8_clamp_mv2(nearest, xd);
    vp8_clamp_mv2(nearby, xd);
    vp8_clamp_mv2(best_mv, xd);
John Koleszar's avatar
John Koleszar committed
278
}
279
#endif
John Koleszar's avatar
John Koleszar committed
280
281
282
283
284
285
286
287
288
289
290
291

vp8_prob *vp8_mv_ref_probs(
    vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
)
{
    p[0] = vp8_mode_contexts [near_mv_ref_ct[0]] [0];
    p[1] = vp8_mode_contexts [near_mv_ref_ct[1]] [1];
    p[2] = vp8_mode_contexts [near_mv_ref_ct[2]] [2];
    p[3] = vp8_mode_contexts [near_mv_ref_ct[3]] [3];
    return p;
}