LCOV - code coverage report
Current view: top level - third_party/aom/av1/common - av1_loopfilter.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 939 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 25 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016, 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             : #include <math.h>
      13             : 
      14             : #include "./aom_config.h"
      15             : #include "./aom_dsp_rtcd.h"
      16             : #include "av1/common/av1_loopfilter.h"
      17             : #include "av1/common/onyxc_int.h"
      18             : #include "av1/common/reconinter.h"
      19             : #include "aom_dsp/aom_dsp_common.h"
      20             : #include "aom_mem/aom_mem.h"
      21             : #include "aom_ports/mem.h"
      22             : 
      23             : #include "av1/common/seg_common.h"
      24             : 
      25             : #define PARALLEL_DEBLOCKING_15TAPLUMAONLY 1
      26             : 
      27             : // 64 bit masks for left transform size. Each 1 represents a position where
      28             : // we should apply a loop filter across the left border of an 8x8 block
      29             : // boundary.
      30             : //
      31             : // In the case of TX_16X16->  ( in low order byte first we end up with
      32             : // a mask that looks like this
      33             : //
      34             : //    10101010
      35             : //    10101010
      36             : //    10101010
      37             : //    10101010
      38             : //    10101010
      39             : //    10101010
      40             : //    10101010
      41             : //    10101010
      42             : //
      43             : // A loopfilter should be applied to every other 8x8 horizontally.
      44             : static const uint64_t left_64x64_txform_mask[TX_SIZES] = {
      45             : #if CONFIG_CHROMA_2X2
      46             :   0xffffffffffffffffULL,  // TX_2X2
      47             : #endif
      48             :   0xffffffffffffffffULL,  // TX_4X4
      49             :   0xffffffffffffffffULL,  // TX_8x8
      50             :   0x5555555555555555ULL,  // TX_16x16
      51             :   0x1111111111111111ULL,  // TX_32x32
      52             : #if CONFIG_TX64X64
      53             :   0x0101010101010101ULL,  // TX_64x64
      54             : #endif                    // CONFIG_TX64X64
      55             : };
      56             : 
      57             : // 64 bit masks for above transform size. Each 1 represents a position where
      58             : // we should apply a loop filter across the top border of an 8x8 block
      59             : // boundary.
      60             : //
      61             : // In the case of TX_32x32 ->  ( in low order byte first we end up with
      62             : // a mask that looks like this
      63             : //
      64             : //    11111111
      65             : //    00000000
      66             : //    00000000
      67             : //    00000000
      68             : //    11111111
      69             : //    00000000
      70             : //    00000000
      71             : //    00000000
      72             : //
      73             : // A loopfilter should be applied to every other 4 the row vertically.
      74             : static const uint64_t above_64x64_txform_mask[TX_SIZES] = {
      75             : #if CONFIG_CHROMA_2X2
      76             :   0xffffffffffffffffULL,  // TX_4X4
      77             : #endif
      78             :   0xffffffffffffffffULL,  // TX_4X4
      79             :   0xffffffffffffffffULL,  // TX_8x8
      80             :   0x00ff00ff00ff00ffULL,  // TX_16x16
      81             :   0x000000ff000000ffULL,  // TX_32x32
      82             : #if CONFIG_TX64X64
      83             :   0x00000000000000ffULL,  // TX_64x64
      84             : #endif                    // CONFIG_TX64X64
      85             : };
      86             : 
      87             : // 64 bit masks for prediction sizes (left). Each 1 represents a position
      88             : // where left border of an 8x8 block. These are aligned to the right most
      89             : // appropriate bit, and then shifted into place.
      90             : //
      91             : // In the case of TX_16x32 ->  ( low order byte first ) we end up with
      92             : // a mask that looks like this :
      93             : //
      94             : //  10000000
      95             : //  10000000
      96             : //  10000000
      97             : //  10000000
      98             : //  00000000
      99             : //  00000000
     100             : //  00000000
     101             : //  00000000
     102             : static const uint64_t left_prediction_mask[BLOCK_SIZES] = {
     103             : #if CONFIG_CB4X4
     104             :   0x0000000000000001ULL,  // BLOCK_2X2,
     105             :   0x0000000000000001ULL,  // BLOCK_2X4,
     106             :   0x0000000000000001ULL,  // BLOCK_4X2,
     107             : #endif
     108             :   0x0000000000000001ULL,  // BLOCK_4X4,
     109             :   0x0000000000000001ULL,  // BLOCK_4X8,
     110             :   0x0000000000000001ULL,  // BLOCK_8X4,
     111             :   0x0000000000000001ULL,  // BLOCK_8X8,
     112             :   0x0000000000000101ULL,  // BLOCK_8X16,
     113             :   0x0000000000000001ULL,  // BLOCK_16X8,
     114             :   0x0000000000000101ULL,  // BLOCK_16X16,
     115             :   0x0000000001010101ULL,  // BLOCK_16X32,
     116             :   0x0000000000000101ULL,  // BLOCK_32X16,
     117             :   0x0000000001010101ULL,  // BLOCK_32X32,
     118             :   0x0101010101010101ULL,  // BLOCK_32X64,
     119             :   0x0000000001010101ULL,  // BLOCK_64X32,
     120             :   0x0101010101010101ULL,  // BLOCK_64X64
     121             : };
     122             : 
     123             : // 64 bit mask to shift and set for each prediction size.
     124             : static const uint64_t above_prediction_mask[BLOCK_SIZES] = {
     125             : #if CONFIG_CB4X4
     126             :   0x0000000000000001ULL,  // BLOCK_2X2
     127             :   0x0000000000000001ULL,  // BLOCK_2X4
     128             :   0x0000000000000001ULL,  // BLOCK_4X2
     129             : #endif
     130             :   0x0000000000000001ULL,  // BLOCK_4X4
     131             :   0x0000000000000001ULL,  // BLOCK_4X8
     132             :   0x0000000000000001ULL,  // BLOCK_8X4
     133             :   0x0000000000000001ULL,  // BLOCK_8X8
     134             :   0x0000000000000001ULL,  // BLOCK_8X16,
     135             :   0x0000000000000003ULL,  // BLOCK_16X8
     136             :   0x0000000000000003ULL,  // BLOCK_16X16
     137             :   0x0000000000000003ULL,  // BLOCK_16X32,
     138             :   0x000000000000000fULL,  // BLOCK_32X16,
     139             :   0x000000000000000fULL,  // BLOCK_32X32,
     140             :   0x000000000000000fULL,  // BLOCK_32X64,
     141             :   0x00000000000000ffULL,  // BLOCK_64X32,
     142             :   0x00000000000000ffULL,  // BLOCK_64X64
     143             : };
     144             : // 64 bit mask to shift and set for each prediction size. A bit is set for
     145             : // each 8x8 block that would be in the left most block of the given block
     146             : // size in the 64x64 block.
     147             : static const uint64_t size_mask[BLOCK_SIZES] = {
     148             : #if CONFIG_CB4X4
     149             :   0x0000000000000001ULL,  // BLOCK_2X2
     150             :   0x0000000000000001ULL,  // BLOCK_2X4
     151             :   0x0000000000000001ULL,  // BLOCK_4X2
     152             : #endif
     153             :   0x0000000000000001ULL,  // BLOCK_4X4
     154             :   0x0000000000000001ULL,  // BLOCK_4X8
     155             :   0x0000000000000001ULL,  // BLOCK_8X4
     156             :   0x0000000000000001ULL,  // BLOCK_8X8
     157             :   0x0000000000000101ULL,  // BLOCK_8X16,
     158             :   0x0000000000000003ULL,  // BLOCK_16X8
     159             :   0x0000000000000303ULL,  // BLOCK_16X16
     160             :   0x0000000003030303ULL,  // BLOCK_16X32,
     161             :   0x0000000000000f0fULL,  // BLOCK_32X16,
     162             :   0x000000000f0f0f0fULL,  // BLOCK_32X32,
     163             :   0x0f0f0f0f0f0f0f0fULL,  // BLOCK_32X64,
     164             :   0x00000000ffffffffULL,  // BLOCK_64X32,
     165             :   0xffffffffffffffffULL,  // BLOCK_64X64
     166             : };
     167             : 
     168             : // These are used for masking the left and above 32x32 borders.
     169             : static const uint64_t left_border = 0x1111111111111111ULL;
     170             : static const uint64_t above_border = 0x000000ff000000ffULL;
     171             : 
     172             : // 16 bit masks for uv transform sizes.
     173             : static const uint16_t left_64x64_txform_mask_uv[TX_SIZES] = {
     174             : #if CONFIG_CHROMA_2X2
     175             :   0xffff,  // TX_2X2
     176             : #endif
     177             :   0xffff,  // TX_4X4
     178             :   0xffff,  // TX_8x8
     179             :   0x5555,  // TX_16x16
     180             :   0x1111,  // TX_32x32
     181             : #if CONFIG_TX64X64
     182             :   0x0101,  // TX_64x64, never used
     183             : #endif     // CONFIG_TX64X64
     184             : };
     185             : 
     186             : static const uint16_t above_64x64_txform_mask_uv[TX_SIZES] = {
     187             : #if CONFIG_CHROMA_2X2
     188             :   0xffff,  // TX_2X2
     189             : #endif
     190             :   0xffff,  // TX_4X4
     191             :   0xffff,  // TX_8x8
     192             :   0x0f0f,  // TX_16x16
     193             :   0x000f,  // TX_32x32
     194             : #if CONFIG_TX64X64
     195             :   0x0003,  // TX_64x64, never used
     196             : #endif     // CONFIG_TX64X64
     197             : };
     198             : 
     199             : // 16 bit left mask to shift and set for each uv prediction size.
     200             : static const uint16_t left_prediction_mask_uv[BLOCK_SIZES] = {
     201             : #if CONFIG_CB4X4
     202             :   0x0001,  // BLOCK_2X2,
     203             :   0x0001,  // BLOCK_2X4,
     204             :   0x0001,  // BLOCK_4X2,
     205             : #endif
     206             :   0x0001,  // BLOCK_4X4,
     207             :   0x0001,  // BLOCK_4X8,
     208             :   0x0001,  // BLOCK_8X4,
     209             :   0x0001,  // BLOCK_8X8,
     210             :   0x0001,  // BLOCK_8X16,
     211             :   0x0001,  // BLOCK_16X8,
     212             :   0x0001,  // BLOCK_16X16,
     213             :   0x0011,  // BLOCK_16X32,
     214             :   0x0001,  // BLOCK_32X16,
     215             :   0x0011,  // BLOCK_32X32,
     216             :   0x1111,  // BLOCK_32X64
     217             :   0x0011,  // BLOCK_64X32,
     218             :   0x1111,  // BLOCK_64X64
     219             : };
     220             : // 16 bit above mask to shift and set for uv each prediction size.
     221             : static const uint16_t above_prediction_mask_uv[BLOCK_SIZES] = {
     222             : #if CONFIG_CB4X4
     223             :   0x0001,  // BLOCK_2X2
     224             :   0x0001,  // BLOCK_2X4
     225             :   0x0001,  // BLOCK_4X2
     226             : #endif
     227             :   0x0001,  // BLOCK_4X4
     228             :   0x0001,  // BLOCK_4X8
     229             :   0x0001,  // BLOCK_8X4
     230             :   0x0001,  // BLOCK_8X8
     231             :   0x0001,  // BLOCK_8X16,
     232             :   0x0001,  // BLOCK_16X8
     233             :   0x0001,  // BLOCK_16X16
     234             :   0x0001,  // BLOCK_16X32,
     235             :   0x0003,  // BLOCK_32X16,
     236             :   0x0003,  // BLOCK_32X32,
     237             :   0x0003,  // BLOCK_32X64,
     238             :   0x000f,  // BLOCK_64X32,
     239             :   0x000f,  // BLOCK_64X64
     240             : };
     241             : 
     242             : // 64 bit mask to shift and set for each uv prediction size
     243             : static const uint16_t size_mask_uv[BLOCK_SIZES] = {
     244             : #if CONFIG_CB4X4
     245             :   0x0001,  // BLOCK_2X2
     246             :   0x0001,  // BLOCK_2X4
     247             :   0x0001,  // BLOCK_4X2
     248             : #endif
     249             :   0x0001,  // BLOCK_4X4
     250             :   0x0001,  // BLOCK_4X8
     251             :   0x0001,  // BLOCK_8X4
     252             :   0x0001,  // BLOCK_8X8
     253             :   0x0001,  // BLOCK_8X16,
     254             :   0x0001,  // BLOCK_16X8
     255             :   0x0001,  // BLOCK_16X16
     256             :   0x0011,  // BLOCK_16X32,
     257             :   0x0003,  // BLOCK_32X16,
     258             :   0x0033,  // BLOCK_32X32,
     259             :   0x3333,  // BLOCK_32X64,
     260             :   0x00ff,  // BLOCK_64X32,
     261             :   0xffff,  // BLOCK_64X64
     262             : };
     263             : static const uint16_t left_border_uv = 0x1111;
     264             : static const uint16_t above_border_uv = 0x000f;
     265             : 
     266             : static const int mode_lf_lut[] = {
     267             :   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // INTRA_MODES
     268             : #if CONFIG_ALT_INTRA
     269             :   0,
     270             : #if CONFIG_SMOOTH_HV
     271             :   0, 0,
     272             : #endif         // CONFIG_SMOOTH_HV
     273             : #endif         // CONFIG_ALT_INTRA
     274             :   1, 1, 0, 1,  // INTER_MODES (ZEROMV == 0)
     275             : #if CONFIG_EXT_INTER
     276             :   1, 1, 1, 1, 1, 1, 0, 1  // INTER_COMPOUND_MODES (ZERO_ZEROMV == 0)
     277             : #endif                    // CONFIG_EXT_INTER
     278             : };
     279             : 
     280           0 : static void update_sharpness(loop_filter_info_n *lfi, int sharpness_lvl) {
     281             :   int lvl;
     282             : 
     283             :   // For each possible value for the loop filter fill out limits
     284           0 :   for (lvl = 0; lvl <= MAX_LOOP_FILTER; lvl++) {
     285             :     // Set loop filter parameters that control sharpness.
     286           0 :     int block_inside_limit = lvl >> ((sharpness_lvl > 0) + (sharpness_lvl > 4));
     287             : 
     288           0 :     if (sharpness_lvl > 0) {
     289           0 :       if (block_inside_limit > (9 - sharpness_lvl))
     290           0 :         block_inside_limit = (9 - sharpness_lvl);
     291             :     }
     292             : 
     293           0 :     if (block_inside_limit < 1) block_inside_limit = 1;
     294             : 
     295           0 :     memset(lfi->lfthr[lvl].lim, block_inside_limit, SIMD_WIDTH);
     296           0 :     memset(lfi->lfthr[lvl].mblim, (2 * (lvl + 2) + block_inside_limit),
     297             :            SIMD_WIDTH);
     298             :   }
     299           0 : }
     300             : #if CONFIG_EXT_DELTA_Q
     301           0 : static uint8_t get_filter_level(const AV1_COMMON *cm,
     302             :                                 const loop_filter_info_n *lfi_n,
     303             :                                 const MB_MODE_INFO *mbmi) {
     304             : #if CONFIG_SUPERTX
     305             :   const int segment_id = AOMMIN(mbmi->segment_id, mbmi->segment_id_supertx);
     306             :   assert(
     307             :       IMPLIES(supertx_enabled(mbmi), mbmi->segment_id_supertx != MAX_SEGMENTS));
     308             :   assert(IMPLIES(supertx_enabled(mbmi),
     309             :                  mbmi->segment_id_supertx <= mbmi->segment_id));
     310             : #else
     311           0 :   const int segment_id = mbmi->segment_id;
     312             : #endif  // CONFIG_SUPERTX
     313           0 :   if (cm->delta_lf_present_flag) {
     314           0 :     int lvl_seg = clamp(mbmi->current_delta_lf_from_base + cm->lf.filter_level,
     315             :                         0, MAX_LOOP_FILTER);
     316           0 :     const int scale = 1 << (lvl_seg >> 5);
     317           0 :     if (segfeature_active(&cm->seg, segment_id, SEG_LVL_ALT_LF)) {
     318           0 :       const int data = get_segdata(&cm->seg, segment_id, SEG_LVL_ALT_LF);
     319           0 :       lvl_seg =
     320           0 :           clamp(cm->seg.abs_delta == SEGMENT_ABSDATA ? data : lvl_seg + data, 0,
     321             :                 MAX_LOOP_FILTER);
     322             :     }
     323             : 
     324           0 :     if (cm->lf.mode_ref_delta_enabled) {
     325           0 :       lvl_seg += cm->lf.ref_deltas[mbmi->ref_frame[0]] * scale;
     326           0 :       if (mbmi->ref_frame[0] > INTRA_FRAME)
     327           0 :         lvl_seg += cm->lf.mode_deltas[mode_lf_lut[mbmi->mode]] * scale;
     328           0 :       lvl_seg = clamp(lvl_seg, 0, MAX_LOOP_FILTER);
     329             :     }
     330           0 :     return lvl_seg;
     331             :   } else {
     332           0 :     return lfi_n->lvl[segment_id][mbmi->ref_frame[0]][mode_lf_lut[mbmi->mode]];
     333             :   }
     334             : }
     335             : #else
     336             : static uint8_t get_filter_level(const loop_filter_info_n *lfi_n,
     337             :                                 const MB_MODE_INFO *mbmi) {
     338             : #if CONFIG_SUPERTX
     339             :   const int segment_id = AOMMIN(mbmi->segment_id, mbmi->segment_id_supertx);
     340             :   assert(
     341             :       IMPLIES(supertx_enabled(mbmi), mbmi->segment_id_supertx != MAX_SEGMENTS));
     342             :   assert(IMPLIES(supertx_enabled(mbmi),
     343             :                  mbmi->segment_id_supertx <= mbmi->segment_id));
     344             : #else
     345             :   const int segment_id = mbmi->segment_id;
     346             : #endif  // CONFIG_SUPERTX
     347             :   return lfi_n->lvl[segment_id][mbmi->ref_frame[0]][mode_lf_lut[mbmi->mode]];
     348             : }
     349             : #endif
     350             : 
     351           0 : void av1_loop_filter_init(AV1_COMMON *cm) {
     352             :   assert(MB_MODE_COUNT == NELEMENTS(mode_lf_lut));
     353           0 :   loop_filter_info_n *lfi = &cm->lf_info;
     354           0 :   struct loopfilter *lf = &cm->lf;
     355             :   int lvl;
     356             : 
     357             :   // init limits for given sharpness
     358           0 :   update_sharpness(lfi, lf->sharpness_level);
     359           0 :   lf->last_sharpness_level = lf->sharpness_level;
     360             : 
     361             :   // init hev threshold const vectors
     362           0 :   for (lvl = 0; lvl <= MAX_LOOP_FILTER; lvl++)
     363           0 :     memset(lfi->lfthr[lvl].hev_thr, (lvl >> 4), SIMD_WIDTH);
     364           0 : }
     365             : 
     366           0 : void av1_loop_filter_frame_init(AV1_COMMON *cm, int default_filt_lvl) {
     367             :   int seg_id;
     368             :   // n_shift is the multiplier for lf_deltas
     369             :   // the multiplier is 1 for when filter_lvl is between 0 and 31;
     370             :   // 2 when filter_lvl is between 32 and 63
     371           0 :   const int scale = 1 << (default_filt_lvl >> 5);
     372           0 :   loop_filter_info_n *const lfi = &cm->lf_info;
     373           0 :   struct loopfilter *const lf = &cm->lf;
     374           0 :   const struct segmentation *const seg = &cm->seg;
     375             : 
     376             :   // update limits if sharpness has changed
     377           0 :   if (lf->last_sharpness_level != lf->sharpness_level) {
     378           0 :     update_sharpness(lfi, lf->sharpness_level);
     379           0 :     lf->last_sharpness_level = lf->sharpness_level;
     380             :   }
     381             : 
     382           0 :   for (seg_id = 0; seg_id < MAX_SEGMENTS; seg_id++) {
     383           0 :     int lvl_seg = default_filt_lvl;
     384           0 :     if (segfeature_active(seg, seg_id, SEG_LVL_ALT_LF)) {
     385           0 :       const int data = get_segdata(seg, seg_id, SEG_LVL_ALT_LF);
     386           0 :       lvl_seg = clamp(
     387           0 :           seg->abs_delta == SEGMENT_ABSDATA ? data : default_filt_lvl + data, 0,
     388             :           MAX_LOOP_FILTER);
     389             :     }
     390             : 
     391           0 :     if (!lf->mode_ref_delta_enabled) {
     392             :       // we could get rid of this if we assume that deltas are set to
     393             :       // zero when not in use; encoder always uses deltas
     394           0 :       memset(lfi->lvl[seg_id], lvl_seg, sizeof(lfi->lvl[seg_id]));
     395             :     } else {
     396             :       int ref, mode;
     397           0 :       const int intra_lvl = lvl_seg + lf->ref_deltas[INTRA_FRAME] * scale;
     398           0 :       lfi->lvl[seg_id][INTRA_FRAME][0] = clamp(intra_lvl, 0, MAX_LOOP_FILTER);
     399             : 
     400           0 :       for (ref = LAST_FRAME; ref < TOTAL_REFS_PER_FRAME; ++ref) {
     401           0 :         for (mode = 0; mode < MAX_MODE_LF_DELTAS; ++mode) {
     402           0 :           const int inter_lvl = lvl_seg + lf->ref_deltas[ref] * scale +
     403           0 :                                 lf->mode_deltas[mode] * scale;
     404           0 :           lfi->lvl[seg_id][ref][mode] = clamp(inter_lvl, 0, MAX_LOOP_FILTER);
     405             :         }
     406             :       }
     407             :     }
     408             :   }
     409           0 : }
     410             : 
     411           0 : static void filter_selectively_vert_row2(int subsampling_factor, uint8_t *s,
     412             :                                          int pitch, unsigned int mask_16x16_l,
     413             :                                          unsigned int mask_8x8_l,
     414             :                                          unsigned int mask_4x4_l,
     415             :                                          unsigned int mask_4x4_int_l,
     416             :                                          const loop_filter_info_n *lfi_n,
     417             :                                          const uint8_t *lfl) {
     418           0 :   const int mask_shift = subsampling_factor ? 4 : 8;
     419           0 :   const int mask_cutoff = subsampling_factor ? 0xf : 0xff;
     420           0 :   const int lfl_forward = subsampling_factor ? 4 : 8;
     421             : 
     422           0 :   unsigned int mask_16x16_0 = mask_16x16_l & mask_cutoff;
     423           0 :   unsigned int mask_8x8_0 = mask_8x8_l & mask_cutoff;
     424           0 :   unsigned int mask_4x4_0 = mask_4x4_l & mask_cutoff;
     425           0 :   unsigned int mask_4x4_int_0 = mask_4x4_int_l & mask_cutoff;
     426           0 :   unsigned int mask_16x16_1 = (mask_16x16_l >> mask_shift) & mask_cutoff;
     427           0 :   unsigned int mask_8x8_1 = (mask_8x8_l >> mask_shift) & mask_cutoff;
     428           0 :   unsigned int mask_4x4_1 = (mask_4x4_l >> mask_shift) & mask_cutoff;
     429           0 :   unsigned int mask_4x4_int_1 = (mask_4x4_int_l >> mask_shift) & mask_cutoff;
     430             :   unsigned int mask;
     431             : 
     432           0 :   for (mask = mask_16x16_0 | mask_8x8_0 | mask_4x4_0 | mask_4x4_int_0 |
     433           0 :               mask_16x16_1 | mask_8x8_1 | mask_4x4_1 | mask_4x4_int_1;
     434           0 :        mask; mask >>= 1) {
     435           0 :     const loop_filter_thresh *lfi0 = lfi_n->lfthr + *lfl;
     436           0 :     const loop_filter_thresh *lfi1 = lfi_n->lfthr + *(lfl + lfl_forward);
     437             : 
     438           0 :     if (mask & 1) {
     439           0 :       if ((mask_16x16_0 | mask_16x16_1) & 1) {
     440           0 :         if ((mask_16x16_0 & mask_16x16_1) & 1) {
     441           0 :           aom_lpf_vertical_16_dual(s, pitch, lfi0->mblim, lfi0->lim,
     442           0 :                                    lfi0->hev_thr);
     443           0 :         } else if (mask_16x16_0 & 1) {
     444           0 :           aom_lpf_vertical_16(s, pitch, lfi0->mblim, lfi0->lim, lfi0->hev_thr);
     445             :         } else {
     446           0 :           aom_lpf_vertical_16(s + 8 * pitch, pitch, lfi1->mblim, lfi1->lim,
     447           0 :                               lfi1->hev_thr);
     448             :         }
     449             :       }
     450             : 
     451           0 :       if ((mask_8x8_0 | mask_8x8_1) & 1) {
     452           0 :         if ((mask_8x8_0 & mask_8x8_1) & 1) {
     453           0 :           aom_lpf_vertical_8_dual(s, pitch, lfi0->mblim, lfi0->lim,
     454           0 :                                   lfi0->hev_thr, lfi1->mblim, lfi1->lim,
     455           0 :                                   lfi1->hev_thr);
     456           0 :         } else if (mask_8x8_0 & 1) {
     457           0 :           aom_lpf_vertical_8(s, pitch, lfi0->mblim, lfi0->lim, lfi0->hev_thr);
     458             :         } else {
     459           0 :           aom_lpf_vertical_8(s + 8 * pitch, pitch, lfi1->mblim, lfi1->lim,
     460           0 :                              lfi1->hev_thr);
     461             :         }
     462             :       }
     463             : 
     464           0 :       if ((mask_4x4_0 | mask_4x4_1) & 1) {
     465           0 :         if ((mask_4x4_0 & mask_4x4_1) & 1) {
     466           0 :           aom_lpf_vertical_4_dual(s, pitch, lfi0->mblim, lfi0->lim,
     467           0 :                                   lfi0->hev_thr, lfi1->mblim, lfi1->lim,
     468           0 :                                   lfi1->hev_thr);
     469           0 :         } else if (mask_4x4_0 & 1) {
     470           0 :           aom_lpf_vertical_4(s, pitch, lfi0->mblim, lfi0->lim, lfi0->hev_thr);
     471             :         } else {
     472           0 :           aom_lpf_vertical_4(s + 8 * pitch, pitch, lfi1->mblim, lfi1->lim,
     473           0 :                              lfi1->hev_thr);
     474             :         }
     475             :       }
     476             : 
     477           0 :       if ((mask_4x4_int_0 | mask_4x4_int_1) & 1) {
     478           0 :         if ((mask_4x4_int_0 & mask_4x4_int_1) & 1) {
     479           0 :           aom_lpf_vertical_4_dual(s + 4, pitch, lfi0->mblim, lfi0->lim,
     480           0 :                                   lfi0->hev_thr, lfi1->mblim, lfi1->lim,
     481           0 :                                   lfi1->hev_thr);
     482           0 :         } else if (mask_4x4_int_0 & 1) {
     483           0 :           aom_lpf_vertical_4(s + 4, pitch, lfi0->mblim, lfi0->lim,
     484           0 :                              lfi0->hev_thr);
     485             :         } else {
     486           0 :           aom_lpf_vertical_4(s + 8 * pitch + 4, pitch, lfi1->mblim, lfi1->lim,
     487           0 :                              lfi1->hev_thr);
     488             :         }
     489             :       }
     490             :     }
     491             : 
     492           0 :     s += 8;
     493           0 :     lfl += 1;
     494           0 :     mask_16x16_0 >>= 1;
     495           0 :     mask_8x8_0 >>= 1;
     496           0 :     mask_4x4_0 >>= 1;
     497           0 :     mask_4x4_int_0 >>= 1;
     498           0 :     mask_16x16_1 >>= 1;
     499           0 :     mask_8x8_1 >>= 1;
     500           0 :     mask_4x4_1 >>= 1;
     501           0 :     mask_4x4_int_1 >>= 1;
     502             :   }
     503           0 : }
     504             : 
     505             : #if CONFIG_HIGHBITDEPTH
     506           0 : static void highbd_filter_selectively_vert_row2(
     507             :     int subsampling_factor, uint16_t *s, int pitch, unsigned int mask_16x16_l,
     508             :     unsigned int mask_8x8_l, unsigned int mask_4x4_l,
     509             :     unsigned int mask_4x4_int_l, const loop_filter_info_n *lfi_n,
     510             :     const uint8_t *lfl, int bd) {
     511           0 :   const int mask_shift = subsampling_factor ? 4 : 8;
     512           0 :   const int mask_cutoff = subsampling_factor ? 0xf : 0xff;
     513           0 :   const int lfl_forward = subsampling_factor ? 4 : 8;
     514             : 
     515           0 :   unsigned int mask_16x16_0 = mask_16x16_l & mask_cutoff;
     516           0 :   unsigned int mask_8x8_0 = mask_8x8_l & mask_cutoff;
     517           0 :   unsigned int mask_4x4_0 = mask_4x4_l & mask_cutoff;
     518           0 :   unsigned int mask_4x4_int_0 = mask_4x4_int_l & mask_cutoff;
     519           0 :   unsigned int mask_16x16_1 = (mask_16x16_l >> mask_shift) & mask_cutoff;
     520           0 :   unsigned int mask_8x8_1 = (mask_8x8_l >> mask_shift) & mask_cutoff;
     521           0 :   unsigned int mask_4x4_1 = (mask_4x4_l >> mask_shift) & mask_cutoff;
     522           0 :   unsigned int mask_4x4_int_1 = (mask_4x4_int_l >> mask_shift) & mask_cutoff;
     523             :   unsigned int mask;
     524             : 
     525           0 :   for (mask = mask_16x16_0 | mask_8x8_0 | mask_4x4_0 | mask_4x4_int_0 |
     526           0 :               mask_16x16_1 | mask_8x8_1 | mask_4x4_1 | mask_4x4_int_1;
     527           0 :        mask; mask >>= 1) {
     528           0 :     const loop_filter_thresh *lfi0 = lfi_n->lfthr + *lfl;
     529           0 :     const loop_filter_thresh *lfi1 = lfi_n->lfthr + *(lfl + lfl_forward);
     530             : 
     531           0 :     if (mask & 1) {
     532           0 :       if ((mask_16x16_0 | mask_16x16_1) & 1) {
     533           0 :         if ((mask_16x16_0 & mask_16x16_1) & 1) {
     534           0 :           aom_highbd_lpf_vertical_16_dual(s, pitch, lfi0->mblim, lfi0->lim,
     535           0 :                                           lfi0->hev_thr, bd);
     536           0 :         } else if (mask_16x16_0 & 1) {
     537           0 :           aom_highbd_lpf_vertical_16(s, pitch, lfi0->mblim, lfi0->lim,
     538           0 :                                      lfi0->hev_thr, bd);
     539             :         } else {
     540           0 :           aom_highbd_lpf_vertical_16(s + 8 * pitch, pitch, lfi1->mblim,
     541           0 :                                      lfi1->lim, lfi1->hev_thr, bd);
     542             :         }
     543             :       }
     544             : 
     545           0 :       if ((mask_8x8_0 | mask_8x8_1) & 1) {
     546           0 :         if ((mask_8x8_0 & mask_8x8_1) & 1) {
     547           0 :           aom_highbd_lpf_vertical_8_dual(s, pitch, lfi0->mblim, lfi0->lim,
     548           0 :                                          lfi0->hev_thr, lfi1->mblim, lfi1->lim,
     549           0 :                                          lfi1->hev_thr, bd);
     550           0 :         } else if (mask_8x8_0 & 1) {
     551           0 :           aom_highbd_lpf_vertical_8(s, pitch, lfi0->mblim, lfi0->lim,
     552           0 :                                     lfi0->hev_thr, bd);
     553             :         } else {
     554           0 :           aom_highbd_lpf_vertical_8(s + 8 * pitch, pitch, lfi1->mblim,
     555           0 :                                     lfi1->lim, lfi1->hev_thr, bd);
     556             :         }
     557             :       }
     558             : 
     559           0 :       if ((mask_4x4_0 | mask_4x4_1) & 1) {
     560           0 :         if ((mask_4x4_0 & mask_4x4_1) & 1) {
     561           0 :           aom_highbd_lpf_vertical_4_dual(s, pitch, lfi0->mblim, lfi0->lim,
     562           0 :                                          lfi0->hev_thr, lfi1->mblim, lfi1->lim,
     563           0 :                                          lfi1->hev_thr, bd);
     564           0 :         } else if (mask_4x4_0 & 1) {
     565           0 :           aom_highbd_lpf_vertical_4(s, pitch, lfi0->mblim, lfi0->lim,
     566           0 :                                     lfi0->hev_thr, bd);
     567             :         } else {
     568           0 :           aom_highbd_lpf_vertical_4(s + 8 * pitch, pitch, lfi1->mblim,
     569           0 :                                     lfi1->lim, lfi1->hev_thr, bd);
     570             :         }
     571             :       }
     572             : 
     573           0 :       if ((mask_4x4_int_0 | mask_4x4_int_1) & 1) {
     574           0 :         if ((mask_4x4_int_0 & mask_4x4_int_1) & 1) {
     575           0 :           aom_highbd_lpf_vertical_4_dual(s + 4, pitch, lfi0->mblim, lfi0->lim,
     576           0 :                                          lfi0->hev_thr, lfi1->mblim, lfi1->lim,
     577           0 :                                          lfi1->hev_thr, bd);
     578           0 :         } else if (mask_4x4_int_0 & 1) {
     579           0 :           aom_highbd_lpf_vertical_4(s + 4, pitch, lfi0->mblim, lfi0->lim,
     580           0 :                                     lfi0->hev_thr, bd);
     581             :         } else {
     582           0 :           aom_highbd_lpf_vertical_4(s + 8 * pitch + 4, pitch, lfi1->mblim,
     583           0 :                                     lfi1->lim, lfi1->hev_thr, bd);
     584             :         }
     585             :       }
     586             :     }
     587             : 
     588           0 :     s += 8;
     589           0 :     lfl += 1;
     590           0 :     mask_16x16_0 >>= 1;
     591           0 :     mask_8x8_0 >>= 1;
     592           0 :     mask_4x4_0 >>= 1;
     593           0 :     mask_4x4_int_0 >>= 1;
     594           0 :     mask_16x16_1 >>= 1;
     595           0 :     mask_8x8_1 >>= 1;
     596           0 :     mask_4x4_1 >>= 1;
     597           0 :     mask_4x4_int_1 >>= 1;
     598             :   }
     599           0 : }
     600             : #endif  // CONFIG_HIGHBITDEPTH
     601             : 
     602           0 : static void filter_selectively_horiz(
     603             :     uint8_t *s, int pitch, unsigned int mask_16x16, unsigned int mask_8x8,
     604             :     unsigned int mask_4x4, unsigned int mask_4x4_int,
     605             :     const loop_filter_info_n *lfi_n, const uint8_t *lfl) {
     606             :   unsigned int mask;
     607             :   int count;
     608             : 
     609           0 :   for (mask = mask_16x16 | mask_8x8 | mask_4x4 | mask_4x4_int; mask;
     610           0 :        mask >>= count) {
     611           0 :     const loop_filter_thresh *lfi = lfi_n->lfthr + *lfl;
     612             : 
     613           0 :     count = 1;
     614           0 :     if (mask & 1) {
     615           0 :       if (mask_16x16 & 1) {
     616           0 :         if ((mask_16x16 & 3) == 3) {
     617           0 :           aom_lpf_horizontal_edge_16(s, pitch, lfi->mblim, lfi->lim,
     618           0 :                                      lfi->hev_thr);
     619           0 :           count = 2;
     620             :         } else {
     621           0 :           aom_lpf_horizontal_edge_8(s, pitch, lfi->mblim, lfi->lim,
     622           0 :                                     lfi->hev_thr);
     623             :         }
     624           0 :       } else if (mask_8x8 & 1) {
     625           0 :         if ((mask_8x8 & 3) == 3) {
     626             :           // Next block's thresholds.
     627           0 :           const loop_filter_thresh *lfin = lfi_n->lfthr + *(lfl + 1);
     628             : 
     629           0 :           aom_lpf_horizontal_8_dual(s, pitch, lfi->mblim, lfi->lim,
     630           0 :                                     lfi->hev_thr, lfin->mblim, lfin->lim,
     631           0 :                                     lfin->hev_thr);
     632             : 
     633           0 :           if ((mask_4x4_int & 3) == 3) {
     634           0 :             aom_lpf_horizontal_4_dual(s + 4 * pitch, pitch, lfi->mblim,
     635           0 :                                       lfi->lim, lfi->hev_thr, lfin->mblim,
     636           0 :                                       lfin->lim, lfin->hev_thr);
     637             :           } else {
     638           0 :             if (mask_4x4_int & 1)
     639           0 :               aom_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
     640           0 :                                    lfi->hev_thr);
     641           0 :             else if (mask_4x4_int & 2)
     642           0 :               aom_lpf_horizontal_4(s + 8 + 4 * pitch, pitch, lfin->mblim,
     643           0 :                                    lfin->lim, lfin->hev_thr);
     644             :           }
     645           0 :           count = 2;
     646             :         } else {
     647           0 :           aom_lpf_horizontal_8(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr);
     648             : 
     649           0 :           if (mask_4x4_int & 1)
     650           0 :             aom_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
     651           0 :                                  lfi->hev_thr);
     652             :         }
     653           0 :       } else if (mask_4x4 & 1) {
     654           0 :         if ((mask_4x4 & 3) == 3) {
     655             :           // Next block's thresholds.
     656           0 :           const loop_filter_thresh *lfin = lfi_n->lfthr + *(lfl + 1);
     657             : 
     658           0 :           aom_lpf_horizontal_4_dual(s, pitch, lfi->mblim, lfi->lim,
     659           0 :                                     lfi->hev_thr, lfin->mblim, lfin->lim,
     660           0 :                                     lfin->hev_thr);
     661           0 :           if ((mask_4x4_int & 3) == 3) {
     662           0 :             aom_lpf_horizontal_4_dual(s + 4 * pitch, pitch, lfi->mblim,
     663           0 :                                       lfi->lim, lfi->hev_thr, lfin->mblim,
     664           0 :                                       lfin->lim, lfin->hev_thr);
     665             :           } else {
     666           0 :             if (mask_4x4_int & 1)
     667           0 :               aom_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
     668           0 :                                    lfi->hev_thr);
     669           0 :             else if (mask_4x4_int & 2)
     670           0 :               aom_lpf_horizontal_4(s + 8 + 4 * pitch, pitch, lfin->mblim,
     671           0 :                                    lfin->lim, lfin->hev_thr);
     672             :           }
     673           0 :           count = 2;
     674             :         } else {
     675           0 :           aom_lpf_horizontal_4(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr);
     676             : 
     677           0 :           if (mask_4x4_int & 1)
     678           0 :             aom_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
     679           0 :                                  lfi->hev_thr);
     680             :         }
     681           0 :       } else if (mask_4x4_int & 1) {
     682           0 :         aom_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
     683           0 :                              lfi->hev_thr);
     684             :       }
     685             :     }
     686           0 :     s += 8 * count;
     687           0 :     lfl += count;
     688           0 :     mask_16x16 >>= count;
     689           0 :     mask_8x8 >>= count;
     690           0 :     mask_4x4 >>= count;
     691           0 :     mask_4x4_int >>= count;
     692             :   }
     693           0 : }
     694             : 
     695             : #if CONFIG_HIGHBITDEPTH
     696           0 : static void highbd_filter_selectively_horiz(
     697             :     uint16_t *s, int pitch, unsigned int mask_16x16, unsigned int mask_8x8,
     698             :     unsigned int mask_4x4, unsigned int mask_4x4_int,
     699             :     const loop_filter_info_n *lfi_n, const uint8_t *lfl, int bd) {
     700             :   unsigned int mask;
     701             :   int count;
     702             : 
     703           0 :   for (mask = mask_16x16 | mask_8x8 | mask_4x4 | mask_4x4_int; mask;
     704           0 :        mask >>= count) {
     705           0 :     const loop_filter_thresh *lfi = lfi_n->lfthr + *lfl;
     706             : 
     707           0 :     count = 1;
     708           0 :     if (mask & 1) {
     709           0 :       if (mask_16x16 & 1) {
     710           0 :         if ((mask_16x16 & 3) == 3) {
     711           0 :           aom_highbd_lpf_horizontal_edge_16(s, pitch, lfi->mblim, lfi->lim,
     712           0 :                                             lfi->hev_thr, bd);
     713           0 :           count = 2;
     714             :         } else {
     715           0 :           aom_highbd_lpf_horizontal_edge_8(s, pitch, lfi->mblim, lfi->lim,
     716           0 :                                            lfi->hev_thr, bd);
     717             :         }
     718           0 :       } else if (mask_8x8 & 1) {
     719           0 :         if ((mask_8x8 & 3) == 3) {
     720             :           // Next block's thresholds.
     721           0 :           const loop_filter_thresh *lfin = lfi_n->lfthr + *(lfl + 1);
     722             : 
     723           0 :           aom_highbd_lpf_horizontal_8_dual(s, pitch, lfi->mblim, lfi->lim,
     724           0 :                                            lfi->hev_thr, lfin->mblim, lfin->lim,
     725           0 :                                            lfin->hev_thr, bd);
     726             : 
     727           0 :           if ((mask_4x4_int & 3) == 3) {
     728           0 :             aom_highbd_lpf_horizontal_4_dual(
     729           0 :                 s + 4 * pitch, pitch, lfi->mblim, lfi->lim, lfi->hev_thr,
     730           0 :                 lfin->mblim, lfin->lim, lfin->hev_thr, bd);
     731             :           } else {
     732           0 :             if (mask_4x4_int & 1) {
     733           0 :               aom_highbd_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim,
     734           0 :                                           lfi->lim, lfi->hev_thr, bd);
     735           0 :             } else if (mask_4x4_int & 2) {
     736           0 :               aom_highbd_lpf_horizontal_4(s + 8 + 4 * pitch, pitch, lfin->mblim,
     737           0 :                                           lfin->lim, lfin->hev_thr, bd);
     738             :             }
     739             :           }
     740           0 :           count = 2;
     741             :         } else {
     742           0 :           aom_highbd_lpf_horizontal_8(s, pitch, lfi->mblim, lfi->lim,
     743           0 :                                       lfi->hev_thr, bd);
     744             : 
     745           0 :           if (mask_4x4_int & 1) {
     746           0 :             aom_highbd_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim,
     747           0 :                                         lfi->lim, lfi->hev_thr, bd);
     748             :           }
     749             :         }
     750           0 :       } else if (mask_4x4 & 1) {
     751           0 :         if ((mask_4x4 & 3) == 3) {
     752             :           // Next block's thresholds.
     753           0 :           const loop_filter_thresh *lfin = lfi_n->lfthr + *(lfl + 1);
     754             : 
     755           0 :           aom_highbd_lpf_horizontal_4_dual(s, pitch, lfi->mblim, lfi->lim,
     756           0 :                                            lfi->hev_thr, lfin->mblim, lfin->lim,
     757           0 :                                            lfin->hev_thr, bd);
     758           0 :           if ((mask_4x4_int & 3) == 3) {
     759           0 :             aom_highbd_lpf_horizontal_4_dual(
     760           0 :                 s + 4 * pitch, pitch, lfi->mblim, lfi->lim, lfi->hev_thr,
     761           0 :                 lfin->mblim, lfin->lim, lfin->hev_thr, bd);
     762             :           } else {
     763           0 :             if (mask_4x4_int & 1) {
     764           0 :               aom_highbd_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim,
     765           0 :                                           lfi->lim, lfi->hev_thr, bd);
     766           0 :             } else if (mask_4x4_int & 2) {
     767           0 :               aom_highbd_lpf_horizontal_4(s + 8 + 4 * pitch, pitch, lfin->mblim,
     768           0 :                                           lfin->lim, lfin->hev_thr, bd);
     769             :             }
     770             :           }
     771           0 :           count = 2;
     772             :         } else {
     773           0 :           aom_highbd_lpf_horizontal_4(s, pitch, lfi->mblim, lfi->lim,
     774           0 :                                       lfi->hev_thr, bd);
     775             : 
     776           0 :           if (mask_4x4_int & 1) {
     777           0 :             aom_highbd_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim,
     778           0 :                                         lfi->lim, lfi->hev_thr, bd);
     779             :           }
     780             :         }
     781           0 :       } else if (mask_4x4_int & 1) {
     782           0 :         aom_highbd_lpf_horizontal_4(s + 4 * pitch, pitch, lfi->mblim, lfi->lim,
     783           0 :                                     lfi->hev_thr, bd);
     784             :       }
     785             :     }
     786           0 :     s += 8 * count;
     787           0 :     lfl += count;
     788           0 :     mask_16x16 >>= count;
     789           0 :     mask_8x8 >>= count;
     790           0 :     mask_4x4 >>= count;
     791           0 :     mask_4x4_int >>= count;
     792             :   }
     793           0 : }
     794             : #endif  // CONFIG_HIGHBITDEPTH
     795             : 
     796             : // This function ors into the current lfm structure, where to do loop
     797             : // filters for the specific mi we are looking at. It uses information
     798             : // including the block_size_type (32x16, 32x32, etc.), the transform size,
     799             : // whether there were any coefficients encoded, and the loop filter strength
     800             : // block we are currently looking at. Shift is used to position the
     801             : // 1's we produce.
     802             : // TODO(JBB) Need another function for different resolution color..
     803           0 : static void build_masks(AV1_COMMON *const cm,
     804             :                         const loop_filter_info_n *const lfi_n,
     805             :                         const MODE_INFO *mi, const int shift_y,
     806             :                         const int shift_uv, LOOP_FILTER_MASK *lfm) {
     807           0 :   const MB_MODE_INFO *mbmi = &mi->mbmi;
     808           0 :   const BLOCK_SIZE block_size = mbmi->sb_type;
     809             :   // TODO(debargha): Check if masks can be setup correctly when
     810             :   // rectangular transfroms are used with the EXT_TX expt.
     811           0 :   const TX_SIZE tx_size_y = txsize_sqr_map[mbmi->tx_size];
     812           0 :   const TX_SIZE tx_size_y_left = txsize_horz_map[mbmi->tx_size];
     813           0 :   const TX_SIZE tx_size_y_above = txsize_vert_map[mbmi->tx_size];
     814           0 :   const TX_SIZE tx_size_uv =
     815           0 :       txsize_sqr_map[uv_txsize_lookup[block_size][mbmi->tx_size][1][1]];
     816           0 :   const TX_SIZE tx_size_uv_left =
     817           0 :       txsize_horz_map[uv_txsize_lookup[block_size][mbmi->tx_size][1][1]];
     818           0 :   const TX_SIZE tx_size_uv_above =
     819           0 :       txsize_vert_map[uv_txsize_lookup[block_size][mbmi->tx_size][1][1]];
     820             : #if CONFIG_EXT_DELTA_Q
     821           0 :   const int filter_level = get_filter_level(cm, lfi_n, mbmi);
     822             : #else
     823             :   const int filter_level = get_filter_level(lfi_n, mbmi);
     824             :   (void)cm;
     825             : #endif
     826           0 :   uint64_t *const left_y = &lfm->left_y[tx_size_y_left];
     827           0 :   uint64_t *const above_y = &lfm->above_y[tx_size_y_above];
     828           0 :   uint64_t *const int_4x4_y = &lfm->int_4x4_y;
     829           0 :   uint16_t *const left_uv = &lfm->left_uv[tx_size_uv_left];
     830           0 :   uint16_t *const above_uv = &lfm->above_uv[tx_size_uv_above];
     831           0 :   uint16_t *const int_4x4_uv = &lfm->left_int_4x4_uv;
     832             :   int i;
     833             : 
     834             :   // If filter level is 0 we don't loop filter.
     835           0 :   if (!filter_level) {
     836           0 :     return;
     837             :   } else {
     838           0 :     const int w = num_8x8_blocks_wide_lookup[block_size];
     839           0 :     const int h = num_8x8_blocks_high_lookup[block_size];
     840           0 :     const int row = (shift_y >> MAX_MIB_SIZE_LOG2);
     841           0 :     const int col = shift_y - (row << MAX_MIB_SIZE_LOG2);
     842             : 
     843           0 :     for (i = 0; i < h; i++) memset(&lfm->lfl_y[row + i][col], filter_level, w);
     844             :   }
     845             : 
     846             :   // These set 1 in the current block size for the block size edges.
     847             :   // For instance if the block size is 32x16, we'll set:
     848             :   //    above =   1111
     849             :   //              0000
     850             :   //    and
     851             :   //    left  =   1000
     852             :   //          =   1000
     853             :   // NOTE : In this example the low bit is left most ( 1000 ) is stored as
     854             :   //        1,  not 8...
     855             :   //
     856             :   // U and V set things on a 16 bit scale.
     857             :   //
     858           0 :   *above_y |= above_prediction_mask[block_size] << shift_y;
     859           0 :   *above_uv |= above_prediction_mask_uv[block_size] << shift_uv;
     860           0 :   *left_y |= left_prediction_mask[block_size] << shift_y;
     861           0 :   *left_uv |= left_prediction_mask_uv[block_size] << shift_uv;
     862             : 
     863             :   // If the block has no coefficients and is not intra we skip applying
     864             :   // the loop filter on block edges.
     865           0 :   if (mbmi->skip && is_inter_block(mbmi)) return;
     866             : 
     867             :   // Here we are adding a mask for the transform size. The transform
     868             :   // size mask is set to be correct for a 64x64 prediction block size. We
     869             :   // mask to match the size of the block we are working on and then shift it
     870             :   // into place..
     871           0 :   *above_y |= (size_mask[block_size] & above_64x64_txform_mask[tx_size_y_above])
     872           0 :               << shift_y;
     873           0 :   *above_uv |=
     874           0 :       (size_mask_uv[block_size] & above_64x64_txform_mask_uv[tx_size_uv_above])
     875           0 :       << shift_uv;
     876             : 
     877           0 :   *left_y |= (size_mask[block_size] & left_64x64_txform_mask[tx_size_y_left])
     878           0 :              << shift_y;
     879           0 :   *left_uv |=
     880           0 :       (size_mask_uv[block_size] & left_64x64_txform_mask_uv[tx_size_uv_left])
     881           0 :       << shift_uv;
     882             : 
     883             :   // Here we are trying to determine what to do with the internal 4x4 block
     884             :   // boundaries.  These differ from the 4x4 boundaries on the outside edge of
     885             :   // an 8x8 in that the internal ones can be skipped and don't depend on
     886             :   // the prediction block size.
     887           0 :   if (tx_size_y == TX_4X4)
     888           0 :     *int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffffULL) << shift_y;
     889             : 
     890           0 :   if (tx_size_uv == TX_4X4)
     891           0 :     *int_4x4_uv |= (size_mask_uv[block_size] & 0xffff) << shift_uv;
     892             : }
     893             : 
     894             : // This function does the same thing as the one above with the exception that
     895             : // it only affects the y masks. It exists because for blocks < 16x16 in size,
     896             : // we only update u and v masks on the first block.
     897           0 : static void build_y_mask(AV1_COMMON *const cm,
     898             :                          const loop_filter_info_n *const lfi_n,
     899             :                          const MODE_INFO *mi, const int shift_y,
     900             : #if CONFIG_SUPERTX
     901             :                          int supertx_enabled,
     902             : #endif  // CONFIG_SUPERTX
     903             :                          LOOP_FILTER_MASK *lfm) {
     904           0 :   const MB_MODE_INFO *mbmi = &mi->mbmi;
     905           0 :   const TX_SIZE tx_size_y = txsize_sqr_map[mbmi->tx_size];
     906           0 :   const TX_SIZE tx_size_y_left = txsize_horz_map[mbmi->tx_size];
     907           0 :   const TX_SIZE tx_size_y_above = txsize_vert_map[mbmi->tx_size];
     908             : #if CONFIG_SUPERTX
     909             :   const BLOCK_SIZE block_size =
     910             :       supertx_enabled ? (BLOCK_SIZE)(3 * tx_size_y) : mbmi->sb_type;
     911             : #else
     912           0 :   const BLOCK_SIZE block_size = mbmi->sb_type;
     913             : #endif
     914             : #if CONFIG_EXT_DELTA_Q
     915           0 :   const int filter_level = get_filter_level(cm, lfi_n, mbmi);
     916             : #else
     917             :   const int filter_level = get_filter_level(lfi_n, mbmi);
     918             :   (void)cm;
     919             : #endif
     920           0 :   uint64_t *const left_y = &lfm->left_y[tx_size_y_left];
     921           0 :   uint64_t *const above_y = &lfm->above_y[tx_size_y_above];
     922           0 :   uint64_t *const int_4x4_y = &lfm->int_4x4_y;
     923             :   int i;
     924             : 
     925           0 :   if (!filter_level) {
     926           0 :     return;
     927             :   } else {
     928           0 :     const int w = num_8x8_blocks_wide_lookup[block_size];
     929           0 :     const int h = num_8x8_blocks_high_lookup[block_size];
     930           0 :     const int row = (shift_y >> MAX_MIB_SIZE_LOG2);
     931           0 :     const int col = shift_y - (row << MAX_MIB_SIZE_LOG2);
     932             : 
     933           0 :     for (i = 0; i < h; i++) memset(&lfm->lfl_y[row + i][col], filter_level, w);
     934             :   }
     935             : 
     936           0 :   *above_y |= above_prediction_mask[block_size] << shift_y;
     937           0 :   *left_y |= left_prediction_mask[block_size] << shift_y;
     938             : 
     939           0 :   if (mbmi->skip && is_inter_block(mbmi)) return;
     940             : 
     941           0 :   *above_y |= (size_mask[block_size] & above_64x64_txform_mask[tx_size_y_above])
     942           0 :               << shift_y;
     943             : 
     944           0 :   *left_y |= (size_mask[block_size] & left_64x64_txform_mask[tx_size_y_left])
     945           0 :              << shift_y;
     946             : 
     947           0 :   if (tx_size_y == TX_4X4)
     948           0 :     *int_4x4_y |= (size_mask[block_size] & 0xffffffffffffffffULL) << shift_y;
     949             : }
     950             : 
     951             : #if CONFIG_LOOPFILTERING_ACROSS_TILES
     952             : // This function update the bit masks for the entire 64x64 region represented
     953             : // by mi_row, mi_col. In case one of the edge is a tile boundary, loop filtering
     954             : // for that edge is disabled. This function only check the tile boundary info
     955             : // for the top left corner mi to determine the boundary information for the
     956             : // top and left edge of the whole super block
     957           0 : static void update_tile_boundary_filter_mask(AV1_COMMON *const cm,
     958             :                                              const int mi_row, const int mi_col,
     959             :                                              LOOP_FILTER_MASK *lfm) {
     960             :   int i;
     961           0 :   MODE_INFO *const mi = cm->mi + mi_row * cm->mi_stride + mi_col;
     962             : 
     963           0 :   if (mi->mbmi.boundary_info & TILE_LEFT_BOUNDARY) {
     964           0 :     for (i = 0; i <= TX_32X32; i++) {
     965           0 :       lfm->left_y[i] &= 0xfefefefefefefefeULL;
     966           0 :       lfm->left_uv[i] &= 0xeeee;
     967             :     }
     968             :   }
     969             : 
     970           0 :   if (mi->mbmi.boundary_info & TILE_ABOVE_BOUNDARY) {
     971           0 :     for (i = 0; i <= TX_32X32; i++) {
     972           0 :       lfm->above_y[i] &= 0xffffffffffffff00ULL;
     973           0 :       lfm->above_uv[i] &= 0xfff0;
     974             :     }
     975             :   }
     976           0 : }
     977             : #endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
     978             : 
     979             : // This function sets up the bit masks for the entire 64x64 region represented
     980             : // by mi_row, mi_col.
     981             : // TODO(JBB): This function only works for yv12.
     982           0 : void av1_setup_mask(AV1_COMMON *const cm, const int mi_row, const int mi_col,
     983             :                     MODE_INFO **mi, const int mode_info_stride,
     984             :                     LOOP_FILTER_MASK *lfm) {
     985             :   int idx_32, idx_16, idx_8;
     986           0 :   const loop_filter_info_n *const lfi_n = &cm->lf_info;
     987           0 :   MODE_INFO **mip = mi;
     988           0 :   MODE_INFO **mip2 = mi;
     989             : 
     990             :   // These are offsets to the next mi in the 64x64 block. It is what gets
     991             :   // added to the mi ptr as we go through each loop. It helps us to avoid
     992             :   // setting up special row and column counters for each index. The last step
     993             :   // brings us out back to the starting position.
     994           0 :   const int offset_32[] = { 4, (mode_info_stride << 2) - 4, 4,
     995           0 :                             -(mode_info_stride << 2) - 4 };
     996           0 :   const int offset_16[] = { 2, (mode_info_stride << 1) - 2, 2,
     997           0 :                             -(mode_info_stride << 1) - 2 };
     998           0 :   const int offset[] = { 1, mode_info_stride - 1, 1, -mode_info_stride - 1 };
     999             : 
    1000             :   // Following variables represent shifts to position the current block
    1001             :   // mask over the appropriate block. A shift of 36 to the left will move
    1002             :   // the bits for the final 32 by 32 block in the 64x64 up 4 rows and left
    1003             :   // 4 rows to the appropriate spot.
    1004           0 :   const int shift_32_y[] = { 0, 4, 32, 36 };
    1005           0 :   const int shift_16_y[] = { 0, 2, 16, 18 };
    1006           0 :   const int shift_8_y[] = { 0, 1, 8, 9 };
    1007           0 :   const int shift_32_uv[] = { 0, 2, 8, 10 };
    1008           0 :   const int shift_16_uv[] = { 0, 1, 4, 5 };
    1009             :   int i;
    1010           0 :   const int max_rows = AOMMIN(cm->mi_rows - mi_row, MAX_MIB_SIZE);
    1011           0 :   const int max_cols = AOMMIN(cm->mi_cols - mi_col, MAX_MIB_SIZE);
    1012             : #if CONFIG_EXT_PARTITION
    1013             :   assert(0 && "Not yet updated");
    1014             : #endif  // CONFIG_EXT_PARTITION
    1015             : 
    1016           0 :   av1_zero(*lfm);
    1017           0 :   assert(mip[0] != NULL);
    1018             : 
    1019             :   // TODO(jimbankoski): Try moving most of the following code into decode
    1020             :   // loop and storing lfm in the mbmi structure so that we don't have to go
    1021             :   // through the recursive loop structure multiple times.
    1022           0 :   switch (mip[0]->mbmi.sb_type) {
    1023           0 :     case BLOCK_64X64: build_masks(cm, lfi_n, mip[0], 0, 0, lfm); break;
    1024           0 :     case BLOCK_64X32: build_masks(cm, lfi_n, mip[0], 0, 0, lfm);
    1025             : #if CONFIG_SUPERTX && CONFIG_TX64X64
    1026             :       if (supertx_enabled(&mip[0]->mbmi)) break;
    1027             : #endif  // CONFIG_SUPERTX && CONFIG_TX64X64
    1028           0 :       mip2 = mip + mode_info_stride * 4;
    1029           0 :       if (4 >= max_rows) break;
    1030           0 :       build_masks(cm, lfi_n, mip2[0], 32, 8, lfm);
    1031           0 :       break;
    1032           0 :     case BLOCK_32X64: build_masks(cm, lfi_n, mip[0], 0, 0, lfm);
    1033             : #if CONFIG_SUPERTX && CONFIG_TX64X64
    1034             :       if (supertx_enabled(&mip[0]->mbmi)) break;
    1035             : #endif  // CONFIG_SUPERTX && CONFIG_TX64X64
    1036           0 :       mip2 = mip + 4;
    1037           0 :       if (4 >= max_cols) break;
    1038           0 :       build_masks(cm, lfi_n, mip2[0], 4, 2, lfm);
    1039           0 :       break;
    1040             :     default:
    1041             : #if CONFIG_SUPERTX && CONFIG_TX64X64
    1042             :       if (mip[0]->mbmi.tx_size == TX_64X64) {
    1043             :         build_masks(cm, lfi_n, mip[0], 0, 0, lfm);
    1044             :       } else {
    1045             : #endif  // CONFIG_SUPERTX && CONFIG_TX64X64
    1046           0 :         for (idx_32 = 0; idx_32 < 4; mip += offset_32[idx_32], ++idx_32) {
    1047           0 :           const int shift_y_32 = shift_32_y[idx_32];
    1048           0 :           const int shift_uv_32 = shift_32_uv[idx_32];
    1049           0 :           const int mi_32_col_offset = ((idx_32 & 1) << 2);
    1050           0 :           const int mi_32_row_offset = ((idx_32 >> 1) << 2);
    1051           0 :           if (mi_32_col_offset >= max_cols || mi_32_row_offset >= max_rows)
    1052           0 :             continue;
    1053           0 :           switch (mip[0]->mbmi.sb_type) {
    1054             :             case BLOCK_32X32:
    1055           0 :               build_masks(cm, lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
    1056           0 :               break;
    1057             :             case BLOCK_32X16:
    1058           0 :               build_masks(cm, lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
    1059             : #if CONFIG_SUPERTX
    1060             :               if (supertx_enabled(&mip[0]->mbmi)) break;
    1061             : #endif
    1062           0 :               if (mi_32_row_offset + 2 >= max_rows) continue;
    1063           0 :               mip2 = mip + mode_info_stride * 2;
    1064           0 :               build_masks(cm, lfi_n, mip2[0], shift_y_32 + 16, shift_uv_32 + 4,
    1065             :                           lfm);
    1066           0 :               break;
    1067             :             case BLOCK_16X32:
    1068           0 :               build_masks(cm, lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
    1069             : #if CONFIG_SUPERTX
    1070             :               if (supertx_enabled(&mip[0]->mbmi)) break;
    1071             : #endif
    1072           0 :               if (mi_32_col_offset + 2 >= max_cols) continue;
    1073           0 :               mip2 = mip + 2;
    1074           0 :               build_masks(cm, lfi_n, mip2[0], shift_y_32 + 2, shift_uv_32 + 1,
    1075             :                           lfm);
    1076           0 :               break;
    1077             :             default:
    1078             : #if CONFIG_SUPERTX
    1079             :               if (mip[0]->mbmi.tx_size == TX_32X32) {
    1080             :                 build_masks(cm, lfi_n, mip[0], shift_y_32, shift_uv_32, lfm);
    1081             :                 break;
    1082             :               }
    1083             : #endif
    1084           0 :               for (idx_16 = 0; idx_16 < 4; mip += offset_16[idx_16], ++idx_16) {
    1085           0 :                 const int shift_y_32_16 = shift_y_32 + shift_16_y[idx_16];
    1086           0 :                 const int shift_uv_32_16 = shift_uv_32 + shift_16_uv[idx_16];
    1087           0 :                 const int mi_16_col_offset =
    1088           0 :                     mi_32_col_offset + ((idx_16 & 1) << 1);
    1089           0 :                 const int mi_16_row_offset =
    1090           0 :                     mi_32_row_offset + ((idx_16 >> 1) << 1);
    1091             : 
    1092           0 :                 if (mi_16_col_offset >= max_cols ||
    1093             :                     mi_16_row_offset >= max_rows)
    1094           0 :                   continue;
    1095             : 
    1096           0 :                 switch (mip[0]->mbmi.sb_type) {
    1097             :                   case BLOCK_16X16:
    1098           0 :                     build_masks(cm, lfi_n, mip[0], shift_y_32_16,
    1099             :                                 shift_uv_32_16, lfm);
    1100           0 :                     break;
    1101             :                   case BLOCK_16X8:
    1102             : #if CONFIG_SUPERTX
    1103             :                     if (supertx_enabled(&mip[0]->mbmi)) break;
    1104             : #endif
    1105           0 :                     build_masks(cm, lfi_n, mip[0], shift_y_32_16,
    1106             :                                 shift_uv_32_16, lfm);
    1107           0 :                     if (mi_16_row_offset + 1 >= max_rows) continue;
    1108           0 :                     mip2 = mip + mode_info_stride;
    1109           0 :                     build_y_mask(cm, lfi_n, mip2[0], shift_y_32_16 + 8,
    1110             : #if CONFIG_SUPERTX
    1111             :                                  0,
    1112             : #endif
    1113             :                                  lfm);
    1114           0 :                     break;
    1115             :                   case BLOCK_8X16:
    1116             : #if CONFIG_SUPERTX
    1117             :                     if (supertx_enabled(&mip[0]->mbmi)) break;
    1118             : #endif
    1119           0 :                     build_masks(cm, lfi_n, mip[0], shift_y_32_16,
    1120             :                                 shift_uv_32_16, lfm);
    1121           0 :                     if (mi_16_col_offset + 1 >= max_cols) continue;
    1122           0 :                     mip2 = mip + 1;
    1123           0 :                     build_y_mask(cm, lfi_n, mip2[0], shift_y_32_16 + 1,
    1124             : #if CONFIG_SUPERTX
    1125             :                                  0,
    1126             : #endif
    1127             :                                  lfm);
    1128           0 :                     break;
    1129             :                   default: {
    1130           0 :                     const int shift_y_32_16_8_zero =
    1131           0 :                         shift_y_32_16 + shift_8_y[0];
    1132             : #if CONFIG_SUPERTX
    1133             :                     if (mip[0]->mbmi.tx_size == TX_16X16) {
    1134             :                       build_masks(cm, lfi_n, mip[0], shift_y_32_16_8_zero,
    1135             :                                   shift_uv_32_16, lfm);
    1136             :                       break;
    1137             :                     }
    1138             : #endif
    1139           0 :                     build_masks(cm, lfi_n, mip[0], shift_y_32_16_8_zero,
    1140             :                                 shift_uv_32_16, lfm);
    1141           0 :                     mip += offset[0];
    1142           0 :                     for (idx_8 = 1; idx_8 < 4; mip += offset[idx_8], ++idx_8) {
    1143           0 :                       const int shift_y_32_16_8 =
    1144           0 :                           shift_y_32_16 + shift_8_y[idx_8];
    1145           0 :                       const int mi_8_col_offset =
    1146           0 :                           mi_16_col_offset + ((idx_8 & 1));
    1147           0 :                       const int mi_8_row_offset =
    1148           0 :                           mi_16_row_offset + ((idx_8 >> 1));
    1149             : 
    1150           0 :                       if (mi_8_col_offset >= max_cols ||
    1151             :                           mi_8_row_offset >= max_rows)
    1152           0 :                         continue;
    1153           0 :                       build_y_mask(cm, lfi_n, mip[0], shift_y_32_16_8,
    1154             : #if CONFIG_SUPERTX
    1155             :                                    supertx_enabled(&mip[0]->mbmi),
    1156             : #endif
    1157             :                                    lfm);
    1158             :                     }
    1159           0 :                     break;
    1160             :                   }
    1161             :                 }
    1162             :               }
    1163           0 :               break;
    1164             :           }
    1165             :         }
    1166             : #if CONFIG_SUPERTX && CONFIG_TX64X64
    1167             :       }
    1168             : #endif  // CONFIG_SUPERTX && CONFIG_TX64X64
    1169           0 :       break;
    1170             :   }
    1171             :   // The largest loopfilter we have is 16x16 so we use the 16x16 mask
    1172             :   // for 32x32 transforms also.
    1173           0 :   lfm->left_y[TX_16X16] |= lfm->left_y[TX_32X32];
    1174           0 :   lfm->above_y[TX_16X16] |= lfm->above_y[TX_32X32];
    1175           0 :   lfm->left_uv[TX_16X16] |= lfm->left_uv[TX_32X32];
    1176           0 :   lfm->above_uv[TX_16X16] |= lfm->above_uv[TX_32X32];
    1177             : 
    1178             :   // We do at least 8 tap filter on every 32x32 even if the transform size
    1179             :   // is 4x4. So if the 4x4 is set on a border pixel add it to the 8x8 and
    1180             :   // remove it from the 4x4.
    1181           0 :   lfm->left_y[TX_8X8] |= lfm->left_y[TX_4X4] & left_border;
    1182           0 :   lfm->left_y[TX_4X4] &= ~left_border;
    1183           0 :   lfm->above_y[TX_8X8] |= lfm->above_y[TX_4X4] & above_border;
    1184           0 :   lfm->above_y[TX_4X4] &= ~above_border;
    1185           0 :   lfm->left_uv[TX_8X8] |= lfm->left_uv[TX_4X4] & left_border_uv;
    1186           0 :   lfm->left_uv[TX_4X4] &= ~left_border_uv;
    1187           0 :   lfm->above_uv[TX_8X8] |= lfm->above_uv[TX_4X4] & above_border_uv;
    1188           0 :   lfm->above_uv[TX_4X4] &= ~above_border_uv;
    1189             : 
    1190             :   // We do some special edge handling.
    1191           0 :   if (mi_row + MAX_MIB_SIZE > cm->mi_rows) {
    1192           0 :     const uint64_t rows = cm->mi_rows - mi_row;
    1193             : 
    1194             :     // Each pixel inside the border gets a 1,
    1195           0 :     const uint64_t mask_y = (((uint64_t)1 << (rows << MAX_MIB_SIZE_LOG2)) - 1);
    1196           0 :     const uint16_t mask_uv =
    1197           0 :         (((uint16_t)1 << (((rows + 1) >> 1) << (MAX_MIB_SIZE_LOG2 - 1))) - 1);
    1198             : 
    1199             :     // Remove values completely outside our border.
    1200           0 :     for (i = 0; i < TX_32X32; i++) {
    1201           0 :       lfm->left_y[i] &= mask_y;
    1202           0 :       lfm->above_y[i] &= mask_y;
    1203           0 :       lfm->left_uv[i] &= mask_uv;
    1204           0 :       lfm->above_uv[i] &= mask_uv;
    1205             :     }
    1206           0 :     lfm->int_4x4_y &= mask_y;
    1207           0 :     lfm->above_int_4x4_uv = lfm->left_int_4x4_uv & mask_uv;
    1208             : 
    1209             :     // We don't apply a wide loop filter on the last uv block row. If set
    1210             :     // apply the shorter one instead.
    1211           0 :     if (rows == 1) {
    1212           0 :       lfm->above_uv[TX_8X8] |= lfm->above_uv[TX_16X16];
    1213           0 :       lfm->above_uv[TX_16X16] = 0;
    1214             :     }
    1215           0 :     if (rows == 5) {
    1216           0 :       lfm->above_uv[TX_8X8] |= lfm->above_uv[TX_16X16] & 0xff00;
    1217           0 :       lfm->above_uv[TX_16X16] &= ~(lfm->above_uv[TX_16X16] & 0xff00);
    1218             :     }
    1219             :   } else {
    1220           0 :     lfm->above_int_4x4_uv = lfm->left_int_4x4_uv;
    1221             :   }
    1222             : 
    1223           0 :   if (mi_col + MAX_MIB_SIZE > cm->mi_cols) {
    1224           0 :     const uint64_t columns = cm->mi_cols - mi_col;
    1225             : 
    1226             :     // Each pixel inside the border gets a 1, the multiply copies the border
    1227             :     // to where we need it.
    1228           0 :     const uint64_t mask_y = (((1 << columns) - 1)) * 0x0101010101010101ULL;
    1229           0 :     const uint16_t mask_uv = ((1 << ((columns + 1) >> 1)) - 1) * 0x1111;
    1230             : 
    1231             :     // Internal edges are not applied on the last column of the image so
    1232             :     // we mask 1 more for the internal edges
    1233           0 :     const uint16_t mask_uv_int = ((1 << (columns >> 1)) - 1) * 0x1111;
    1234             : 
    1235             :     // Remove the bits outside the image edge.
    1236           0 :     for (i = 0; i < TX_32X32; i++) {
    1237           0 :       lfm->left_y[i] &= mask_y;
    1238           0 :       lfm->above_y[i] &= mask_y;
    1239           0 :       lfm->left_uv[i] &= mask_uv;
    1240           0 :       lfm->above_uv[i] &= mask_uv;
    1241             :     }
    1242           0 :     lfm->int_4x4_y &= mask_y;
    1243           0 :     lfm->left_int_4x4_uv &= mask_uv_int;
    1244             : 
    1245             :     // We don't apply a wide loop filter on the last uv column. If set
    1246             :     // apply the shorter one instead.
    1247           0 :     if (columns == 1) {
    1248           0 :       lfm->left_uv[TX_8X8] |= lfm->left_uv[TX_16X16];
    1249           0 :       lfm->left_uv[TX_16X16] = 0;
    1250             :     }
    1251           0 :     if (columns == 5) {
    1252           0 :       lfm->left_uv[TX_8X8] |= (lfm->left_uv[TX_16X16] & 0xcccc);
    1253           0 :       lfm->left_uv[TX_16X16] &= ~(lfm->left_uv[TX_16X16] & 0xcccc);
    1254             :     }
    1255             :   }
    1256             :   // We don't apply a loop filter on the first column in the image, mask that
    1257             :   // out.
    1258           0 :   if (mi_col == 0) {
    1259           0 :     for (i = 0; i < TX_32X32; i++) {
    1260           0 :       lfm->left_y[i] &= 0xfefefefefefefefeULL;
    1261           0 :       lfm->left_uv[i] &= 0xeeee;
    1262             :     }
    1263             :   }
    1264             : 
    1265             : #if CONFIG_LOOPFILTERING_ACROSS_TILES
    1266           0 :   if (av1_disable_loopfilter_on_tile_boundary(cm)) {
    1267           0 :     update_tile_boundary_filter_mask(cm, mi_row, mi_col, lfm);
    1268             :   }
    1269             : #endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
    1270             : 
    1271             :   // Assert if we try to apply 2 different loop filters at the same position.
    1272           0 :   assert(!(lfm->left_y[TX_16X16] & lfm->left_y[TX_8X8]));
    1273           0 :   assert(!(lfm->left_y[TX_16X16] & lfm->left_y[TX_4X4]));
    1274           0 :   assert(!(lfm->left_y[TX_8X8] & lfm->left_y[TX_4X4]));
    1275           0 :   assert(!(lfm->int_4x4_y & lfm->left_y[TX_16X16]));
    1276           0 :   assert(!(lfm->left_uv[TX_16X16] & lfm->left_uv[TX_8X8]));
    1277           0 :   assert(!(lfm->left_uv[TX_16X16] & lfm->left_uv[TX_4X4]));
    1278           0 :   assert(!(lfm->left_uv[TX_8X8] & lfm->left_uv[TX_4X4]));
    1279           0 :   assert(!(lfm->left_int_4x4_uv & lfm->left_uv[TX_16X16]));
    1280           0 :   assert(!(lfm->above_y[TX_16X16] & lfm->above_y[TX_8X8]));
    1281           0 :   assert(!(lfm->above_y[TX_16X16] & lfm->above_y[TX_4X4]));
    1282           0 :   assert(!(lfm->above_y[TX_8X8] & lfm->above_y[TX_4X4]));
    1283           0 :   assert(!(lfm->int_4x4_y & lfm->above_y[TX_16X16]));
    1284           0 :   assert(!(lfm->above_uv[TX_16X16] & lfm->above_uv[TX_8X8]));
    1285           0 :   assert(!(lfm->above_uv[TX_16X16] & lfm->above_uv[TX_4X4]));
    1286           0 :   assert(!(lfm->above_uv[TX_8X8] & lfm->above_uv[TX_4X4]));
    1287           0 :   assert(!(lfm->above_int_4x4_uv & lfm->above_uv[TX_16X16]));
    1288           0 : }
    1289             : 
    1290           0 : static void filter_selectively_vert(
    1291             :     uint8_t *s, int pitch, unsigned int mask_16x16, unsigned int mask_8x8,
    1292             :     unsigned int mask_4x4, unsigned int mask_4x4_int,
    1293             :     const loop_filter_info_n *lfi_n, const uint8_t *lfl) {
    1294             :   unsigned int mask;
    1295             : 
    1296           0 :   for (mask = mask_16x16 | mask_8x8 | mask_4x4 | mask_4x4_int; mask;
    1297           0 :        mask >>= 1) {
    1298           0 :     const loop_filter_thresh *lfi = lfi_n->lfthr + *lfl;
    1299             : 
    1300           0 :     if (mask & 1) {
    1301           0 :       if (mask_16x16 & 1) {
    1302           0 :         aom_lpf_vertical_16(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr);
    1303           0 :       } else if (mask_8x8 & 1) {
    1304           0 :         aom_lpf_vertical_8(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr);
    1305           0 :       } else if (mask_4x4 & 1) {
    1306           0 :         aom_lpf_vertical_4(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr);
    1307             :       }
    1308             :     }
    1309           0 :     if (mask_4x4_int & 1)
    1310           0 :       aom_lpf_vertical_4(s + 4, pitch, lfi->mblim, lfi->lim, lfi->hev_thr);
    1311           0 :     s += 8;
    1312           0 :     lfl += 1;
    1313           0 :     mask_16x16 >>= 1;
    1314           0 :     mask_8x8 >>= 1;
    1315           0 :     mask_4x4 >>= 1;
    1316           0 :     mask_4x4_int >>= 1;
    1317             :   }
    1318           0 : }
    1319             : 
    1320             : #if CONFIG_HIGHBITDEPTH
    1321           0 : static void highbd_filter_selectively_vert(
    1322             :     uint16_t *s, int pitch, unsigned int mask_16x16, unsigned int mask_8x8,
    1323             :     unsigned int mask_4x4, unsigned int mask_4x4_int,
    1324             :     const loop_filter_info_n *lfi_n, const uint8_t *lfl, int bd) {
    1325             :   unsigned int mask;
    1326             : 
    1327           0 :   for (mask = mask_16x16 | mask_8x8 | mask_4x4 | mask_4x4_int; mask;
    1328           0 :        mask >>= 1) {
    1329           0 :     const loop_filter_thresh *lfi = lfi_n->lfthr + *lfl;
    1330             : 
    1331           0 :     if (mask & 1) {
    1332           0 :       if (mask_16x16 & 1) {
    1333           0 :         aom_highbd_lpf_vertical_16(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr,
    1334             :                                    bd);
    1335           0 :       } else if (mask_8x8 & 1) {
    1336           0 :         aom_highbd_lpf_vertical_8(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr,
    1337             :                                   bd);
    1338           0 :       } else if (mask_4x4 & 1) {
    1339           0 :         aom_highbd_lpf_vertical_4(s, pitch, lfi->mblim, lfi->lim, lfi->hev_thr,
    1340             :                                   bd);
    1341             :       }
    1342             :     }
    1343           0 :     if (mask_4x4_int & 1)
    1344           0 :       aom_highbd_lpf_vertical_4(s + 4, pitch, lfi->mblim, lfi->lim,
    1345           0 :                                 lfi->hev_thr, bd);
    1346           0 :     s += 8;
    1347           0 :     lfl += 1;
    1348           0 :     mask_16x16 >>= 1;
    1349           0 :     mask_8x8 >>= 1;
    1350           0 :     mask_4x4 >>= 1;
    1351           0 :     mask_4x4_int >>= 1;
    1352             :   }
    1353           0 : }
    1354             : #endif  // CONFIG_HIGHBITDEPTH
    1355             : 
    1356             : typedef struct {
    1357             :   unsigned int m16x16;
    1358             :   unsigned int m8x8;
    1359             :   unsigned int m4x4;
    1360             : } FilterMasks;
    1361             : 
    1362             : // Get filter level and masks for the given row index 'idx_r'. (Only used for
    1363             : // the non420 case).
    1364             : // Note: 'row_masks_ptr' and/or 'col_masks_ptr' can be passed NULL.
    1365           0 : static void get_filter_level_and_masks_non420(
    1366             :     AV1_COMMON *const cm, const struct macroblockd_plane *const plane, int pl,
    1367             :     MODE_INFO **mib, int mi_row, int mi_col, int idx_r, uint8_t *const lfl_r,
    1368             :     unsigned int *const mask_4x4_int_r_ptr,
    1369             :     unsigned int *const mask_4x4_int_c_ptr, FilterMasks *const row_masks_ptr,
    1370             :     FilterMasks *const col_masks_ptr) {
    1371           0 :   const int ss_x = plane->subsampling_x;
    1372           0 :   const int ss_y = plane->subsampling_y;
    1373           0 :   const int col_step = mi_size_wide[BLOCK_8X8] << ss_x;
    1374             :   FilterMasks row_masks, col_masks;
    1375           0 :   memset(&row_masks, 0, sizeof(row_masks));
    1376           0 :   memset(&col_masks, 0, sizeof(col_masks));
    1377           0 :   unsigned int mask_4x4_int_r = 0, mask_4x4_int_c = 0;
    1378           0 :   const int r = idx_r >> mi_height_log2_lookup[BLOCK_8X8];
    1379             : 
    1380             :   // Determine the vertical edges that need filtering
    1381             :   int idx_c;
    1382           0 :   for (idx_c = 0; idx_c < cm->mib_size && mi_col + idx_c < cm->mi_cols;
    1383           0 :        idx_c += col_step) {
    1384           0 :     const MODE_INFO *mi = mib[idx_r * cm->mi_stride + idx_c];
    1385           0 :     const MB_MODE_INFO *mbmi = &mi[0].mbmi;
    1386           0 :     const BLOCK_SIZE sb_type = mbmi->sb_type;
    1387           0 :     const int skip_this = mbmi->skip && is_inter_block(mbmi);
    1388             :     // Map index to 8x8 unit
    1389           0 :     const int c = idx_c >> mi_width_log2_lookup[BLOCK_8X8];
    1390             : 
    1391           0 :     const int blk_row = r & (num_8x8_blocks_high_lookup[sb_type] - 1);
    1392           0 :     const int blk_col = c & (num_8x8_blocks_wide_lookup[sb_type] - 1);
    1393             : 
    1394             :     // left edge of current unit is block/partition edge -> no skip
    1395           0 :     const int block_edge_left =
    1396           0 :         (num_4x4_blocks_wide_lookup[sb_type] > 1) ? !blk_col : 1;
    1397           0 :     const int skip_this_c = skip_this && !block_edge_left;
    1398             :     // top edge of current unit is block/partition edge -> no skip
    1399           0 :     const int block_edge_above =
    1400           0 :         (num_4x4_blocks_high_lookup[sb_type] > 1) ? !blk_row : 1;
    1401           0 :     const int skip_this_r = skip_this && !block_edge_above;
    1402             : 
    1403           0 :     TX_SIZE tx_size = (plane->plane_type == PLANE_TYPE_UV)
    1404             :                           ? get_uv_tx_size(mbmi, plane)
    1405           0 :                           : mbmi->tx_size;
    1406             : 
    1407           0 :     const int skip_border_4x4_c =
    1408           0 :         ss_x && mi_col + idx_c >= cm->mi_cols - mi_size_wide[BLOCK_8X8];
    1409           0 :     const int skip_border_4x4_r =
    1410           0 :         ss_y && mi_row + idx_r >= cm->mi_rows - mi_size_high[BLOCK_8X8];
    1411             : 
    1412           0 :     int tx_size_mask = 0;
    1413           0 :     const int c_step = (c >> ss_x);
    1414           0 :     const int r_step = (r >> ss_y);
    1415           0 :     const int col_mask = 1 << c_step;
    1416             : 
    1417             : #if CONFIG_VAR_TX
    1418           0 :     if (is_inter_block(mbmi) && !mbmi->skip) {
    1419           0 :       const int tx_row_idx =
    1420           0 :           (blk_row * mi_size_high[BLOCK_8X8] << TX_UNIT_HIGH_LOG2) >> 1;
    1421           0 :       const int tx_col_idx =
    1422           0 :           (blk_col * mi_size_wide[BLOCK_8X8] << TX_UNIT_WIDE_LOG2) >> 1;
    1423           0 :       const BLOCK_SIZE bsize =
    1424           0 :           AOMMAX(BLOCK_4X4, get_plane_block_size(mbmi->sb_type, plane));
    1425           0 :       const TX_SIZE mb_tx_size = mbmi->inter_tx_size[tx_row_idx][tx_col_idx];
    1426           0 :       tx_size = (plane->plane_type == PLANE_TYPE_UV)
    1427             :                     ? uv_txsize_lookup[bsize][mb_tx_size][0][0]
    1428           0 :                     : mb_tx_size;
    1429             :     }
    1430             : #endif
    1431             : 
    1432             : // Filter level can vary per MI
    1433             : #if CONFIG_EXT_DELTA_Q
    1434           0 :     if (!(lfl_r[c_step] = get_filter_level(cm, &cm->lf_info, mbmi))) continue;
    1435             : #else
    1436             :     if (!(lfl_r[c_step] = get_filter_level(&cm->lf_info, mbmi))) continue;
    1437             : #endif
    1438             : 
    1439             : #if CONFIG_VAR_TX
    1440             :     TX_SIZE tx_size_r, tx_size_c;
    1441             : 
    1442           0 :     const int tx_wide =
    1443           0 :         AOMMIN(tx_size_wide[tx_size],
    1444             :                tx_size_wide[cm->top_txfm_context[pl][(mi_col + idx_c)
    1445             :                                                      << TX_UNIT_WIDE_LOG2]]);
    1446           0 :     const int tx_high = AOMMIN(
    1447             :         tx_size_high[tx_size],
    1448             :         tx_size_high[cm->left_txfm_context[pl][((mi_row + idx_r) & MAX_MIB_MASK)
    1449             :                                                << TX_UNIT_HIGH_LOG2]]);
    1450             : 
    1451           0 :     tx_size_c = get_sqr_tx_size(tx_wide);
    1452           0 :     tx_size_r = get_sqr_tx_size(tx_high);
    1453             : 
    1454           0 :     memset(cm->top_txfm_context[pl] + ((mi_col + idx_c) << TX_UNIT_WIDE_LOG2),
    1455           0 :            tx_size, mi_size_wide[BLOCK_8X8] << TX_UNIT_WIDE_LOG2);
    1456           0 :     memset(cm->left_txfm_context[pl] +
    1457           0 :                (((mi_row + idx_r) & MAX_MIB_MASK) << TX_UNIT_HIGH_LOG2),
    1458           0 :            tx_size, mi_size_high[BLOCK_8X8] << TX_UNIT_HIGH_LOG2);
    1459             : #else
    1460             :     TX_SIZE tx_size_c = txsize_horz_map[tx_size];
    1461             :     TX_SIZE tx_size_r = txsize_vert_map[tx_size];
    1462             :     (void)pl;
    1463             : #endif  // CONFIG_VAR_TX
    1464             : 
    1465           0 :     if (tx_size_c == TX_32X32)
    1466           0 :       tx_size_mask = 3;
    1467           0 :     else if (tx_size_c == TX_16X16)
    1468           0 :       tx_size_mask = 1;
    1469             :     else
    1470           0 :       tx_size_mask = 0;
    1471             : 
    1472             :     // Build masks based on the transform size of each block
    1473             :     // handle vertical mask
    1474           0 :     if (tx_size_c == TX_32X32) {
    1475           0 :       if (!skip_this_c && (c_step & tx_size_mask) == 0) {
    1476           0 :         if (!skip_border_4x4_c)
    1477           0 :           col_masks.m16x16 |= col_mask;
    1478             :         else
    1479           0 :           col_masks.m8x8 |= col_mask;
    1480             :       }
    1481           0 :     } else if (tx_size_c == TX_16X16) {
    1482           0 :       if (!skip_this_c && (c_step & tx_size_mask) == 0) {
    1483           0 :         if (!skip_border_4x4_c)
    1484           0 :           col_masks.m16x16 |= col_mask;
    1485             :         else
    1486           0 :           col_masks.m8x8 |= col_mask;
    1487             :       }
    1488             :     } else {
    1489             :       // force 8x8 filtering on 32x32 boundaries
    1490           0 :       if (!skip_this_c && (c_step & tx_size_mask) == 0) {
    1491           0 :         if (tx_size_c == TX_8X8 || ((c >> ss_x) & 3) == 0)
    1492           0 :           col_masks.m8x8 |= col_mask;
    1493             :         else
    1494           0 :           col_masks.m4x4 |= col_mask;
    1495             :       }
    1496             : 
    1497           0 :       if (!skip_this && tx_size_c < TX_8X8 && !skip_border_4x4_c &&
    1498           0 :           (c_step & tx_size_mask) == 0)
    1499           0 :         mask_4x4_int_c |= col_mask;
    1500             :     }
    1501             : 
    1502           0 :     if (tx_size_r == TX_32X32)
    1503           0 :       tx_size_mask = 3;
    1504           0 :     else if (tx_size_r == TX_16X16)
    1505           0 :       tx_size_mask = 1;
    1506             :     else
    1507           0 :       tx_size_mask = 0;
    1508             : 
    1509             :     // set horizontal mask
    1510           0 :     if (tx_size_r == TX_32X32) {
    1511           0 :       if (!skip_this_r && (r_step & tx_size_mask) == 0) {
    1512           0 :         if (!skip_border_4x4_r)
    1513           0 :           row_masks.m16x16 |= col_mask;
    1514             :         else
    1515           0 :           row_masks.m8x8 |= col_mask;
    1516             :       }
    1517           0 :     } else if (tx_size_r == TX_16X16) {
    1518           0 :       if (!skip_this_r && (r_step & tx_size_mask) == 0) {
    1519           0 :         if (!skip_border_4x4_r)
    1520           0 :           row_masks.m16x16 |= col_mask;
    1521             :         else
    1522           0 :           row_masks.m8x8 |= col_mask;
    1523             :       }
    1524             :     } else {
    1525             :       // force 8x8 filtering on 32x32 boundaries
    1526           0 :       if (!skip_this_r && (r_step & tx_size_mask) == 0) {
    1527           0 :         if (tx_size_r == TX_8X8 || (r_step & 3) == 0)
    1528           0 :           row_masks.m8x8 |= col_mask;
    1529             :         else
    1530           0 :           row_masks.m4x4 |= col_mask;
    1531             :       }
    1532             : 
    1533           0 :       if (!skip_this && tx_size_r < TX_8X8 && !skip_border_4x4_r &&
    1534           0 :           ((r >> ss_y) & tx_size_mask) == 0)
    1535           0 :         mask_4x4_int_r |= col_mask;
    1536             :     }
    1537             :   }
    1538             : 
    1539           0 :   if (row_masks_ptr) *row_masks_ptr = row_masks;
    1540           0 :   if (col_masks_ptr) *col_masks_ptr = col_masks;
    1541           0 :   if (mask_4x4_int_c_ptr) *mask_4x4_int_c_ptr = mask_4x4_int_c;
    1542           0 :   if (mask_4x4_int_r_ptr) *mask_4x4_int_r_ptr = mask_4x4_int_r;
    1543           0 : }
    1544             : 
    1545           0 : void av1_filter_block_plane_non420_ver(AV1_COMMON *const cm,
    1546             :                                        struct macroblockd_plane *plane,
    1547             :                                        MODE_INFO **mib, int mi_row, int mi_col,
    1548             :                                        int pl) {
    1549           0 :   const int ss_y = plane->subsampling_y;
    1550           0 :   const int row_step = mi_size_high[BLOCK_8X8] << ss_y;
    1551           0 :   struct buf_2d *const dst = &plane->dst;
    1552           0 :   uint8_t *const dst0 = dst->buf;
    1553           0 :   uint8_t lfl[MAX_MIB_SIZE][MAX_MIB_SIZE] = { { 0 } };
    1554             : 
    1555             :   int idx_r;
    1556           0 :   for (idx_r = 0; idx_r < cm->mib_size && mi_row + idx_r < cm->mi_rows;
    1557           0 :        idx_r += row_step) {
    1558             :     unsigned int mask_4x4_int;
    1559             :     FilterMasks col_masks;
    1560           0 :     const int r = idx_r >> mi_height_log2_lookup[BLOCK_8X8];
    1561           0 :     get_filter_level_and_masks_non420(cm, plane, pl, mib, mi_row, mi_col, idx_r,
    1562             :                                       &lfl[r][0], NULL, &mask_4x4_int, NULL,
    1563             :                                       &col_masks);
    1564             : 
    1565             :     // Disable filtering on the leftmost column or tile boundary
    1566           0 :     unsigned int border_mask = ~(mi_col == 0);
    1567             : #if CONFIG_LOOPFILTERING_ACROSS_TILES
    1568           0 :     if (av1_disable_loopfilter_on_tile_boundary(cm) &&
    1569           0 :         ((mib[0]->mbmi.boundary_info & TILE_LEFT_BOUNDARY) != 0)) {
    1570           0 :       border_mask = 0xfffffffe;
    1571             :     }
    1572             : #endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
    1573             : 
    1574             : #if CONFIG_HIGHBITDEPTH
    1575           0 :     if (cm->use_highbitdepth)
    1576           0 :       highbd_filter_selectively_vert(
    1577           0 :           CONVERT_TO_SHORTPTR(dst->buf), dst->stride,
    1578           0 :           col_masks.m16x16 & border_mask, col_masks.m8x8 & border_mask,
    1579           0 :           col_masks.m4x4 & border_mask, mask_4x4_int, &cm->lf_info, &lfl[r][0],
    1580           0 :           (int)cm->bit_depth);
    1581             :     else
    1582             : #endif  // CONFIG_HIGHBITDEPTH
    1583           0 :       filter_selectively_vert(
    1584           0 :           dst->buf, dst->stride, col_masks.m16x16 & border_mask,
    1585           0 :           col_masks.m8x8 & border_mask, col_masks.m4x4 & border_mask,
    1586           0 :           mask_4x4_int, &cm->lf_info, &lfl[r][0]);
    1587           0 :     dst->buf += 8 * dst->stride;
    1588             :   }
    1589             : 
    1590             :   // Now do horizontal pass
    1591           0 :   dst->buf = dst0;
    1592           0 : }
    1593             : 
    1594           0 : void av1_filter_block_plane_non420_hor(AV1_COMMON *const cm,
    1595             :                                        struct macroblockd_plane *plane,
    1596             :                                        MODE_INFO **mib, int mi_row, int mi_col,
    1597             :                                        int pl) {
    1598           0 :   const int ss_y = plane->subsampling_y;
    1599           0 :   const int row_step = mi_size_high[BLOCK_8X8] << ss_y;
    1600           0 :   struct buf_2d *const dst = &plane->dst;
    1601           0 :   uint8_t *const dst0 = dst->buf;
    1602             :   FilterMasks row_masks_array[MAX_MIB_SIZE];
    1603           0 :   unsigned int mask_4x4_int[MAX_MIB_SIZE] = { 0 };
    1604           0 :   uint8_t lfl[MAX_MIB_SIZE][MAX_MIB_SIZE] = { { 0 } };
    1605             :   int idx_r;
    1606           0 :   for (idx_r = 0; idx_r < cm->mib_size && mi_row + idx_r < cm->mi_rows;
    1607           0 :        idx_r += row_step) {
    1608           0 :     const int r = idx_r >> mi_height_log2_lookup[BLOCK_8X8];
    1609           0 :     get_filter_level_and_masks_non420(cm, plane, pl, mib, mi_row, mi_col, idx_r,
    1610           0 :                                       &lfl[r][0], mask_4x4_int + r, NULL,
    1611           0 :                                       row_masks_array + r, NULL);
    1612             :   }
    1613           0 :   for (idx_r = 0; idx_r < cm->mib_size && mi_row + idx_r < cm->mi_rows;
    1614           0 :        idx_r += row_step) {
    1615           0 :     const int r = idx_r >> mi_width_log2_lookup[BLOCK_8X8];
    1616             :     FilterMasks row_masks;
    1617             : 
    1618             : #if CONFIG_LOOPFILTERING_ACROSS_TILES
    1619             :     // Disable filtering on the abovemost row or tile boundary
    1620           0 :     const MODE_INFO *mi = cm->mi + (mi_row + r) * cm->mi_stride;
    1621           0 :     if ((av1_disable_loopfilter_on_tile_boundary(cm) &&
    1622           0 :          (mi->mbmi.boundary_info & TILE_ABOVE_BOUNDARY)) ||
    1623           0 :         (mi_row + idx_r == 0)) {
    1624           0 :       memset(&row_masks, 0, sizeof(row_masks));
    1625             : #else
    1626             :     if (mi_row + idx_r == 0) {
    1627             :       memset(&row_masks, 0, sizeof(row_masks));
    1628             : #endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
    1629             :     } else {
    1630           0 :       memcpy(&row_masks, row_masks_array + r, sizeof(row_masks));
    1631             :     }
    1632             : #if CONFIG_HIGHBITDEPTH
    1633           0 :     if (cm->use_highbitdepth)
    1634           0 :       highbd_filter_selectively_horiz(
    1635           0 :           CONVERT_TO_SHORTPTR(dst->buf), dst->stride, row_masks.m16x16,
    1636           0 :           row_masks.m8x8, row_masks.m4x4, mask_4x4_int[r], &cm->lf_info,
    1637           0 :           &lfl[r][0], (int)cm->bit_depth);
    1638             :     else
    1639             : #endif  // CONFIG_HIGHBITDEPTH
    1640           0 :       filter_selectively_horiz(dst->buf, dst->stride, row_masks.m16x16,
    1641             :                                row_masks.m8x8, row_masks.m4x4, mask_4x4_int[r],
    1642           0 :                                &cm->lf_info, &lfl[r][0]);
    1643           0 :     dst->buf += 8 * dst->stride;
    1644             :   }
    1645           0 :   dst->buf = dst0;
    1646           0 : }
    1647             : 
    1648           0 : void av1_filter_block_plane_ss00_ver(AV1_COMMON *const cm,
    1649             :                                      struct macroblockd_plane *const plane,
    1650             :                                      int mi_row, LOOP_FILTER_MASK *lfm) {
    1651           0 :   struct buf_2d *const dst = &plane->dst;
    1652           0 :   uint8_t *const dst0 = dst->buf;
    1653             :   int r;
    1654           0 :   uint64_t mask_16x16 = lfm->left_y[TX_16X16];
    1655           0 :   uint64_t mask_8x8 = lfm->left_y[TX_8X8];
    1656           0 :   uint64_t mask_4x4 = lfm->left_y[TX_4X4];
    1657           0 :   uint64_t mask_4x4_int = lfm->int_4x4_y;
    1658             : 
    1659           0 :   assert(plane->subsampling_x == 0 && plane->subsampling_y == 0);
    1660             : 
    1661             :   // Vertical pass: do 2 rows at one time
    1662           0 :   for (r = 0; r < cm->mib_size && mi_row + r < cm->mi_rows; r += 2) {
    1663           0 :     unsigned int mask_16x16_l = mask_16x16 & 0xffff;
    1664           0 :     unsigned int mask_8x8_l = mask_8x8 & 0xffff;
    1665           0 :     unsigned int mask_4x4_l = mask_4x4 & 0xffff;
    1666           0 :     unsigned int mask_4x4_int_l = mask_4x4_int & 0xffff;
    1667             : 
    1668             : // Disable filtering on the leftmost column.
    1669             : #if CONFIG_HIGHBITDEPTH
    1670           0 :     if (cm->use_highbitdepth)
    1671           0 :       highbd_filter_selectively_vert_row2(
    1672           0 :           plane->subsampling_x, CONVERT_TO_SHORTPTR(dst->buf), dst->stride,
    1673           0 :           mask_16x16_l, mask_8x8_l, mask_4x4_l, mask_4x4_int_l, &cm->lf_info,
    1674           0 :           &lfm->lfl_y[r][0], (int)cm->bit_depth);
    1675             :     else
    1676             : #endif  // CONFIG_HIGHBITDEPTH
    1677           0 :       filter_selectively_vert_row2(
    1678             :           plane->subsampling_x, dst->buf, dst->stride, mask_16x16_l, mask_8x8_l,
    1679           0 :           mask_4x4_l, mask_4x4_int_l, &cm->lf_info, &lfm->lfl_y[r][0]);
    1680             : 
    1681           0 :     dst->buf += 2 * MI_SIZE * dst->stride;
    1682           0 :     mask_16x16 >>= 2 * MI_SIZE;
    1683           0 :     mask_8x8 >>= 2 * MI_SIZE;
    1684           0 :     mask_4x4 >>= 2 * MI_SIZE;
    1685           0 :     mask_4x4_int >>= 2 * MI_SIZE;
    1686             :   }
    1687             : 
    1688             :   // Horizontal pass
    1689           0 :   dst->buf = dst0;
    1690           0 : }
    1691             : 
    1692           0 : void av1_filter_block_plane_ss00_hor(AV1_COMMON *const cm,
    1693             :                                      struct macroblockd_plane *const plane,
    1694             :                                      int mi_row, LOOP_FILTER_MASK *lfm) {
    1695           0 :   struct buf_2d *const dst = &plane->dst;
    1696           0 :   uint8_t *const dst0 = dst->buf;
    1697             :   int r;
    1698           0 :   uint64_t mask_16x16 = lfm->above_y[TX_16X16];
    1699           0 :   uint64_t mask_8x8 = lfm->above_y[TX_8X8];
    1700           0 :   uint64_t mask_4x4 = lfm->above_y[TX_4X4];
    1701           0 :   uint64_t mask_4x4_int = lfm->int_4x4_y;
    1702             : 
    1703           0 :   assert(plane->subsampling_x == 0 && plane->subsampling_y == 0);
    1704             : 
    1705           0 :   for (r = 0; r < cm->mib_size && mi_row + r < cm->mi_rows; r++) {
    1706             :     unsigned int mask_16x16_r;
    1707             :     unsigned int mask_8x8_r;
    1708             :     unsigned int mask_4x4_r;
    1709             : 
    1710           0 :     if (mi_row + r == 0) {
    1711           0 :       mask_16x16_r = 0;
    1712           0 :       mask_8x8_r = 0;
    1713           0 :       mask_4x4_r = 0;
    1714             :     } else {
    1715           0 :       mask_16x16_r = mask_16x16 & 0xff;
    1716           0 :       mask_8x8_r = mask_8x8 & 0xff;
    1717           0 :       mask_4x4_r = mask_4x4 & 0xff;
    1718             :     }
    1719             : 
    1720             : #if CONFIG_HIGHBITDEPTH
    1721           0 :     if (cm->use_highbitdepth)
    1722           0 :       highbd_filter_selectively_horiz(
    1723           0 :           CONVERT_TO_SHORTPTR(dst->buf), dst->stride, mask_16x16_r, mask_8x8_r,
    1724           0 :           mask_4x4_r, mask_4x4_int & 0xff, &cm->lf_info, &lfm->lfl_y[r][0],
    1725           0 :           (int)cm->bit_depth);
    1726             :     else
    1727             : #endif  // CONFIG_HIGHBITDEPTH
    1728           0 :       filter_selectively_horiz(dst->buf, dst->stride, mask_16x16_r, mask_8x8_r,
    1729           0 :                                mask_4x4_r, mask_4x4_int & 0xff, &cm->lf_info,
    1730           0 :                                &lfm->lfl_y[r][0]);
    1731             : 
    1732           0 :     dst->buf += MI_SIZE * dst->stride;
    1733           0 :     mask_16x16 >>= MI_SIZE;
    1734           0 :     mask_8x8 >>= MI_SIZE;
    1735           0 :     mask_4x4 >>= MI_SIZE;
    1736           0 :     mask_4x4_int >>= MI_SIZE;
    1737             :   }
    1738             :   // restore the buf pointer in case there is additional filter pass.
    1739           0 :   dst->buf = dst0;
    1740           0 : }
    1741             : 
    1742           0 : void av1_filter_block_plane_ss11_ver(AV1_COMMON *const cm,
    1743             :                                      struct macroblockd_plane *const plane,
    1744             :                                      int mi_row, LOOP_FILTER_MASK *lfm) {
    1745           0 :   struct buf_2d *const dst = &plane->dst;
    1746           0 :   uint8_t *const dst0 = dst->buf;
    1747             :   int r, c;
    1748             : 
    1749           0 :   uint16_t mask_16x16 = lfm->left_uv[TX_16X16];
    1750           0 :   uint16_t mask_8x8 = lfm->left_uv[TX_8X8];
    1751           0 :   uint16_t mask_4x4 = lfm->left_uv[TX_4X4];
    1752           0 :   uint16_t mask_4x4_int = lfm->left_int_4x4_uv;
    1753             : 
    1754           0 :   assert(plane->subsampling_x == 1 && plane->subsampling_y == 1);
    1755           0 :   assert(plane->plane_type == PLANE_TYPE_UV);
    1756           0 :   memset(lfm->lfl_uv, 0, sizeof(lfm->lfl_uv));
    1757             : 
    1758             :   // Vertical pass: do 2 rows at one time
    1759           0 :   for (r = 0; r < cm->mib_size && mi_row + r < cm->mi_rows; r += 4) {
    1760           0 :     for (c = 0; c < (cm->mib_size >> 1); c++) {
    1761           0 :       lfm->lfl_uv[r >> 1][c] = lfm->lfl_y[r][c << 1];
    1762           0 :       lfm->lfl_uv[(r + 2) >> 1][c] = lfm->lfl_y[r + 2][c << 1];
    1763             :     }
    1764             : 
    1765             :     {
    1766           0 :       unsigned int mask_16x16_l = mask_16x16 & 0xff;
    1767           0 :       unsigned int mask_8x8_l = mask_8x8 & 0xff;
    1768           0 :       unsigned int mask_4x4_l = mask_4x4 & 0xff;
    1769           0 :       unsigned int mask_4x4_int_l = mask_4x4_int & 0xff;
    1770             : 
    1771             : // Disable filtering on the leftmost column.
    1772             : #if CONFIG_HIGHBITDEPTH
    1773           0 :       if (cm->use_highbitdepth)
    1774           0 :         highbd_filter_selectively_vert_row2(
    1775           0 :             plane->subsampling_x, CONVERT_TO_SHORTPTR(dst->buf), dst->stride,
    1776           0 :             mask_16x16_l, mask_8x8_l, mask_4x4_l, mask_4x4_int_l, &cm->lf_info,
    1777           0 :             &lfm->lfl_uv[r >> 1][0], (int)cm->bit_depth);
    1778             :       else
    1779             : #endif  // CONFIG_HIGHBITDEPTH
    1780           0 :         filter_selectively_vert_row2(plane->subsampling_x, dst->buf,
    1781             :                                      dst->stride, mask_16x16_l, mask_8x8_l,
    1782           0 :                                      mask_4x4_l, mask_4x4_int_l, &cm->lf_info,
    1783           0 :                                      &lfm->lfl_uv[r >> 1][0]);
    1784             : 
    1785           0 :       dst->buf += 2 * MI_SIZE * dst->stride;
    1786           0 :       mask_16x16 >>= MI_SIZE;
    1787           0 :       mask_8x8 >>= MI_SIZE;
    1788           0 :       mask_4x4 >>= MI_SIZE;
    1789           0 :       mask_4x4_int >>= MI_SIZE;
    1790             :     }
    1791             :   }
    1792             : 
    1793             :   // Horizontal pass
    1794           0 :   dst->buf = dst0;
    1795           0 : }
    1796             : 
    1797           0 : void av1_filter_block_plane_ss11_hor(AV1_COMMON *const cm,
    1798             :                                      struct macroblockd_plane *const plane,
    1799             :                                      int mi_row, LOOP_FILTER_MASK *lfm) {
    1800           0 :   struct buf_2d *const dst = &plane->dst;
    1801           0 :   uint8_t *const dst0 = dst->buf;
    1802             :   int r, c;
    1803           0 :   uint64_t mask_16x16 = lfm->above_uv[TX_16X16];
    1804           0 :   uint64_t mask_8x8 = lfm->above_uv[TX_8X8];
    1805           0 :   uint64_t mask_4x4 = lfm->above_uv[TX_4X4];
    1806           0 :   uint64_t mask_4x4_int = lfm->above_int_4x4_uv;
    1807             : 
    1808           0 :   assert(plane->subsampling_x == 1 && plane->subsampling_y == 1);
    1809           0 :   memset(lfm->lfl_uv, 0, sizeof(lfm->lfl_uv));
    1810             : 
    1811             :   // re-porpulate the filter level for uv, same as the code for vertical
    1812             :   // filter in av1_filter_block_plane_ss11_ver
    1813           0 :   for (r = 0; r < cm->mib_size && mi_row + r < cm->mi_rows; r += 4) {
    1814           0 :     for (c = 0; c < (cm->mib_size >> 1); c++) {
    1815           0 :       lfm->lfl_uv[r >> 1][c] = lfm->lfl_y[r][c << 1];
    1816           0 :       lfm->lfl_uv[(r + 2) >> 1][c] = lfm->lfl_y[r + 2][c << 1];
    1817             :     }
    1818             :   }
    1819             : 
    1820           0 :   for (r = 0; r < cm->mib_size && mi_row + r < cm->mi_rows; r += 2) {
    1821           0 :     const int skip_border_4x4_r = mi_row + r == cm->mi_rows - 1;
    1822           0 :     const unsigned int mask_4x4_int_r =
    1823           0 :         skip_border_4x4_r ? 0 : (mask_4x4_int & 0xf);
    1824             :     unsigned int mask_16x16_r;
    1825             :     unsigned int mask_8x8_r;
    1826             :     unsigned int mask_4x4_r;
    1827             : 
    1828           0 :     if (mi_row + r == 0) {
    1829           0 :       mask_16x16_r = 0;
    1830           0 :       mask_8x8_r = 0;
    1831           0 :       mask_4x4_r = 0;
    1832             :     } else {
    1833           0 :       mask_16x16_r = mask_16x16 & 0xf;
    1834           0 :       mask_8x8_r = mask_8x8 & 0xf;
    1835           0 :       mask_4x4_r = mask_4x4 & 0xf;
    1836             :     }
    1837             : 
    1838             : #if CONFIG_HIGHBITDEPTH
    1839           0 :     if (cm->use_highbitdepth)
    1840           0 :       highbd_filter_selectively_horiz(
    1841           0 :           CONVERT_TO_SHORTPTR(dst->buf), dst->stride, mask_16x16_r, mask_8x8_r,
    1842           0 :           mask_4x4_r, mask_4x4_int_r, &cm->lf_info, &lfm->lfl_uv[r >> 1][0],
    1843           0 :           (int)cm->bit_depth);
    1844             :     else
    1845             : #endif  // CONFIG_HIGHBITDEPTH
    1846           0 :       filter_selectively_horiz(dst->buf, dst->stride, mask_16x16_r, mask_8x8_r,
    1847           0 :                                mask_4x4_r, mask_4x4_int_r, &cm->lf_info,
    1848           0 :                                &lfm->lfl_uv[r >> 1][0]);
    1849             : 
    1850           0 :     dst->buf += MI_SIZE * dst->stride;
    1851           0 :     mask_16x16 >>= MI_SIZE / 2;
    1852           0 :     mask_8x8 >>= MI_SIZE / 2;
    1853           0 :     mask_4x4 >>= MI_SIZE / 2;
    1854           0 :     mask_4x4_int >>= MI_SIZE / 2;
    1855             :   }
    1856             :   // restore the buf pointer in case there is additional filter pass.
    1857           0 :   dst->buf = dst0;
    1858           0 : }
    1859             : 
    1860             : #if CONFIG_PARALLEL_DEBLOCKING
    1861             : typedef enum EDGE_DIR { VERT_EDGE = 0, HORZ_EDGE = 1, NUM_EDGE_DIRS } EDGE_DIR;
    1862             : static const uint32_t av1_prediction_masks[NUM_EDGE_DIRS][BLOCK_SIZES] = {
    1863             :   // mask for vertical edges filtering
    1864             :   {
    1865             : #if CONFIG_CB4X4
    1866             :       2 - 1,   // BLOCK_2X2
    1867             :       2 - 1,   // BLOCK_2X4
    1868             :       4 - 1,   // BLOCK_4X2
    1869             : #endif         // CONFIG_CB4X4
    1870             :       4 - 1,   // BLOCK_4X4
    1871             :       4 - 1,   // BLOCK_4X8
    1872             :       8 - 1,   // BLOCK_8X4
    1873             :       8 - 1,   // BLOCK_8X8
    1874             :       8 - 1,   // BLOCK_8X16
    1875             :       16 - 1,  // BLOCK_16X8
    1876             :       16 - 1,  // BLOCK_16X16
    1877             :       16 - 1,  // BLOCK_16X32
    1878             :       32 - 1,  // BLOCK_32X16
    1879             :       32 - 1,  // BLOCK_32X32
    1880             :       32 - 1,  // BLOCK_32X64
    1881             :       64 - 1,  // BLOCK_64X32
    1882             :       64 - 1,  // BLOCK_64X64
    1883             : #if CONFIG_EXT_PARTITION
    1884             :       64 - 1,   // BLOCK_64X128
    1885             :       128 - 1,  // BLOCK_128X64
    1886             :       128 - 1   // BLOCK_128X128
    1887             : #endif          // CONFIG_EXT_PARTITION
    1888             :   },
    1889             :   // mask for horizontal edges filtering
    1890             :   {
    1891             : #if CONFIG_CB4X4
    1892             :       2 - 1,   // BLOCK_2X2
    1893             :       4 - 1,   // BLOCK_2X4
    1894             :       2 - 1,   // BLOCK_4X2
    1895             : #endif         // CONFIG_CB4X4
    1896             :       4 - 1,   // BLOCK_4X4
    1897             :       8 - 1,   // BLOCK_4X8
    1898             :       4 - 1,   // BLOCK_8X4
    1899             :       8 - 1,   // BLOCK_8X8
    1900             :       16 - 1,  // BLOCK_8X16
    1901             :       8 - 1,   // BLOCK_16X8
    1902             :       16 - 1,  // BLOCK_16X16
    1903             :       32 - 1,  // BLOCK_16X32
    1904             :       16 - 1,  // BLOCK_32X16
    1905             :       32 - 1,  // BLOCK_32X32
    1906             :       64 - 1,  // BLOCK_32X64
    1907             :       32 - 1,  // BLOCK_64X32
    1908             :       64 - 1,  // BLOCK_64X64
    1909             : #if CONFIG_EXT_PARTITION
    1910             :       128 - 1,  // BLOCK_64X128
    1911             :       64 - 1,   // BLOCK_128X64
    1912             :       128 - 1   // BLOCK_128X128
    1913             : #endif          // CONFIG_EXT_PARTITION
    1914             :   },
    1915             : };
    1916             : 
    1917             : static const uint32_t av1_transform_masks[NUM_EDGE_DIRS][TX_SIZES_ALL] = {
    1918             :   {
    1919             : #if CONFIG_CHROMA_2X2
    1920             :       2 - 1,  // TX_2X2
    1921             : #endif
    1922             :       4 - 1,   // TX_4X4
    1923             :       8 - 1,   // TX_8X8
    1924             :       16 - 1,  // TX_16X16
    1925             :       32 - 1,  // TX_32X32
    1926             : #if CONFIG_TX64X64
    1927             :       64 - 1,  // TX_64X64
    1928             : #endif         // CONFIG_TX64X64
    1929             :       4 - 1,   // TX_4X8
    1930             :       8 - 1,   // TX_8X4
    1931             :       8 - 1,   // TX_8X16
    1932             :       16 - 1,  // TX_16X8
    1933             :       16 - 1,  // TX_16X32
    1934             :       32 - 1,  // TX_32X16
    1935             :       4 - 1,   // TX_4X16
    1936             :       16 - 1,  // TX_16X4
    1937             :       8 - 1,   // TX_8X32
    1938             :       32 - 1   // TX_32X8
    1939             :   },
    1940             :   {
    1941             : #if CONFIG_CHROMA_2X2
    1942             :       2 - 1,  // TX_2X2
    1943             : #endif
    1944             :       4 - 1,   // TX_4X4
    1945             :       8 - 1,   // TX_8X8
    1946             :       16 - 1,  // TX_16X16
    1947             :       32 - 1,  // TX_32X32
    1948             : #if CONFIG_TX64X64
    1949             :       64 - 1,  // TX_64X64
    1950             : #endif         // CONFIG_TX64X64
    1951             :       8 - 1,   // TX_4X8
    1952             :       4 - 1,   // TX_8X4
    1953             :       16 - 1,  // TX_8X16
    1954             :       8 - 1,   // TX_16X8
    1955             :       32 - 1,  // TX_16X32
    1956             :       16 - 1,  // TX_32X16
    1957             :       16 - 1,  // TX_4X16
    1958             :       4 - 1,   // TX_16X4
    1959             :       32 - 1,  // TX_8X32
    1960             :       8 - 1    // TX_32X8
    1961             :   }
    1962             : };
    1963             : 
    1964             : static TX_SIZE av1_get_transform_size(const MODE_INFO *const pCurr,
    1965             :                                       const EDGE_DIR edgeDir,
    1966             :                                       const uint32_t scaleHorz,
    1967             :                                       const uint32_t scaleVert) {
    1968             :   const BLOCK_SIZE bs = pCurr->mbmi.sb_type;
    1969             :   TX_SIZE txSize;
    1970             :   // since in case of chrominance or non-square transorm need to convert
    1971             :   // transform size into transform size in particular direction.
    1972             :   txSize = uv_txsize_lookup[bs][pCurr->mbmi.tx_size][scaleHorz][scaleVert];
    1973             :   if (VERT_EDGE == edgeDir) {
    1974             :     txSize = txsize_horz_map[txSize];
    1975             :   } else {
    1976             :     txSize = txsize_vert_map[txSize];
    1977             :   }
    1978             :   return txSize;
    1979             : }
    1980             : 
    1981             : typedef struct AV1_DEBLOCKING_PARAMETERS {
    1982             :   // length of the filter applied to the outer edge
    1983             :   uint32_t filterLength;
    1984             :   // length of the filter applied to the inner edge
    1985             :   uint32_t filterLengthInternal;
    1986             :   // deblocking limits
    1987             :   const uint8_t *lim;
    1988             :   const uint8_t *mblim;
    1989             :   const uint8_t *hev_thr;
    1990             : } AV1_DEBLOCKING_PARAMETERS;
    1991             : 
    1992             : static void set_lpf_parameters(AV1_DEBLOCKING_PARAMETERS *const pParams,
    1993             :                                const MODE_INFO **const ppCurr,
    1994             :                                const ptrdiff_t modeStep,
    1995             :                                const AV1_COMMON *const cm,
    1996             :                                const EDGE_DIR edgeDir, const uint32_t x,
    1997             :                                const uint32_t y, const uint32_t width,
    1998             :                                const uint32_t height, const uint32_t scaleHorz,
    1999             :                                const uint32_t scaleVert) {
    2000             :   // reset to initial values
    2001             :   pParams->filterLength = 0;
    2002             :   pParams->filterLengthInternal = 0;
    2003             :   // no deblocking is required
    2004             :   if ((width <= x) || (height <= y)) {
    2005             :     return;
    2006             :   }
    2007             : #if CONFIG_EXT_PARTITION
    2008             :   // not sure if changes are required.
    2009             :   assert(0 && "Not yet updated");
    2010             : #endif  // CONFIG_EXT_PARTITION
    2011             : 
    2012             :   {
    2013             :     const TX_SIZE ts =
    2014             :         av1_get_transform_size(ppCurr[0], edgeDir, scaleHorz, scaleVert);
    2015             : #if CONFIG_EXT_DELTA_Q
    2016             :     const uint32_t currLevel =
    2017             :         get_filter_level(cm, &cm->lf_info, &ppCurr[0]->mbmi);
    2018             : #else
    2019             :     const uint32_t currLevel = get_filter_level(&cm->lf_info, &ppCurr[0]->mbmi);
    2020             : #endif  // CONFIG_EXT_DELTA_Q
    2021             : 
    2022             :     const int currSkipped =
    2023             :         ppCurr[0]->mbmi.skip && is_inter_block(&ppCurr[0]->mbmi);
    2024             :     const uint32_t coord = (VERT_EDGE == edgeDir) ? (x) : (y);
    2025             :     uint32_t level = currLevel;
    2026             :     // prepare outer edge parameters. deblock the edge if it's an edge of a TU
    2027             :     if (coord) {
    2028             : #if CONFIG_LOOPFILTERING_ACROSS_TILES
    2029             :       if (!av1_disable_loopfilter_on_tile_boundary(cm) ||
    2030             :           ((VERT_EDGE == edgeDir) &&
    2031             :            (0 == (ppCurr[0]->mbmi.boundary_info & TILE_LEFT_BOUNDARY))) ||
    2032             :           ((HORZ_EDGE == edgeDir) &&
    2033             :            (0 == (ppCurr[0]->mbmi.boundary_info & TILE_ABOVE_BOUNDARY))))
    2034             : #endif  // CONFIG_LOOPFILTERING_ACROSS_TILES
    2035             :       {
    2036             :         const int32_t tuEdge =
    2037             :             (coord & av1_transform_masks[edgeDir][ts]) ? (0) : (1);
    2038             :         if (tuEdge) {
    2039             :           const MODE_INFO *const pPrev = *(ppCurr - modeStep);
    2040             :           const TX_SIZE pvTs =
    2041             :               av1_get_transform_size(pPrev, edgeDir, scaleHorz, scaleVert);
    2042             : #if CONFIG_EXT_DELTA_Q
    2043             :           const uint32_t pvLvl =
    2044             :               get_filter_level(cm, &cm->lf_info, &pPrev->mbmi);
    2045             : #else
    2046             :           const uint32_t pvLvl = get_filter_level(&cm->lf_info, &pPrev->mbmi);
    2047             : #endif  // CONFIG_EXT_DELTA_Q
    2048             : 
    2049             :           const int pvSkip = pPrev->mbmi.skip && is_inter_block(&pPrev->mbmi);
    2050             :           const int32_t puEdge =
    2051             :               (coord &
    2052             :                av1_prediction_masks[edgeDir]
    2053             :                                    [ss_size_lookup[ppCurr[0]->mbmi.sb_type]
    2054             :                                                   [scaleHorz][scaleVert]])
    2055             :                   ? (0)
    2056             :                   : (1);
    2057             :           // if the current and the previous blocks are skipped,
    2058             :           // deblock the edge if the edge belongs to a PU's edge only.
    2059             :           if ((currLevel || pvLvl) && (!pvSkip || !currSkipped || puEdge)) {
    2060             : #if CONFIG_PARALLEL_DEBLOCKING_15TAP || PARALLEL_DEBLOCKING_15TAPLUMAONLY
    2061             :             const TX_SIZE minTs = AOMMIN(ts, pvTs);
    2062             :             if (TX_4X4 >= minTs) {
    2063             :               pParams->filterLength = 4;
    2064             :             } else if (TX_8X8 == minTs) {
    2065             :               pParams->filterLength = 8;
    2066             :             } else {
    2067             :               pParams->filterLength = 16;
    2068             : #if PARALLEL_DEBLOCKING_15TAPLUMAONLY
    2069             :               // No wide filtering for chroma plane
    2070             :               if (scaleHorz || scaleVert) {
    2071             :                 pParams->filterLength = 8;
    2072             :               }
    2073             : #endif
    2074             :             }
    2075             : #else
    2076             :             pParams->filterLength = (TX_4X4 >= AOMMIN(ts, pvTs)) ? (4) : (8);
    2077             : 
    2078             : #endif  // CONFIG_PARALLEL_DEBLOCKING_15TAP || PARALLEL_DEBLOCKING_15TAPLUMAONLY
    2079             : 
    2080             :             // update the level if the current block is skipped,
    2081             :             // but the previous one is not
    2082             :             level = (currLevel) ? (currLevel) : (pvLvl);
    2083             :           }
    2084             :         }
    2085             :       }
    2086             : 
    2087             : #if !CONFIG_CB4X4
    2088             :       // prepare internal edge parameters
    2089             :       if (currLevel && !currSkipped) {
    2090             :         pParams->filterLengthInternal = (TX_4X4 >= ts) ? (4) : (0);
    2091             :       }
    2092             : #endif
    2093             : 
    2094             :       // prepare common parameters
    2095             :       if (pParams->filterLength || pParams->filterLengthInternal) {
    2096             :         const loop_filter_thresh *const limits = cm->lf_info.lfthr + level;
    2097             :         pParams->lim = limits->lim;
    2098             :         pParams->mblim = limits->mblim;
    2099             :         pParams->hev_thr = limits->hev_thr;
    2100             :       }
    2101             :     }
    2102             :   }
    2103             : }
    2104             : 
    2105             : static void av1_filter_block_plane_vert(const AV1_COMMON *const cm,
    2106             :                                         const MACROBLOCKD_PLANE *const pPlane,
    2107             :                                         const MODE_INFO **ppModeInfo,
    2108             :                                         const ptrdiff_t modeStride,
    2109             :                                         const uint32_t cuX,
    2110             :                                         const uint32_t cuY) {
    2111             :   const int col_step = MI_SIZE >> MI_SIZE_LOG2;
    2112             :   const int row_step = MI_SIZE >> MI_SIZE_LOG2;
    2113             :   const uint32_t scaleHorz = pPlane->subsampling_x;
    2114             :   const uint32_t scaleVert = pPlane->subsampling_y;
    2115             :   const uint32_t width = pPlane->dst.width;
    2116             :   const uint32_t height = pPlane->dst.height;
    2117             :   uint8_t *const pDst = pPlane->dst.buf;
    2118             :   const int dstStride = pPlane->dst.stride;
    2119             :   for (int y = 0; y < (MAX_MIB_SIZE >> scaleVert); y += row_step) {
    2120             :     uint8_t *p = pDst + y * MI_SIZE * dstStride;
    2121             :     for (int x = 0; x < (MAX_MIB_SIZE >> scaleHorz); x += col_step) {
    2122             :       // inner loop always filter vertical edges in a MI block. If MI size
    2123             :       // is 8x8, it will filter the vertical edge aligned with a 8x8 block.
    2124             :       // If 4x4 trasnform is used, it will then filter the internal edge
    2125             :       //  aligned with a 4x4 block
    2126             :       const MODE_INFO **const pCurr =
    2127             :           ppModeInfo + (y << scaleVert) * modeStride + (x << scaleHorz);
    2128             :       AV1_DEBLOCKING_PARAMETERS params;
    2129             :       memset(&params, 0, sizeof(params));
    2130             :       set_lpf_parameters(&params, pCurr, ((ptrdiff_t)1 << scaleHorz), cm,
    2131             :                          VERT_EDGE, cuX + x * MI_SIZE, cuY + y * MI_SIZE, width,
    2132             :                          height, scaleHorz, scaleVert);
    2133             :       switch (params.filterLength) {
    2134             :         // apply 4-tap filtering
    2135             :         case 4:
    2136             : #if CONFIG_HIGHBITDEPTH
    2137             :           if (cm->use_highbitdepth)
    2138             :             aom_highbd_lpf_vertical_4_c(CONVERT_TO_SHORTPTR(p), dstStride,
    2139             :                                         params.mblim, params.lim,
    2140             :                                         params.hev_thr, cm->bit_depth);
    2141             :           else
    2142             : #endif  // CONFIG_HIGHBITDEPTH
    2143             :             aom_lpf_vertical_4_c(p, dstStride, params.mblim, params.lim,
    2144             :                                  params.hev_thr);
    2145             :           break;
    2146             :         // apply 8-tap filtering
    2147             :         case 8:
    2148             : #if CONFIG_HIGHBITDEPTH
    2149             :           if (cm->use_highbitdepth)
    2150             :             aom_highbd_lpf_vertical_8_c(CONVERT_TO_SHORTPTR(p), dstStride,
    2151             :                                         params.mblim, params.lim,
    2152             :                                         params.hev_thr, cm->bit_depth);
    2153             :           else
    2154             : #endif  // CONFIG_HIGHBITDEPTH
    2155             :             aom_lpf_vertical_8_c(p, dstStride, params.mblim, params.lim,
    2156             :                                  params.hev_thr);
    2157             :           break;
    2158             : #if CONFIG_PARALLEL_DEBLOCKING_15TAP || PARALLEL_DEBLOCKING_15TAPLUMAONLY
    2159             :         // apply 16-tap filtering
    2160             :         case 16:
    2161             : #if CONFIG_HIGHBITDEPTH
    2162             :           if (cm->use_highbitdepth)
    2163             :             aom_highbd_lpf_vertical_16_c(CONVERT_TO_SHORTPTR(p), dstStride,
    2164             :                                          params.mblim, params.lim,
    2165             :                                          params.hev_thr, cm->bit_depth);
    2166             :           else
    2167             : #endif  // CONFIG_HIGHBITDEPTH
    2168             :             aom_lpf_vertical_16_c(p, dstStride, params.mblim, params.lim,
    2169             :                                   params.hev_thr);
    2170             :           break;
    2171             : #endif  // CONFIG_PARALLEL_DEBLOCKING_15TAP || PARALLEL_DEBLOCKING_15TAPLUMAONLY
    2172             :         // no filtering
    2173             :         default: break;
    2174             :       }
    2175             :       // process the internal edge
    2176             :       if (params.filterLengthInternal) {
    2177             : #if CONFIG_HIGHBITDEPTH
    2178             :         if (cm->use_highbitdepth)
    2179             :           aom_highbd_lpf_vertical_4_c(CONVERT_TO_SHORTPTR(p + 4), dstStride,
    2180             :                                       params.mblim, params.lim, params.hev_thr,
    2181             :                                       cm->bit_depth);
    2182             :         else
    2183             : #endif  // CONFIG_HIGHBITDEPTH
    2184             :           aom_lpf_vertical_4_c(p + 4, dstStride, params.mblim, params.lim,
    2185             :                                params.hev_thr);
    2186             :       }
    2187             :       // advance the destination pointer
    2188             :       p += MI_SIZE;
    2189             :     }
    2190             :   }
    2191             : }
    2192             : 
    2193             : static void av1_filter_block_plane_horz(const AV1_COMMON *const cm,
    2194             :                                         const MACROBLOCKD_PLANE *const pPlane,
    2195             :                                         const MODE_INFO **ppModeInfo,
    2196             :                                         const ptrdiff_t modeStride,
    2197             :                                         const uint32_t cuX,
    2198             :                                         const uint32_t cuY) {
    2199             :   const int col_step = MI_SIZE >> MI_SIZE_LOG2;
    2200             :   const int row_step = MI_SIZE >> MI_SIZE_LOG2;
    2201             :   const uint32_t scaleHorz = pPlane->subsampling_x;
    2202             :   const uint32_t scaleVert = pPlane->subsampling_y;
    2203             :   const uint32_t width = pPlane->dst.width;
    2204             :   const uint32_t height = pPlane->dst.height;
    2205             :   uint8_t *const pDst = pPlane->dst.buf;
    2206             :   const int dstStride = pPlane->dst.stride;
    2207             :   for (int y = 0; y < (MAX_MIB_SIZE >> scaleVert); y += row_step) {
    2208             :     uint8_t *p = pDst + y * MI_SIZE * dstStride;
    2209             :     for (int x = 0; x < (MAX_MIB_SIZE >> scaleHorz); x += col_step) {
    2210             :       // inner loop always filter vertical edges in a MI block. If MI size
    2211             :       // is 8x8, it will first filter the vertical edge aligned with a 8x8
    2212             :       // block. If 4x4 trasnform is used, it will then filter the internal
    2213             :       // edge aligned with a 4x4 block
    2214             :       const MODE_INFO **const pCurr =
    2215             :           ppModeInfo + (y << scaleVert) * modeStride + (x << scaleHorz);
    2216             :       AV1_DEBLOCKING_PARAMETERS params;
    2217             :       memset(&params, 0, sizeof(params));
    2218             :       set_lpf_parameters(&params, pCurr, (modeStride << scaleVert), cm,
    2219             :                          HORZ_EDGE, cuX + x * MI_SIZE, cuY + y * MI_SIZE, width,
    2220             :                          height, scaleHorz, scaleVert);
    2221             :       switch (params.filterLength) {
    2222             :         // apply 4-tap filtering
    2223             :         case 4:
    2224             : #if CONFIG_HIGHBITDEPTH
    2225             :           if (cm->use_highbitdepth)
    2226             :             aom_highbd_lpf_horizontal_4_c(CONVERT_TO_SHORTPTR(p), dstStride,
    2227             :                                           params.mblim, params.lim,
    2228             :                                           params.hev_thr, cm->bit_depth);
    2229             :           else
    2230             : #endif  // CONFIG_HIGHBITDEPTH
    2231             :             aom_lpf_horizontal_4_c(p, dstStride, params.mblim, params.lim,
    2232             :                                    params.hev_thr);
    2233             :           break;
    2234             :         // apply 8-tap filtering
    2235             :         case 8:
    2236             : #if CONFIG_HIGHBITDEPTH
    2237             :           if (cm->use_highbitdepth)
    2238             :             aom_highbd_lpf_horizontal_8_c(CONVERT_TO_SHORTPTR(p), dstStride,
    2239             :                                           params.mblim, params.lim,
    2240             :                                           params.hev_thr, cm->bit_depth);
    2241             :           else
    2242             : #endif  // CONFIG_HIGHBITDEPTH
    2243             :             aom_lpf_horizontal_8_c(p, dstStride, params.mblim, params.lim,
    2244             :                                    params.hev_thr);
    2245             :           break;
    2246             : #if CONFIG_PARALLEL_DEBLOCKING_15TAP || PARALLEL_DEBLOCKING_15TAPLUMAONLY
    2247             :         // apply 16-tap filtering
    2248             :         case 16:
    2249             : #if CONFIG_HIGHBITDEPTH
    2250             :           if (cm->use_highbitdepth)
    2251             :             aom_highbd_lpf_horizontal_edge_16_c(
    2252             :                 CONVERT_TO_SHORTPTR(p), dstStride, params.mblim, params.lim,
    2253             :                 params.hev_thr, cm->bit_depth);
    2254             :           else
    2255             : #endif  // CONFIG_HIGHBITDEPTH
    2256             :             aom_lpf_horizontal_edge_16_c(p, dstStride, params.mblim, params.lim,
    2257             :                                          params.hev_thr);
    2258             :           break;
    2259             : #endif  // CONFIG_PARALLEL_DEBLOCKING_15TAP || PARALLEL_DEBLOCKING_15TAPLUMAONLY
    2260             :         // no filtering
    2261             :         default: break;
    2262             :       }
    2263             :       // process the internal edge
    2264             :       if (params.filterLengthInternal) {
    2265             : #if CONFIG_HIGHBITDEPTH
    2266             :         if (cm->use_highbitdepth)
    2267             :           aom_highbd_lpf_horizontal_4_c(CONVERT_TO_SHORTPTR(p + 4 * dstStride),
    2268             :                                         dstStride, params.mblim, params.lim,
    2269             :                                         params.hev_thr, cm->bit_depth);
    2270             :         else
    2271             : #endif  // CONFIG_HIGHBITDEPTH
    2272             :           aom_lpf_horizontal_4_c(p + 4 * dstStride, dstStride, params.mblim,
    2273             :                                  params.lim, params.hev_thr);
    2274             :       }
    2275             :       // advance the destination pointer
    2276             :       p += MI_SIZE;
    2277             :     }
    2278             :   }
    2279             : }
    2280             : #endif  // CONFIG_PARALLEL_DEBLOCKING
    2281             : 
    2282           0 : void av1_loop_filter_rows(YV12_BUFFER_CONFIG *frame_buffer, AV1_COMMON *cm,
    2283             :                           struct macroblockd_plane planes[MAX_MB_PLANE],
    2284             :                           int start, int stop, int y_only) {
    2285           0 :   const int num_planes = y_only ? 1 : MAX_MB_PLANE;
    2286             :   int mi_row, mi_col;
    2287             : 
    2288             : #if CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_EXT_PARTITION_TYPES || \
    2289             :     CONFIG_CB4X4
    2290             : 
    2291             : #if !CONFIG_PARALLEL_DEBLOCKING
    2292             : #if CONFIG_VAR_TX
    2293           0 :   for (int i = 0; i < MAX_MB_PLANE; ++i)
    2294           0 :     memset(cm->top_txfm_context[i], TX_32X32, cm->mi_cols << TX_UNIT_WIDE_LOG2);
    2295             : #endif  // CONFIG_VAR_TX
    2296           0 :   for (mi_row = start; mi_row < stop; mi_row += cm->mib_size) {
    2297           0 :     MODE_INFO **mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
    2298             : #if CONFIG_VAR_TX
    2299           0 :     for (int i = 0; i < MAX_MB_PLANE; ++i)
    2300           0 :       memset(cm->left_txfm_context[i], TX_32X32, MAX_MIB_SIZE
    2301           0 :                                                      << TX_UNIT_WIDE_LOG2);
    2302             : #endif  // CONFIG_VAR_TX
    2303           0 :     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += cm->mib_size) {
    2304             :       int plane;
    2305             : 
    2306           0 :       av1_setup_dst_planes(planes, cm->sb_size, frame_buffer, mi_row, mi_col);
    2307             : 
    2308           0 :       for (plane = 0; plane < num_planes; ++plane) {
    2309           0 :         av1_filter_block_plane_non420_ver(cm, &planes[plane], mi + mi_col,
    2310             :                                           mi_row, mi_col, plane);
    2311           0 :         av1_filter_block_plane_non420_hor(cm, &planes[plane], mi + mi_col,
    2312             :                                           mi_row, mi_col, plane);
    2313             :       }
    2314             :     }
    2315             :   }
    2316             : #else
    2317             : 
    2318             : #if CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_EXT_PARTITION_TYPES
    2319             :   assert(0 && "Not yet updated. ToDo as next steps");
    2320             : #endif  // CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_EXT_PARTITION_TYPES
    2321             : 
    2322             :   for (mi_row = start; mi_row < stop; mi_row += MAX_MIB_SIZE) {
    2323             :     MODE_INFO **mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
    2324             :     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MAX_MIB_SIZE) {
    2325             :       av1_setup_dst_planes(planes, cm->sb_size, frame_buffer, mi_row, mi_col);
    2326             :       // filter all vertical edges in every 64x64 super block
    2327             :       for (int planeIdx = 0; planeIdx < num_planes; planeIdx += 1) {
    2328             :         const int32_t scaleHorz = planes[planeIdx].subsampling_x;
    2329             :         const int32_t scaleVert = planes[planeIdx].subsampling_y;
    2330             :         av1_filter_block_plane_vert(
    2331             :             cm, planes + planeIdx, (const MODE_INFO **)(mi + mi_col),
    2332             :             cm->mi_stride, (mi_col * MI_SIZE) >> scaleHorz,
    2333             :             (mi_row * MI_SIZE) >> scaleVert);
    2334             :       }
    2335             :     }
    2336             :   }
    2337             :   for (mi_row = start; mi_row < stop; mi_row += MAX_MIB_SIZE) {
    2338             :     MODE_INFO **mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
    2339             :     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MAX_MIB_SIZE) {
    2340             :       av1_setup_dst_planes(planes, cm->sb_size, frame_buffer, mi_row, mi_col);
    2341             :       // filter all horizontal edges in every 64x64 super block
    2342             :       for (int planeIdx = 0; planeIdx < num_planes; planeIdx += 1) {
    2343             :         const int32_t scaleHorz = planes[planeIdx].subsampling_x;
    2344             :         const int32_t scaleVert = planes[planeIdx].subsampling_y;
    2345             :         av1_filter_block_plane_horz(
    2346             :             cm, planes + planeIdx, (const MODE_INFO **)(mi + mi_col),
    2347             :             cm->mi_stride, (mi_col * MI_SIZE) >> scaleHorz,
    2348             :             (mi_row * MI_SIZE) >> scaleVert);
    2349             :       }
    2350             :     }
    2351             :   }
    2352             : #endif  // CONFIG_PARALLEL_DEBLOCKING
    2353             : 
    2354             : #else  // CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_EXT_PARTITION_TYPES
    2355             : 
    2356             : #if CONFIG_PARALLEL_DEBLOCKING
    2357             :   for (mi_row = start; mi_row < stop; mi_row += MAX_MIB_SIZE) {
    2358             :     MODE_INFO **mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
    2359             :     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MAX_MIB_SIZE) {
    2360             :       av1_setup_dst_planes(planes, cm->sb_size, frame_buffer, mi_row, mi_col);
    2361             :       // filter all vertical edges in every 64x64 super block
    2362             :       for (int planeIdx = 0; planeIdx < num_planes; planeIdx += 1) {
    2363             :         const int32_t scaleHorz = planes[planeIdx].subsampling_x;
    2364             :         const int32_t scaleVert = planes[planeIdx].subsampling_y;
    2365             :         av1_filter_block_plane_vert(
    2366             :             cm, planes + planeIdx, (const MODE_INFO **)(mi + mi_col),
    2367             :             cm->mi_stride, (mi_col * MI_SIZE) >> scaleHorz,
    2368             :             (mi_row * MI_SIZE) >> scaleVert);
    2369             :       }
    2370             :     }
    2371             :   }
    2372             :   for (mi_row = start; mi_row < stop; mi_row += MAX_MIB_SIZE) {
    2373             :     MODE_INFO **mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
    2374             :     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MAX_MIB_SIZE) {
    2375             :       av1_setup_dst_planes(planes, cm->sb_size, frame_buffer, mi_row, mi_col);
    2376             :       // filter all horizontal edges in every 64x64 super block
    2377             :       for (int planeIdx = 0; planeIdx < num_planes; planeIdx += 1) {
    2378             :         const int32_t scaleHorz = planes[planeIdx].subsampling_x;
    2379             :         const int32_t scaleVert = planes[planeIdx].subsampling_y;
    2380             :         av1_filter_block_plane_horz(
    2381             :             cm, planes + planeIdx, (const MODE_INFO **)(mi + mi_col),
    2382             :             cm->mi_stride, (mi_col * MI_SIZE) >> scaleHorz,
    2383             :             (mi_row * MI_SIZE) >> scaleVert);
    2384             :       }
    2385             :     }
    2386             :   }
    2387             : #else   // CONFIG_PARALLEL_DEBLOCKING
    2388             :   enum lf_path path;
    2389             :   LOOP_FILTER_MASK lfm;
    2390             : 
    2391             :   if (y_only)
    2392             :     path = LF_PATH_444;
    2393             :   else if (planes[1].subsampling_y == 1 && planes[1].subsampling_x == 1)
    2394             :     path = LF_PATH_420;
    2395             :   else if (planes[1].subsampling_y == 0 && planes[1].subsampling_x == 0)
    2396             :     path = LF_PATH_444;
    2397             :   else
    2398             :     path = LF_PATH_SLOW;
    2399             : 
    2400             :   for (mi_row = start; mi_row < stop; mi_row += MAX_MIB_SIZE) {
    2401             :     MODE_INFO **mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
    2402             :     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MAX_MIB_SIZE) {
    2403             :       int plane;
    2404             : 
    2405             :       av1_setup_dst_planes(planes, cm->sb_size, frame_buffer, mi_row, mi_col);
    2406             : 
    2407             :       // TODO(JBB): Make setup_mask work for non 420.
    2408             :       av1_setup_mask(cm, mi_row, mi_col, mi + mi_col, cm->mi_stride, &lfm);
    2409             : 
    2410             :       av1_filter_block_plane_ss00_ver(cm, &planes[0], mi_row, &lfm);
    2411             :       av1_filter_block_plane_ss00_hor(cm, &planes[0], mi_row, &lfm);
    2412             :       for (plane = 1; plane < num_planes; ++plane) {
    2413             :         switch (path) {
    2414             :           case LF_PATH_420:
    2415             :             av1_filter_block_plane_ss11_ver(cm, &planes[plane], mi_row, &lfm);
    2416             :             av1_filter_block_plane_ss11_hor(cm, &planes[plane], mi_row, &lfm);
    2417             :             break;
    2418             :           case LF_PATH_444:
    2419             :             av1_filter_block_plane_ss00_ver(cm, &planes[plane], mi_row, &lfm);
    2420             :             av1_filter_block_plane_ss00_hor(cm, &planes[plane], mi_row, &lfm);
    2421             :             break;
    2422             :           case LF_PATH_SLOW:
    2423             :             av1_filter_block_plane_non420_ver(cm, &planes[plane], mi + mi_col,
    2424             :                                               mi_row, mi_col, plane);
    2425             :             av1_filter_block_plane_non420_hor(cm, &planes[plane], mi + mi_col,
    2426             :                                               mi_row, mi_col, plane);
    2427             : 
    2428             :             break;
    2429             :         }
    2430             :       }
    2431             :     }
    2432             :   }
    2433             : #endif  // CONFIG_PARALLEL_DEBLOCKING
    2434             : #endif  // CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_EXT_PARTITION_TYPES
    2435           0 : }
    2436             : 
    2437           0 : void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
    2438             :                            MACROBLOCKD *xd, int frame_filter_level, int y_only,
    2439             :                            int partial_frame) {
    2440             :   int start_mi_row, end_mi_row, mi_rows_to_filter;
    2441             : #if CONFIG_EXT_DELTA_Q
    2442           0 :   int orig_filter_level = cm->lf.filter_level;
    2443             : #endif
    2444           0 :   if (!frame_filter_level) return;
    2445           0 :   start_mi_row = 0;
    2446           0 :   mi_rows_to_filter = cm->mi_rows;
    2447           0 :   if (partial_frame && cm->mi_rows > 8) {
    2448           0 :     start_mi_row = cm->mi_rows >> 1;
    2449           0 :     start_mi_row &= 0xfffffff8;
    2450           0 :     mi_rows_to_filter = AOMMAX(cm->mi_rows / 8, 8);
    2451             :   }
    2452           0 :   end_mi_row = start_mi_row + mi_rows_to_filter;
    2453           0 :   av1_loop_filter_frame_init(cm, frame_filter_level);
    2454             : #if CONFIG_EXT_DELTA_Q
    2455           0 :   cm->lf.filter_level = frame_filter_level;
    2456             : #endif
    2457           0 :   av1_loop_filter_rows(frame, cm, xd->plane, start_mi_row, end_mi_row, y_only);
    2458             : #if CONFIG_EXT_DELTA_Q
    2459           0 :   cm->lf.filter_level = orig_filter_level;
    2460             : #endif
    2461             : }
    2462             : 
    2463           0 : void av1_loop_filter_data_reset(
    2464             :     LFWorkerData *lf_data, YV12_BUFFER_CONFIG *frame_buffer,
    2465             :     struct AV1Common *cm, const struct macroblockd_plane planes[MAX_MB_PLANE]) {
    2466           0 :   lf_data->frame_buffer = frame_buffer;
    2467           0 :   lf_data->cm = cm;
    2468           0 :   lf_data->start = 0;
    2469           0 :   lf_data->stop = 0;
    2470           0 :   lf_data->y_only = 0;
    2471           0 :   memcpy(lf_data->planes, planes, sizeof(lf_data->planes));
    2472           0 : }
    2473             : 
    2474           0 : int av1_loop_filter_worker(LFWorkerData *const lf_data, void *unused) {
    2475             :   (void)unused;
    2476           0 :   av1_loop_filter_rows(lf_data->frame_buffer, lf_data->cm, lf_data->planes,
    2477             :                        lf_data->start, lf_data->stop, lf_data->y_only);
    2478           0 :   return 1;
    2479             : }

Generated by: LCOV version 1.13