Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / vp9 / common / vp9_pred_common.c
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
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
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
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
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
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
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
222       if (above_has_second && left_has_second) {
223         pred_context = 1 + (above_mbmi->ref_frame[0] == LAST_FRAME ||
224                             above_mbmi->ref_frame[1] == LAST_FRAME ||
225                             left_mbmi->ref_frame[0] == LAST_FRAME ||
226                             left_mbmi->ref_frame[1] == LAST_FRAME);
227       } else if (above_has_second || left_has_second) {
228         const MV_REFERENCE_FRAME rfs = !above_has_second ?
229             above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
230         const MV_REFERENCE_FRAME crf1 = above_has_second ?
231             above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
232         const MV_REFERENCE_FRAME crf2 = above_has_second ?
233             above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
234
235         if (rfs == LAST_FRAME)
236           pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
237         else
238           pred_context = (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
239       } else {
240         pred_context = 2 * (above_mbmi->ref_frame[0] == LAST_FRAME) +
241                        2 * (left_mbmi->ref_frame[0] == LAST_FRAME);
242       }
243     }
244   } else if (has_above || has_left) {  // one edge available
245     const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
246     if (!is_inter_block(edge_mbmi)) {  // intra
247       pred_context = 2;
248     } else {  // inter
249       if (!has_second_ref(edge_mbmi))
250         pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
251       else
252         pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
253                             edge_mbmi->ref_frame[1] == LAST_FRAME);
254     }
255   } else {  // no edges available
256     pred_context = 2;
257   }
258
259   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
260   return pred_context;
261 }
262
263 int vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
264   int pred_context;
265   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
266   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
267   const int has_above = above_mbmi != NULL;
268   const int has_left = left_mbmi != NULL;
269
270   // Note:
271   // The mode info data structure has a one element border above and to the
272   // left of the entries correpsonding to real macroblocks.
273   // The prediction flags in these dummy entries are initialised to 0.
274   if (has_above && has_left) {  // both edges available
275     const int above_intra = !is_inter_block(above_mbmi);
276     const int left_intra = !is_inter_block(left_mbmi);
277
278     if (above_intra && left_intra) {  // intra/intra
279       pred_context = 2;
280     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
281       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
282       if (!has_second_ref(edge_mbmi)) {
283         if (edge_mbmi->ref_frame[0] == LAST_FRAME)
284           pred_context = 3;
285         else
286           pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
287       } else {
288         pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
289                                 edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
290       }
291     } else {  // inter/inter
292       const int above_has_second = has_second_ref(above_mbmi);
293       const int left_has_second = has_second_ref(left_mbmi);
294
295       if (above_has_second && left_has_second) {
296         if (above_mbmi->ref_frame[0] == left_mbmi->ref_frame[0] &&
297             above_mbmi->ref_frame[1] == left_mbmi->ref_frame[1])
298           pred_context = 3 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME ||
299                               above_mbmi->ref_frame[1] == GOLDEN_FRAME ||
300                               left_mbmi->ref_frame[0] == GOLDEN_FRAME ||
301                               left_mbmi->ref_frame[1] == GOLDEN_FRAME);
302         else
303           pred_context = 2;
304       } else if (above_has_second || left_has_second) {
305         const MV_REFERENCE_FRAME rfs = !above_has_second ?
306                      above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
307         const MV_REFERENCE_FRAME crf1 = above_has_second ?
308                    above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
309         const MV_REFERENCE_FRAME crf2 = above_has_second ?
310                      above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
311
312         if (rfs == GOLDEN_FRAME)
313           pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
314         else if (rfs == ALTREF_FRAME)
315           pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME;
316         else
317           pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
318       } else {
319         if (above_mbmi->ref_frame[0] == LAST_FRAME &&
320             left_mbmi->ref_frame[0] == LAST_FRAME) {
321           pred_context = 3;
322         } else if (above_mbmi->ref_frame[0] == LAST_FRAME ||
323                    left_mbmi->ref_frame[0] == LAST_FRAME) {
324           const MB_MODE_INFO *edge_mbmi =
325               above_mbmi->ref_frame[0] == LAST_FRAME ? left_mbmi : above_mbmi;
326             pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
327         } else {
328           pred_context = 2 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME) +
329                          2 * (left_mbmi->ref_frame[0] == GOLDEN_FRAME);
330         }
331       }
332     }
333   } else if (has_above || has_left) {  // one edge available
334     const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
335
336     if (!is_inter_block(edge_mbmi) ||
337         (edge_mbmi->ref_frame[0] == LAST_FRAME && !has_second_ref(edge_mbmi)))
338       pred_context = 2;
339     else if (!has_second_ref(edge_mbmi))
340       pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
341     else
342       pred_context = 3 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
343                           edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
344   } else {  // no edges available (2)
345     pred_context = 2;
346   }
347   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
348   return pred_context;
349 }
350 // Returns a context number for the given MB prediction signal
351 // The mode info data structure has a one element border above and to the
352 // left of the entries corresponding to real blocks.
353 // The prediction flags in these dummy entries are initialized to 0.
354 int vp9_get_tx_size_context(const MACROBLOCKD *xd) {
355   const int max_tx_size = max_txsize_lookup[xd->mi_8x8[0]->mbmi.sb_type];
356   const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd));
357   const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd));
358   const int has_above = above_mbmi != NULL;
359   const int has_left = left_mbmi != NULL;
360   int above_ctx = (has_above && !above_mbmi->skip_coeff) ? above_mbmi->tx_size
361                                                          : max_tx_size;
362   int left_ctx = (has_left && !left_mbmi->skip_coeff) ? left_mbmi->tx_size
363                                                       : max_tx_size;
364   if (!has_left)
365     left_ctx = above_ctx;
366
367   if (!has_above)
368     above_ctx = left_ctx;
369
370   return (above_ctx + left_ctx) > max_tx_size;
371 }
372
373 int vp9_get_segment_id(VP9_COMMON *cm, const uint8_t *segment_ids,
374                        BLOCK_SIZE bsize, int mi_row, int mi_col) {
375   const int mi_offset = mi_row * cm->mi_cols + mi_col;
376   const int bw = num_8x8_blocks_wide_lookup[bsize];
377   const int bh = num_8x8_blocks_high_lookup[bsize];
378   const int xmis = MIN(cm->mi_cols - mi_col, bw);
379   const int ymis = MIN(cm->mi_rows - mi_row, bh);
380   int x, y, segment_id = INT_MAX;
381
382   for (y = 0; y < ymis; y++)
383     for (x = 0; x < xmis; x++)
384       segment_id = MIN(segment_id,
385                        segment_ids[mi_offset + y * cm->mi_cols + x]);
386
387   assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
388   return segment_id;
389 }