1 /* 2 * Copyright 2019 The libgav1 Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LIBGAV1_SRC_POST_FILTER_H_ 18 #define LIBGAV1_SRC_POST_FILTER_H_ 19 20 #include <algorithm> 21 #include <array> 22 #include <atomic> 23 #include <cstddef> 24 #include <cstdint> 25 #include <cstring> 26 #include <type_traits> 27 28 #include "src/dsp/common.h" 29 #include "src/dsp/dsp.h" 30 #include "src/frame_scratch_buffer.h" 31 #include "src/loop_restoration_info.h" 32 #include "src/obu_parser.h" 33 #include "src/utils/array_2d.h" 34 #include "src/utils/block_parameters_holder.h" 35 #include "src/utils/common.h" 36 #include "src/utils/constants.h" 37 #include "src/utils/memory.h" 38 #include "src/utils/threadpool.h" 39 #include "src/yuv_buffer.h" 40 41 namespace libgav1 { 42 43 // This class applies in-loop filtering for each frame after it is 44 // reconstructed. The in-loop filtering contains all post processing filtering 45 // for the reconstructed frame, including deblock filter, CDEF, superres, 46 // and loop restoration. 47 // Historically, for example in libaom, loop filter refers to deblock filter. 48 // To avoid name conflicts, we call this class PostFilter (post processing). 49 // In-loop post filtering order is: 50 // deblock --> CDEF --> super resolution--> loop restoration. 51 // When CDEF and super resolution is not used, we can combine deblock 52 // and restoration together to only filter frame buffer once. 53 class PostFilter { 54 public: 55 // This class does not take ownership of the masks/restoration_info, but it 56 // may change their values. 57 // 58 // The overall flow of data in this class (for both single and multi-threaded 59 // cases) is as follows: 60 // -> Input: |frame_buffer_|. 61 // -> Initialize |source_buffer_|, |cdef_buffer_| and 62 // |loop_restoration_buffer_|. 63 // -> Deblocking: 64 // * Input: |source_buffer_| 65 // * Output: |source_buffer_| 66 // -> CDEF: 67 // * Input: |source_buffer_| 68 // * Output: |cdef_buffer_| 69 // -> SuperRes: 70 // * Input: |cdef_buffer_| 71 // * Output: |cdef_buffer_| 72 // -> Loop Restoration: 73 // * Input: |cdef_buffer_| 74 // * Output: |loop_restoration_buffer_|. 75 // -> Now |frame_buffer_| contains the filtered frame. 76 PostFilter(const ObuFrameHeader& frame_header, 77 const ObuSequenceHeader& sequence_header, 78 FrameScratchBuffer* frame_scratch_buffer, YuvBuffer* frame_buffer, 79 const dsp::Dsp* dsp, int do_post_filter_mask); 80 81 // non copyable/movable. 82 PostFilter(const PostFilter&) = delete; 83 PostFilter& operator=(const PostFilter&) = delete; 84 PostFilter(PostFilter&&) = delete; 85 PostFilter& operator=(PostFilter&&) = delete; 86 87 // The overall function that applies all post processing filtering with 88 // multiple threads. 89 // * The filtering order is: 90 // deblock --> CDEF --> super resolution--> loop restoration. 91 // * The output of each filter is the input for the following filter. A 92 // special case is that loop restoration needs a few rows of the deblocked 93 // frame and the entire cdef filtered frame: 94 // deblock --> CDEF --> super resolution --> loop restoration. 95 // | ^ 96 // | | 97 // -----------> super resolution ----- 98 // * Any of these filters could be present or absent. 99 // * |frame_buffer_| points to the decoded frame buffer. When 100 // ApplyFilteringThreaded() is called, |frame_buffer_| is modified by each 101 // of the filters as described below. 102 // Filter behavior (multi-threaded): 103 // * Deblock: In-place filtering. The output is written to |source_buffer_|. 104 // If cdef and loop restoration are both on, then 4 rows (as 105 // specified by |kDeblockedRowsForLoopRestoration|) in every 64x64 106 // block is copied into |deblock_buffer_|. 107 // * Cdef: Filtering output is written into |threaded_window_buffer_| and then 108 // copied into the |cdef_buffer_| (which is just |source_buffer_| with 109 // a shift to the top-left). 110 // * SuperRes: Near in-place filtering (with an additional line buffer for 111 // each row). The output is written to |cdef_buffer_|. 112 // * Restoration: Uses the |cdef_buffer_| and |deblock_buffer_| as the input 113 // and the output is written into the 114 // |threaded_window_buffer_|. It is then copied to the 115 // |loop_restoration_buffer_| (which is just |cdef_buffer_| 116 // with a shift to the top-left). 117 void ApplyFilteringThreaded(); 118 119 // Does the overall post processing filter for one superblock row starting at 120 // |row4x4| with height 4*|sb4x4|. If |do_deblock| is false, deblocking filter 121 // will not be applied. 122 // 123 // Filter behavior (single-threaded): 124 // * Deblock: In-place filtering. The output is written to |source_buffer_|. 125 // If cdef and loop restoration are both on, then 4 rows (as 126 // specified by |kDeblockedRowsForLoopRestoration|) in every 64x64 127 // block is copied into |deblock_buffer_|. 128 // * Cdef: In-place filtering. The output is written into |cdef_buffer_| 129 // (which is just |source_buffer_| with a shift to the top-left). 130 // * SuperRes: Near in-place filtering (with an additional line buffer for 131 // each row). The output is written to |cdef_buffer_|. 132 // * Restoration: Near in-place filtering. Uses a local block of size 64x64. 133 // Uses the |cdef_buffer_| and |deblock_buffer_| as the input 134 // and the output is written into |loop_restoration_buffer_| 135 // (which is just |source_buffer_| with a shift to the 136 // top-left). 137 // Returns the index of the last row whose post processing is complete and can 138 // be used for referencing. 139 int ApplyFilteringForOneSuperBlockRow(int row4x4, int sb4x4, bool is_last_row, 140 bool do_deblock); 141 142 // Apply deblocking filter in one direction (specified by |loop_filter_type|) 143 // for the superblock row starting at |row4x4_start| for columns starting from 144 // |column4x4_start| in increments of 16 (or 8 for chroma with subsampling) 145 // until the smallest multiple of 16 that is >= |column4x4_end| or until 146 // |frame_header_.columns4x4|, whichever is lower. This function must be 147 // called only if |DoDeblock()| returns true. 148 void ApplyDeblockFilter(LoopFilterType loop_filter_type, int row4x4_start, 149 int column4x4_start, int column4x4_end, int sb4x4); 150 DoCdef(const ObuFrameHeader & frame_header,int do_post_filter_mask)151 static bool DoCdef(const ObuFrameHeader& frame_header, 152 int do_post_filter_mask) { 153 return (frame_header.cdef.bits > 0 || 154 frame_header.cdef.y_primary_strength[0] > 0 || 155 frame_header.cdef.y_secondary_strength[0] > 0 || 156 frame_header.cdef.uv_primary_strength[0] > 0 || 157 frame_header.cdef.uv_secondary_strength[0] > 0) && 158 (do_post_filter_mask & 0x02) != 0; 159 } DoCdef()160 bool DoCdef() const { return DoCdef(frame_header_, do_post_filter_mask_); } 161 // If filter levels for Y plane (0 for vertical, 1 for horizontal), 162 // are all zero, deblock filter will not be applied. DoDeblock(const ObuFrameHeader & frame_header,uint8_t do_post_filter_mask)163 static bool DoDeblock(const ObuFrameHeader& frame_header, 164 uint8_t do_post_filter_mask) { 165 return (frame_header.loop_filter.level[0] > 0 || 166 frame_header.loop_filter.level[1] > 0) && 167 (do_post_filter_mask & 0x01) != 0; 168 } DoDeblock()169 bool DoDeblock() const { 170 return DoDeblock(frame_header_, do_post_filter_mask_); 171 } 172 173 // This function takes the cdef filtered buffer and the deblocked buffer to 174 // prepare a block as input for loop restoration. 175 // In striped loop restoration: 176 // The filtering needs to fetch the area of size (width + 6) x (height + 4), 177 // in which (width + 6) x height area is from upscaled frame 178 // (superres_buffer). Top 2 rows and bottom 2 rows are from deblocked frame 179 // (deblock_buffer). Special cases are: (1). when it is the top border, the 180 // top 2 rows are from cdef filtered frame. (2). when it is the bottom border, 181 // the bottom 2 rows are from cdef filtered frame. This function is called 182 // only when cdef is applied for this frame. 183 template <typename Pixel> 184 static void PrepareLoopRestorationBlock(const Pixel* src_buffer, 185 ptrdiff_t src_stride, 186 const Pixel* deblock_buffer, 187 ptrdiff_t deblock_stride, Pixel* dst, 188 ptrdiff_t dst_stride, int width, 189 int height, bool frame_top_border, 190 bool frame_bottom_border); 191 GetZeroDeltaDeblockFilterLevel(int segment_id,int level_index,ReferenceFrameType type,int mode_id)192 uint8_t GetZeroDeltaDeblockFilterLevel(int segment_id, int level_index, 193 ReferenceFrameType type, 194 int mode_id) const { 195 return deblock_filter_levels_[segment_id][level_index][type][mode_id]; 196 } 197 // Computes the deblock filter levels using |delta_lf| and stores them in 198 // |deblock_filter_levels|. 199 void ComputeDeblockFilterLevels( 200 const int8_t delta_lf[kFrameLfCount], 201 uint8_t deblock_filter_levels[kMaxSegments][kFrameLfCount] 202 [kNumReferenceFrameTypes][2]) const; 203 // Returns true if loop restoration will be performed for the given parameters 204 // and mask. DoRestoration(const LoopRestoration & loop_restoration,uint8_t do_post_filter_mask,int num_planes)205 static bool DoRestoration(const LoopRestoration& loop_restoration, 206 uint8_t do_post_filter_mask, int num_planes) { 207 if (num_planes == kMaxPlanesMonochrome) { 208 return loop_restoration.type[kPlaneY] != kLoopRestorationTypeNone && 209 (do_post_filter_mask & 0x08) != 0; 210 } 211 return (loop_restoration.type[kPlaneY] != kLoopRestorationTypeNone || 212 loop_restoration.type[kPlaneU] != kLoopRestorationTypeNone || 213 loop_restoration.type[kPlaneV] != kLoopRestorationTypeNone) && 214 (do_post_filter_mask & 0x08) != 0; 215 } DoRestoration()216 bool DoRestoration() const { 217 return DoRestoration(loop_restoration_, do_post_filter_mask_, planes_); 218 } 219 220 // Returns a pointer to the unfiltered buffer. This is used by the Tile class 221 // to determine where to write the output of the tile decoding process taking 222 // in-place filtering offsets into consideration. GetUnfilteredBuffer(int plane)223 uint8_t* GetUnfilteredBuffer(int plane) { return source_buffer_[plane]; } frame_buffer()224 const YuvBuffer& frame_buffer() const { return frame_buffer_; } 225 226 // Returns true if SuperRes will be performed for the given frame header and 227 // mask. DoSuperRes(const ObuFrameHeader & frame_header,uint8_t do_post_filter_mask)228 static bool DoSuperRes(const ObuFrameHeader& frame_header, 229 uint8_t do_post_filter_mask) { 230 return frame_header.width != frame_header.upscaled_width && 231 (do_post_filter_mask & 0x04) != 0; 232 } DoSuperRes()233 bool DoSuperRes() const { 234 return DoSuperRes(frame_header_, do_post_filter_mask_); 235 } restoration_info()236 LoopRestorationInfo* restoration_info() const { return restoration_info_; } GetBufferOffset(uint8_t * base_buffer,int stride,Plane plane,int row4x4,int column4x4)237 uint8_t* GetBufferOffset(uint8_t* base_buffer, int stride, Plane plane, 238 int row4x4, int column4x4) const { 239 return base_buffer + 240 RowOrColumn4x4ToPixel(row4x4, plane, subsampling_y_[plane]) * 241 stride + 242 RowOrColumn4x4ToPixel(column4x4, plane, subsampling_x_[plane]) * 243 pixel_size_; 244 } GetSourceBuffer(Plane plane,int row4x4,int column4x4)245 uint8_t* GetSourceBuffer(Plane plane, int row4x4, int column4x4) const { 246 return GetBufferOffset(source_buffer_[plane], frame_buffer_.stride(plane), 247 plane, row4x4, column4x4); 248 } 249 GetWindowBufferWidth(const ThreadPool * const thread_pool,const ObuFrameHeader & frame_header)250 static int GetWindowBufferWidth(const ThreadPool* const thread_pool, 251 const ObuFrameHeader& frame_header) { 252 return (thread_pool == nullptr) ? 0 253 : Align(frame_header.upscaled_width, 64); 254 } 255 256 // For multi-threaded cdef and loop restoration, window height is the minimum 257 // of the following two quantities: 258 // 1) thread_count * 64 259 // 2) frame_height rounded up to the nearest power of 64 260 // Where 64 is the block size for cdef and loop restoration. GetWindowBufferHeight(const ThreadPool * const thread_pool,const ObuFrameHeader & frame_header)261 static int GetWindowBufferHeight(const ThreadPool* const thread_pool, 262 const ObuFrameHeader& frame_header) { 263 if (thread_pool == nullptr) return 0; 264 const int thread_count = 1 + thread_pool->num_threads(); 265 const int window_height = MultiplyBy64(thread_count); 266 const int adjusted_frame_height = Align(frame_header.height, 64); 267 return std::min(adjusted_frame_height, window_height); 268 } 269 270 template <typename Pixel> 271 static void ExtendFrame(Pixel* frame_start, int width, int height, 272 ptrdiff_t stride, int left, int right, int top, 273 int bottom); 274 275 private: 276 // The type of the HorizontalDeblockFilter and VerticalDeblockFilter member 277 // functions. 278 using DeblockFilter = void (PostFilter::*)(int row4x4_start, 279 int column4x4_start); 280 // The lookup table for picking the deblock filter, according to deblock 281 // filter type. 282 const DeblockFilter deblock_filter_func_[2] = { 283 &PostFilter::VerticalDeblockFilter, &PostFilter::HorizontalDeblockFilter}; 284 285 // Functions common to all post filters. 286 287 // Extends the frame by setting the border pixel values to the one from its 288 // closest frame boundary. 289 void ExtendFrameBoundary(uint8_t* frame_start, int width, int height, 290 ptrdiff_t stride, int left, int right, int top, 291 int bottom) const; 292 // Extend frame boundary for referencing if the frame will be saved as a 293 // reference frame. 294 void ExtendBordersForReferenceFrame(); 295 // Copies the deblocked pixels needed for loop restoration. 296 void CopyDeblockedPixels(Plane plane, int row4x4); 297 // Copies the border for one superblock row. If |for_loop_restoration| is 298 // true, then it assumes that the border extension is being performed for the 299 // input of the loop restoration process. If |for_loop_restoration| is false, 300 // then it assumes that the border extension is being performed for using the 301 // current frame as a reference frame. In this case, |progress_row_| is also 302 // updated. 303 void CopyBordersForOneSuperBlockRow(int row4x4, int sb4x4, 304 bool for_loop_restoration); 305 // Sets up the |deblock_buffer_| for loop restoration. 306 void SetupDeblockBuffer(int row4x4_start, int sb4x4); 307 // Returns true if we can perform border extension in loop (i.e.) without 308 // waiting until the entire frame is decoded. If intra_block_copy is true, we 309 // do in-loop border extension only if the upscaled_width is the same as 4 * 310 // columns4x4. Otherwise, we cannot do in loop border extension since those 311 // pixels may be used by intra block copy. DoBorderExtensionInLoop()312 bool DoBorderExtensionInLoop() const { 313 return !frame_header_.allow_intrabc || 314 frame_header_.upscaled_width == 315 MultiplyBy4(frame_header_.columns4x4); 316 } 317 template <typename Pixel> CopyPlane(const Pixel * src,ptrdiff_t src_stride,int width,int height,Pixel * dst,ptrdiff_t dst_stride)318 void CopyPlane(const Pixel* src, ptrdiff_t src_stride, int width, int height, 319 Pixel* dst, ptrdiff_t dst_stride) { 320 for (int y = 0; y < height; ++y) { 321 memcpy(dst, src, width * sizeof(Pixel)); 322 src += src_stride; 323 dst += dst_stride; 324 } 325 } 326 327 // Functions for the Deblocking filter. 328 GetIndex(int row4x4)329 static int GetIndex(int row4x4) { return DivideBy4(row4x4); } GetShift(int row4x4,int column4x4)330 static int GetShift(int row4x4, int column4x4) { 331 return ((row4x4 & 3) << 4) | column4x4; 332 } GetDeblockUnitId(int row_unit,int column_unit)333 int GetDeblockUnitId(int row_unit, int column_unit) const { 334 return row_unit * num_64x64_blocks_per_row_ + column_unit; 335 } 336 bool GetHorizontalDeblockFilterEdgeInfo(int row4x4, int column4x4, 337 uint8_t* level, int* step, 338 int* filter_length) const; 339 void GetHorizontalDeblockFilterEdgeInfoUV(int row4x4, int column4x4, 340 uint8_t* level_u, uint8_t* level_v, 341 int* step, 342 int* filter_length) const; 343 bool GetVerticalDeblockFilterEdgeInfo(int row4x4, int column4x4, 344 BlockParameters* const* bp_ptr, 345 uint8_t* level, int* step, 346 int* filter_length) const; 347 void GetVerticalDeblockFilterEdgeInfoUV(int column4x4, 348 BlockParameters* const* bp_ptr, 349 uint8_t* level_u, uint8_t* level_v, 350 int* step, int* filter_length) const; 351 void HorizontalDeblockFilter(int row4x4_start, int column4x4_start); 352 void VerticalDeblockFilter(int row4x4_start, int column4x4_start); 353 // HorizontalDeblockFilter and VerticalDeblockFilter must have the correct 354 // signature. 355 static_assert(std::is_same<decltype(&PostFilter::HorizontalDeblockFilter), 356 DeblockFilter>::value, 357 ""); 358 static_assert(std::is_same<decltype(&PostFilter::VerticalDeblockFilter), 359 DeblockFilter>::value, 360 ""); 361 // Applies deblock filtering for the superblock row starting at |row4x4| with 362 // a height of 4*|sb4x4|. 363 void ApplyDeblockFilterForOneSuperBlockRow(int row4x4, int sb4x4); 364 void DeblockFilterWorker(int jobs_per_plane, const Plane* planes, 365 int num_planes, std::atomic<int>* job_counter, 366 DeblockFilter deblock_filter); 367 void ApplyDeblockFilterThreaded(); 368 369 // Functions for the cdef filter. 370 371 uint8_t* GetCdefBufferAndStride(int start_x, int start_y, int plane, 372 int window_buffer_plane_size, 373 int* cdef_stride) const; 374 // This function prepares the input source block for cdef filtering. The input 375 // source block contains a 12x12 block, with the inner 8x8 as the desired 376 // filter region. It pads the block if the 12x12 block includes out of frame 377 // pixels with a large value. This achieves the required behavior defined in 378 // section 5.11.52 of the spec. 379 template <typename Pixel> 380 void PrepareCdefBlock(int block_width4x4, int block_height4x4, int row4x4, 381 int column4x4, uint16_t* cdef_source, 382 ptrdiff_t cdef_stride, bool y_plane); 383 template <typename Pixel> 384 void ApplyCdefForOneUnit(uint16_t* cdef_block, int index, int block_width4x4, 385 int block_height4x4, int row4x4_start, 386 int column4x4_start); 387 // Helper function used by ApplyCdefForOneSuperBlockRow to avoid some code 388 // duplication. 389 void ApplyCdefForOneSuperBlockRowHelper(int row4x4, int block_height4x4); 390 // Applies cdef filtering for the superblock row starting at |row4x4| with a 391 // height of 4*|sb4x4|. 392 void ApplyCdefForOneSuperBlockRow(int row4x4, int sb4x4, bool is_last_row); 393 template <typename Pixel> 394 void ApplyCdefForOneRowInWindow(int row, int column); 395 template <typename Pixel> 396 void ApplyCdefThreaded(); 397 void ApplyCdef(); // Sections 7.15 and 7.15.1. 398 399 // Functions for the SuperRes filter. 400 401 // Applies super resolution for the |buffers| for |rows[plane]| rows of each 402 // plane. If |in_place| is true, the line buffer will not be used and the 403 // SuperRes output will be written to a row above the input row. If |in_place| 404 // is false, the line buffer will be used to store a copy of the input and the 405 // output will be written to the same row as the input row. 406 template <bool in_place> 407 void ApplySuperRes(const std::array<uint8_t*, kMaxPlanes>& buffers, 408 const std::array<int, kMaxPlanes>& strides, 409 const std::array<int, kMaxPlanes>& rows, 410 size_t line_buffer_offset); // Section 7.16. 411 // Applies SuperRes for the superblock row starting at |row4x4| with a height 412 // of 4*|sb4x4|. 413 void ApplySuperResForOneSuperBlockRow(int row4x4, int sb4x4, 414 bool is_last_row); 415 void ApplySuperResThreaded(); 416 417 // Functions for the Loop Restoration filter. 418 419 template <typename Pixel> 420 void ApplyLoopRestorationForOneRowInWindow( 421 const Pixel* src_buffer, Plane plane, int plane_height, int plane_width, 422 int y, int x, int row, int unit_row, int current_process_unit_height, 423 int plane_unit_size, int window_width, 424 Array2DView<Pixel>* loop_restored_window); 425 // Applies loop restoration for the superblock row starting at |row4x4_start| 426 // with a height of 4*|sb4x4|. 427 template <typename Pixel> 428 void ApplyLoopRestorationSingleThread(int row4x4_start, int sb4x4); 429 void ApplyLoopRestoration(int row4x4_start, int sb4x4); 430 template <typename Pixel> 431 void ApplyLoopRestorationThreaded(); 432 // Note for ApplyLoopRestoration(): 433 // First, we must differentiate loop restoration processing unit from loop 434 // restoration unit. 435 // (1). Loop restoration processing unit size is default to 64x64. 436 // Only when the remaining filtering area is smaller than 64x64, the 437 // processing unit size is the actual area size. 438 // For U/V plane, it is (64 >> subsampling_x) x (64 >> subsampling_y). 439 // (2). Loop restoration unit size can be 64x64, 128x128, 256x256 for Y 440 // plane. The unit size for chroma can be the same or half, depending on 441 // subsampling. If either subsampling_x or subsampling_y is one, unit size 442 // is halved on both x and y sides. 443 // All loop restoration units have the same size for one plane. 444 // One loop restoration unit could contain multiple processing units. 445 // But they share the same sets of loop restoration parameters. 446 // (3). Loop restoration has a row offset, kRestorationUnitOffset = 8. The 447 // size of first row of loop restoration units and processing units is 448 // shrunk by the offset. 449 // (4). Loop restoration units wrap the bottom and the right of the frame, 450 // if the remaining area is small. The criteria is whether the number of 451 // remaining rows/columns is smaller than half of loop restoration unit 452 // size. 453 // For example, if the frame size is 140x140, loop restoration unit size is 454 // 128x128. The size of the first loop restoration unit is 128x(128-8) = 455 // 128 columns x 120 rows. 456 // Since 140 - 120 < 128/2. The remaining 20 rows will be folded to the loop 457 // restoration unit. Similarly, the remaining 12 columns will also be folded 458 // to current loop restoration unit. So, even frame size is 140x140, 459 // there's only one loop restoration unit. Suppose processing unit is 64x64, 460 // then sizes of the first row of processing units are 64x56, 64x56, 12x56, 461 // respectively. The second row is 64x64, 64x64, 12x64. 462 // The third row is 64x20, 64x20, 12x20. 463 void ApplyLoopRestoration(); 464 465 const ObuFrameHeader& frame_header_; 466 const LoopRestoration& loop_restoration_; 467 const dsp::Dsp& dsp_; 468 const int num_64x64_blocks_per_row_; 469 const int upscaled_width_; 470 const int width_; 471 const int height_; 472 const int8_t bitdepth_; 473 const int8_t subsampling_x_[kMaxPlanes]; 474 const int8_t subsampling_y_[kMaxPlanes]; 475 const int8_t planes_; 476 const int pixel_size_; 477 const uint8_t* const inner_thresh_; 478 const uint8_t* const outer_thresh_; 479 const bool needs_chroma_deblock_; 480 // This stores the deblocking filter levels assuming that the delta is zero. 481 // This will be used by all superblocks whose delta is zero (without having to 482 // recompute them). The dimensions (in order) are: segment_id, level_index 483 // (based on plane and direction), reference_frame and mode_id. 484 uint8_t deblock_filter_levels_[kMaxSegments][kFrameLfCount] 485 [kNumReferenceFrameTypes][2]; 486 // Stores the SuperRes info for the frame. 487 struct { 488 int upscaled_width; 489 int initial_subpixel_x; 490 int step; 491 } super_res_info_[kMaxPlanes]; 492 const Array2D<int16_t>& cdef_index_; 493 const Array2D<TransformSize>& inter_transform_sizes_; 494 // Pointer to the data buffer used for multi-threaded cdef or loop 495 // restoration. The size of this buffer must be at least 496 // |window_buffer_width_| * |window_buffer_height_| * |pixel_size_|. 497 // Or |planes_| times that for multi-threaded cdef. 498 // If |thread_pool_| is nullptr, then this buffer is not used and can be 499 // nullptr as well. 500 uint8_t* const threaded_window_buffer_; 501 LoopRestorationInfo* const restoration_info_; 502 // Pointer to the line buffer used by ApplySuperRes(). If SuperRes is on, then 503 // the buffer will be large enough to hold one downscaled row + 504 // 2 * kSuperResHorizontalBorder + kSuperResHorizontalPadding. 505 uint8_t* const superres_line_buffer_; 506 const BlockParametersHolder& block_parameters_; 507 // Frame buffer to hold cdef filtered frame. 508 YuvBuffer cdef_filtered_buffer_; 509 // Input frame buffer. 510 YuvBuffer& frame_buffer_; 511 // A view into |frame_buffer_| that points to the input and output of the 512 // deblocking process. 513 uint8_t* source_buffer_[kMaxPlanes]; 514 // A view into |frame_buffer_| that points to the output of the CDEF filtered 515 // planes (to facilitate in-place CDEF filtering). 516 uint8_t* cdef_buffer_[kMaxPlanes]; 517 // A view into |frame_buffer_| that points to the planes after the SuperRes 518 // filter is applied (to facilitate in-place SuperRes). 519 uint8_t* superres_buffer_[kMaxPlanes]; 520 // A view into |frame_buffer_| that points to the output of the Loop Restored 521 // planes (to facilitate in-place Loop Restoration). 522 uint8_t* loop_restoration_buffer_[kMaxPlanes]; 523 // Buffer used to store the deblocked pixels that are necessary for loop 524 // restoration. This buffer will store 4 rows for every 64x64 block (4 rows 525 // for every 32x32 for chroma with subsampling). The indices of the rows that 526 // are stored are specified in |kDeblockedRowsForLoopRestoration|. First 4 527 // rows of this buffer are never populated and never used. 528 // This buffer is used only when both Cdef and Loop Restoration are on. 529 YuvBuffer& deblock_buffer_; 530 const uint8_t do_post_filter_mask_; 531 ThreadPool* const thread_pool_; 532 const int window_buffer_width_; 533 const int window_buffer_height_; 534 535 // Tracks the progress of the post filters. 536 int progress_row_ = -1; 537 538 // A block buffer to hold the input that is converted to uint16_t before 539 // cdef filtering. Only used in single threaded case. 540 uint16_t cdef_block_[kCdefUnitSizeWithBorders * kCdefUnitSizeWithBorders * 3]; 541 542 template <int bitdepth, typename Pixel> 543 friend class PostFilterSuperResTest; 544 545 template <int bitdepth, typename Pixel> 546 friend class PostFilterHelperFuncTest; 547 }; 548 549 extern template void PostFilter::ExtendFrame<uint8_t>(uint8_t* frame_start, 550 int width, int height, 551 ptrdiff_t stride, 552 int left, int right, 553 int top, int bottom); 554 extern template void PostFilter::PrepareLoopRestorationBlock<uint8_t>( 555 const uint8_t* src_buffer, ptrdiff_t src_stride, 556 const uint8_t* deblock_buffer, ptrdiff_t deblock_stride, uint8_t* dst, 557 ptrdiff_t dst_stride, const int width, const int height, 558 const bool frame_top_border, const bool frame_bottom_border); 559 560 #if LIBGAV1_MAX_BITDEPTH >= 10 561 extern template void PostFilter::ExtendFrame<uint16_t>(uint16_t* frame_start, 562 int width, int height, 563 ptrdiff_t stride, 564 int left, int right, 565 int top, int bottom); 566 extern template void PostFilter::PrepareLoopRestorationBlock<uint16_t>( 567 const uint16_t* src_buffer, ptrdiff_t src_stride, 568 const uint16_t* deblock_buffer, ptrdiff_t deblock_stride, uint16_t* dst, 569 ptrdiff_t dst_stride, const int width, const int height, 570 const bool frame_top_border, const bool frame_bottom_border); 571 #endif 572 573 } // namespace libgav1 574 575 #endif // LIBGAV1_SRC_POST_FILTER_H_ 576