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 "vp9/common/vp9_common.h"
13 #include "vp9/common/vp9_pred_common.h"
14 #include "vp9/common/vp9_seg_common.h"
15 
16 // Returns a context number for the given MB prediction signal
vp9_get_pred_context_switchable_interp(const MACROBLOCKD * xd)17 int vp9_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
18   // Note:
19   // The mode info data structure has a one element border above and to the
20   // left of the entries correpsonding to real macroblocks.
21   // The prediction flags in these dummy entries are initialised to 0.
22   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
23   const int left_type = xd->left_available && is_inter_block(left_mbmi) ?
24                             left_mbmi->interp_filter : SWITCHABLE_FILTERS;
25   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
26   const int above_type = xd->up_available && is_inter_block(above_mbmi) ?
27                              above_mbmi->interp_filter : SWITCHABLE_FILTERS;
28 
29   if (left_type == above_type)
30     return left_type;
31   else if (left_type == SWITCHABLE_FILTERS && above_type != SWITCHABLE_FILTERS)
32     return above_type;
33   else if (left_type != SWITCHABLE_FILTERS && above_type == SWITCHABLE_FILTERS)
34     return left_type;
35   else
36     return SWITCHABLE_FILTERS;
37 }
38 
39 // The mode info data structure has a one element border above and to the
40 // left of the entries corresponding to real macroblocks.
41 // The prediction flags in these dummy entries are initialized to 0.
42 // 0 - inter/inter, inter/--, --/inter, --/--
43 // 1 - intra/inter, inter/intra
44 // 2 - intra/--, --/intra
45 // 3 - intra/intra
vp9_get_intra_inter_context(const MACROBLOCKD * xd)46 int vp9_get_intra_inter_context(const MACROBLOCKD *xd) {
47   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
48   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
49   const int has_above = xd->up_available;
50   const int has_left = xd->left_available;
51 
52   if (has_above && has_left) {  // both edges available
53     const int above_intra = !is_inter_block(above_mbmi);
54     const int left_intra = !is_inter_block(left_mbmi);
55     return left_intra && above_intra ? 3
56                                      : left_intra || above_intra;
57   } else if (has_above || has_left) {  // one edge available
58     return 2 * !is_inter_block(has_above ? above_mbmi : left_mbmi);
59   } else {
60     return 0;
61   }
62 }
63 
vp9_get_reference_mode_context(const VP9_COMMON * cm,const MACROBLOCKD * xd)64 int vp9_get_reference_mode_context(const VP9_COMMON *cm,
65                                    const MACROBLOCKD *xd) {
66   int ctx;
67   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
68   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
69   const int has_above = xd->up_available;
70   const int has_left = xd->left_available;
71   // Note:
72   // The mode info data structure has a one element border above and to the
73   // left of the entries correpsonding to real macroblocks.
74   // The prediction flags in these dummy entries are initialised to 0.
75   if (has_above && has_left) {  // both edges available
76     if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi))
77       // neither edge uses comp pred (0/1)
78       ctx = (above_mbmi->ref_frame[0] == cm->comp_fixed_ref) ^
79             (left_mbmi->ref_frame[0] == cm->comp_fixed_ref);
80     else if (!has_second_ref(above_mbmi))
81       // one of two edges uses comp pred (2/3)
82       ctx = 2 + (above_mbmi->ref_frame[0] == cm->comp_fixed_ref ||
83                  !is_inter_block(above_mbmi));
84     else if (!has_second_ref(left_mbmi))
85       // one of two edges uses comp pred (2/3)
86       ctx = 2 + (left_mbmi->ref_frame[0] == cm->comp_fixed_ref ||
87                  !is_inter_block(left_mbmi));
88     else  // both edges use comp pred (4)
89       ctx = 4;
90   } else if (has_above || has_left) {  // one edge available
91     const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
92 
93     if (!has_second_ref(edge_mbmi))
94       // edge does not use comp pred (0/1)
95       ctx = edge_mbmi->ref_frame[0] == cm->comp_fixed_ref;
96     else
97       // edge uses comp pred (3)
98       ctx = 3;
99   } else {  // no edges available (1)
100     ctx = 1;
101   }
102   assert(ctx >= 0 && ctx < COMP_INTER_CONTEXTS);
103   return ctx;
104 }
105 
106 // Returns a context number for the given MB prediction signal
vp9_get_pred_context_comp_ref_p(const VP9_COMMON * cm,const MACROBLOCKD * xd)107 int vp9_get_pred_context_comp_ref_p(const VP9_COMMON *cm,
108                                     const MACROBLOCKD *xd) {
109   int pred_context;
110   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
111   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
112   const int above_in_image = xd->up_available;
113   const int left_in_image = xd->left_available;
114 
115   // Note:
116   // The mode info data structure has a one element border above and to the
117   // left of the entries correpsonding to real macroblocks.
118   // The prediction flags in these dummy entries are initialised to 0.
119   const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
120   const int var_ref_idx = !fix_ref_idx;
121 
122   if (above_in_image && left_in_image) {  // both edges available
123     const int above_intra = !is_inter_block(above_mbmi);
124     const int left_intra = !is_inter_block(left_mbmi);
125 
126     if (above_intra && left_intra) {  // intra/intra (2)
127       pred_context = 2;
128     } else if (above_intra || left_intra) {  // intra/inter
129       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
130 
131       if (!has_second_ref(edge_mbmi))  // single pred (1/3)
132         pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
133       else  // comp pred (1/3)
134         pred_context = 1 + 2 * (edge_mbmi->ref_frame[var_ref_idx]
135                                     != cm->comp_var_ref[1]);
136     } else {  // inter/inter
137       const int l_sg = !has_second_ref(left_mbmi);
138       const int a_sg = !has_second_ref(above_mbmi);
139       const MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
140                                            : above_mbmi->ref_frame[var_ref_idx];
141       const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
142                                            : left_mbmi->ref_frame[var_ref_idx];
143 
144       if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) {
145         pred_context = 0;
146       } else if (l_sg && a_sg) {  // single/single
147         if ((vrfa == cm->comp_fixed_ref && vrfl == cm->comp_var_ref[0]) ||
148             (vrfl == cm->comp_fixed_ref && vrfa == cm->comp_var_ref[0]))
149           pred_context = 4;
150         else if (vrfa == vrfl)
151           pred_context = 3;
152         else
153           pred_context = 1;
154       } else if (l_sg || a_sg) {  // single/comp
155         const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
156         const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
157         if (vrfc == cm->comp_var_ref[1] && rfs != cm->comp_var_ref[1])
158           pred_context = 1;
159         else if (rfs == cm->comp_var_ref[1] && vrfc != cm->comp_var_ref[1])
160           pred_context = 2;
161         else
162           pred_context = 4;
163       } else if (vrfa == vrfl) {  // comp/comp
164         pred_context = 4;
165       } else {
166         pred_context = 2;
167       }
168     }
169   } else if (above_in_image || left_in_image) {  // one edge available
170     const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
171 
172     if (!is_inter_block(edge_mbmi)) {
173       pred_context = 2;
174     } else {
175       if (has_second_ref(edge_mbmi))
176         pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx]
177                               != cm->comp_var_ref[1]);
178       else
179         pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
180     }
181   } else {  // no edges available (2)
182     pred_context = 2;
183   }
184   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
185 
186   return pred_context;
187 }
188 
vp9_get_pred_context_single_ref_p1(const MACROBLOCKD * xd)189 int vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) {
190   int pred_context;
191   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
192   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
193   const int has_above = xd->up_available;
194   const int has_left = xd->left_available;
195   // Note:
196   // The mode info data structure has a one element border above and to the
197   // left of the entries correpsonding to real macroblocks.
198   // The prediction flags in these dummy entries are initialised to 0.
199   if (has_above && has_left) {  // both edges available
200     const int above_intra = !is_inter_block(above_mbmi);
201     const int left_intra = !is_inter_block(left_mbmi);
202 
203     if (above_intra && left_intra) {  // intra/intra
204       pred_context = 2;
205     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
206       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
207       if (!has_second_ref(edge_mbmi))
208         pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
209       else
210         pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
211                             edge_mbmi->ref_frame[1] == LAST_FRAME);
212     } else {  // inter/inter
213       const int above_has_second = has_second_ref(above_mbmi);
214       const int left_has_second = has_second_ref(left_mbmi);
215       const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
216       const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
217       const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
218       const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
219 
220       if (above_has_second && left_has_second) {
221         pred_context = 1 + (above0 == LAST_FRAME || above1 == LAST_FRAME ||
222                             left0 == LAST_FRAME || left1 == LAST_FRAME);
223       } else if (above_has_second || left_has_second) {
224         const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
225         const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
226         const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
227 
228         if (rfs == LAST_FRAME)
229           pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
230         else
231           pred_context = (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
232       } else {
233         pred_context = 2 * (above0 == LAST_FRAME) + 2 * (left0 == LAST_FRAME);
234       }
235     }
236   } else if (has_above || has_left) {  // one edge available
237     const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
238     if (!is_inter_block(edge_mbmi)) {  // intra
239       pred_context = 2;
240     } else {  // inter
241       if (!has_second_ref(edge_mbmi))
242         pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
243       else
244         pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
245                             edge_mbmi->ref_frame[1] == LAST_FRAME);
246     }
247   } else {  // no edges available
248     pred_context = 2;
249   }
250 
251   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
252   return pred_context;
253 }
254 
vp9_get_pred_context_single_ref_p2(const MACROBLOCKD * xd)255 int vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
256   int pred_context;
257   const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
258   const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
259   const int has_above = xd->up_available;
260   const int has_left = xd->left_available;
261 
262   // Note:
263   // The mode info data structure has a one element border above and to the
264   // left of the entries correpsonding to real macroblocks.
265   // The prediction flags in these dummy entries are initialised to 0.
266   if (has_above && has_left) {  // both edges available
267     const int above_intra = !is_inter_block(above_mbmi);
268     const int left_intra = !is_inter_block(left_mbmi);
269 
270     if (above_intra && left_intra) {  // intra/intra
271       pred_context = 2;
272     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
273       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
274       if (!has_second_ref(edge_mbmi)) {
275         if (edge_mbmi->ref_frame[0] == LAST_FRAME)
276           pred_context = 3;
277         else
278           pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
279       } else {
280         pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
281                                 edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
282       }
283     } else {  // inter/inter
284       const int above_has_second = has_second_ref(above_mbmi);
285       const int left_has_second = has_second_ref(left_mbmi);
286       const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
287       const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
288       const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
289       const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
290 
291       if (above_has_second && left_has_second) {
292         if (above0 == left0 && above1 == left1)
293           pred_context = 3 * (above0 == GOLDEN_FRAME ||
294                               above1 == GOLDEN_FRAME ||
295                               left0 == GOLDEN_FRAME ||
296                               left1 == GOLDEN_FRAME);
297         else
298           pred_context = 2;
299       } else if (above_has_second || left_has_second) {
300         const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
301         const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
302         const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;
303 
304         if (rfs == GOLDEN_FRAME)
305           pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
306         else if (rfs == ALTREF_FRAME)
307           pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME;
308         else
309           pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
310       } else {
311         if (above0 == LAST_FRAME && left0 == LAST_FRAME) {
312           pred_context = 3;
313         } else if (above0 == LAST_FRAME || left0 == LAST_FRAME) {
314           const MV_REFERENCE_FRAME edge0 = (above0 == LAST_FRAME) ? left0
315                                                                   : above0;
316           pred_context = 4 * (edge0 == GOLDEN_FRAME);
317         } else {
318           pred_context = 2 * (above0 == GOLDEN_FRAME) +
319                              2 * (left0 == GOLDEN_FRAME);
320         }
321       }
322     }
323   } else if (has_above || has_left) {  // one edge available
324     const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
325 
326     if (!is_inter_block(edge_mbmi) ||
327         (edge_mbmi->ref_frame[0] == LAST_FRAME && !has_second_ref(edge_mbmi)))
328       pred_context = 2;
329     else if (!has_second_ref(edge_mbmi))
330       pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
331     else
332       pred_context = 3 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
333                           edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
334   } else {  // no edges available (2)
335     pred_context = 2;
336   }
337   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
338   return pred_context;
339 }
340