| /* |
| * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
| * |
| * This source code is subject to the terms of the BSD 2 Clause License and |
| * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| * was not distributed with this source code in the LICENSE file, you can |
| * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| * Media Patent License 1.0 was not distributed with this source code in the |
| * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| */ |
| |
| #ifndef AOM_AV1_COMMON_AV1_LOOPFILTER_H_ |
| #define AOM_AV1_COMMON_AV1_LOOPFILTER_H_ |
| |
| #include "config/aom_config.h" |
| |
| #include "aom_ports/mem.h" |
| #include "av1/common/blockd.h" |
| #include "av1/common/seg_common.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #define MAX_LOOP_FILTER 63 |
| #define MAX_SHARPNESS 7 |
| |
| #define SIMD_WIDTH 16 |
| |
| enum lf_path { |
| LF_PATH_420, |
| LF_PATH_444, |
| LF_PATH_SLOW, |
| }; |
| |
| typedef struct { |
| uint64_t bits[4]; |
| } FilterMask; |
| |
| #if LOOP_FILTER_BITMASK |
| // This structure holds bit masks for all 4x4 blocks in a 64x64 region. |
| // Each 1 bit represents a position in which we want to apply the loop filter. |
| // For Y plane, 4x4 in 64x64 requires 16x16 = 256 bit, therefore we use 4 |
| // uint64_t; For U, V plane, for 420 format, plane size is 32x32, thus we use |
| // a uint64_t to represent bitmask. |
| // Left_ entries refer to whether we apply a filter on the border to the |
| // left of the block. Above_ entries refer to whether or not to apply a |
| // filter on the above border. |
| // Since each transform is accompanied by a potentially different type of |
| // loop filter there is a different entry in the array for each transform size. |
| typedef struct { |
| FilterMask left_y[TX_SIZES]; |
| FilterMask above_y[TX_SIZES]; |
| FilterMask left_u[TX_SIZES]; |
| FilterMask above_u[TX_SIZES]; |
| FilterMask left_v[TX_SIZES]; |
| FilterMask above_v[TX_SIZES]; |
| |
| // Y plane vertical edge and horizontal edge filter level |
| uint8_t lfl_y_hor[MI_SIZE_64X64][MI_SIZE_64X64]; |
| uint8_t lfl_y_ver[MI_SIZE_64X64][MI_SIZE_64X64]; |
| |
| // U plane filter level |
| uint8_t lfl_u_ver[MI_SIZE_64X64][MI_SIZE_64X64]; |
| uint8_t lfl_u_hor[MI_SIZE_64X64][MI_SIZE_64X64]; |
| |
| // V plane filter level |
| uint8_t lfl_v_ver[MI_SIZE_64X64][MI_SIZE_64X64]; |
| uint8_t lfl_v_hor[MI_SIZE_64X64][MI_SIZE_64X64]; |
| |
| // other info |
| FilterMask skip; |
| FilterMask is_vert_border; |
| FilterMask is_horz_border; |
| // Y or UV planes, 5 tx sizes: 4x4, 8x8, 16x16, 32x32, 64x64 |
| FilterMask tx_size_ver[2][5]; |
| FilterMask tx_size_hor[2][5]; |
| } LoopFilterMask; |
| #endif // LOOP_FILTER_BITMASK |
| |
| struct loopfilter { |
| int filter_level[2]; |
| int filter_level_u; |
| int filter_level_v; |
| |
| int sharpness_level; |
| |
| uint8_t mode_ref_delta_enabled; |
| uint8_t mode_ref_delta_update; |
| |
| // 0 = Intra, Last, Last2+Last3, |
| // GF, BRF, ARF2, ARF |
| int8_t ref_deltas[REF_FRAMES]; |
| |
| // 0 = ZERO_MV, MV |
| int8_t mode_deltas[MAX_MODE_LF_DELTAS]; |
| |
| int combine_vert_horz_lf; |
| |
| #if LOOP_FILTER_BITMASK |
| LoopFilterMask *lfm; |
| size_t lfm_num; |
| int lfm_stride; |
| #endif // LOOP_FILTER_BITMASK |
| }; |
| |
| // Need to align this structure so when it is declared and |
| // passed it can be loaded into vector registers. |
| typedef struct { |
| DECLARE_ALIGNED(SIMD_WIDTH, uint8_t, mblim[SIMD_WIDTH]); |
| DECLARE_ALIGNED(SIMD_WIDTH, uint8_t, lim[SIMD_WIDTH]); |
| DECLARE_ALIGNED(SIMD_WIDTH, uint8_t, hev_thr[SIMD_WIDTH]); |
| } loop_filter_thresh; |
| |
| typedef struct { |
| loop_filter_thresh lfthr[MAX_LOOP_FILTER + 1]; |
| uint8_t lvl[MAX_MB_PLANE][MAX_SEGMENTS][2][REF_FRAMES][MAX_MODE_LF_DELTAS]; |
| } loop_filter_info_n; |
| |
| /* assorted loopfilter functions which get used elsewhere */ |
| struct AV1Common; |
| struct macroblockd; |
| struct AV1LfSyncData; |
| |
| void av1_loop_filter_init(struct AV1Common *cm); |
| |
| void av1_loop_filter_frame_init(struct AV1Common *cm, int plane_start, |
| int plane_end); |
| |
| #if LOOP_FILTER_BITMASK |
| void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, struct AV1Common *cm, |
| struct macroblockd *mbd, int is_decoding, |
| int plane_start, int plane_end, int partial_frame); |
| #else |
| void av1_loop_filter_frame(YV12_BUFFER_CONFIG *frame, struct AV1Common *cm, |
| struct macroblockd *mbd, int plane_start, |
| int plane_end, int partial_frame); |
| #endif |
| |
| void av1_filter_block_plane_vert(const struct AV1Common *const cm, |
| const MACROBLOCKD *const xd, const int plane, |
| const MACROBLOCKD_PLANE *const plane_ptr, |
| const uint32_t mi_row, const uint32_t mi_col); |
| |
| void av1_filter_block_plane_horz(const struct AV1Common *const cm, |
| const MACROBLOCKD *const xd, const int plane, |
| const MACROBLOCKD_PLANE *const plane_ptr, |
| const uint32_t mi_row, const uint32_t mi_col); |
| |
| typedef struct LoopFilterWorkerData { |
| YV12_BUFFER_CONFIG *frame_buffer; |
| struct AV1Common *cm; |
| struct macroblockd_plane planes[MAX_MB_PLANE]; |
| // TODO(Ranjit): When the filter functions are modified to use xd->lossless |
| // add lossless as a member here. |
| MACROBLOCKD *xd; |
| } LFWorkerData; |
| |
| uint8_t get_filter_level(const struct AV1Common *cm, |
| const loop_filter_info_n *lfi_n, const int dir_idx, |
| int plane, const MB_MODE_INFO *mbmi); |
| #if LOOP_FILTER_BITMASK |
| void av1_setup_bitmask(struct AV1Common *const cm, int mi_row, int mi_col, |
| int plane, int subsampling_x, int subsampling_y, |
| int row_end, int col_end); |
| |
| void av1_filter_block_plane_ver(struct AV1Common *const cm, |
| struct macroblockd_plane *const plane_ptr, |
| int pl, int mi_row, int mi_col); |
| |
| void av1_filter_block_plane_hor(struct AV1Common *const cm, |
| struct macroblockd_plane *const plane, int pl, |
| int mi_row, int mi_col); |
| LoopFilterMask *get_loop_filter_mask(const struct AV1Common *const cm, |
| int mi_row, int mi_col); |
| int get_index_shift(int mi_col, int mi_row, int *index); |
| |
| void av1_build_bitmask_vert_info( |
| struct AV1Common *const cm, const struct macroblockd_plane *const plane_ptr, |
| int plane); |
| |
| void av1_build_bitmask_horz_info( |
| struct AV1Common *const cm, const struct macroblockd_plane *const plane_ptr, |
| int plane); |
| |
| void av1_filter_block_plane_bitmask_vert( |
| struct AV1Common *const cm, struct macroblockd_plane *const plane_ptr, |
| int pl, int mi_row, int mi_col); |
| |
| void av1_filter_block_plane_bitmask_horz( |
| struct AV1Common *const cm, struct macroblockd_plane *const plane_ptr, |
| int pl, int mi_row, int mi_col); |
| |
| #endif // LOOP_FILTER_BITMASK |
| |
| extern const int mask_id_table_tx_4x4[BLOCK_SIZES_ALL]; |
| |
| extern const int mask_id_table_tx_8x8[BLOCK_SIZES_ALL]; |
| |
| extern const int mask_id_table_tx_16x16[BLOCK_SIZES_ALL]; |
| |
| extern const int mask_id_table_tx_32x32[BLOCK_SIZES_ALL]; |
| |
| // corresponds to entry id in table left_mask_univariant_reordered, |
| // of block size mxn and TX_mxn. |
| extern const int mask_id_table_vert_border[BLOCK_SIZES_ALL]; |
| |
| extern const FilterMask left_mask_univariant_reordered[67]; |
| |
| extern const FilterMask above_mask_univariant_reordered[67]; |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif |
| |
| #endif // AOM_AV1_COMMON_AV1_LOOPFILTER_H_ |