func: void vp8_decode_mvs(VP8Context *s, VP8Macroblock *mb,
  
                      int mb_x, int mb_y, int layout)
  
  {
  
      VP8Macroblock *mb_edge[3] = { 0      /* top */,
  
                                    mb - 1 /* left */,
  
                                    0      /* top-left */ };
  
      enum { CNT_ZERO, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV };
  
      enum { VP8_EDGE_TOP, VP8_EDGE_LEFT, VP8_EDGE_TOPLEFT };
  
      int idx = CNT_ZERO;
  
      int cur_sign_bias = s->sign_bias[mb->ref_frame];
  
      int8_t *sign_bias = s->sign_bias;
  
      VP56mv near_mv[4];
  
      uint8_t cnt[4] = { 0 };
  
      VP56RangeCoder *c = &s->c;
  
  
  
      if (!layout) { // layout is inlined (s->mb_layout is not)
  
          mb_edge[0] = mb + 2;
  
          mb_edge[2] = mb + 1;
  
      } else {
  
          mb_edge[0] = mb - s->mb_width - 1;
  
          mb_edge[2] = mb - s->mb_width - 2;
  
      }
  
  
  
      AV_ZERO32(&near_mv[0]);
  
      AV_ZERO32(&near_mv[1]);
  
      AV_ZERO32(&near_mv[2]);
  
  
  
      /* Process MB on top, left and top-left */
  
  #define MV_EDGE_CHECK(n)                                                      \
  
      {                                                                         \
  
          VP8Macroblock *edge = mb_edge[n];                                     \
  
          int edge_ref = edge->ref_frame;                                       \
  
          if (edge_ref != VP56_FRAME_CURRENT) {                                 \
  
              uint32_t mv = AV_RN32A(&edge->mv);                                \
  
              if (mv) {                                                         \
  
                  if (cur_sign_bias != sign_bias[edge_ref]) {                   \
  
                      /* SWAR negate of the values in mv. */                    \
  
                      mv = ~mv;                                                 \
  
                      mv = ((mv & 0x7fff7fff) +                                 \
  
                            0x00010001) ^ (mv & 0x80008000);                    \
  
                  }                                                             \
  
                  if (!n || mv != AV_RN32A(&near_mv[idx]))                      \
  
                      AV_WN32A(&near_mv[++idx], mv);                            \
  
                  cnt[idx] += 1 + (n != 2);                                     \
  
              } else                                                            \
  
                  cnt[CNT_ZERO] += 1 + (n != 2);                                \
  
          }                                                                     \
  
      }
  
  
  
      MV_EDGE_CHECK(0)
  
      MV_EDGE_CHECK(1)
  
      MV_EDGE_CHECK(2)
  
  
  
      mb->partitioning = VP8_SPLITMVMODE_NONE;
  
      if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_ZERO]][0])) {
  
          mb->mode = VP8_MVMODE_MV;
  
  
  
          /* If we have three distinct MVs, merge first and last if they're the same */
  
          if (cnt[CNT_SPLITMV] &&
  
              AV_RN32A(&near_mv[1 + VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1 + VP8_EDGE_TOPLEFT]))
  
              cnt[CNT_NEAREST] += 1;
  
  
  
          /* Swap near and nearest if necessary */
  
          if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) {
  
              FFSWAP(uint8_t,     cnt[CNT_NEAREST],     cnt[CNT_NEAR]);
  
              FFSWAP( VP56mv, near_mv[CNT_NEAREST], near_mv[CNT_NEAR]);
  
          }
  
  
  
          if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAREST]][1])) {
  
              if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAR]][2])) {
  
                  /* Choose the best mv out of 0,0 and the nearest mv */
  
                  clamp_mv(s, &mb->mv, &near_mv[CNT_ZERO + (cnt[CNT_NEAREST] >= cnt[CNT_ZERO])]);
  
                  cnt[CNT_SPLITMV] = ((mb_edge[VP8_EDGE_LEFT]->mode    == VP8_MVMODE_SPLIT) +
  
                                      (mb_edge[VP8_EDGE_TOP]->mode     == VP8_MVMODE_SPLIT)) * 2 +
  
                                      (mb_edge[VP8_EDGE_TOPLEFT]->mode == VP8_MVMODE_SPLIT);
  
  
  
                  if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_SPLITMV]][3])) {
  
                      mb->mode = VP8_MVMODE_SPLIT;
  
                      mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP8) - 1];
  
                  } else {
  
                      mb->mv.y  += vp8_read_mv_component(c, s->prob->mvc[0]);
  
                      mb->mv.x  += vp8_read_mv_component(c, s->prob->mvc[1]);
  
                      mb->bmv[0] = mb->mv;
  
                  }
  
              } else {
  
                  clamp_mv(s, &mb->mv, &near_mv[CNT_NEAR]);
  
                  mb->bmv[0] = mb->mv;
  
              }
  
          } else {
  
              clamp_mv(s, &mb->mv, &near_mv[CNT_NEAREST]);
  
              mb->bmv[0] = mb->mv;
  
          }
  
      } else {
  
          mb->mode = VP8_MVMODE_ZERO;
  
          AV_ZERO32(&mb->mv);
  
          mb->bmv[0] = mb->mv;
  
      }
  
  }
  