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