1 /*
2  * Copyright (c) 2017, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #ifndef AV1_COMMON_TXB_COMMON_H_
13 #define AV1_COMMON_TXB_COMMON_H_
14 
15 #define REDUCE_CONTEXT_DEPENDENCY 0
16 #define MIN_SCAN_IDX_REDUCE_CONTEXT_DEPENDENCY 0
17 
18 extern const int16_t av1_coeff_band_4x4[16];
19 
20 extern const int16_t av1_coeff_band_8x8[64];
21 
22 extern const int16_t av1_coeff_band_16x16[256];
23 
24 extern const int16_t av1_coeff_band_32x32[1024];
25 
26 typedef struct txb_ctx {
27   int txb_skip_ctx;
28   int dc_sign_ctx;
29 } TXB_CTX;
30 
get_txsize_context(TX_SIZE tx_size)31 static INLINE TX_SIZE get_txsize_context(TX_SIZE tx_size) {
32   return txsize_sqr_up_map[tx_size];
33 }
34 
35 static int base_ref_offset[BASE_CONTEXT_POSITION_NUM][2] = {
36   /* clang-format off*/
37   { -2, 0 }, { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -2 }, { 0, -1 }, { 0, 1 },
38   { 0, 2 },  { 1, -1 },  { 1, 0 },  { 1, 1 },  { 2, 0 }
39   /* clang-format on*/
40 };
41 
get_level_count(const tran_low_t * tcoeffs,int bwl,int height,int row,int col,int level,int (* nb_offset)[2],int nb_num)42 static INLINE int get_level_count(const tran_low_t *tcoeffs, int bwl,
43                                   int height, int row, int col, int level,
44                                   int (*nb_offset)[2], int nb_num) {
45   int count = 0;
46   for (int idx = 0; idx < nb_num; ++idx) {
47     const int ref_row = row + nb_offset[idx][0];
48     const int ref_col = col + nb_offset[idx][1];
49     if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
50         ref_col >= (1 << bwl))
51       continue;
52     const int pos = (ref_row << bwl) + ref_col;
53     tran_low_t abs_coeff = abs(tcoeffs[pos]);
54     count += abs_coeff > level;
55   }
56   return count;
57 }
58 
get_mag(int * mag,const tran_low_t * tcoeffs,int bwl,int height,int row,int col,int (* nb_offset)[2],int nb_num)59 static INLINE void get_mag(int *mag, const tran_low_t *tcoeffs, int bwl,
60                            int height, int row, int col, int (*nb_offset)[2],
61                            int nb_num) {
62   mag[0] = 0;
63   mag[1] = 0;
64   for (int idx = 0; idx < nb_num; ++idx) {
65     const int ref_row = row + nb_offset[idx][0];
66     const int ref_col = col + nb_offset[idx][1];
67     if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
68         ref_col >= (1 << bwl))
69       continue;
70     const int pos = (ref_row << bwl) + ref_col;
71     tran_low_t abs_coeff = abs(tcoeffs[pos]);
72     if (nb_offset[idx][0] >= 0 && nb_offset[idx][1] >= 0) {
73       if (abs_coeff > mag[0]) {
74         mag[0] = abs_coeff;
75         mag[1] = 1;
76       } else if (abs_coeff == mag[0]) {
77         ++mag[1];
78       }
79     }
80   }
81 }
82 
get_base_count_mag(int * mag,int * count,const tran_low_t * tcoeffs,int bwl,int height,int row,int col)83 static INLINE void get_base_count_mag(int *mag, int *count,
84                                       const tran_low_t *tcoeffs, int bwl,
85                                       int height, int row, int col) {
86   mag[0] = 0;
87   mag[1] = 0;
88   for (int i = 0; i < NUM_BASE_LEVELS; ++i) count[i] = 0;
89   for (int idx = 0; idx < BASE_CONTEXT_POSITION_NUM; ++idx) {
90     const int ref_row = row + base_ref_offset[idx][0];
91     const int ref_col = col + base_ref_offset[idx][1];
92     if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
93         ref_col >= (1 << bwl))
94       continue;
95     const int pos = (ref_row << bwl) + ref_col;
96     tran_low_t abs_coeff = abs(tcoeffs[pos]);
97     // count
98     for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
99       count[i] += abs_coeff > i;
100     }
101     // mag
102     if (base_ref_offset[idx][0] >= 0 && base_ref_offset[idx][1] >= 0) {
103       if (abs_coeff > mag[0]) {
104         mag[0] = abs_coeff;
105         mag[1] = 1;
106       } else if (abs_coeff == mag[0]) {
107         ++mag[1];
108       }
109     }
110   }
111 }
112 
get_level_count_mag(int * mag,const tran_low_t * tcoeffs,int bwl,int height,int row,int col,int level,int (* nb_offset)[2],int nb_num)113 static INLINE int get_level_count_mag(int *mag, const tran_low_t *tcoeffs,
114                                       int bwl, int height, int row, int col,
115                                       int level, int (*nb_offset)[2],
116                                       int nb_num) {
117   const int stride = 1 << bwl;
118   int count = 0;
119   *mag = 0;
120   for (int idx = 0; idx < nb_num; ++idx) {
121     const int ref_row = row + nb_offset[idx][0];
122     const int ref_col = col + nb_offset[idx][1];
123     if (ref_row < 0 || ref_col < 0 || ref_row >= height || ref_col >= stride)
124       continue;
125     const int pos = (ref_row << bwl) + ref_col;
126     tran_low_t abs_coeff = abs(tcoeffs[pos]);
127     count += abs_coeff > level;
128     if (nb_offset[idx][0] >= 0 && nb_offset[idx][1] >= 0)
129       *mag = AOMMAX(*mag, abs_coeff);
130   }
131   return count;
132 }
133 
get_base_ctx_from_count_mag(int row,int col,int count,int sig_mag)134 static INLINE int get_base_ctx_from_count_mag(int row, int col, int count,
135                                               int sig_mag) {
136   const int ctx = (count + 1) >> 1;
137   int ctx_idx = -1;
138   if (row == 0 && col == 0) {
139     ctx_idx = (ctx << 1) + sig_mag;
140     // TODO(angiebird): turn this on once the optimization is finalized
141     // assert(ctx_idx < 8);
142   } else if (row == 0) {
143     ctx_idx = 8 + (ctx << 1) + sig_mag;
144     // TODO(angiebird): turn this on once the optimization is finalized
145     // assert(ctx_idx < 18);
146   } else if (col == 0) {
147     ctx_idx = 8 + 10 + (ctx << 1) + sig_mag;
148     // TODO(angiebird): turn this on once the optimization is finalized
149     // assert(ctx_idx < 28);
150   } else {
151     ctx_idx = 8 + 10 + 10 + (ctx << 1) + sig_mag;
152     assert(ctx_idx < COEFF_BASE_CONTEXTS);
153   }
154   return ctx_idx;
155 }
156 
get_base_ctx(const tran_low_t * tcoeffs,int c,const int bwl,const int height,const int level)157 static INLINE int get_base_ctx(const tran_low_t *tcoeffs,
158                                int c,  // raster order
159                                const int bwl, const int height,
160                                const int level) {
161   const int row = c >> bwl;
162   const int col = c - (row << bwl);
163   const int level_minus_1 = level - 1;
164   int mag;
165   int count =
166       get_level_count_mag(&mag, tcoeffs, bwl, height, row, col, level_minus_1,
167                           base_ref_offset, BASE_CONTEXT_POSITION_NUM);
168   int ctx_idx = get_base_ctx_from_count_mag(row, col, count, mag > level);
169   return ctx_idx;
170 }
171 
172 #define BR_CONTEXT_POSITION_NUM 8  // Base range coefficient context
173 static int br_ref_offset[BR_CONTEXT_POSITION_NUM][2] = {
174   /* clang-format off*/
175   { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 },
176   { 0, 1 },   { 1, -1 }, { 1, 0 },  { 1, 1 },
177   /* clang-format on*/
178 };
179 
180 static const int br_level_map[9] = {
181   0, 0, 1, 1, 2, 2, 3, 3, 3,
182 };
183 
184 static const int coeff_to_br_index[COEFF_BASE_RANGE] = {
185   0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
186 };
187 
188 static const int br_index_to_coeff[BASE_RANGE_SETS] = {
189   0, 2, 6,
190 };
191 
192 static const int br_extra_bits[BASE_RANGE_SETS] = {
193   1, 2, 3,
194 };
195 
196 #define BR_MAG_OFFSET 1
197 // TODO(angiebird): optimize this function by using a table to map from
198 // count/mag to ctx
199 
get_br_count_mag(int * mag,const tran_low_t * tcoeffs,int bwl,int height,int row,int col,int level)200 static INLINE int get_br_count_mag(int *mag, const tran_low_t *tcoeffs, int bwl,
201                                    int height, int row, int col, int level) {
202   mag[0] = 0;
203   mag[1] = 0;
204   int count = 0;
205   for (int idx = 0; idx < BR_CONTEXT_POSITION_NUM; ++idx) {
206     const int ref_row = row + br_ref_offset[idx][0];
207     const int ref_col = col + br_ref_offset[idx][1];
208     if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
209         ref_col >= (1 << bwl))
210       continue;
211     const int pos = (ref_row << bwl) + ref_col;
212     tran_low_t abs_coeff = abs(tcoeffs[pos]);
213     count += abs_coeff > level;
214     if (br_ref_offset[idx][0] >= 0 && br_ref_offset[idx][1] >= 0) {
215       if (abs_coeff > mag[0]) {
216         mag[0] = abs_coeff;
217         mag[1] = 1;
218       } else if (abs_coeff == mag[0]) {
219         ++mag[1];
220       }
221     }
222   }
223   return count;
224 }
225 
get_br_ctx_from_count_mag(int row,int col,int count,int mag)226 static INLINE int get_br_ctx_from_count_mag(int row, int col, int count,
227                                             int mag) {
228   int offset = 0;
229   if (mag <= BR_MAG_OFFSET)
230     offset = 0;
231   else if (mag <= 3)
232     offset = 1;
233   else if (mag <= 5)
234     offset = 2;
235   else
236     offset = 3;
237 
238   int ctx = br_level_map[count];
239   ctx += offset * BR_TMP_OFFSET;
240 
241   // DC: 0 - 1
242   if (row == 0 && col == 0) return ctx;
243 
244   // Top row: 2 - 4
245   if (row == 0) return 2 + ctx;
246 
247   // Left column: 5 - 7
248   if (col == 0) return 5 + ctx;
249 
250   // others: 8 - 11
251   return 8 + ctx;
252 }
253 
get_br_ctx(const tran_low_t * tcoeffs,const int c,const int bwl,const int height)254 static INLINE int get_br_ctx(const tran_low_t *tcoeffs,
255                              const int c,  // raster order
256                              const int bwl, const int height) {
257   const int row = c >> bwl;
258   const int col = c - (row << bwl);
259   const int level_minus_1 = NUM_BASE_LEVELS;
260   int mag;
261   const int count =
262       get_level_count_mag(&mag, tcoeffs, bwl, height, row, col, level_minus_1,
263                           br_ref_offset, BR_CONTEXT_POSITION_NUM);
264   const int ctx = get_br_ctx_from_count_mag(row, col, count, mag);
265   return ctx;
266 }
267 
268 #define SIG_REF_OFFSET_NUM 7
269 static int sig_ref_offset[SIG_REF_OFFSET_NUM][2] = {
270   { -2, -1 }, { -2, 0 }, { -1, -2 }, { -1, -1 },
271   { -1, 0 },  { 0, -2 }, { 0, -1 },
272 };
273 
274 #if REDUCE_CONTEXT_DEPENDENCY
get_nz_count(const tran_low_t * tcoeffs,int bwl,int height,int row,int col,int prev_row,int prev_col)275 static INLINE int get_nz_count(const tran_low_t *tcoeffs, int bwl, int height,
276                                int row, int col, int prev_row, int prev_col) {
277   int count = 0;
278   for (int idx = 0; idx < SIG_REF_OFFSET_NUM; ++idx) {
279     const int ref_row = row + sig_ref_offset[idx][0];
280     const int ref_col = col + sig_ref_offset[idx][1];
281     if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
282         ref_col >= (1 << bwl) || (prev_row == ref_row && prev_col == ref_col))
283       continue;
284     const int nb_pos = (ref_row << bwl) + ref_col;
285     count += (tcoeffs[nb_pos] != 0);
286   }
287   return count;
288 }
289 #else
get_nz_count(const tran_low_t * tcoeffs,int bwl,int height,int row,int col)290 static INLINE int get_nz_count(const tran_low_t *tcoeffs, int bwl, int height,
291                                int row, int col) {
292   int count = 0;
293   for (int idx = 0; idx < SIG_REF_OFFSET_NUM; ++idx) {
294     const int ref_row = row + sig_ref_offset[idx][0];
295     const int ref_col = col + sig_ref_offset[idx][1];
296     if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
297         ref_col >= (1 << bwl))
298       continue;
299     const int nb_pos = (ref_row << bwl) + ref_col;
300     count += (tcoeffs[nb_pos] != 0);
301   }
302   return count;
303 }
304 #endif
305 
get_tx_class(TX_TYPE tx_type)306 static INLINE TX_CLASS get_tx_class(TX_TYPE tx_type) {
307   switch (tx_type) {
308 #if CONFIG_EXT_TX
309     case V_DCT:
310     case V_ADST:
311     case V_FLIPADST: return TX_CLASS_VERT;
312     case H_DCT:
313     case H_ADST:
314     case H_FLIPADST: return TX_CLASS_HORIZ;
315 #endif
316     default: return TX_CLASS_2D;
317   }
318 }
319 
320 // TODO(angiebird): optimize this function by generate a table that maps from
321 // count to ctx
get_nz_map_ctx_from_count(int count,int coeff_idx,int bwl,TX_TYPE tx_type)322 static INLINE int get_nz_map_ctx_from_count(int count,
323                                             int coeff_idx,  // raster order
324                                             int bwl, TX_TYPE tx_type) {
325   (void)tx_type;
326   const int row = coeff_idx >> bwl;
327   const int col = coeff_idx - (row << bwl);
328   int ctx = 0;
329 #if CONFIG_EXT_TX
330   int tx_class = get_tx_class(tx_type);
331   int offset;
332   if (tx_class == TX_CLASS_2D)
333     offset = 0;
334   else if (tx_class == TX_CLASS_VERT)
335     offset = SIG_COEF_CONTEXTS_2D;
336   else
337     offset = SIG_COEF_CONTEXTS_2D + SIG_COEF_CONTEXTS_1D;
338 #else
339   int offset = 0;
340 #endif
341 
342   if (row == 0 && col == 0) return offset + 0;
343 
344   if (row == 0 && col == 1) return offset + 1 + count;
345 
346   if (row == 1 && col == 0) return offset + 3 + count;
347 
348   if (row == 1 && col == 1) {
349     ctx = (count + 1) >> 1;
350 
351     assert(5 + ctx <= 7);
352 
353     return offset + 5 + ctx;
354   }
355 
356   if (row == 0) {
357     ctx = (count + 1) >> 1;
358 
359     assert(ctx < 2);
360     return offset + 8 + ctx;
361   }
362 
363   if (col == 0) {
364     ctx = (count + 1) >> 1;
365 
366     assert(ctx < 2);
367     return offset + 10 + ctx;
368   }
369 
370   ctx = count >> 1;
371 
372   assert(12 + ctx < 16);
373 
374   return offset + 12 + ctx;
375 }
376 
get_nz_map_ctx(const tran_low_t * tcoeffs,const int scan_idx,const int16_t * scan,const int bwl,const int height,TX_TYPE tx_type)377 static INLINE int get_nz_map_ctx(const tran_low_t *tcoeffs, const int scan_idx,
378                                  const int16_t *scan, const int bwl,
379                                  const int height, TX_TYPE tx_type) {
380   const int coeff_idx = scan[scan_idx];
381   const int row = coeff_idx >> bwl;
382   const int col = coeff_idx - (row << bwl);
383 #if REDUCE_CONTEXT_DEPENDENCY
384   int prev_coeff_idx;
385   int prev_row;
386   int prev_col;
387   if (scan_idx > MIN_SCAN_IDX_REDUCE_CONTEXT_DEPENDENCY) {
388     prev_coeff_idx = scan[scan_idx - 1];  // raster order
389     prev_row = prev_coeff_idx >> bwl;
390     prev_col = prev_coeff_idx - (prev_row << bwl);
391   } else {
392     prev_coeff_idx = -1;
393     prev_row = -1;
394     prev_col = -1;
395   }
396   int count = get_nz_count(tcoeffs, bwl, height, row, col, prev_row, prev_col);
397 #else
398   int count = get_nz_count(tcoeffs, bwl, height, row, col);
399 #endif
400   return get_nz_map_ctx_from_count(count, coeff_idx, bwl, tx_type);
401 }
402 
get_eob_ctx(const tran_low_t * tcoeffs,const int coeff_idx,const TX_SIZE txs_ctx,TX_TYPE tx_type)403 static INLINE int get_eob_ctx(const tran_low_t *tcoeffs,
404                               const int coeff_idx,  // raster order
405                               const TX_SIZE txs_ctx, TX_TYPE tx_type) {
406   (void)tcoeffs;
407   int offset = 0;
408 #if CONFIG_CTX1D
409   TX_CLASS tx_class = get_tx_class(tx_type);
410   if (tx_class == TX_CLASS_VERT)
411     offset = EOB_COEF_CONTEXTS_2D;
412   else if (tx_class == TX_CLASS_HORIZ)
413     offset = EOB_COEF_CONTEXTS_2D + EOB_COEF_CONTEXTS_1D;
414 #else
415   (void)tx_type;
416 #endif
417 
418   if (txs_ctx == TX_4X4) return offset + av1_coeff_band_4x4[coeff_idx];
419   if (txs_ctx == TX_8X8) return offset + av1_coeff_band_8x8[coeff_idx];
420   if (txs_ctx == TX_16X16) return offset + av1_coeff_band_16x16[coeff_idx];
421   if (txs_ctx == TX_32X32) return offset + av1_coeff_band_32x32[coeff_idx];
422 
423   assert(0);
424   return 0;
425 }
426 
set_dc_sign(int * cul_level,tran_low_t v)427 static INLINE void set_dc_sign(int *cul_level, tran_low_t v) {
428   if (v < 0)
429     *cul_level |= 1 << COEFF_CONTEXT_BITS;
430   else if (v > 0)
431     *cul_level += 2 << COEFF_CONTEXT_BITS;
432 }
433 
get_dc_sign_ctx(int dc_sign)434 static INLINE int get_dc_sign_ctx(int dc_sign) {
435   int dc_sign_ctx = 0;
436   if (dc_sign < 0)
437     dc_sign_ctx = 1;
438   else if (dc_sign > 0)
439     dc_sign_ctx = 2;
440 
441   return dc_sign_ctx;
442 }
443 
get_txb_ctx(BLOCK_SIZE plane_bsize,TX_SIZE tx_size,int plane,const ENTROPY_CONTEXT * a,const ENTROPY_CONTEXT * l,TXB_CTX * txb_ctx)444 static INLINE void get_txb_ctx(BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
445                                int plane, const ENTROPY_CONTEXT *a,
446                                const ENTROPY_CONTEXT *l, TXB_CTX *txb_ctx) {
447   const int txb_w_unit = tx_size_wide_unit[tx_size];
448   const int txb_h_unit = tx_size_high_unit[tx_size];
449   int ctx_offset = (plane == 0) ? 0 : 7;
450 
451   if (plane_bsize > txsize_to_bsize[tx_size]) ctx_offset += 3;
452 
453   int dc_sign = 0;
454   for (int k = 0; k < txb_w_unit; ++k) {
455     int sign = ((uint8_t)a[k]) >> COEFF_CONTEXT_BITS;
456     if (sign == 1)
457       --dc_sign;
458     else if (sign == 2)
459       ++dc_sign;
460     else if (sign != 0)
461       assert(0);
462   }
463 
464   for (int k = 0; k < txb_h_unit; ++k) {
465     int sign = ((uint8_t)l[k]) >> COEFF_CONTEXT_BITS;
466     if (sign == 1)
467       --dc_sign;
468     else if (sign == 2)
469       ++dc_sign;
470     else if (sign != 0)
471       assert(0);
472   }
473 
474   txb_ctx->dc_sign_ctx = get_dc_sign_ctx(dc_sign);
475 
476   if (plane == 0) {
477     int top = 0;
478     int left = 0;
479 
480     for (int k = 0; k < txb_w_unit; ++k) {
481       top = AOMMAX(top, ((uint8_t)a[k] & COEFF_CONTEXT_MASK));
482     }
483 
484     for (int k = 0; k < txb_h_unit; ++k) {
485       left = AOMMAX(left, ((uint8_t)l[k] & COEFF_CONTEXT_MASK));
486     }
487 
488     top = AOMMIN(top, 255);
489     left = AOMMIN(left, 255);
490 
491     if (plane_bsize == txsize_to_bsize[tx_size])
492       txb_ctx->txb_skip_ctx = 0;
493     else if (top == 0 && left == 0)
494       txb_ctx->txb_skip_ctx = 1;
495     else if (top == 0 || left == 0)
496       txb_ctx->txb_skip_ctx = 2 + (AOMMAX(top, left) > 3);
497     else if (AOMMAX(top, left) <= 3)
498       txb_ctx->txb_skip_ctx = 4;
499     else if (AOMMIN(top, left) <= 3)
500       txb_ctx->txb_skip_ctx = 5;
501     else
502       txb_ctx->txb_skip_ctx = 6;
503   } else {
504     int ctx_base = get_entropy_context(tx_size, a, l);
505     txb_ctx->txb_skip_ctx = ctx_offset + ctx_base;
506   }
507 }
508 
509 #if LV_MAP_PROB
510 void av1_init_txb_probs(FRAME_CONTEXT *fc);
511 #endif  // LV_MAP_PROB
512 
513 void av1_adapt_txb_probs(AV1_COMMON *cm, unsigned int count_sat,
514                          unsigned int update_factor);
515 
516 void av1_init_lv_map(AV1_COMMON *cm);
517 
518 #if CONFIG_CTX1D
get_eob_vert(int16_t * eob_ls,const tran_low_t * tcoeff,int w,int h)519 static INLINE void get_eob_vert(int16_t *eob_ls, const tran_low_t *tcoeff,
520                                 int w, int h) {
521   for (int c = 0; c < w; ++c) {
522     eob_ls[c] = 0;
523     for (int r = h - 1; r >= 0; --r) {
524       int coeff_idx = r * w + c;
525       if (tcoeff[coeff_idx] != 0) {
526         eob_ls[c] = r + 1;
527         break;
528       }
529     }
530   }
531 }
532 
get_eob_horiz(int16_t * eob_ls,const tran_low_t * tcoeff,int w,int h)533 static INLINE void get_eob_horiz(int16_t *eob_ls, const tran_low_t *tcoeff,
534                                  int w, int h) {
535   for (int r = 0; r < h; ++r) {
536     eob_ls[r] = 0;
537     for (int c = w - 1; c >= 0; --c) {
538       int coeff_idx = r * w + c;
539       if (tcoeff[coeff_idx] != 0) {
540         eob_ls[r] = c + 1;
541         break;
542       }
543     }
544   }
545 }
546 
get_empty_line_ctx(int line_idx,int16_t * eob_ls)547 static INLINE int get_empty_line_ctx(int line_idx, int16_t *eob_ls) {
548   if (line_idx > 0) {
549     int prev_eob = eob_ls[line_idx - 1];
550     if (prev_eob == 0) {
551       return 1;
552     } else if (prev_eob < 3) {
553       return 2;
554     } else if (prev_eob < 6) {
555       return 3;
556     } else {
557       return 4;
558     }
559   } else {
560     return 0;
561   }
562 }
563 
564 #define MAX_POS_CTX 8
565 static int pos_ctx[MAX_HVTX_SIZE] = {
566   0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
567   6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
568 };
get_hv_eob_ctx(int line_idx,int pos,int16_t * eob_ls)569 static INLINE int get_hv_eob_ctx(int line_idx, int pos, int16_t *eob_ls) {
570   if (line_idx > 0) {
571     int prev_eob = eob_ls[line_idx - 1];
572     int diff = pos + 1 - prev_eob;
573     int abs_diff = abs(diff);
574     int ctx_idx = pos_ctx[abs_diff];
575     assert(ctx_idx < MAX_POS_CTX);
576     if (diff < 0) {
577       ctx_idx += MAX_POS_CTX;
578       assert(ctx_idx >= MAX_POS_CTX);
579       assert(ctx_idx < 2 * MAX_POS_CTX);
580     }
581     return ctx_idx;
582   } else {
583     int ctx_idx = MAX_POS_CTX + MAX_POS_CTX + pos_ctx[pos];
584     assert(ctx_idx < HV_EOB_CONTEXTS);
585     assert(HV_EOB_CONTEXTS == MAX_POS_CTX * 3);
586     return ctx_idx;
587   }
588 }
589 #endif  // CONFIG_CTX1D
590 
591 #endif  // AV1_COMMON_TXB_COMMON_H_
592