configure: add --extra-cxxflags option
[platform/upstream/libvpx.git] / vp10 / decoder / decodemv.c
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 #include <assert.h>
12
13 #include "vp10/common/common.h"
14 #include "vp10/common/entropy.h"
15 #include "vp10/common/entropymode.h"
16 #include "vp10/common/entropymv.h"
17 #include "vp10/common/mvref_common.h"
18 #include "vp10/common/pred_common.h"
19 #include "vp10/common/reconinter.h"
20 #include "vp10/common/seg_common.h"
21
22 #include "vp10/decoder/decodemv.h"
23 #include "vp10/decoder/decodeframe.h"
24
25 #include "vpx_dsp/vpx_dsp_common.h"
26
27 static PREDICTION_MODE read_intra_mode(vpx_reader *r, const vpx_prob *p) {
28   return (PREDICTION_MODE)vpx_read_tree(r, vp10_intra_mode_tree, p);
29 }
30
31 static PREDICTION_MODE read_intra_mode_y(VP10_COMMON *cm, MACROBLOCKD *xd,
32                                          vpx_reader *r, int size_group) {
33   const PREDICTION_MODE y_mode =
34       read_intra_mode(r, cm->fc->y_mode_prob[size_group]);
35   FRAME_COUNTS *counts = xd->counts;
36   if (counts)
37     ++counts->y_mode[size_group][y_mode];
38   return y_mode;
39 }
40
41 static PREDICTION_MODE read_intra_mode_uv(VP10_COMMON *cm, MACROBLOCKD *xd,
42                                           vpx_reader *r,
43                                           PREDICTION_MODE y_mode) {
44   const PREDICTION_MODE uv_mode = read_intra_mode(r,
45                                          cm->fc->uv_mode_prob[y_mode]);
46   FRAME_COUNTS *counts = xd->counts;
47   if (counts)
48     ++counts->uv_mode[y_mode][uv_mode];
49   return uv_mode;
50 }
51
52 static PREDICTION_MODE read_inter_mode(VP10_COMMON *cm, MACROBLOCKD *xd,
53                                        vpx_reader *r, int ctx) {
54   const int mode = vpx_read_tree(r, vp10_inter_mode_tree,
55                                  cm->fc->inter_mode_probs[ctx]);
56   FRAME_COUNTS *counts = xd->counts;
57   if (counts)
58     ++counts->inter_mode[ctx][mode];
59
60   return NEARESTMV + mode;
61 }
62
63 static int read_segment_id(vpx_reader *r, const struct segmentation *seg) {
64   return vpx_read_tree(r, vp10_segment_tree, seg->tree_probs);
65 }
66
67 static TX_SIZE read_selected_tx_size(VP10_COMMON *cm, MACROBLOCKD *xd,
68                                      TX_SIZE max_tx_size, vpx_reader *r) {
69   FRAME_COUNTS *counts = xd->counts;
70   const int ctx = get_tx_size_context(xd);
71   const vpx_prob *tx_probs = get_tx_probs(max_tx_size, ctx, &cm->fc->tx_probs);
72   int tx_size = vpx_read(r, tx_probs[0]);
73   if (tx_size != TX_4X4 && max_tx_size >= TX_16X16) {
74     tx_size += vpx_read(r, tx_probs[1]);
75     if (tx_size != TX_8X8 && max_tx_size >= TX_32X32)
76       tx_size += vpx_read(r, tx_probs[2]);
77   }
78
79   if (counts)
80     ++get_tx_counts(max_tx_size, ctx, &counts->tx)[tx_size];
81   return (TX_SIZE)tx_size;
82 }
83
84 static TX_SIZE read_tx_size(VP10_COMMON *cm, MACROBLOCKD *xd,
85                             int allow_select, vpx_reader *r) {
86   TX_MODE tx_mode = cm->tx_mode;
87   BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
88   const TX_SIZE max_tx_size = max_txsize_lookup[bsize];
89   if (allow_select && tx_mode == TX_MODE_SELECT && bsize >= BLOCK_8X8)
90     return read_selected_tx_size(cm, xd, max_tx_size, r);
91   else
92     return VPXMIN(max_tx_size, tx_mode_to_biggest_tx_size[tx_mode]);
93 }
94
95 static int dec_get_segment_id(const VP10_COMMON *cm, const uint8_t *segment_ids,
96                               int mi_offset, int x_mis, int y_mis) {
97   int x, y, segment_id = INT_MAX;
98
99   for (y = 0; y < y_mis; y++)
100     for (x = 0; x < x_mis; x++)
101       segment_id =
102           VPXMIN(segment_id, segment_ids[mi_offset + y * cm->mi_cols + x]);
103
104   assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
105   return segment_id;
106 }
107
108 static void set_segment_id(VP10_COMMON *cm, int mi_offset,
109                            int x_mis, int y_mis, int segment_id) {
110   int x, y;
111
112   assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
113
114   for (y = 0; y < y_mis; y++)
115     for (x = 0; x < x_mis; x++)
116       cm->current_frame_seg_map[mi_offset + y * cm->mi_cols + x] = segment_id;
117 }
118
119 static int read_intra_segment_id(VP10_COMMON *const cm, int mi_offset,
120                                  int x_mis, int y_mis,
121                                  vpx_reader *r) {
122   struct segmentation *const seg = &cm->seg;
123   int segment_id;
124
125   if (!seg->enabled)
126     return 0;  // Default for disabled segmentation
127
128   assert(seg->update_map && !seg->temporal_update);
129
130   segment_id = read_segment_id(r, seg);
131   set_segment_id(cm, mi_offset, x_mis, y_mis, segment_id);
132   return segment_id;
133 }
134
135 static void copy_segment_id(const VP10_COMMON *cm,
136                            const uint8_t *last_segment_ids,
137                            uint8_t *current_segment_ids,
138                            int mi_offset, int x_mis, int y_mis) {
139   int x, y;
140
141   for (y = 0; y < y_mis; y++)
142     for (x = 0; x < x_mis; x++)
143       current_segment_ids[mi_offset + y * cm->mi_cols + x] =  last_segment_ids ?
144           last_segment_ids[mi_offset + y * cm->mi_cols + x] : 0;
145 }
146
147 static int read_inter_segment_id(VP10_COMMON *const cm, MACROBLOCKD *const xd,
148                                  int mi_row, int mi_col, vpx_reader *r) {
149   struct segmentation *const seg = &cm->seg;
150   MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
151   int predicted_segment_id, segment_id;
152   const int mi_offset = mi_row * cm->mi_cols + mi_col;
153   const int bw = xd->plane[0].n4_w >> 1;
154   const int bh = xd->plane[0].n4_h >> 1;
155
156   // TODO(slavarnway): move x_mis, y_mis into xd ?????
157   const int x_mis = VPXMIN(cm->mi_cols - mi_col, bw);
158   const int y_mis = VPXMIN(cm->mi_rows - mi_row, bh);
159
160   if (!seg->enabled)
161     return 0;  // Default for disabled segmentation
162
163   predicted_segment_id = cm->last_frame_seg_map ?
164       dec_get_segment_id(cm, cm->last_frame_seg_map, mi_offset, x_mis, y_mis) :
165       0;
166
167   if (!seg->update_map) {
168     copy_segment_id(cm, cm->last_frame_seg_map, cm->current_frame_seg_map,
169                     mi_offset, x_mis, y_mis);
170     return predicted_segment_id;
171   }
172
173   if (seg->temporal_update) {
174     const vpx_prob pred_prob = vp10_get_pred_prob_seg_id(seg, xd);
175     mbmi->seg_id_predicted = vpx_read(r, pred_prob);
176     segment_id = mbmi->seg_id_predicted ? predicted_segment_id
177                                         : read_segment_id(r, seg);
178   } else {
179     segment_id = read_segment_id(r, seg);
180   }
181   set_segment_id(cm, mi_offset, x_mis, y_mis, segment_id);
182   return segment_id;
183 }
184
185 static int read_skip(VP10_COMMON *cm, const MACROBLOCKD *xd,
186                      int segment_id, vpx_reader *r) {
187   if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
188     return 1;
189   } else {
190     const int ctx = vp10_get_skip_context(xd);
191     const int skip = vpx_read(r, cm->fc->skip_probs[ctx]);
192     FRAME_COUNTS *counts = xd->counts;
193     if (counts)
194       ++counts->skip[ctx][skip];
195     return skip;
196   }
197 }
198
199 static void read_intra_frame_mode_info(VP10_COMMON *const cm,
200                                        MACROBLOCKD *const xd,
201                                        int mi_row, int mi_col, vpx_reader *r) {
202   MODE_INFO *const mi = xd->mi[0];
203   MB_MODE_INFO *const mbmi = &mi->mbmi;
204   const MODE_INFO *above_mi = xd->above_mi;
205   const MODE_INFO *left_mi  = xd->left_mi;
206   const BLOCK_SIZE bsize = mbmi->sb_type;
207   int i;
208   const int mi_offset = mi_row * cm->mi_cols + mi_col;
209   const int bw = xd->plane[0].n4_w >> 1;
210   const int bh = xd->plane[0].n4_h >> 1;
211
212   // TODO(slavarnway): move x_mis, y_mis into xd ?????
213   const int x_mis = VPXMIN(cm->mi_cols - mi_col, bw);
214   const int y_mis = VPXMIN(cm->mi_rows - mi_row, bh);
215
216   mbmi->segment_id = read_intra_segment_id(cm, mi_offset, x_mis, y_mis, r);
217   mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
218   mbmi->tx_size = read_tx_size(cm, xd, 1, r);
219   mbmi->ref_frame[0] = INTRA_FRAME;
220   mbmi->ref_frame[1] = NONE;
221
222   switch (bsize) {
223     case BLOCK_4X4:
224       for (i = 0; i < 4; ++i)
225         mi->bmi[i].as_mode =
226             read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, i));
227       mbmi->mode = mi->bmi[3].as_mode;
228       break;
229     case BLOCK_4X8:
230       mi->bmi[0].as_mode = mi->bmi[2].as_mode =
231           read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
232       mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
233           read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 1));
234       break;
235     case BLOCK_8X4:
236       mi->bmi[0].as_mode = mi->bmi[1].as_mode =
237           read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
238       mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
239           read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 2));
240       break;
241     default:
242       mbmi->mode = read_intra_mode(r,
243                                    get_y_mode_probs(mi, above_mi, left_mi, 0));
244   }
245
246   mbmi->uv_mode = read_intra_mode(r, vp10_kf_uv_mode_prob[mbmi->mode]);
247 }
248
249 static int read_mv_component(vpx_reader *r,
250                              const nmv_component *mvcomp, int usehp) {
251   int mag, d, fr, hp;
252   const int sign = vpx_read(r, mvcomp->sign);
253   const int mv_class = vpx_read_tree(r, vp10_mv_class_tree, mvcomp->classes);
254   const int class0 = mv_class == MV_CLASS_0;
255
256   // Integer part
257   if (class0) {
258     d = vpx_read_tree(r, vp10_mv_class0_tree, mvcomp->class0);
259     mag = 0;
260   } else {
261     int i;
262     const int n = mv_class + CLASS0_BITS - 1;  // number of bits
263
264     d = 0;
265     for (i = 0; i < n; ++i)
266       d |= vpx_read(r, mvcomp->bits[i]) << i;
267     mag = CLASS0_SIZE << (mv_class + 2);
268   }
269
270   // Fractional part
271   fr = vpx_read_tree(r, vp10_mv_fp_tree, class0 ? mvcomp->class0_fp[d]
272                                                : mvcomp->fp);
273
274   // High precision part (if hp is not used, the default value of the hp is 1)
275   hp = usehp ? vpx_read(r, class0 ? mvcomp->class0_hp : mvcomp->hp)
276              : 1;
277
278   // Result
279   mag += ((d << 3) | (fr << 1) | hp) + 1;
280   return sign ? -mag : mag;
281 }
282
283 static INLINE void read_mv(vpx_reader *r, MV *mv, const MV *ref,
284                            const nmv_context *ctx,
285                            nmv_context_counts *counts, int allow_hp) {
286   const MV_JOINT_TYPE joint_type =
287       (MV_JOINT_TYPE)vpx_read_tree(r, vp10_mv_joint_tree, ctx->joints);
288   const int use_hp = allow_hp && vp10_use_mv_hp(ref);
289   MV diff = {0, 0};
290
291   if (mv_joint_vertical(joint_type))
292     diff.row = read_mv_component(r, &ctx->comps[0], use_hp);
293
294   if (mv_joint_horizontal(joint_type))
295     diff.col = read_mv_component(r, &ctx->comps[1], use_hp);
296
297   vp10_inc_mv(&diff, counts);
298
299   mv->row = ref->row + diff.row;
300   mv->col = ref->col + diff.col;
301 }
302
303 static REFERENCE_MODE read_block_reference_mode(VP10_COMMON *cm,
304                                                 const MACROBLOCKD *xd,
305                                                 vpx_reader *r) {
306   if (cm->reference_mode == REFERENCE_MODE_SELECT) {
307     const int ctx = vp10_get_reference_mode_context(cm, xd);
308     const REFERENCE_MODE mode =
309         (REFERENCE_MODE)vpx_read(r, cm->fc->comp_inter_prob[ctx]);
310     FRAME_COUNTS *counts = xd->counts;
311     if (counts)
312       ++counts->comp_inter[ctx][mode];
313     return mode;  // SINGLE_REFERENCE or COMPOUND_REFERENCE
314   } else {
315     return cm->reference_mode;
316   }
317 }
318
319 // Read the referncence frame
320 static void read_ref_frames(VP10_COMMON *const cm, MACROBLOCKD *const xd,
321                             vpx_reader *r,
322                             int segment_id, MV_REFERENCE_FRAME ref_frame[2]) {
323   FRAME_CONTEXT *const fc = cm->fc;
324   FRAME_COUNTS *counts = xd->counts;
325
326   if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
327     ref_frame[0] = (MV_REFERENCE_FRAME)get_segdata(&cm->seg, segment_id,
328                                                    SEG_LVL_REF_FRAME);
329     ref_frame[1] = NONE;
330   } else {
331     const REFERENCE_MODE mode = read_block_reference_mode(cm, xd, r);
332     // FIXME(rbultje) I'm pretty sure this breaks segmentation ref frame coding
333     if (mode == COMPOUND_REFERENCE) {
334       const int idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
335       const int ctx = vp10_get_pred_context_comp_ref_p(cm, xd);
336       const int bit = vpx_read(r, fc->comp_ref_prob[ctx]);
337       if (counts)
338         ++counts->comp_ref[ctx][bit];
339       ref_frame[idx] = cm->comp_fixed_ref;
340       ref_frame[!idx] = cm->comp_var_ref[bit];
341     } else if (mode == SINGLE_REFERENCE) {
342       const int ctx0 = vp10_get_pred_context_single_ref_p1(xd);
343       const int bit0 = vpx_read(r, fc->single_ref_prob[ctx0][0]);
344       if (counts)
345         ++counts->single_ref[ctx0][0][bit0];
346       if (bit0) {
347         const int ctx1 = vp10_get_pred_context_single_ref_p2(xd);
348         const int bit1 = vpx_read(r, fc->single_ref_prob[ctx1][1]);
349         if (counts)
350           ++counts->single_ref[ctx1][1][bit1];
351         ref_frame[0] = bit1 ? ALTREF_FRAME : GOLDEN_FRAME;
352       } else {
353         ref_frame[0] = LAST_FRAME;
354       }
355
356       ref_frame[1] = NONE;
357     } else {
358       assert(0 && "Invalid prediction mode.");
359     }
360   }
361 }
362
363
364 static INLINE INTERP_FILTER read_switchable_interp_filter(
365     VP10_COMMON *const cm, MACROBLOCKD *const xd,
366     vpx_reader *r) {
367   const int ctx = vp10_get_pred_context_switchable_interp(xd);
368   const INTERP_FILTER type =
369       (INTERP_FILTER)vpx_read_tree(r, vp10_switchable_interp_tree,
370                                    cm->fc->switchable_interp_prob[ctx]);
371   FRAME_COUNTS *counts = xd->counts;
372   if (counts)
373     ++counts->switchable_interp[ctx][type];
374   return type;
375 }
376
377 static void read_intra_block_mode_info(VP10_COMMON *const cm,
378                                        MACROBLOCKD *const xd, MODE_INFO *mi,
379                                        vpx_reader *r) {
380   MB_MODE_INFO *const mbmi = &mi->mbmi;
381   const BLOCK_SIZE bsize = mi->mbmi.sb_type;
382   int i;
383
384   mbmi->ref_frame[0] = INTRA_FRAME;
385   mbmi->ref_frame[1] = NONE;
386
387   switch (bsize) {
388     case BLOCK_4X4:
389       for (i = 0; i < 4; ++i)
390         mi->bmi[i].as_mode = read_intra_mode_y(cm, xd, r, 0);
391       mbmi->mode = mi->bmi[3].as_mode;
392       break;
393     case BLOCK_4X8:
394       mi->bmi[0].as_mode = mi->bmi[2].as_mode = read_intra_mode_y(cm, xd,
395                                                                   r, 0);
396       mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
397           read_intra_mode_y(cm, xd, r, 0);
398       break;
399     case BLOCK_8X4:
400       mi->bmi[0].as_mode = mi->bmi[1].as_mode = read_intra_mode_y(cm, xd,
401                                                                   r, 0);
402       mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
403           read_intra_mode_y(cm, xd, r, 0);
404       break;
405     default:
406       mbmi->mode = read_intra_mode_y(cm, xd, r, size_group_lookup[bsize]);
407   }
408
409   mbmi->uv_mode = read_intra_mode_uv(cm, xd, r, mbmi->mode);
410 }
411
412 static INLINE int is_mv_valid(const MV *mv) {
413   return mv->row > MV_LOW && mv->row < MV_UPP &&
414          mv->col > MV_LOW && mv->col < MV_UPP;
415 }
416
417 static INLINE int assign_mv(VP10_COMMON *cm, MACROBLOCKD *xd,
418                             PREDICTION_MODE mode,
419                             int_mv mv[2], int_mv ref_mv[2],
420                             int_mv nearest_mv[2], int_mv near_mv[2],
421                             int is_compound, int allow_hp, vpx_reader *r) {
422   int i;
423   int ret = 1;
424
425   switch (mode) {
426     case NEWMV: {
427       FRAME_COUNTS *counts = xd->counts;
428       nmv_context_counts *const mv_counts = counts ? &counts->mv : NULL;
429       for (i = 0; i < 1 + is_compound; ++i) {
430         read_mv(r, &mv[i].as_mv, &ref_mv[i].as_mv, &cm->fc->nmvc, mv_counts,
431                 allow_hp);
432         ret = ret && is_mv_valid(&mv[i].as_mv);
433       }
434       break;
435     }
436     case NEARESTMV: {
437       mv[0].as_int = nearest_mv[0].as_int;
438       if (is_compound)
439         mv[1].as_int = nearest_mv[1].as_int;
440       break;
441     }
442     case NEARMV: {
443       mv[0].as_int = near_mv[0].as_int;
444       if (is_compound)
445         mv[1].as_int = near_mv[1].as_int;
446       break;
447     }
448     case ZEROMV: {
449       mv[0].as_int = 0;
450       if (is_compound)
451         mv[1].as_int = 0;
452       break;
453     }
454     default: {
455       return 0;
456     }
457   }
458   return ret;
459 }
460
461 static int read_is_inter_block(VP10_COMMON *const cm, MACROBLOCKD *const xd,
462                                int segment_id, vpx_reader *r) {
463   if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
464     return get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME) != INTRA_FRAME;
465   } else {
466     const int ctx = vp10_get_intra_inter_context(xd);
467     const int is_inter = vpx_read(r, cm->fc->intra_inter_prob[ctx]);
468     FRAME_COUNTS *counts = xd->counts;
469     if (counts)
470       ++counts->intra_inter[ctx][is_inter];
471     return is_inter;
472   }
473 }
474
475 static void fpm_sync(void *const data, int mi_row) {
476   VP10Decoder *const pbi = (VP10Decoder *)data;
477   vp10_frameworker_wait(pbi->frame_worker_owner, pbi->common.prev_frame,
478                        mi_row << MI_BLOCK_SIZE_LOG2);
479 }
480
481 static void read_inter_block_mode_info(VP10Decoder *const pbi,
482                                        MACROBLOCKD *const xd,
483                                        MODE_INFO *const mi,
484                                        int mi_row, int mi_col, vpx_reader *r) {
485   VP10_COMMON *const cm = &pbi->common;
486   MB_MODE_INFO *const mbmi = &mi->mbmi;
487   const BLOCK_SIZE bsize = mbmi->sb_type;
488   const int allow_hp = cm->allow_high_precision_mv;
489   int_mv nearestmv[2], nearmv[2];
490   int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
491   int ref, is_compound;
492   uint8_t inter_mode_ctx[MAX_REF_FRAMES];
493
494   read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame);
495   is_compound = has_second_ref(mbmi);
496
497   for (ref = 0; ref < 1 + is_compound; ++ref) {
498     const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
499     RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];
500
501     xd->block_refs[ref] = ref_buf;
502     if ((!vp10_is_valid_scale(&ref_buf->sf)))
503       vpx_internal_error(xd->error_info, VPX_CODEC_UNSUP_BITSTREAM,
504                          "Reference frame has invalid dimensions");
505     vp10_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col,
506                          &ref_buf->sf);
507     vp10_find_mv_refs(cm, xd, mi, frame, ref_mvs[frame],
508                      mi_row, mi_col, fpm_sync, (void *)pbi, inter_mode_ctx);
509   }
510
511   if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
512     mbmi->mode = ZEROMV;
513     if (bsize < BLOCK_8X8) {
514         vpx_internal_error(xd->error_info, VPX_CODEC_UNSUP_BITSTREAM,
515                            "Invalid usage of segement feature on small blocks");
516         return;
517     }
518   } else {
519     if (bsize >= BLOCK_8X8)
520       mbmi->mode = read_inter_mode(cm, xd, r,
521                                    inter_mode_ctx[mbmi->ref_frame[0]]);
522   }
523
524   if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) {
525     for (ref = 0; ref < 1 + is_compound; ++ref) {
526       vp10_find_best_ref_mvs(xd, allow_hp, ref_mvs[mbmi->ref_frame[ref]],
527                             &nearestmv[ref], &nearmv[ref]);
528     }
529   }
530
531   mbmi->interp_filter = (cm->interp_filter == SWITCHABLE)
532                       ? read_switchable_interp_filter(cm, xd, r)
533                       : cm->interp_filter;
534
535   if (bsize < BLOCK_8X8) {
536     const int num_4x4_w = 1 << xd->bmode_blocks_wl;
537     const int num_4x4_h = 1 << xd->bmode_blocks_hl;
538     int idx, idy;
539     PREDICTION_MODE b_mode;
540     int_mv nearest_sub8x8[2], near_sub8x8[2];
541     for (idy = 0; idy < 2; idy += num_4x4_h) {
542       for (idx = 0; idx < 2; idx += num_4x4_w) {
543         int_mv block[2];
544         const int j = idy * 2 + idx;
545         b_mode = read_inter_mode(cm, xd, r, inter_mode_ctx[mbmi->ref_frame[0]]);
546
547         if (b_mode == NEARESTMV || b_mode == NEARMV) {
548           uint8_t dummy_mode_ctx[MAX_REF_FRAMES];
549           for (ref = 0; ref < 1 + is_compound; ++ref)
550             vp10_append_sub8x8_mvs_for_idx(cm, xd, j, ref, mi_row, mi_col,
551                                           &nearest_sub8x8[ref],
552                                           &near_sub8x8[ref],
553                                           dummy_mode_ctx);
554         }
555
556         if (!assign_mv(cm, xd, b_mode, block, nearestmv,
557                        nearest_sub8x8, near_sub8x8,
558                        is_compound, allow_hp, r)) {
559           xd->corrupted |= 1;
560           break;
561         };
562
563         mi->bmi[j].as_mv[0].as_int = block[0].as_int;
564         if (is_compound)
565           mi->bmi[j].as_mv[1].as_int = block[1].as_int;
566
567         if (num_4x4_h == 2)
568           mi->bmi[j + 2] = mi->bmi[j];
569         if (num_4x4_w == 2)
570           mi->bmi[j + 1] = mi->bmi[j];
571       }
572     }
573
574     mi->mbmi.mode = b_mode;
575
576     mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
577     mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
578   } else {
579     xd->corrupted |= !assign_mv(cm, xd, mbmi->mode, mbmi->mv, nearestmv,
580                                 nearestmv, nearmv, is_compound, allow_hp, r);
581   }
582 }
583
584 static void read_inter_frame_mode_info(VP10Decoder *const pbi,
585                                        MACROBLOCKD *const xd,
586                                        int mi_row, int mi_col, vpx_reader *r) {
587   VP10_COMMON *const cm = &pbi->common;
588   MODE_INFO *const mi = xd->mi[0];
589   MB_MODE_INFO *const mbmi = &mi->mbmi;
590   int inter_block;
591
592   mbmi->mv[0].as_int = 0;
593   mbmi->mv[1].as_int = 0;
594   mbmi->segment_id = read_inter_segment_id(cm, xd, mi_row, mi_col, r);
595   mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
596   inter_block = read_is_inter_block(cm, xd, mbmi->segment_id, r);
597   mbmi->tx_size = read_tx_size(cm, xd, !mbmi->skip || !inter_block, r);
598
599   if (inter_block)
600     read_inter_block_mode_info(pbi, xd, mi, mi_row, mi_col, r);
601   else
602     read_intra_block_mode_info(cm, xd, mi, r);
603 }
604
605 void vp10_read_mode_info(VP10Decoder *const pbi, MACROBLOCKD *xd,
606                         int mi_row, int mi_col, vpx_reader *r,
607                         int x_mis, int y_mis) {
608   VP10_COMMON *const cm = &pbi->common;
609   MODE_INFO *const mi = xd->mi[0];
610   MV_REF* frame_mvs = cm->cur_frame->mvs + mi_row * cm->mi_cols + mi_col;
611   int w, h;
612
613   if (frame_is_intra_only(cm)) {
614     read_intra_frame_mode_info(cm, xd, mi_row, mi_col, r);
615   } else {
616     read_inter_frame_mode_info(pbi, xd, mi_row, mi_col, r);
617
618     for (h = 0; h < y_mis; ++h) {
619       MV_REF *const frame_mv = frame_mvs + h * cm->mi_cols;
620       for (w = 0; w < x_mis; ++w) {
621         MV_REF *const mv = frame_mv + w;
622         mv->ref_frame[0] = mi->mbmi.ref_frame[0];
623         mv->ref_frame[1] = mi->mbmi.ref_frame[1];
624         mv->mv[0].as_int = mi->mbmi.mv[0].as_int;
625         mv->mv[1].as_int = mi->mbmi.mv[1].as_int;
626       }
627     }
628   }
629 }