Home | History | Annotate | Download | only in common
      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 "findnearmv.h"
     13 
     14 #define FINDNEAR_SEARCH_SITES   3
     15 
     16 /* Predict motion vectors using those from already-decoded nearby blocks.
     17    Note that we only consider one 4x4 subblock from each candidate 16x16
     18    macroblock.   */
     19 
     20 typedef union
     21 {
     22     unsigned int as_int;
     23     MV           as_mv;
     24 } int_mv;        /* facilitates rapid equality tests */
     25 
     26 static void mv_bias(const MODE_INFO *x, int refframe, int_mv *mvp, const int *ref_frame_sign_bias)
     27 {
     28     MV xmv;
     29     xmv = x->mbmi.mv.as_mv;
     30 
     31     if (ref_frame_sign_bias[x->mbmi.ref_frame] != ref_frame_sign_bias[refframe])
     32     {
     33         xmv.row *= -1;
     34         xmv.col *= -1;
     35     }
     36 
     37     mvp->as_mv = xmv;
     38 }
     39 
     40 
     41 void vp8_clamp_mv(MV *mv, const MACROBLOCKD *xd)
     42 {
     43     if (mv->col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
     44         mv->col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
     45     else if (mv->col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
     46         mv->col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
     47 
     48     if (mv->row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
     49         mv->row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
     50     else if (mv->row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
     51         mv->row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
     52 }
     53 
     54 
     55 void vp8_find_near_mvs
     56 (
     57     MACROBLOCKD *xd,
     58     const MODE_INFO *here,
     59     MV *nearest,
     60     MV *nearby,
     61     MV *best_mv,
     62     int cnt[4],
     63     int refframe,
     64     int *ref_frame_sign_bias
     65 )
     66 {
     67     const MODE_INFO *above = here - xd->mode_info_stride;
     68     const MODE_INFO *left = here - 1;
     69     const MODE_INFO *aboveleft = above - 1;
     70     int_mv            near_mvs[4];
     71     int_mv           *mv = near_mvs;
     72     int             *cntx = cnt;
     73     enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};
     74 
     75     /* Zero accumulators */
     76     mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
     77     cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
     78 
     79     /* Process above */
     80     if (above->mbmi.ref_frame != INTRA_FRAME)
     81     {
     82         if (above->mbmi.mv.as_int)
     83         {
     84             (++mv)->as_int = above->mbmi.mv.as_int;
     85             mv_bias(above, refframe, mv, ref_frame_sign_bias);
     86             ++cntx;
     87         }
     88 
     89         *cntx += 2;
     90     }
     91 
     92     /* Process left */
     93     if (left->mbmi.ref_frame != INTRA_FRAME)
     94     {
     95         if (left->mbmi.mv.as_int)
     96         {
     97             int_mv this_mv;
     98 
     99             this_mv.as_int = left->mbmi.mv.as_int;
    100             mv_bias(left, refframe, &this_mv, ref_frame_sign_bias);
    101 
    102             if (this_mv.as_int != mv->as_int)
    103             {
    104                 (++mv)->as_int = this_mv.as_int;
    105                 ++cntx;
    106             }
    107 
    108             *cntx += 2;
    109         }
    110         else
    111             cnt[CNT_INTRA] += 2;
    112     }
    113 
    114     /* Process above left */
    115     if (aboveleft->mbmi.ref_frame != INTRA_FRAME)
    116     {
    117         if (aboveleft->mbmi.mv.as_int)
    118         {
    119             int_mv this_mv;
    120 
    121             this_mv.as_int = aboveleft->mbmi.mv.as_int;
    122             mv_bias(aboveleft, refframe, &this_mv, ref_frame_sign_bias);
    123 
    124             if (this_mv.as_int != mv->as_int)
    125             {
    126                 (++mv)->as_int = this_mv.as_int;
    127                 ++cntx;
    128             }
    129 
    130             *cntx += 1;
    131         }
    132         else
    133             cnt[CNT_INTRA] += 1;
    134     }
    135 
    136     /* If we have three distinct MV's ... */
    137     if (cnt[CNT_SPLITMV])
    138     {
    139         /* See if above-left MV can be merged with NEAREST */
    140         if (mv->as_int == near_mvs[CNT_NEAREST].as_int)
    141             cnt[CNT_NEAREST] += 1;
    142     }
    143 
    144     cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
    145                         + (left->mbmi.mode == SPLITMV)) * 2
    146                        + (aboveleft->mbmi.mode == SPLITMV);
    147 
    148     /* Swap near and nearest if necessary */
    149     if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
    150     {
    151         int tmp;
    152         tmp = cnt[CNT_NEAREST];
    153         cnt[CNT_NEAREST] = cnt[CNT_NEAR];
    154         cnt[CNT_NEAR] = tmp;
    155         tmp = near_mvs[CNT_NEAREST].as_int;
    156         near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
    157         near_mvs[CNT_NEAR].as_int = tmp;
    158     }
    159 
    160     /* Use near_mvs[0] to store the "best" MV */
    161     if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA])
    162         near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST];
    163 
    164     /* Set up return values */
    165     *best_mv = near_mvs[0].as_mv;
    166     *nearest = near_mvs[CNT_NEAREST].as_mv;
    167     *nearby = near_mvs[CNT_NEAR].as_mv;
    168 
    169     vp8_clamp_mv(nearest, xd);
    170     vp8_clamp_mv(nearby, xd);
    171     vp8_clamp_mv(best_mv, xd); /*TODO: move this up before the copy*/
    172 }
    173 
    174 vp8_prob *vp8_mv_ref_probs(
    175     vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
    176 )
    177 {
    178     p[0] = vp8_mode_contexts [near_mv_ref_ct[0]] [0];
    179     p[1] = vp8_mode_contexts [near_mv_ref_ct[1]] [1];
    180     p[2] = vp8_mode_contexts [near_mv_ref_ct[2]] [2];
    181     p[3] = vp8_mode_contexts [near_mv_ref_ct[3]] [3];
    182     /*p[3] = vp8_mode_contexts [near_mv_ref_ct[1] + near_mv_ref_ct[2] + near_mv_ref_ct[3]] [3];*/
    183     return p;
    184 }
    185 
    186 const B_MODE_INFO *vp8_left_bmi(const MODE_INFO *cur_mb, int b)
    187 {
    188     if (!(b & 3))
    189     {
    190         /* On L edge, get from MB to left of us */
    191         --cur_mb;
    192         b += 4;
    193     }
    194 
    195     return cur_mb->bmi + b - 1;
    196 }
    197 
    198 const B_MODE_INFO *vp8_above_bmi(const MODE_INFO *cur_mb, int b, int mi_stride)
    199 {
    200     if (!(b >> 2))
    201     {
    202         /* On top edge, get from MB above us */
    203         cur_mb -= mi_stride;
    204         b += 16;
    205     }
    206 
    207     return cur_mb->bmi + b - 4;
    208 }
    209