1 
2 /*
3  *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
4  *
5  *  Use of this source code is governed by a BSD-style license
6  *  that can be found in the LICENSE file in the root of the source
7  *  tree. An additional intellectual property rights grant can be found
8  *  in the file PATENTS.  All contributing project authors may
9  *  be found in the AUTHORS file in the root of the source tree.
10  */
11 
12 #include <limits.h>
13 
14 #include "vp9/common/vp9_common.h"
15 #include "vp9/common/vp9_pred_common.h"
16 #include "vp9/common/vp9_seg_common.h"
17 
get_mbmi(const MODE_INFO * const mi)18 static INLINE const MB_MODE_INFO *get_mbmi(const MODE_INFO *const mi) {
19   return (mi != NULL) ? &mi->mbmi : NULL;
20 }
21 
22 // Returns a context number for the given MB prediction signal
vp9_get_pred_context_switchable_interp(const MACROBLOCKD * xd)23 int vp9_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
24   // Note:
25   // The mode info data structure has a one element border above and to the
26   // left of the entries correpsonding to real macroblocks.
27   // The prediction flags in these dummy entries are initialised to 0.
28   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
29   const int left_type = left_mbmi != NULL && is_inter_block(left_mbmi) ?
30                            left_mbmi->interp_filter : SWITCHABLE_FILTERS;
31   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
32   const int above_type = above_mbmi != NULL && is_inter_block(above_mbmi) ?
33                              above_mbmi->interp_filter : SWITCHABLE_FILTERS;
34 
35   if (left_type == above_type)
36     return left_type;
37   else if (left_type == SWITCHABLE_FILTERS && above_type != SWITCHABLE_FILTERS)
38     return above_type;
39   else if (left_type != SWITCHABLE_FILTERS && above_type == SWITCHABLE_FILTERS)
40     return left_type;
41   else
42     return SWITCHABLE_FILTERS;
43 }
44 
45 // The mode info data structure has a one element border above and to the
46 // left of the entries corresponding to real macroblocks.
47 // The prediction flags in these dummy entries are initialized to 0.
48 // 0 - inter/inter, inter/--, --/inter, --/--
49 // 1 - intra/inter, inter/intra
50 // 2 - intra/--, --/intra
51 // 3 - intra/intra
vp9_get_intra_inter_context(const MACROBLOCKD * xd)52 int vp9_get_intra_inter_context(const MACROBLOCKD *xd) {
53   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
54   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
55   const int has_above = above_mbmi != NULL;
56   const int has_left = left_mbmi != NULL;
57 
58   if (has_above && has_left) {  // both edges available
59     const int above_intra = !is_inter_block(above_mbmi);
60     const int left_intra = !is_inter_block(left_mbmi);
61     return left_intra && above_intra ? 3
62                                      : left_intra || above_intra;
63   } else if (has_above || has_left) {  // one edge available
64     return 2 * !is_inter_block(has_above ? above_mbmi : left_mbmi);
65   } else {
66     return 0;
67   }
68 }
69 
vp9_get_reference_mode_context(const VP9_COMMON * cm,const MACROBLOCKD * xd)70 int vp9_get_reference_mode_context(const VP9_COMMON *cm,
71                                    const MACROBLOCKD *xd) {
72   int ctx;
73   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
74   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
75   const int has_above = above_mbmi != NULL;
76   const int has_left = left_mbmi != NULL;
77   // Note:
78   // The mode info data structure has a one element border above and to the
79   // left of the entries correpsonding to real macroblocks.
80   // The prediction flags in these dummy entries are initialised to 0.
81   if (has_above && has_left) {  // both edges available
82     if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi))
83       // neither edge uses comp pred (0/1)
84       ctx = (above_mbmi->ref_frame[0] == cm->comp_fixed_ref) ^
85             (left_mbmi->ref_frame[0] == cm->comp_fixed_ref);
86     else if (!has_second_ref(above_mbmi))
87       // one of two edges uses comp pred (2/3)
88       ctx = 2 + (above_mbmi->ref_frame[0] == cm->comp_fixed_ref ||
89                  !is_inter_block(above_mbmi));
90     else if (!has_second_ref(left_mbmi))
91       // one of two edges uses comp pred (2/3)
92       ctx = 2 + (left_mbmi->ref_frame[0] == cm->comp_fixed_ref ||
93                  !is_inter_block(left_mbmi));
94     else  // both edges use comp pred (4)
95       ctx = 4;
96   } else if (has_above || has_left) {  // one edge available
97     const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
98 
99     if (!has_second_ref(edge_mbmi))
100       // edge does not use comp pred (0/1)
101       ctx = edge_mbmi->ref_frame[0] == cm->comp_fixed_ref;
102     else
103       // edge uses comp pred (3)
104       ctx = 3;
105   } else {  // no edges available (1)
106     ctx = 1;
107   }
108   assert(ctx >= 0 && ctx < COMP_INTER_CONTEXTS);
109   return ctx;
110 }
111 
112 // Returns a context number for the given MB prediction signal
vp9_get_pred_context_comp_ref_p(const VP9_COMMON * cm,const MACROBLOCKD * xd)113 int vp9_get_pred_context_comp_ref_p(const VP9_COMMON *cm,
114                                     const MACROBLOCKD *xd) {
115   int pred_context;
116   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
117   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
118   const int above_in_image = above_mbmi != NULL;
119   const int left_in_image = left_mbmi != NULL;
120 
121   // Note:
122   // The mode info data structure has a one element border above and to the
123   // left of the entries correpsonding to real macroblocks.
124   // The prediction flags in these dummy entries are initialised to 0.
125   const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
126   const int var_ref_idx = !fix_ref_idx;
127 
128   if (above_in_image && left_in_image) {  // both edges available
129     const int above_intra = !is_inter_block(above_mbmi);
130     const int left_intra = !is_inter_block(left_mbmi);
131 
132     if (above_intra && left_intra) {  // intra/intra (2)
133       pred_context = 2;
134     } else if (above_intra || left_intra) {  // intra/inter
135       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
136 
137       if (!has_second_ref(edge_mbmi))  // single pred (1/3)
138         pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
139       else  // comp pred (1/3)
140         pred_context = 1 + 2 * (edge_mbmi->ref_frame[var_ref_idx]
141                                     != cm->comp_var_ref[1]);
142     } else {  // inter/inter
143       const int l_sg = !has_second_ref(left_mbmi);
144       const int a_sg = !has_second_ref(above_mbmi);
145       const MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
146                                            : above_mbmi->ref_frame[var_ref_idx];
147       const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
148                                            : left_mbmi->ref_frame[var_ref_idx];
149 
150       if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) {
151         pred_context = 0;
152       } else if (l_sg && a_sg) {  // single/single
153         if ((vrfa == cm->comp_fixed_ref && vrfl == cm->comp_var_ref[0]) ||
154             (vrfl == cm->comp_fixed_ref && vrfa == cm->comp_var_ref[0]))
155           pred_context = 4;
156         else if (vrfa == vrfl)
157           pred_context = 3;
158         else
159           pred_context = 1;
160       } else if (l_sg || a_sg) {  // single/comp
161         const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
162         const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
163         if (vrfc == cm->comp_var_ref[1] && rfs != cm->comp_var_ref[1])
164           pred_context = 1;
165         else if (rfs == cm->comp_var_ref[1] && vrfc != cm->comp_var_ref[1])
166           pred_context = 2;
167         else
168           pred_context = 4;
169       } else if (vrfa == vrfl) {  // comp/comp
170         pred_context = 4;
171       } else {
172         pred_context = 2;
173       }
174     }
175   } else if (above_in_image || left_in_image) {  // one edge available
176     const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
177 
178     if (!is_inter_block(edge_mbmi)) {
179       pred_context = 2;
180     } else {
181       if (has_second_ref(edge_mbmi))
182         pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx]
183                               != cm->comp_var_ref[1]);
184       else
185         pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
186     }
187   } else {  // no edges available (2)
188     pred_context = 2;
189   }
190   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
191 
192   return pred_context;
193 }
194 
vp9_get_pred_context_single_ref_p1(const MACROBLOCKD * xd)195 int vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) {
196   int pred_context;
197   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
198   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
199   const int has_above = above_mbmi != NULL;
200   const int has_left = left_mbmi != NULL;
201   // Note:
202   // The mode info data structure has a one element border above and to the
203   // left of the entries correpsonding to real macroblocks.
204   // The prediction flags in these dummy entries are initialised to 0.
205   if (has_above && has_left) {  // both edges available
206     const int above_intra = !is_inter_block(above_mbmi);
207     const int left_intra = !is_inter_block(left_mbmi);
208 
209     if (above_intra && left_intra) {  // intra/intra
210       pred_context = 2;
211     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
212       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
213       if (!has_second_ref(edge_mbmi))
214         pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
215       else
216         pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
217                             edge_mbmi->ref_frame[1] == LAST_FRAME);
218     } else {  // inter/inter
219       const int above_has_second = has_second_ref(above_mbmi);
220       const int left_has_second = has_second_ref(left_mbmi);
221       const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
222       const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
223       const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
224       const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
225 
226       if (above_has_second && left_has_second) {
227         pred_context = 1 + (above0 == LAST_FRAME || above1 == LAST_FRAME ||
228                             left0 == LAST_FRAME || left1 == LAST_FRAME);
229       } else if (above_has_second || left_has_second) {
230         const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
231         const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
232         const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
233 
234         if (rfs == LAST_FRAME)
235           pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
236         else
237           pred_context = (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
238       } else {
239         pred_context = 2 * (above0 == LAST_FRAME) + 2 * (left0 == LAST_FRAME);
240       }
241     }
242   } else if (has_above || has_left) {  // one edge available
243     const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
244     if (!is_inter_block(edge_mbmi)) {  // intra
245       pred_context = 2;
246     } else {  // inter
247       if (!has_second_ref(edge_mbmi))
248         pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
249       else
250         pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
251                             edge_mbmi->ref_frame[1] == LAST_FRAME);
252     }
253   } else {  // no edges available
254     pred_context = 2;
255   }
256 
257   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
258   return pred_context;
259 }
260 
vp9_get_pred_context_single_ref_p2(const MACROBLOCKD * xd)261 int vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
262   int pred_context;
263   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
264   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
265   const int has_above = above_mbmi != NULL;
266   const int has_left = left_mbmi != NULL;
267 
268   // Note:
269   // The mode info data structure has a one element border above and to the
270   // left of the entries correpsonding to real macroblocks.
271   // The prediction flags in these dummy entries are initialised to 0.
272   if (has_above && has_left) {  // both edges available
273     const int above_intra = !is_inter_block(above_mbmi);
274     const int left_intra = !is_inter_block(left_mbmi);
275 
276     if (above_intra && left_intra) {  // intra/intra
277       pred_context = 2;
278     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
279       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
280       if (!has_second_ref(edge_mbmi)) {
281         if (edge_mbmi->ref_frame[0] == LAST_FRAME)
282           pred_context = 3;
283         else
284           pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
285       } else {
286         pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
287                                 edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
288       }
289     } else {  // inter/inter
290       const int above_has_second = has_second_ref(above_mbmi);
291       const int left_has_second = has_second_ref(left_mbmi);
292       const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
293       const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
294       const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
295       const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
296 
297       if (above_has_second && left_has_second) {
298         if (above0 == left0 && above1 == left1)
299           pred_context = 3 * (above0 == GOLDEN_FRAME ||
300                               above1 == GOLDEN_FRAME ||
301                               left0 == GOLDEN_FRAME ||
302                               left1 == GOLDEN_FRAME);
303         else
304           pred_context = 2;
305       } else if (above_has_second || left_has_second) {
306         const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
307         const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
308         const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
309 
310         if (rfs == GOLDEN_FRAME)
311           pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
312         else if (rfs == ALTREF_FRAME)
313           pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME;
314         else
315           pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
316       } else {
317         if (above0 == LAST_FRAME && left0 == LAST_FRAME) {
318           pred_context = 3;
319         } else if (above0 == LAST_FRAME || left0 == LAST_FRAME) {
320           const MV_REFERENCE_FRAME edge0 = (above0 == LAST_FRAME) ? left0
321                                                                   : above0;
322           pred_context = 4 * (edge0 == GOLDEN_FRAME);
323         } else {
324           pred_context = 2 * (above0 == GOLDEN_FRAME) +
325                              2 * (left0 == GOLDEN_FRAME);
326         }
327       }
328     }
329   } else if (has_above || has_left) {  // one edge available
330     const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
331 
332     if (!is_inter_block(edge_mbmi) ||
333         (edge_mbmi->ref_frame[0] == LAST_FRAME && !has_second_ref(edge_mbmi)))
334       pred_context = 2;
335     else if (!has_second_ref(edge_mbmi))
336       pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
337     else
338       pred_context = 3 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
339                           edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
340   } else {  // no edges available (2)
341     pred_context = 2;
342   }
343   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
344   return pred_context;
345 }
346 // Returns a context number for the given MB prediction signal
347 // The mode info data structure has a one element border above and to the
348 // left of the entries corresponding to real blocks.
349 // The prediction flags in these dummy entries are initialized to 0.
vp9_get_tx_size_context(const MACROBLOCKD * xd)350 int vp9_get_tx_size_context(const MACROBLOCKD *xd) {
351   const int max_tx_size = max_txsize_lookup[xd->mi[0]->mbmi.sb_type];
352   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
353   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
354   const int has_above = above_mbmi != NULL;
355   const int has_left = left_mbmi != NULL;
356   int above_ctx = (has_above && !above_mbmi->skip) ? (int)above_mbmi->tx_size
357                                                    : max_tx_size;
358   int left_ctx = (has_left && !left_mbmi->skip) ? (int)left_mbmi->tx_size
359                                                 : max_tx_size;
360   if (!has_left)
361     left_ctx = above_ctx;
362 
363   if (!has_above)
364     above_ctx = left_ctx;
365 
366   return (above_ctx + left_ctx) > max_tx_size;
367 }
368 
vp9_get_segment_id(const VP9_COMMON * cm,const uint8_t * segment_ids,BLOCK_SIZE bsize,int mi_row,int mi_col)369 int vp9_get_segment_id(const VP9_COMMON *cm, const uint8_t *segment_ids,
370                        BLOCK_SIZE bsize, int mi_row, int mi_col) {
371   const int mi_offset = mi_row * cm->mi_cols + mi_col;
372   const int bw = num_8x8_blocks_wide_lookup[bsize];
373   const int bh = num_8x8_blocks_high_lookup[bsize];
374   const int xmis = MIN(cm->mi_cols - mi_col, bw);
375   const int ymis = MIN(cm->mi_rows - mi_row, bh);
376   int x, y, segment_id = INT_MAX;
377 
378   for (y = 0; y < ymis; y++)
379     for (x = 0; x < xmis; x++)
380       segment_id = MIN(segment_id,
381                        segment_ids[mi_offset + y * cm->mi_cols + x]);
382 
383   assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
384   return segment_id;
385 }
386