1*09537850SAkhilesh Sanikop /* 2*09537850SAkhilesh Sanikop * Copyright 2019 The libgav1 Authors 3*09537850SAkhilesh Sanikop * 4*09537850SAkhilesh Sanikop * Licensed under the Apache License, Version 2.0 (the "License"); 5*09537850SAkhilesh Sanikop * you may not use this file except in compliance with the License. 6*09537850SAkhilesh Sanikop * You may obtain a copy of the License at 7*09537850SAkhilesh Sanikop * 8*09537850SAkhilesh Sanikop * http://www.apache.org/licenses/LICENSE-2.0 9*09537850SAkhilesh Sanikop * 10*09537850SAkhilesh Sanikop * Unless required by applicable law or agreed to in writing, software 11*09537850SAkhilesh Sanikop * distributed under the License is distributed on an "AS IS" BASIS, 12*09537850SAkhilesh Sanikop * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*09537850SAkhilesh Sanikop * See the License for the specific language governing permissions and 14*09537850SAkhilesh Sanikop * limitations under the License. 15*09537850SAkhilesh Sanikop */ 16*09537850SAkhilesh Sanikop 17*09537850SAkhilesh Sanikop #ifndef LIBGAV1_SRC_TILE_H_ 18*09537850SAkhilesh Sanikop #define LIBGAV1_SRC_TILE_H_ 19*09537850SAkhilesh Sanikop 20*09537850SAkhilesh Sanikop #include <algorithm> 21*09537850SAkhilesh Sanikop #include <array> 22*09537850SAkhilesh Sanikop #include <cassert> 23*09537850SAkhilesh Sanikop #include <condition_variable> // NOLINT (unapproved c++11 header) 24*09537850SAkhilesh Sanikop #include <cstddef> 25*09537850SAkhilesh Sanikop #include <cstdint> 26*09537850SAkhilesh Sanikop #include <memory> 27*09537850SAkhilesh Sanikop #include <mutex> // NOLINT (unapproved c++11 header) 28*09537850SAkhilesh Sanikop #include <vector> 29*09537850SAkhilesh Sanikop 30*09537850SAkhilesh Sanikop #include "src/buffer_pool.h" 31*09537850SAkhilesh Sanikop #include "src/decoder_state.h" 32*09537850SAkhilesh Sanikop #include "src/dsp/common.h" 33*09537850SAkhilesh Sanikop #include "src/dsp/constants.h" 34*09537850SAkhilesh Sanikop #include "src/dsp/dsp.h" 35*09537850SAkhilesh Sanikop #include "src/frame_scratch_buffer.h" 36*09537850SAkhilesh Sanikop #include "src/loop_restoration_info.h" 37*09537850SAkhilesh Sanikop #include "src/obu_parser.h" 38*09537850SAkhilesh Sanikop #include "src/post_filter.h" 39*09537850SAkhilesh Sanikop #include "src/quantizer.h" 40*09537850SAkhilesh Sanikop #include "src/residual_buffer_pool.h" 41*09537850SAkhilesh Sanikop #include "src/symbol_decoder_context.h" 42*09537850SAkhilesh Sanikop #include "src/tile_scratch_buffer.h" 43*09537850SAkhilesh Sanikop #include "src/utils/array_2d.h" 44*09537850SAkhilesh Sanikop #include "src/utils/block_parameters_holder.h" 45*09537850SAkhilesh Sanikop #include "src/utils/blocking_counter.h" 46*09537850SAkhilesh Sanikop #include "src/utils/common.h" 47*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h" 48*09537850SAkhilesh Sanikop #include "src/utils/constants.h" 49*09537850SAkhilesh Sanikop #include "src/utils/entropy_decoder.h" 50*09537850SAkhilesh Sanikop #include "src/utils/memory.h" 51*09537850SAkhilesh Sanikop #include "src/utils/segmentation_map.h" 52*09537850SAkhilesh Sanikop #include "src/utils/threadpool.h" 53*09537850SAkhilesh Sanikop #include "src/utils/types.h" 54*09537850SAkhilesh Sanikop #include "src/yuv_buffer.h" 55*09537850SAkhilesh Sanikop 56*09537850SAkhilesh Sanikop namespace libgav1 { 57*09537850SAkhilesh Sanikop 58*09537850SAkhilesh Sanikop // Indicates what the ProcessSuperBlock() and TransformBlock() functions should 59*09537850SAkhilesh Sanikop // do. "Parse" refers to consuming the bitstream, reading the transform 60*09537850SAkhilesh Sanikop // coefficients and performing the dequantization. "Decode" refers to computing 61*09537850SAkhilesh Sanikop // the prediction, applying the inverse transforms and adding the residual. 62*09537850SAkhilesh Sanikop enum ProcessingMode { 63*09537850SAkhilesh Sanikop kProcessingModeParseOnly, 64*09537850SAkhilesh Sanikop kProcessingModeDecodeOnly, 65*09537850SAkhilesh Sanikop kProcessingModeParseAndDecode, 66*09537850SAkhilesh Sanikop }; 67*09537850SAkhilesh Sanikop 68*09537850SAkhilesh Sanikop // The alignment requirement is due to the SymbolDecoderContext member 69*09537850SAkhilesh Sanikop // symbol_decoder_context_. 70*09537850SAkhilesh Sanikop class Tile : public MaxAlignedAllocable { 71*09537850SAkhilesh Sanikop public: Create(int tile_number,const uint8_t * const data,size_t size,const ObuSequenceHeader & sequence_header,const ObuFrameHeader & frame_header,RefCountedBuffer * const current_frame,const DecoderState & state,FrameScratchBuffer * const frame_scratch_buffer,const WedgeMaskArray & wedge_masks,const QuantizerMatrix & quantizer_matrix,SymbolDecoderContext * const saved_symbol_decoder_context,const SegmentationMap * prev_segment_ids,PostFilter * const post_filter,const dsp::Dsp * const dsp,ThreadPool * const thread_pool,BlockingCounterWithStatus * const pending_tiles,bool frame_parallel,bool use_intra_prediction_buffer)72*09537850SAkhilesh Sanikop static std::unique_ptr<Tile> Create( 73*09537850SAkhilesh Sanikop int tile_number, const uint8_t* const data, size_t size, 74*09537850SAkhilesh Sanikop const ObuSequenceHeader& sequence_header, 75*09537850SAkhilesh Sanikop const ObuFrameHeader& frame_header, RefCountedBuffer* const current_frame, 76*09537850SAkhilesh Sanikop const DecoderState& state, FrameScratchBuffer* const frame_scratch_buffer, 77*09537850SAkhilesh Sanikop const WedgeMaskArray& wedge_masks, 78*09537850SAkhilesh Sanikop const QuantizerMatrix& quantizer_matrix, 79*09537850SAkhilesh Sanikop SymbolDecoderContext* const saved_symbol_decoder_context, 80*09537850SAkhilesh Sanikop const SegmentationMap* prev_segment_ids, PostFilter* const post_filter, 81*09537850SAkhilesh Sanikop const dsp::Dsp* const dsp, ThreadPool* const thread_pool, 82*09537850SAkhilesh Sanikop BlockingCounterWithStatus* const pending_tiles, bool frame_parallel, 83*09537850SAkhilesh Sanikop bool use_intra_prediction_buffer) { 84*09537850SAkhilesh Sanikop std::unique_ptr<Tile> tile(new (std::nothrow) Tile( 85*09537850SAkhilesh Sanikop tile_number, data, size, sequence_header, frame_header, current_frame, 86*09537850SAkhilesh Sanikop state, frame_scratch_buffer, wedge_masks, quantizer_matrix, 87*09537850SAkhilesh Sanikop saved_symbol_decoder_context, prev_segment_ids, post_filter, dsp, 88*09537850SAkhilesh Sanikop thread_pool, pending_tiles, frame_parallel, 89*09537850SAkhilesh Sanikop use_intra_prediction_buffer)); 90*09537850SAkhilesh Sanikop return (tile != nullptr && tile->Init()) ? std::move(tile) : nullptr; 91*09537850SAkhilesh Sanikop } 92*09537850SAkhilesh Sanikop 93*09537850SAkhilesh Sanikop // Move only. 94*09537850SAkhilesh Sanikop Tile(Tile&& tile) noexcept; 95*09537850SAkhilesh Sanikop Tile& operator=(Tile&& tile) noexcept; 96*09537850SAkhilesh Sanikop Tile(const Tile&) = delete; 97*09537850SAkhilesh Sanikop Tile& operator=(const Tile&) = delete; 98*09537850SAkhilesh Sanikop 99*09537850SAkhilesh Sanikop struct Block; // Defined after this class. 100*09537850SAkhilesh Sanikop 101*09537850SAkhilesh Sanikop // Parses the entire tile. 102*09537850SAkhilesh Sanikop bool Parse(); 103*09537850SAkhilesh Sanikop // Decodes the entire tile. |superblock_row_progress| and 104*09537850SAkhilesh Sanikop // |superblock_row_progress_condvar| are arrays of size equal to the number of 105*09537850SAkhilesh Sanikop // superblock rows in the frame. Increments |superblock_row_progress[i]| after 106*09537850SAkhilesh Sanikop // each superblock row at index |i| is decoded. If the count reaches the 107*09537850SAkhilesh Sanikop // number of tile columns, then it notifies 108*09537850SAkhilesh Sanikop // |superblock_row_progress_condvar[i]|. 109*09537850SAkhilesh Sanikop bool Decode(std::mutex* mutex, int* superblock_row_progress, 110*09537850SAkhilesh Sanikop std::condition_variable* superblock_row_progress_condvar); 111*09537850SAkhilesh Sanikop // Parses and decodes the entire tile. Depending on the configuration of this 112*09537850SAkhilesh Sanikop // Tile, this function may do multithreaded decoding. 113*09537850SAkhilesh Sanikop bool ParseAndDecode(); // 5.11.2. 114*09537850SAkhilesh Sanikop // Processes all the columns of the superblock row at |row4x4| that are within 115*09537850SAkhilesh Sanikop // this Tile. If |save_symbol_decoder_context| is true, then 116*09537850SAkhilesh Sanikop // SaveSymbolDecoderContext() is invoked for the last superblock row. 117*09537850SAkhilesh Sanikop template <ProcessingMode processing_mode, bool save_symbol_decoder_context> 118*09537850SAkhilesh Sanikop bool ProcessSuperBlockRow(int row4x4, TileScratchBuffer* scratch_buffer); 119*09537850SAkhilesh Sanikop sequence_header()120*09537850SAkhilesh Sanikop const ObuSequenceHeader& sequence_header() const { return sequence_header_; } frame_header()121*09537850SAkhilesh Sanikop const ObuFrameHeader& frame_header() const { return frame_header_; } current_frame()122*09537850SAkhilesh Sanikop const RefCountedBuffer& current_frame() const { return current_frame_; } motion_field()123*09537850SAkhilesh Sanikop const TemporalMotionField& motion_field() const { return motion_field_; } reference_frame_sign_bias()124*09537850SAkhilesh Sanikop const std::array<bool, kNumReferenceFrameTypes>& reference_frame_sign_bias() 125*09537850SAkhilesh Sanikop const { 126*09537850SAkhilesh Sanikop return reference_frame_sign_bias_; 127*09537850SAkhilesh Sanikop } 128*09537850SAkhilesh Sanikop IsRow4x4Inside(int row4x4)129*09537850SAkhilesh Sanikop bool IsRow4x4Inside(int row4x4) const { 130*09537850SAkhilesh Sanikop return row4x4 >= row4x4_start_ && row4x4 < row4x4_end_; 131*09537850SAkhilesh Sanikop } 132*09537850SAkhilesh Sanikop 133*09537850SAkhilesh Sanikop // 5.11.51. IsInside(int row4x4,int column4x4)134*09537850SAkhilesh Sanikop bool IsInside(int row4x4, int column4x4) const { 135*09537850SAkhilesh Sanikop return IsRow4x4Inside(row4x4) && column4x4 >= column4x4_start_ && 136*09537850SAkhilesh Sanikop column4x4 < column4x4_end_; 137*09537850SAkhilesh Sanikop } 138*09537850SAkhilesh Sanikop IsLeftInside(int column4x4)139*09537850SAkhilesh Sanikop bool IsLeftInside(int column4x4) const { 140*09537850SAkhilesh Sanikop // We use "larger than" as the condition. Don't pass in the left column 141*09537850SAkhilesh Sanikop // offset column4x4 - 1. 142*09537850SAkhilesh Sanikop assert(column4x4 <= column4x4_end_); 143*09537850SAkhilesh Sanikop return column4x4 > column4x4_start_; 144*09537850SAkhilesh Sanikop } 145*09537850SAkhilesh Sanikop IsTopInside(int row4x4)146*09537850SAkhilesh Sanikop bool IsTopInside(int row4x4) const { 147*09537850SAkhilesh Sanikop // We use "larger than" as the condition. Don't pass in the top row offset 148*09537850SAkhilesh Sanikop // row4x4 - 1. 149*09537850SAkhilesh Sanikop assert(row4x4 <= row4x4_end_); 150*09537850SAkhilesh Sanikop return row4x4 > row4x4_start_; 151*09537850SAkhilesh Sanikop } 152*09537850SAkhilesh Sanikop IsTopLeftInside(int row4x4,int column4x4)153*09537850SAkhilesh Sanikop bool IsTopLeftInside(int row4x4, int column4x4) const { 154*09537850SAkhilesh Sanikop // We use "larger than" as the condition. Don't pass in the top row offset 155*09537850SAkhilesh Sanikop // row4x4 - 1 or the left column offset column4x4 - 1. 156*09537850SAkhilesh Sanikop assert(row4x4 <= row4x4_end_); 157*09537850SAkhilesh Sanikop assert(column4x4 <= column4x4_end_); 158*09537850SAkhilesh Sanikop return row4x4 > row4x4_start_ && column4x4 > column4x4_start_; 159*09537850SAkhilesh Sanikop } 160*09537850SAkhilesh Sanikop IsBottomRightInside(int row4x4,int column4x4)161*09537850SAkhilesh Sanikop bool IsBottomRightInside(int row4x4, int column4x4) const { 162*09537850SAkhilesh Sanikop assert(row4x4 >= row4x4_start_); 163*09537850SAkhilesh Sanikop assert(column4x4 >= column4x4_start_); 164*09537850SAkhilesh Sanikop return row4x4 < row4x4_end_ && column4x4 < column4x4_end_; 165*09537850SAkhilesh Sanikop } 166*09537850SAkhilesh Sanikop BlockParametersAddress(int row4x4,int column4x4)167*09537850SAkhilesh Sanikop BlockParameters** BlockParametersAddress(int row4x4, int column4x4) const { 168*09537850SAkhilesh Sanikop return block_parameters_holder_.Address(row4x4, column4x4); 169*09537850SAkhilesh Sanikop } 170*09537850SAkhilesh Sanikop BlockParametersStride()171*09537850SAkhilesh Sanikop int BlockParametersStride() const { 172*09537850SAkhilesh Sanikop return block_parameters_holder_.columns4x4(); 173*09537850SAkhilesh Sanikop } 174*09537850SAkhilesh Sanikop 175*09537850SAkhilesh Sanikop // Returns true if Parameters() can be called with |row| and |column| as 176*09537850SAkhilesh Sanikop // inputs, false otherwise. HasParameters(int row,int column)177*09537850SAkhilesh Sanikop bool HasParameters(int row, int column) const { 178*09537850SAkhilesh Sanikop return block_parameters_holder_.Find(row, column) != nullptr; 179*09537850SAkhilesh Sanikop } Parameters(int row,int column)180*09537850SAkhilesh Sanikop const BlockParameters& Parameters(int row, int column) const { 181*09537850SAkhilesh Sanikop return *block_parameters_holder_.Find(row, column); 182*09537850SAkhilesh Sanikop } 183*09537850SAkhilesh Sanikop number()184*09537850SAkhilesh Sanikop int number() const { return number_; } superblock_rows()185*09537850SAkhilesh Sanikop int superblock_rows() const { return superblock_rows_; } superblock_columns()186*09537850SAkhilesh Sanikop int superblock_columns() const { return superblock_columns_; } row4x4_start()187*09537850SAkhilesh Sanikop int row4x4_start() const { return row4x4_start_; } column4x4_start()188*09537850SAkhilesh Sanikop int column4x4_start() const { return column4x4_start_; } column4x4_end()189*09537850SAkhilesh Sanikop int column4x4_end() const { return column4x4_end_; } 190*09537850SAkhilesh Sanikop 191*09537850SAkhilesh Sanikop private: 192*09537850SAkhilesh Sanikop // Stores the transform tree state when reading variable size transform trees 193*09537850SAkhilesh Sanikop // and when applying the transform tree. When applying the transform tree, 194*09537850SAkhilesh Sanikop // |depth| is not used. 195*09537850SAkhilesh Sanikop struct TransformTreeNode { 196*09537850SAkhilesh Sanikop // The default constructor is invoked by the Stack<TransformTreeNode, n> 197*09537850SAkhilesh Sanikop // constructor. Stack<> does not use the default-constructed elements, so it 198*09537850SAkhilesh Sanikop // is safe for the default constructor to not initialize the members. 199*09537850SAkhilesh Sanikop TransformTreeNode() = default; 200*09537850SAkhilesh Sanikop TransformTreeNode(int x, int y, TransformSize tx_size, int depth = -1) xTransformTreeNode201*09537850SAkhilesh Sanikop : x(x), y(y), tx_size(tx_size), depth(depth) {} 202*09537850SAkhilesh Sanikop 203*09537850SAkhilesh Sanikop int x; 204*09537850SAkhilesh Sanikop int y; 205*09537850SAkhilesh Sanikop TransformSize tx_size; 206*09537850SAkhilesh Sanikop int depth; 207*09537850SAkhilesh Sanikop }; 208*09537850SAkhilesh Sanikop 209*09537850SAkhilesh Sanikop // Enum to track the processing state of a superblock. 210*09537850SAkhilesh Sanikop enum SuperBlockState : uint8_t { 211*09537850SAkhilesh Sanikop kSuperBlockStateNone, // Not yet parsed or decoded. 212*09537850SAkhilesh Sanikop kSuperBlockStateParsed, // Parsed but not yet decoded. 213*09537850SAkhilesh Sanikop kSuperBlockStateScheduled, // Scheduled for decoding. 214*09537850SAkhilesh Sanikop kSuperBlockStateDecoded // Parsed and decoded. 215*09537850SAkhilesh Sanikop }; 216*09537850SAkhilesh Sanikop 217*09537850SAkhilesh Sanikop // Parameters used to facilitate multi-threading within the Tile. 218*09537850SAkhilesh Sanikop struct ThreadingParameters { 219*09537850SAkhilesh Sanikop std::mutex mutex; 220*09537850SAkhilesh Sanikop // 2d array of size |superblock_rows_| by |superblock_columns_| containing 221*09537850SAkhilesh Sanikop // the processing state of each superblock. 222*09537850SAkhilesh Sanikop Array2D<SuperBlockState> sb_state LIBGAV1_GUARDED_BY(mutex); 223*09537850SAkhilesh Sanikop // Variable used to indicate either parse or decode failure. 224*09537850SAkhilesh Sanikop bool abort LIBGAV1_GUARDED_BY(mutex) = false; 225*09537850SAkhilesh Sanikop int pending_jobs LIBGAV1_GUARDED_BY(mutex) = 0; 226*09537850SAkhilesh Sanikop std::condition_variable pending_jobs_zero_condvar; 227*09537850SAkhilesh Sanikop }; 228*09537850SAkhilesh Sanikop 229*09537850SAkhilesh Sanikop // The residual pointer is used to traverse the |residual_buffer_|. It is 230*09537850SAkhilesh Sanikop // used in two different ways. 231*09537850SAkhilesh Sanikop // If |split_parse_and_decode_| is true: 232*09537850SAkhilesh Sanikop // The pointer points to the beginning of the |residual_buffer_| when the 233*09537850SAkhilesh Sanikop // "parse" and "decode" steps begin. It is then moved forward tx_size in 234*09537850SAkhilesh Sanikop // each iteration of the "parse" and the "decode" steps. In this case, the 235*09537850SAkhilesh Sanikop // ResidualPtr variable passed into various functions starting from 236*09537850SAkhilesh Sanikop // ProcessSuperBlock is used as an in/out parameter to keep track of the 237*09537850SAkhilesh Sanikop // residual pointer. 238*09537850SAkhilesh Sanikop // If |split_parse_and_decode_| is false: 239*09537850SAkhilesh Sanikop // The pointer is reset to the beginning of the |residual_buffer_| for 240*09537850SAkhilesh Sanikop // every transform block. 241*09537850SAkhilesh Sanikop using ResidualPtr = uint8_t*; 242*09537850SAkhilesh Sanikop 243*09537850SAkhilesh Sanikop Tile(int tile_number, const uint8_t* data, size_t size, 244*09537850SAkhilesh Sanikop const ObuSequenceHeader& sequence_header, 245*09537850SAkhilesh Sanikop const ObuFrameHeader& frame_header, RefCountedBuffer* current_frame, 246*09537850SAkhilesh Sanikop const DecoderState& state, FrameScratchBuffer* frame_scratch_buffer, 247*09537850SAkhilesh Sanikop const WedgeMaskArray& wedge_masks, 248*09537850SAkhilesh Sanikop const QuantizerMatrix& quantizer_matrix, 249*09537850SAkhilesh Sanikop SymbolDecoderContext* saved_symbol_decoder_context, 250*09537850SAkhilesh Sanikop const SegmentationMap* prev_segment_ids, PostFilter* post_filter, 251*09537850SAkhilesh Sanikop const dsp::Dsp* dsp, ThreadPool* thread_pool, 252*09537850SAkhilesh Sanikop BlockingCounterWithStatus* pending_tiles, bool frame_parallel, 253*09537850SAkhilesh Sanikop bool use_intra_prediction_buffer); 254*09537850SAkhilesh Sanikop 255*09537850SAkhilesh Sanikop // Performs member initializations that may fail. Helper function used by 256*09537850SAkhilesh Sanikop // Create(). 257*09537850SAkhilesh Sanikop LIBGAV1_MUST_USE_RESULT bool Init(); 258*09537850SAkhilesh Sanikop 259*09537850SAkhilesh Sanikop // Saves the symbol decoder context of this tile into 260*09537850SAkhilesh Sanikop // |saved_symbol_decoder_context_| if necessary. 261*09537850SAkhilesh Sanikop void SaveSymbolDecoderContext(); 262*09537850SAkhilesh Sanikop 263*09537850SAkhilesh Sanikop // Entry point for multi-threaded decoding. This function performs the same 264*09537850SAkhilesh Sanikop // functionality as ParseAndDecode(). The current thread does the "parse" step 265*09537850SAkhilesh Sanikop // while the worker threads do the "decode" step. 266*09537850SAkhilesh Sanikop bool ThreadedParseAndDecode(); 267*09537850SAkhilesh Sanikop 268*09537850SAkhilesh Sanikop // Returns whether or not the prerequisites for decoding the superblock at 269*09537850SAkhilesh Sanikop // |row_index| and |column_index| are satisfied. |threading_.mutex| must be 270*09537850SAkhilesh Sanikop // held when calling this function. 271*09537850SAkhilesh Sanikop bool CanDecode(int row_index, int column_index) const; 272*09537850SAkhilesh Sanikop 273*09537850SAkhilesh Sanikop // This function is run by the worker threads when multi-threaded decoding is 274*09537850SAkhilesh Sanikop // enabled. Once a superblock is decoded, this function will set the 275*09537850SAkhilesh Sanikop // corresponding |threading_.sb_state| entry to kSuperBlockStateDecoded. On 276*09537850SAkhilesh Sanikop // failure, |threading_.abort| will be set to true. If at any point 277*09537850SAkhilesh Sanikop // |threading_.abort| becomes true, this function will return as early as it 278*09537850SAkhilesh Sanikop // can. If the decoding succeeds, this function will also schedule the 279*09537850SAkhilesh Sanikop // decoding jobs for the superblock to the bottom-left and the superblock to 280*09537850SAkhilesh Sanikop // the right of this superblock (if it is allowed). 281*09537850SAkhilesh Sanikop void DecodeSuperBlock(int row_index, int column_index, int block_width4x4); 282*09537850SAkhilesh Sanikop 283*09537850SAkhilesh Sanikop // If |use_intra_prediction_buffer_| is true, then this function copies the 284*09537850SAkhilesh Sanikop // last row of the superblockrow starting at |row4x4| into the 285*09537850SAkhilesh Sanikop // |intra_prediction_buffer_| (which may be used by the intra prediction 286*09537850SAkhilesh Sanikop // process for the next superblock row). 287*09537850SAkhilesh Sanikop void PopulateIntraPredictionBuffer(int row4x4); 288*09537850SAkhilesh Sanikop 289*09537850SAkhilesh Sanikop uint16_t* GetPartitionCdf(int row4x4, int column4x4, BlockSize block_size); 290*09537850SAkhilesh Sanikop bool ReadPartition(int row4x4, int column4x4, BlockSize block_size, 291*09537850SAkhilesh Sanikop bool has_rows, bool has_columns, Partition* partition); 292*09537850SAkhilesh Sanikop // Processes the Partition starting at |row4x4_start|, |column4x4_start| 293*09537850SAkhilesh Sanikop // iteratively. It performs a DFS traversal over the partition tree to process 294*09537850SAkhilesh Sanikop // the blocks in the right order. 295*09537850SAkhilesh Sanikop bool ProcessPartition( 296*09537850SAkhilesh Sanikop int row4x4_start, int column4x4_start, TileScratchBuffer* scratch_buffer, 297*09537850SAkhilesh Sanikop ResidualPtr* residual); // Iterative implementation of 5.11.4. 298*09537850SAkhilesh Sanikop bool ProcessBlock(int row4x4, int column4x4, BlockSize block_size, 299*09537850SAkhilesh Sanikop TileScratchBuffer* scratch_buffer, 300*09537850SAkhilesh Sanikop ResidualPtr* residual); // 5.11.5. 301*09537850SAkhilesh Sanikop void ResetCdef(int row4x4, int column4x4); // 5.11.55. 302*09537850SAkhilesh Sanikop 303*09537850SAkhilesh Sanikop // This function is used to decode a superblock when the parsing has already 304*09537850SAkhilesh Sanikop // been done for that superblock. 305*09537850SAkhilesh Sanikop bool DecodeSuperBlock(int sb_row_index, int sb_column_index, 306*09537850SAkhilesh Sanikop TileScratchBuffer* scratch_buffer); 307*09537850SAkhilesh Sanikop // Helper function used by DecodeSuperBlock(). Note that the decode_block() 308*09537850SAkhilesh Sanikop // function in the spec is equivalent to ProcessBlock() in the code. 309*09537850SAkhilesh Sanikop bool DecodeBlock(int row4x4, int column4x4, BlockSize block_size, 310*09537850SAkhilesh Sanikop TileScratchBuffer* scratch_buffer, ResidualPtr* residual); 311*09537850SAkhilesh Sanikop 312*09537850SAkhilesh Sanikop void ClearBlockDecoded(TileScratchBuffer* scratch_buffer, int row4x4, 313*09537850SAkhilesh Sanikop int column4x4); // 5.11.3. 314*09537850SAkhilesh Sanikop bool ProcessSuperBlock(int row4x4, int column4x4, 315*09537850SAkhilesh Sanikop TileScratchBuffer* scratch_buffer, 316*09537850SAkhilesh Sanikop ProcessingMode mode); 317*09537850SAkhilesh Sanikop void ResetLoopRestorationParams(); 318*09537850SAkhilesh Sanikop void ReadLoopRestorationCoefficients(int row4x4, int column4x4, 319*09537850SAkhilesh Sanikop BlockSize block_size); // 5.11.57. 320*09537850SAkhilesh Sanikop 321*09537850SAkhilesh Sanikop // Helper functions for DecodeBlock. 322*09537850SAkhilesh Sanikop bool ReadSegmentId(const Block& block); // 5.11.9. 323*09537850SAkhilesh Sanikop bool ReadIntraSegmentId(const Block& block); // 5.11.8. 324*09537850SAkhilesh Sanikop void ReadSkip(const Block& block); // 5.11.11. 325*09537850SAkhilesh Sanikop bool ReadSkipMode(const Block& block); // 5.11.10. 326*09537850SAkhilesh Sanikop void ReadCdef(const Block& block); // 5.11.56. 327*09537850SAkhilesh Sanikop // Returns the new value. |cdf| is an array of size kDeltaSymbolCount + 1. 328*09537850SAkhilesh Sanikop int ReadAndClipDelta(uint16_t* cdf, int delta_small, int scale, int min_value, 329*09537850SAkhilesh Sanikop int max_value, int value); 330*09537850SAkhilesh Sanikop void ReadQuantizerIndexDelta(const Block& block); // 5.11.12. 331*09537850SAkhilesh Sanikop void ReadLoopFilterDelta(const Block& block); // 5.11.13. 332*09537850SAkhilesh Sanikop // Populates |BlockParameters::deblock_filter_level| for the given |block| 333*09537850SAkhilesh Sanikop // using |deblock_filter_levels_|. 334*09537850SAkhilesh Sanikop void PopulateDeblockFilterLevel(const Block& block); 335*09537850SAkhilesh Sanikop void PopulateCdefSkip(const Block& block); 336*09537850SAkhilesh Sanikop void ReadPredictionModeY(const Block& block, bool intra_y_mode); 337*09537850SAkhilesh Sanikop void ReadIntraAngleInfo(const Block& block, 338*09537850SAkhilesh Sanikop PlaneType plane_type); // 5.11.42 and 5.11.43. 339*09537850SAkhilesh Sanikop void ReadPredictionModeUV(const Block& block); 340*09537850SAkhilesh Sanikop void ReadCflAlpha(const Block& block); // 5.11.45. 341*09537850SAkhilesh Sanikop int GetPaletteCache(const Block& block, PlaneType plane_type, 342*09537850SAkhilesh Sanikop uint16_t* cache); 343*09537850SAkhilesh Sanikop void ReadPaletteColors(const Block& block, Plane plane); 344*09537850SAkhilesh Sanikop void ReadPaletteModeInfo(const Block& block); // 5.11.46. 345*09537850SAkhilesh Sanikop void ReadFilterIntraModeInfo(const Block& block); // 5.11.24. 346*09537850SAkhilesh Sanikop int ReadMotionVectorComponent(const Block& block, 347*09537850SAkhilesh Sanikop int component); // 5.11.32. 348*09537850SAkhilesh Sanikop void ReadMotionVector(const Block& block, int index); // 5.11.31. 349*09537850SAkhilesh Sanikop bool DecodeIntraModeInfo(const Block& block); // 5.11.7. 350*09537850SAkhilesh Sanikop int8_t ComputePredictedSegmentId(const Block& block) const; // 5.11.21. 351*09537850SAkhilesh Sanikop bool ReadInterSegmentId(const Block& block, bool pre_skip); // 5.11.19. 352*09537850SAkhilesh Sanikop void ReadIsInter(const Block& block, bool skip_mode); // 5.11.20. 353*09537850SAkhilesh Sanikop bool ReadIntraBlockModeInfo(const Block& block, 354*09537850SAkhilesh Sanikop bool intra_y_mode); // 5.11.22. 355*09537850SAkhilesh Sanikop CompoundReferenceType ReadCompoundReferenceType(const Block& block); 356*09537850SAkhilesh Sanikop template <bool is_single, bool is_backward, int index> 357*09537850SAkhilesh Sanikop uint16_t* GetReferenceCdf(const Block& block, CompoundReferenceType type = 358*09537850SAkhilesh Sanikop kNumCompoundReferenceTypes); 359*09537850SAkhilesh Sanikop void ReadReferenceFrames(const Block& block, bool skip_mode); // 5.11.25. 360*09537850SAkhilesh Sanikop void ReadInterPredictionModeY(const Block& block, 361*09537850SAkhilesh Sanikop const MvContexts& mode_contexts, 362*09537850SAkhilesh Sanikop bool skip_mode); 363*09537850SAkhilesh Sanikop void ReadRefMvIndex(const Block& block); 364*09537850SAkhilesh Sanikop void ReadInterIntraMode(const Block& block, bool is_compound, 365*09537850SAkhilesh Sanikop bool skip_mode); // 5.11.28. IsScaled(ReferenceFrameType type)366*09537850SAkhilesh Sanikop bool IsScaled(ReferenceFrameType type) const { // Part of 5.11.27. 367*09537850SAkhilesh Sanikop const int index = 368*09537850SAkhilesh Sanikop frame_header_.reference_frame_index[type - kReferenceFrameLast]; 369*09537850SAkhilesh Sanikop return reference_frames_[index]->upscaled_width() != frame_header_.width || 370*09537850SAkhilesh Sanikop reference_frames_[index]->frame_height() != frame_header_.height; 371*09537850SAkhilesh Sanikop } 372*09537850SAkhilesh Sanikop void ReadMotionMode(const Block& block, bool is_compound, 373*09537850SAkhilesh Sanikop bool skip_mode); // 5.11.27. 374*09537850SAkhilesh Sanikop uint16_t* GetIsExplicitCompoundTypeCdf(const Block& block); 375*09537850SAkhilesh Sanikop uint16_t* GetIsCompoundTypeAverageCdf(const Block& block); 376*09537850SAkhilesh Sanikop void ReadCompoundType(const Block& block, bool is_compound, bool skip_mode, 377*09537850SAkhilesh Sanikop bool* is_explicit_compound_type, 378*09537850SAkhilesh Sanikop bool* is_compound_type_average); // 5.11.29. 379*09537850SAkhilesh Sanikop uint16_t* GetInterpolationFilterCdf(const Block& block, int direction); 380*09537850SAkhilesh Sanikop void ReadInterpolationFilter(const Block& block, bool skip_mode); 381*09537850SAkhilesh Sanikop bool ReadInterBlockModeInfo(const Block& block, bool skip_mode); // 5.11.23. 382*09537850SAkhilesh Sanikop bool DecodeInterModeInfo(const Block& block); // 5.11.18. 383*09537850SAkhilesh Sanikop bool DecodeModeInfo(const Block& block); // 5.11.6. 384*09537850SAkhilesh Sanikop bool IsMvValid(const Block& block, bool is_compound) const; // 6.10.25. 385*09537850SAkhilesh Sanikop bool AssignInterMv(const Block& block, bool is_compound); // 5.11.26. 386*09537850SAkhilesh Sanikop bool AssignIntraMv(const Block& block); // 5.11.26. 387*09537850SAkhilesh Sanikop int GetTopTransformWidth(const Block& block, int row4x4, int column4x4, 388*09537850SAkhilesh Sanikop bool ignore_skip); 389*09537850SAkhilesh Sanikop int GetLeftTransformHeight(const Block& block, int row4x4, int column4x4, 390*09537850SAkhilesh Sanikop bool ignore_skip); 391*09537850SAkhilesh Sanikop TransformSize ReadFixedTransformSize(const Block& block); // 5.11.15. 392*09537850SAkhilesh Sanikop // Iterative implementation of 5.11.17. 393*09537850SAkhilesh Sanikop void ReadVariableTransformTree(const Block& block, int row4x4, int column4x4, 394*09537850SAkhilesh Sanikop TransformSize tx_size); 395*09537850SAkhilesh Sanikop void DecodeTransformSize(const Block& block); // 5.11.16. 396*09537850SAkhilesh Sanikop bool ComputePrediction(const Block& block); // 5.11.33. 397*09537850SAkhilesh Sanikop // |x4| and |y4| are the column and row positions of the 4x4 block. |w4| and 398*09537850SAkhilesh Sanikop // |h4| are the width and height in 4x4 units of |tx_size|. 399*09537850SAkhilesh Sanikop int GetTransformAllZeroContext(const Block& block, Plane plane, 400*09537850SAkhilesh Sanikop TransformSize tx_size, int x4, int y4, int w4, 401*09537850SAkhilesh Sanikop int h4); 402*09537850SAkhilesh Sanikop TransformSet GetTransformSet(TransformSize tx_size, 403*09537850SAkhilesh Sanikop bool is_inter) const; // 5.11.48. 404*09537850SAkhilesh Sanikop TransformType ComputeTransformType(const Block& block, Plane plane, 405*09537850SAkhilesh Sanikop TransformSize tx_size, int block_x, 406*09537850SAkhilesh Sanikop int block_y); // 5.11.40. 407*09537850SAkhilesh Sanikop void ReadTransformType(const Block& block, int x4, int y4, 408*09537850SAkhilesh Sanikop TransformSize tx_size); // 5.11.47. 409*09537850SAkhilesh Sanikop template <typename ResidualType> 410*09537850SAkhilesh Sanikop void ReadCoeffBase2D( 411*09537850SAkhilesh Sanikop const uint16_t* scan, TransformSize tx_size, int adjusted_tx_width_log2, 412*09537850SAkhilesh Sanikop int eob, 413*09537850SAkhilesh Sanikop uint16_t coeff_base_cdf[kCoeffBaseContexts][kCoeffBaseSymbolCount + 1], 414*09537850SAkhilesh Sanikop uint16_t coeff_base_range_cdf[kCoeffBaseRangeContexts] 415*09537850SAkhilesh Sanikop [kCoeffBaseRangeSymbolCount + 1], 416*09537850SAkhilesh Sanikop ResidualType* quantized_buffer, uint8_t* level_buffer); 417*09537850SAkhilesh Sanikop template <typename ResidualType> 418*09537850SAkhilesh Sanikop void ReadCoeffBaseHorizontal( 419*09537850SAkhilesh Sanikop const uint16_t* scan, TransformSize tx_size, int adjusted_tx_width_log2, 420*09537850SAkhilesh Sanikop int eob, 421*09537850SAkhilesh Sanikop uint16_t coeff_base_cdf[kCoeffBaseContexts][kCoeffBaseSymbolCount + 1], 422*09537850SAkhilesh Sanikop uint16_t coeff_base_range_cdf[kCoeffBaseRangeContexts] 423*09537850SAkhilesh Sanikop [kCoeffBaseRangeSymbolCount + 1], 424*09537850SAkhilesh Sanikop ResidualType* quantized_buffer, uint8_t* level_buffer); 425*09537850SAkhilesh Sanikop template <typename ResidualType> 426*09537850SAkhilesh Sanikop void ReadCoeffBaseVertical( 427*09537850SAkhilesh Sanikop const uint16_t* scan, TransformSize tx_size, int adjusted_tx_width_log2, 428*09537850SAkhilesh Sanikop int eob, 429*09537850SAkhilesh Sanikop uint16_t coeff_base_cdf[kCoeffBaseContexts][kCoeffBaseSymbolCount + 1], 430*09537850SAkhilesh Sanikop uint16_t coeff_base_range_cdf[kCoeffBaseRangeContexts] 431*09537850SAkhilesh Sanikop [kCoeffBaseRangeSymbolCount + 1], 432*09537850SAkhilesh Sanikop ResidualType* quantized_buffer, uint8_t* level_buffer); 433*09537850SAkhilesh Sanikop int GetDcSignContext(int x4, int y4, int w4, int h4, Plane plane); 434*09537850SAkhilesh Sanikop void SetEntropyContexts(int x4, int y4, int w4, int h4, Plane plane, 435*09537850SAkhilesh Sanikop uint8_t coefficient_level, int8_t dc_category); 436*09537850SAkhilesh Sanikop void InterIntraPrediction( 437*09537850SAkhilesh Sanikop uint16_t* prediction_0, const uint8_t* prediction_mask, 438*09537850SAkhilesh Sanikop ptrdiff_t prediction_mask_stride, 439*09537850SAkhilesh Sanikop const PredictionParameters& prediction_parameters, int prediction_width, 440*09537850SAkhilesh Sanikop int prediction_height, int subsampling_x, int subsampling_y, 441*09537850SAkhilesh Sanikop uint8_t* dest, 442*09537850SAkhilesh Sanikop ptrdiff_t dest_stride); // Part of section 7.11.3.1 in the spec. 443*09537850SAkhilesh Sanikop void CompoundInterPrediction( 444*09537850SAkhilesh Sanikop const Block& block, const uint8_t* prediction_mask, 445*09537850SAkhilesh Sanikop ptrdiff_t prediction_mask_stride, int prediction_width, 446*09537850SAkhilesh Sanikop int prediction_height, int subsampling_x, int subsampling_y, 447*09537850SAkhilesh Sanikop int candidate_row, int candidate_column, uint8_t* dest, 448*09537850SAkhilesh Sanikop ptrdiff_t dest_stride); // Part of section 7.11.3.1 in the spec. 449*09537850SAkhilesh Sanikop GlobalMotion* GetWarpParams(const Block& block, Plane plane, 450*09537850SAkhilesh Sanikop int prediction_width, int prediction_height, 451*09537850SAkhilesh Sanikop const PredictionParameters& prediction_parameters, 452*09537850SAkhilesh Sanikop ReferenceFrameType reference_type, 453*09537850SAkhilesh Sanikop bool* is_local_valid, 454*09537850SAkhilesh Sanikop GlobalMotion* global_motion_params, 455*09537850SAkhilesh Sanikop GlobalMotion* local_warp_params) 456*09537850SAkhilesh Sanikop const; // Part of section 7.11.3.1 in the spec. 457*09537850SAkhilesh Sanikop bool InterPrediction(const Block& block, Plane plane, int x, int y, 458*09537850SAkhilesh Sanikop int prediction_width, int prediction_height, 459*09537850SAkhilesh Sanikop int candidate_row, int candidate_column, 460*09537850SAkhilesh Sanikop bool* is_local_valid, 461*09537850SAkhilesh Sanikop GlobalMotion* local_warp_params); // 7.11.3.1. 462*09537850SAkhilesh Sanikop void ScaleMotionVector(const MotionVector& mv, Plane plane, 463*09537850SAkhilesh Sanikop int reference_frame_index, int x, int y, int* start_x, 464*09537850SAkhilesh Sanikop int* start_y, int* step_x, int* step_y); // 7.11.3.3. 465*09537850SAkhilesh Sanikop // If the method returns false, the caller only uses the output parameters 466*09537850SAkhilesh Sanikop // *ref_block_start_x and *ref_block_start_y. If the method returns true, the 467*09537850SAkhilesh Sanikop // caller uses all four output parameters. 468*09537850SAkhilesh Sanikop static bool GetReferenceBlockPosition( 469*09537850SAkhilesh Sanikop int reference_frame_index, bool is_scaled, int width, int height, 470*09537850SAkhilesh Sanikop int ref_start_x, int ref_last_x, int ref_start_y, int ref_last_y, 471*09537850SAkhilesh Sanikop int start_x, int start_y, int step_x, int step_y, int left_border, 472*09537850SAkhilesh Sanikop int right_border, int top_border, int bottom_border, 473*09537850SAkhilesh Sanikop int* ref_block_start_x, int* ref_block_start_y, int* ref_block_end_x, 474*09537850SAkhilesh Sanikop int* ref_block_end_y); 475*09537850SAkhilesh Sanikop 476*09537850SAkhilesh Sanikop template <typename Pixel> 477*09537850SAkhilesh Sanikop void BuildConvolveBlock(Plane plane, int reference_frame_index, 478*09537850SAkhilesh Sanikop bool is_scaled, int height, int ref_start_x, 479*09537850SAkhilesh Sanikop int ref_last_x, int ref_start_y, int ref_last_y, 480*09537850SAkhilesh Sanikop int step_y, int ref_block_start_x, 481*09537850SAkhilesh Sanikop int ref_block_end_x, int ref_block_start_y, 482*09537850SAkhilesh Sanikop uint8_t* block_buffer, 483*09537850SAkhilesh Sanikop ptrdiff_t convolve_buffer_stride, 484*09537850SAkhilesh Sanikop ptrdiff_t block_extended_width); 485*09537850SAkhilesh Sanikop bool BlockInterPrediction(const Block& block, Plane plane, 486*09537850SAkhilesh Sanikop int reference_frame_index, const MotionVector& mv, 487*09537850SAkhilesh Sanikop int x, int y, int width, int height, 488*09537850SAkhilesh Sanikop int candidate_row, int candidate_column, 489*09537850SAkhilesh Sanikop uint16_t* prediction, bool is_compound, 490*09537850SAkhilesh Sanikop bool is_inter_intra, uint8_t* dest, 491*09537850SAkhilesh Sanikop ptrdiff_t dest_stride); // 7.11.3.4. 492*09537850SAkhilesh Sanikop bool BlockWarpProcess(const Block& block, Plane plane, int index, 493*09537850SAkhilesh Sanikop int block_start_x, int block_start_y, int width, 494*09537850SAkhilesh Sanikop int height, GlobalMotion* warp_params, bool is_compound, 495*09537850SAkhilesh Sanikop bool is_inter_intra, uint8_t* dest, 496*09537850SAkhilesh Sanikop ptrdiff_t dest_stride); // 7.11.3.5. 497*09537850SAkhilesh Sanikop bool ObmcBlockPrediction(const Block& block, const MotionVector& mv, 498*09537850SAkhilesh Sanikop Plane plane, int reference_frame_index, int width, 499*09537850SAkhilesh Sanikop int height, int x, int y, int candidate_row, 500*09537850SAkhilesh Sanikop int candidate_column, 501*09537850SAkhilesh Sanikop ObmcDirection blending_direction); 502*09537850SAkhilesh Sanikop bool ObmcPrediction(const Block& block, Plane plane, int width, 503*09537850SAkhilesh Sanikop int height); // 7.11.3.9. 504*09537850SAkhilesh Sanikop void DistanceWeightedPrediction(void* prediction_0, void* prediction_1, 505*09537850SAkhilesh Sanikop int width, int height, int candidate_row, 506*09537850SAkhilesh Sanikop int candidate_column, uint8_t* dest, 507*09537850SAkhilesh Sanikop ptrdiff_t dest_stride); // 7.11.3.15. 508*09537850SAkhilesh Sanikop // This function specializes the parsing of DC coefficient by removing some of 509*09537850SAkhilesh Sanikop // the branches when i == 0 (since scan[0] is always 0 and scan[i] is always 510*09537850SAkhilesh Sanikop // non-zero for all other possible values of i). |dc_category| is an output 511*09537850SAkhilesh Sanikop // parameter that is populated when |is_dc_coefficient| is true. 512*09537850SAkhilesh Sanikop // |coefficient_level| is an output parameter which accumulates the 513*09537850SAkhilesh Sanikop // coefficient level. 514*09537850SAkhilesh Sanikop template <typename ResidualType, bool is_dc_coefficient> 515*09537850SAkhilesh Sanikop LIBGAV1_ALWAYS_INLINE bool ReadSignAndApplyDequantization( 516*09537850SAkhilesh Sanikop const uint16_t* scan, int i, int q_value, const uint8_t* quantizer_matrix, 517*09537850SAkhilesh Sanikop int shift, int max_value, uint16_t* dc_sign_cdf, int8_t* dc_category, 518*09537850SAkhilesh Sanikop int* coefficient_level, 519*09537850SAkhilesh Sanikop ResidualType* residual_buffer); // Part of 5.11.39. 520*09537850SAkhilesh Sanikop int ReadCoeffBaseRange(uint16_t* cdf); // Part of 5.11.39. 521*09537850SAkhilesh Sanikop // Returns the number of non-zero coefficients that were read. |tx_type| is an 522*09537850SAkhilesh Sanikop // output parameter that stores the computed transform type for the plane 523*09537850SAkhilesh Sanikop // whose coefficients were read. Returns -1 on failure. 524*09537850SAkhilesh Sanikop template <typename ResidualType> 525*09537850SAkhilesh Sanikop int ReadTransformCoefficients(const Block& block, Plane plane, int start_x, 526*09537850SAkhilesh Sanikop int start_y, TransformSize tx_size, 527*09537850SAkhilesh Sanikop TransformType* tx_type); // 5.11.39. 528*09537850SAkhilesh Sanikop bool TransformBlock(const Block& block, Plane plane, int base_x, int base_y, 529*09537850SAkhilesh Sanikop TransformSize tx_size, int x, int y, 530*09537850SAkhilesh Sanikop ProcessingMode mode); // 5.11.35. 531*09537850SAkhilesh Sanikop // Iterative implementation of 5.11.36. 532*09537850SAkhilesh Sanikop bool TransformTree(const Block& block, int start_x, int start_y, 533*09537850SAkhilesh Sanikop BlockSize plane_size, ProcessingMode mode); 534*09537850SAkhilesh Sanikop void ReconstructBlock(const Block& block, Plane plane, int start_x, 535*09537850SAkhilesh Sanikop int start_y, TransformSize tx_size, 536*09537850SAkhilesh Sanikop TransformType tx_type, 537*09537850SAkhilesh Sanikop int non_zero_coeff_count); // Part of 7.12.3. 538*09537850SAkhilesh Sanikop bool Residual(const Block& block, ProcessingMode mode); // 5.11.34. 539*09537850SAkhilesh Sanikop // part of 5.11.5 (reset_block_context() in the spec). 540*09537850SAkhilesh Sanikop void ResetEntropyContext(const Block& block); 541*09537850SAkhilesh Sanikop // Populates the |color_context| and |color_order| for the |i|th iteration 542*09537850SAkhilesh Sanikop // with entries counting down from |start| to |end| (|start| > |end|). 543*09537850SAkhilesh Sanikop void PopulatePaletteColorContexts( 544*09537850SAkhilesh Sanikop const Block& block, PlaneType plane_type, int i, int start, int end, 545*09537850SAkhilesh Sanikop uint8_t color_order[kMaxPaletteSquare][kMaxPaletteSize], 546*09537850SAkhilesh Sanikop uint8_t color_context[kMaxPaletteSquare]); // 5.11.50. 547*09537850SAkhilesh Sanikop bool ReadPaletteTokens(const Block& block); // 5.11.49. 548*09537850SAkhilesh Sanikop template <typename Pixel> 549*09537850SAkhilesh Sanikop void IntraPrediction(const Block& block, Plane plane, int x, int y, 550*09537850SAkhilesh Sanikop bool has_left, bool has_top, bool has_top_right, 551*09537850SAkhilesh Sanikop bool has_bottom_left, PredictionMode mode, 552*09537850SAkhilesh Sanikop TransformSize tx_size); 553*09537850SAkhilesh Sanikop int GetIntraEdgeFilterType(const Block& block, 554*09537850SAkhilesh Sanikop Plane plane) const; // 7.11.2.8. 555*09537850SAkhilesh Sanikop template <typename Pixel> 556*09537850SAkhilesh Sanikop void DirectionalPrediction(const Block& block, Plane plane, int x, int y, 557*09537850SAkhilesh Sanikop bool has_left, bool has_top, bool needs_left, 558*09537850SAkhilesh Sanikop bool needs_top, int prediction_angle, int width, 559*09537850SAkhilesh Sanikop int height, int max_x, int max_y, 560*09537850SAkhilesh Sanikop TransformSize tx_size, Pixel* top_row, 561*09537850SAkhilesh Sanikop Pixel* left_column); // 7.11.2.4. 562*09537850SAkhilesh Sanikop template <typename Pixel> 563*09537850SAkhilesh Sanikop void PalettePrediction(const Block& block, Plane plane, int start_x, 564*09537850SAkhilesh Sanikop int start_y, int x, int y, 565*09537850SAkhilesh Sanikop TransformSize tx_size); // 7.11.4. 566*09537850SAkhilesh Sanikop template <typename Pixel> 567*09537850SAkhilesh Sanikop void ChromaFromLumaPrediction(const Block& block, Plane plane, int start_x, 568*09537850SAkhilesh Sanikop int start_y, 569*09537850SAkhilesh Sanikop TransformSize tx_size); // 7.11.5. 570*09537850SAkhilesh Sanikop // Section 7.19. Applies some filtering and reordering to the motion vectors 571*09537850SAkhilesh Sanikop // for the given |block| and stores them into |current_frame_|. 572*09537850SAkhilesh Sanikop void StoreMotionFieldMvsIntoCurrentFrame(const Block& block); 573*09537850SAkhilesh Sanikop 574*09537850SAkhilesh Sanikop // SetCdfContext*() functions will populate the |left_context_| and 575*09537850SAkhilesh Sanikop // |top_context_| for the |block|. 576*09537850SAkhilesh Sanikop void SetCdfContextUsePredictedSegmentId(const Block& block, 577*09537850SAkhilesh Sanikop bool use_predicted_segment_id); 578*09537850SAkhilesh Sanikop void SetCdfContextCompoundType(const Block& block, 579*09537850SAkhilesh Sanikop bool is_explicit_compound_type, 580*09537850SAkhilesh Sanikop bool is_compound_type_average); 581*09537850SAkhilesh Sanikop void SetCdfContextSkipMode(const Block& block, bool skip_mode); 582*09537850SAkhilesh Sanikop void SetCdfContextPaletteSize(const Block& block); 583*09537850SAkhilesh Sanikop void SetCdfContextUVMode(const Block& block); 584*09537850SAkhilesh Sanikop 585*09537850SAkhilesh Sanikop // Returns the zero-based index of the super block that contains |row4x4| 586*09537850SAkhilesh Sanikop // relative to the start of this tile. SuperBlockRowIndex(int row4x4)587*09537850SAkhilesh Sanikop int SuperBlockRowIndex(int row4x4) const { 588*09537850SAkhilesh Sanikop return (row4x4 - row4x4_start_) >> 589*09537850SAkhilesh Sanikop (sequence_header_.use_128x128_superblock ? 5 : 4); 590*09537850SAkhilesh Sanikop } 591*09537850SAkhilesh Sanikop 592*09537850SAkhilesh Sanikop // Returns the zero-based index of the super block that contains |column4x4| 593*09537850SAkhilesh Sanikop // relative to the start of this tile. SuperBlockColumnIndex(int column4x4)594*09537850SAkhilesh Sanikop int SuperBlockColumnIndex(int column4x4) const { 595*09537850SAkhilesh Sanikop return (column4x4 - column4x4_start_) >> 596*09537850SAkhilesh Sanikop (sequence_header_.use_128x128_superblock ? 5 : 4); 597*09537850SAkhilesh Sanikop } 598*09537850SAkhilesh Sanikop 599*09537850SAkhilesh Sanikop // Returns the zero-based index of the block that starts at row4x4 or 600*09537850SAkhilesh Sanikop // column4x4 relative to the start of the superblock that contains the block. 601*09537850SAkhilesh Sanikop // This is used to index into the members of |left_context_| and 602*09537850SAkhilesh Sanikop // |top_context_|. CdfContextIndex(int row_or_column4x4)603*09537850SAkhilesh Sanikop int CdfContextIndex(int row_or_column4x4) const { 604*09537850SAkhilesh Sanikop return row_or_column4x4 - 605*09537850SAkhilesh Sanikop (row_or_column4x4 & 606*09537850SAkhilesh Sanikop (sequence_header_.use_128x128_superblock ? ~31 : ~15)); 607*09537850SAkhilesh Sanikop } 608*09537850SAkhilesh Sanikop SuperBlockSize()609*09537850SAkhilesh Sanikop BlockSize SuperBlockSize() const { 610*09537850SAkhilesh Sanikop return sequence_header_.use_128x128_superblock ? kBlock128x128 611*09537850SAkhilesh Sanikop : kBlock64x64; 612*09537850SAkhilesh Sanikop } PlaneCount()613*09537850SAkhilesh Sanikop int PlaneCount() const { 614*09537850SAkhilesh Sanikop return sequence_header_.color_config.is_monochrome ? kMaxPlanesMonochrome 615*09537850SAkhilesh Sanikop : kMaxPlanes; 616*09537850SAkhilesh Sanikop } 617*09537850SAkhilesh Sanikop 618*09537850SAkhilesh Sanikop const int number_; 619*09537850SAkhilesh Sanikop const int row_; 620*09537850SAkhilesh Sanikop const int column_; 621*09537850SAkhilesh Sanikop const uint8_t* const data_; 622*09537850SAkhilesh Sanikop size_t size_; 623*09537850SAkhilesh Sanikop int row4x4_start_; 624*09537850SAkhilesh Sanikop int row4x4_end_; 625*09537850SAkhilesh Sanikop int column4x4_start_; 626*09537850SAkhilesh Sanikop int column4x4_end_; 627*09537850SAkhilesh Sanikop int superblock_rows_; 628*09537850SAkhilesh Sanikop int superblock_columns_; 629*09537850SAkhilesh Sanikop bool read_deltas_; 630*09537850SAkhilesh Sanikop const int8_t subsampling_x_[kMaxPlanes]; 631*09537850SAkhilesh Sanikop const int8_t subsampling_y_[kMaxPlanes]; 632*09537850SAkhilesh Sanikop 633*09537850SAkhilesh Sanikop // The dimensions (in order) are: segment_id, level_index (based on plane and 634*09537850SAkhilesh Sanikop // direction), reference_frame and mode_id. 635*09537850SAkhilesh Sanikop uint8_t deblock_filter_levels_[kMaxSegments][kFrameLfCount] 636*09537850SAkhilesh Sanikop [kNumReferenceFrameTypes][2]; 637*09537850SAkhilesh Sanikop 638*09537850SAkhilesh Sanikop // current_quantizer_index_ is in the range [0, 255]. 639*09537850SAkhilesh Sanikop uint8_t current_quantizer_index_; 640*09537850SAkhilesh Sanikop // These two arrays (|coefficient_levels_| and |dc_categories_|) are used to 641*09537850SAkhilesh Sanikop // store the entropy context. Their dimensions are as follows: First - 642*09537850SAkhilesh Sanikop // left/top; Second - plane; Third - row4x4 (if first dimension is 643*09537850SAkhilesh Sanikop // left)/column4x4 (if first dimension is top). 644*09537850SAkhilesh Sanikop // 645*09537850SAkhilesh Sanikop // This is equivalent to the LeftLevelContext and AboveLevelContext arrays in 646*09537850SAkhilesh Sanikop // the spec. In the spec, it stores values from 0 through 63 (inclusive). The 647*09537850SAkhilesh Sanikop // stored values are used to compute the left and top contexts in 648*09537850SAkhilesh Sanikop // GetTransformAllZeroContext. In that function, we only care about the 649*09537850SAkhilesh Sanikop // following values: 0, 1, 2, 3 and >= 4. So instead of clamping to 63, we 650*09537850SAkhilesh Sanikop // clamp to 4 (i.e.) all the values greater than 4 are stored as 4. 651*09537850SAkhilesh Sanikop std::array<Array2D<uint8_t>, 2> coefficient_levels_; 652*09537850SAkhilesh Sanikop // This is equivalent to the LeftDcContext and AboveDcContext arrays in the 653*09537850SAkhilesh Sanikop // spec. In the spec, it can store 3 possible values: 0, 1 and 2 (where 1 654*09537850SAkhilesh Sanikop // means the value is < 0, 2 means the value is > 0 and 0 means the value is 655*09537850SAkhilesh Sanikop // equal to 0). 656*09537850SAkhilesh Sanikop // 657*09537850SAkhilesh Sanikop // The stored values are used in two places: 658*09537850SAkhilesh Sanikop // * GetTransformAllZeroContext: Here, we only care about whether the 659*09537850SAkhilesh Sanikop // value is 0 or not (whether it is 1 or 2 is irrelevant). 660*09537850SAkhilesh Sanikop // * GetDcSignContext: Here, we do the following computation: if the 661*09537850SAkhilesh Sanikop // stored value is 1, we decrement a counter. If the stored value is 2 662*09537850SAkhilesh Sanikop // we increment a counter. 663*09537850SAkhilesh Sanikop // 664*09537850SAkhilesh Sanikop // Based on this usage, we can simply replace 1 with -1 and 2 with 1 and 665*09537850SAkhilesh Sanikop // use that value to compute the counter. 666*09537850SAkhilesh Sanikop // 667*09537850SAkhilesh Sanikop // The usage on GetTransformAllZeroContext is unaffected since there we 668*09537850SAkhilesh Sanikop // only care about whether it is 0 or not. 669*09537850SAkhilesh Sanikop std::array<Array2D<int8_t>, 2> dc_categories_; 670*09537850SAkhilesh Sanikop const ObuSequenceHeader& sequence_header_; 671*09537850SAkhilesh Sanikop const ObuFrameHeader& frame_header_; 672*09537850SAkhilesh Sanikop const std::array<bool, kNumReferenceFrameTypes>& reference_frame_sign_bias_; 673*09537850SAkhilesh Sanikop const std::array<RefCountedBufferPtr, kNumReferenceFrameTypes>& 674*09537850SAkhilesh Sanikop reference_frames_; 675*09537850SAkhilesh Sanikop TemporalMotionField& motion_field_; 676*09537850SAkhilesh Sanikop const std::array<uint8_t, kNumReferenceFrameTypes>& reference_order_hint_; 677*09537850SAkhilesh Sanikop const WedgeMaskArray& wedge_masks_; 678*09537850SAkhilesh Sanikop const QuantizerMatrix& quantizer_matrix_; 679*09537850SAkhilesh Sanikop EntropyDecoder reader_; 680*09537850SAkhilesh Sanikop SymbolDecoderContext symbol_decoder_context_; 681*09537850SAkhilesh Sanikop SymbolDecoderContext* const saved_symbol_decoder_context_; 682*09537850SAkhilesh Sanikop const SegmentationMap* prev_segment_ids_; 683*09537850SAkhilesh Sanikop const dsp::Dsp& dsp_; 684*09537850SAkhilesh Sanikop PostFilter& post_filter_; 685*09537850SAkhilesh Sanikop BlockParametersHolder& block_parameters_holder_; 686*09537850SAkhilesh Sanikop Quantizer quantizer_; 687*09537850SAkhilesh Sanikop // When there is no multi-threading within the Tile, |residual_buffer_| is 688*09537850SAkhilesh Sanikop // used. When there is multi-threading within the Tile, 689*09537850SAkhilesh Sanikop // |residual_buffer_threaded_| is used. In the following comment, 690*09537850SAkhilesh Sanikop // |residual_buffer| refers to either |residual_buffer_| or 691*09537850SAkhilesh Sanikop // |residual_buffer_threaded_| depending on whether multi-threading is enabled 692*09537850SAkhilesh Sanikop // within the Tile or not. 693*09537850SAkhilesh Sanikop // The |residual_buffer| is used to help with the dequantization and the 694*09537850SAkhilesh Sanikop // inverse transform processes. It is declared as a uint8_t, but is always 695*09537850SAkhilesh Sanikop // accessed either as an int16_t or int32_t depending on |bitdepth|. Here is 696*09537850SAkhilesh Sanikop // what it stores at various stages of the decoding process (in the order 697*09537850SAkhilesh Sanikop // which they happen): 698*09537850SAkhilesh Sanikop // 1) In ReadTransformCoefficients(), this buffer is used to store the 699*09537850SAkhilesh Sanikop // dequantized values. 700*09537850SAkhilesh Sanikop // 2) In Reconstruct(), this buffer is used as the input to the row 701*09537850SAkhilesh Sanikop // transform process. 702*09537850SAkhilesh Sanikop // The size of this buffer would be: 703*09537850SAkhilesh Sanikop // For |residual_buffer_|: (4096 + 32 * |kResidualPaddingVertical|) * 704*09537850SAkhilesh Sanikop // |residual_size_|. Where 4096 = 64x64 which is the maximum transform 705*09537850SAkhilesh Sanikop // size, and 32 * |kResidualPaddingVertical| is the padding to avoid 706*09537850SAkhilesh Sanikop // bottom boundary checks when parsing quantized coefficients. This 707*09537850SAkhilesh Sanikop // memory is allocated and owned by the Tile class. 708*09537850SAkhilesh Sanikop // For |residual_buffer_threaded_|: See the comment below. This memory is 709*09537850SAkhilesh Sanikop // not allocated or owned by the Tile class. 710*09537850SAkhilesh Sanikop AlignedUniquePtr<uint8_t> residual_buffer_; 711*09537850SAkhilesh Sanikop // This is a 2d array of pointers of size |superblock_rows_| by 712*09537850SAkhilesh Sanikop // |superblock_columns_| where each pointer points to a ResidualBuffer for a 713*09537850SAkhilesh Sanikop // single super block. The array is populated when the parsing process begins 714*09537850SAkhilesh Sanikop // by calling |residual_buffer_pool_->Get()| and the memory is released back 715*09537850SAkhilesh Sanikop // to the pool by calling |residual_buffer_pool_->Release()| when the decoding 716*09537850SAkhilesh Sanikop // process is complete. 717*09537850SAkhilesh Sanikop Array2D<std::unique_ptr<ResidualBuffer>> residual_buffer_threaded_; 718*09537850SAkhilesh Sanikop // sizeof(int16_t or int32_t) depending on |bitdepth|. 719*09537850SAkhilesh Sanikop const size_t residual_size_; 720*09537850SAkhilesh Sanikop // Number of superblocks on the top-right that will have to be decoded before 721*09537850SAkhilesh Sanikop // the current superblock can be decoded. This will be 1 if allow_intrabc is 722*09537850SAkhilesh Sanikop // false. If allow_intrabc is true, then this value will be 723*09537850SAkhilesh Sanikop // use_128x128_superblock ? 3 : 5. This is the allowed range of reference for 724*09537850SAkhilesh Sanikop // the top rows for intrabc. 725*09537850SAkhilesh Sanikop const int intra_block_copy_lag_; 726*09537850SAkhilesh Sanikop 727*09537850SAkhilesh Sanikop // In the Tile class, we use the "current_frame" in two ways: 728*09537850SAkhilesh Sanikop // 1) To write the decoded output into (using the |buffer_| view). 729*09537850SAkhilesh Sanikop // 2) To read the pixels for intra block copy (using the |current_frame_| 730*09537850SAkhilesh Sanikop // reference). 731*09537850SAkhilesh Sanikop // 732*09537850SAkhilesh Sanikop // When intra block copy is off, |buffer_| and |current_frame_| may or may not 733*09537850SAkhilesh Sanikop // point to the same plane pointers. But it is okay since |current_frame_| is 734*09537850SAkhilesh Sanikop // never used in this case. 735*09537850SAkhilesh Sanikop // 736*09537850SAkhilesh Sanikop // When intra block copy is on, |buffer_| and |current_frame_| always point to 737*09537850SAkhilesh Sanikop // the same plane pointers (since post filtering is disabled). So the usage in 738*09537850SAkhilesh Sanikop // both case 1 and case 2 remain valid. 739*09537850SAkhilesh Sanikop Array2DView<uint8_t> buffer_[kMaxPlanes]; 740*09537850SAkhilesh Sanikop RefCountedBuffer& current_frame_; 741*09537850SAkhilesh Sanikop 742*09537850SAkhilesh Sanikop Array2D<int8_t>& cdef_index_; 743*09537850SAkhilesh Sanikop Array2D<uint8_t>& cdef_skip_; 744*09537850SAkhilesh Sanikop Array2D<TransformSize>& inter_transform_sizes_; 745*09537850SAkhilesh Sanikop std::array<RestorationUnitInfo, kMaxPlanes> reference_unit_info_; 746*09537850SAkhilesh Sanikop // If |thread_pool_| is nullptr, the calling thread will do the parsing and 747*09537850SAkhilesh Sanikop // the decoding in one pass. If |thread_pool_| is not nullptr, then the main 748*09537850SAkhilesh Sanikop // thread will do the parsing while the thread pool workers will do the 749*09537850SAkhilesh Sanikop // decoding. 750*09537850SAkhilesh Sanikop ThreadPool* const thread_pool_; 751*09537850SAkhilesh Sanikop ThreadingParameters threading_; 752*09537850SAkhilesh Sanikop ResidualBufferPool* const residual_buffer_pool_; 753*09537850SAkhilesh Sanikop TileScratchBufferPool* const tile_scratch_buffer_pool_; 754*09537850SAkhilesh Sanikop BlockingCounterWithStatus* const pending_tiles_; 755*09537850SAkhilesh Sanikop bool split_parse_and_decode_; 756*09537850SAkhilesh Sanikop // This is used only when |split_parse_and_decode_| is false. 757*09537850SAkhilesh Sanikop std::unique_ptr<PredictionParameters> prediction_parameters_ = nullptr; 758*09537850SAkhilesh Sanikop // Stores the |transform_type| for the super block being decoded at a 4x4 759*09537850SAkhilesh Sanikop // granularity. The spec uses absolute indices for this array but it is 760*09537850SAkhilesh Sanikop // sufficient to use indices relative to the super block being decoded. 761*09537850SAkhilesh Sanikop TransformType transform_types_[32][32]; 762*09537850SAkhilesh Sanikop // delta_lf_[i] is in the range [-63, 63]. 763*09537850SAkhilesh Sanikop int8_t delta_lf_[kFrameLfCount]; 764*09537850SAkhilesh Sanikop // True if all the values in |delta_lf_| are zero. False otherwise. 765*09537850SAkhilesh Sanikop bool delta_lf_all_zero_; 766*09537850SAkhilesh Sanikop const bool frame_parallel_; 767*09537850SAkhilesh Sanikop const bool use_intra_prediction_buffer_; 768*09537850SAkhilesh Sanikop // Buffer used to store the unfiltered pixels that are necessary for decoding 769*09537850SAkhilesh Sanikop // the next superblock row (for the intra prediction process). Used only if 770*09537850SAkhilesh Sanikop // |use_intra_prediction_buffer_| is true. The |frame_scratch_buffer| contains 771*09537850SAkhilesh Sanikop // one row buffer for each tile row. This tile will have to use the buffer 772*09537850SAkhilesh Sanikop // corresponding to this tile's row. 773*09537850SAkhilesh Sanikop IntraPredictionBuffer* const intra_prediction_buffer_; 774*09537850SAkhilesh Sanikop // Stores the progress of the reference frames. This will be used to avoid 775*09537850SAkhilesh Sanikop // unnecessary calls into RefCountedBuffer::WaitUntil(). 776*09537850SAkhilesh Sanikop std::array<int, kNumReferenceFrameTypes> reference_frame_progress_cache_; 777*09537850SAkhilesh Sanikop // Stores the CDF contexts necessary for the "left" block. 778*09537850SAkhilesh Sanikop BlockCdfContext left_context_; 779*09537850SAkhilesh Sanikop // Stores the CDF contexts necessary for the "top" block. The size of this 780*09537850SAkhilesh Sanikop // buffer is the number of superblock columns in this tile. For each block, 781*09537850SAkhilesh Sanikop // the access index will be the corresponding SuperBlockColumnIndex()'th 782*09537850SAkhilesh Sanikop // entry. 783*09537850SAkhilesh Sanikop DynamicBuffer<BlockCdfContext> top_context_; 784*09537850SAkhilesh Sanikop }; 785*09537850SAkhilesh Sanikop 786*09537850SAkhilesh Sanikop struct Tile::Block { BlockBlock787*09537850SAkhilesh Sanikop Block(Tile* tile_ptr, BlockSize size, int row4x4, int column4x4, 788*09537850SAkhilesh Sanikop TileScratchBuffer* const scratch_buffer, ResidualPtr* residual) 789*09537850SAkhilesh Sanikop : tile(*tile_ptr), 790*09537850SAkhilesh Sanikop size(size), 791*09537850SAkhilesh Sanikop row4x4(row4x4), 792*09537850SAkhilesh Sanikop column4x4(column4x4), 793*09537850SAkhilesh Sanikop width(kBlockWidthPixels[size]), 794*09537850SAkhilesh Sanikop height(kBlockHeightPixels[size]), 795*09537850SAkhilesh Sanikop width4x4(width >> 2), 796*09537850SAkhilesh Sanikop height4x4(height >> 2), 797*09537850SAkhilesh Sanikop scratch_buffer(scratch_buffer), 798*09537850SAkhilesh Sanikop residual(residual), 799*09537850SAkhilesh Sanikop top_context(tile.top_context_.get() + 800*09537850SAkhilesh Sanikop tile.SuperBlockColumnIndex(column4x4)), 801*09537850SAkhilesh Sanikop top_context_index(tile.CdfContextIndex(column4x4)), 802*09537850SAkhilesh Sanikop left_context_index(tile.CdfContextIndex(row4x4)) { 803*09537850SAkhilesh Sanikop assert(size != kBlockInvalid); 804*09537850SAkhilesh Sanikop residual_size[kPlaneY] = kPlaneResidualSize[size][0][0]; 805*09537850SAkhilesh Sanikop residual_size[kPlaneU] = residual_size[kPlaneV] = 806*09537850SAkhilesh Sanikop kPlaneResidualSize[size][tile.subsampling_x_[kPlaneU]] 807*09537850SAkhilesh Sanikop [tile.subsampling_y_[kPlaneU]]; 808*09537850SAkhilesh Sanikop assert(residual_size[kPlaneY] != kBlockInvalid); 809*09537850SAkhilesh Sanikop if (tile.PlaneCount() > 1) { 810*09537850SAkhilesh Sanikop assert(residual_size[kPlaneU] != kBlockInvalid); 811*09537850SAkhilesh Sanikop } 812*09537850SAkhilesh Sanikop if ((row4x4 & 1) == 0 && 813*09537850SAkhilesh Sanikop (tile.sequence_header_.color_config.subsampling_y & height4x4) == 1) { 814*09537850SAkhilesh Sanikop has_chroma = false; 815*09537850SAkhilesh Sanikop } else if ((column4x4 & 1) == 0 && 816*09537850SAkhilesh Sanikop (tile.sequence_header_.color_config.subsampling_x & width4x4) == 817*09537850SAkhilesh Sanikop 1) { 818*09537850SAkhilesh Sanikop has_chroma = false; 819*09537850SAkhilesh Sanikop } else { 820*09537850SAkhilesh Sanikop has_chroma = !tile.sequence_header_.color_config.is_monochrome; 821*09537850SAkhilesh Sanikop } 822*09537850SAkhilesh Sanikop top_available[kPlaneY] = tile.IsTopInside(row4x4); 823*09537850SAkhilesh Sanikop left_available[kPlaneY] = tile.IsLeftInside(column4x4); 824*09537850SAkhilesh Sanikop if (has_chroma) { 825*09537850SAkhilesh Sanikop // top_available[kPlaneU] and top_available[kPlaneV] are valid only if 826*09537850SAkhilesh Sanikop // has_chroma is true. 827*09537850SAkhilesh Sanikop // The next 3 lines are equivalent to: 828*09537850SAkhilesh Sanikop // top_available[kPlaneU] = top_available[kPlaneV] = 829*09537850SAkhilesh Sanikop // top_available[kPlaneY] && 830*09537850SAkhilesh Sanikop // ((tile.sequence_header_.color_config.subsampling_y & height4x4) == 831*09537850SAkhilesh Sanikop // 0 || tile.IsTopInside(row4x4 - 1)); 832*09537850SAkhilesh Sanikop top_available[kPlaneU] = top_available[kPlaneV] = tile.IsTopInside( 833*09537850SAkhilesh Sanikop row4x4 - 834*09537850SAkhilesh Sanikop (tile.sequence_header_.color_config.subsampling_y & height4x4)); 835*09537850SAkhilesh Sanikop // left_available[kPlaneU] and left_available[kPlaneV] are valid only if 836*09537850SAkhilesh Sanikop // has_chroma is true. 837*09537850SAkhilesh Sanikop // The next 3 lines are equivalent to: 838*09537850SAkhilesh Sanikop // left_available[kPlaneU] = left_available[kPlaneV] = 839*09537850SAkhilesh Sanikop // left_available[kPlaneY] && 840*09537850SAkhilesh Sanikop // ((tile.sequence_header_.color_config.subsampling_x & width4x4) == 0 841*09537850SAkhilesh Sanikop // || tile.IsLeftInside(column4x4 - 1)); 842*09537850SAkhilesh Sanikop left_available[kPlaneU] = left_available[kPlaneV] = tile.IsLeftInside( 843*09537850SAkhilesh Sanikop column4x4 - 844*09537850SAkhilesh Sanikop (tile.sequence_header_.color_config.subsampling_x & width4x4)); 845*09537850SAkhilesh Sanikop } 846*09537850SAkhilesh Sanikop const ptrdiff_t stride = tile.BlockParametersStride(); 847*09537850SAkhilesh Sanikop BlockParameters** const bps = 848*09537850SAkhilesh Sanikop tile.BlockParametersAddress(row4x4, column4x4); 849*09537850SAkhilesh Sanikop bp = *bps; 850*09537850SAkhilesh Sanikop // bp_top is valid only if top_available[kPlaneY] is true. 851*09537850SAkhilesh Sanikop if (top_available[kPlaneY]) { 852*09537850SAkhilesh Sanikop bp_top = *(bps - stride); 853*09537850SAkhilesh Sanikop } 854*09537850SAkhilesh Sanikop // bp_left is valid only if left_available[kPlaneY] is true. 855*09537850SAkhilesh Sanikop if (left_available[kPlaneY]) { 856*09537850SAkhilesh Sanikop bp_left = *(bps - 1); 857*09537850SAkhilesh Sanikop } 858*09537850SAkhilesh Sanikop } 859*09537850SAkhilesh Sanikop HasChromaBlock860*09537850SAkhilesh Sanikop bool HasChroma() const { return has_chroma; } 861*09537850SAkhilesh Sanikop 862*09537850SAkhilesh Sanikop // These return values of these group of functions are valid only if the 863*09537850SAkhilesh Sanikop // corresponding top_available or left_available is true. TopReferenceBlock864*09537850SAkhilesh Sanikop ReferenceFrameType TopReference(int index) const { 865*09537850SAkhilesh Sanikop return bp_top->reference_frame[index]; 866*09537850SAkhilesh Sanikop } 867*09537850SAkhilesh Sanikop LeftReferenceBlock868*09537850SAkhilesh Sanikop ReferenceFrameType LeftReference(int index) const { 869*09537850SAkhilesh Sanikop return bp_left->reference_frame[index]; 870*09537850SAkhilesh Sanikop } 871*09537850SAkhilesh Sanikop IsTopIntraBlock872*09537850SAkhilesh Sanikop bool IsTopIntra() const { return TopReference(0) <= kReferenceFrameIntra; } IsLeftIntraBlock873*09537850SAkhilesh Sanikop bool IsLeftIntra() const { return LeftReference(0) <= kReferenceFrameIntra; } 874*09537850SAkhilesh Sanikop IsTopSingleBlock875*09537850SAkhilesh Sanikop bool IsTopSingle() const { return TopReference(1) <= kReferenceFrameIntra; } IsLeftSingleBlock876*09537850SAkhilesh Sanikop bool IsLeftSingle() const { return LeftReference(1) <= kReferenceFrameIntra; } 877*09537850SAkhilesh Sanikop CountReferencesBlock878*09537850SAkhilesh Sanikop int CountReferences(ReferenceFrameType type) const { 879*09537850SAkhilesh Sanikop return static_cast<int>(top_available[kPlaneY] && 880*09537850SAkhilesh Sanikop bp_top->reference_frame[0] == type) + 881*09537850SAkhilesh Sanikop static_cast<int>(top_available[kPlaneY] && 882*09537850SAkhilesh Sanikop bp_top->reference_frame[1] == type) + 883*09537850SAkhilesh Sanikop static_cast<int>(left_available[kPlaneY] && 884*09537850SAkhilesh Sanikop bp_left->reference_frame[0] == type) + 885*09537850SAkhilesh Sanikop static_cast<int>(left_available[kPlaneY] && 886*09537850SAkhilesh Sanikop bp_left->reference_frame[1] == type); 887*09537850SAkhilesh Sanikop } 888*09537850SAkhilesh Sanikop 889*09537850SAkhilesh Sanikop // 7.10.3. 890*09537850SAkhilesh Sanikop // Checks if there are any inter blocks to the left or above. If so, it 891*09537850SAkhilesh Sanikop // returns true indicating that the block has neighbors that are suitable for 892*09537850SAkhilesh Sanikop // use by overlapped motion compensation. HasOverlappableCandidatesBlock893*09537850SAkhilesh Sanikop bool HasOverlappableCandidates() const { 894*09537850SAkhilesh Sanikop const ptrdiff_t stride = tile.BlockParametersStride(); 895*09537850SAkhilesh Sanikop BlockParameters** const bps = tile.BlockParametersAddress(0, 0); 896*09537850SAkhilesh Sanikop if (top_available[kPlaneY]) { 897*09537850SAkhilesh Sanikop BlockParameters** bps_top = bps + (row4x4 - 1) * stride + (column4x4 | 1); 898*09537850SAkhilesh Sanikop const int columns = std::min(tile.frame_header_.columns4x4 - column4x4, 899*09537850SAkhilesh Sanikop static_cast<int>(width4x4)); 900*09537850SAkhilesh Sanikop BlockParameters** const bps_top_end = bps_top + columns; 901*09537850SAkhilesh Sanikop do { 902*09537850SAkhilesh Sanikop if ((*bps_top)->reference_frame[0] > kReferenceFrameIntra) { 903*09537850SAkhilesh Sanikop return true; 904*09537850SAkhilesh Sanikop } 905*09537850SAkhilesh Sanikop bps_top += 2; 906*09537850SAkhilesh Sanikop } while (bps_top < bps_top_end); 907*09537850SAkhilesh Sanikop } 908*09537850SAkhilesh Sanikop if (left_available[kPlaneY]) { 909*09537850SAkhilesh Sanikop BlockParameters** bps_left = bps + (row4x4 | 1) * stride + column4x4 - 1; 910*09537850SAkhilesh Sanikop const int rows = std::min(tile.frame_header_.rows4x4 - row4x4, 911*09537850SAkhilesh Sanikop static_cast<int>(height4x4)); 912*09537850SAkhilesh Sanikop BlockParameters** const bps_left_end = bps_left + rows * stride; 913*09537850SAkhilesh Sanikop do { 914*09537850SAkhilesh Sanikop if ((*bps_left)->reference_frame[0] > kReferenceFrameIntra) { 915*09537850SAkhilesh Sanikop return true; 916*09537850SAkhilesh Sanikop } 917*09537850SAkhilesh Sanikop bps_left += 2 * stride; 918*09537850SAkhilesh Sanikop } while (bps_left < bps_left_end); 919*09537850SAkhilesh Sanikop } 920*09537850SAkhilesh Sanikop return false; 921*09537850SAkhilesh Sanikop } 922*09537850SAkhilesh Sanikop 923*09537850SAkhilesh Sanikop Tile& tile; 924*09537850SAkhilesh Sanikop bool has_chroma; 925*09537850SAkhilesh Sanikop const BlockSize size; 926*09537850SAkhilesh Sanikop bool top_available[kMaxPlanes]; 927*09537850SAkhilesh Sanikop bool left_available[kMaxPlanes]; 928*09537850SAkhilesh Sanikop BlockSize residual_size[kMaxPlanes]; 929*09537850SAkhilesh Sanikop const int row4x4; 930*09537850SAkhilesh Sanikop const int column4x4; 931*09537850SAkhilesh Sanikop const int width; 932*09537850SAkhilesh Sanikop const int height; 933*09537850SAkhilesh Sanikop const int width4x4; 934*09537850SAkhilesh Sanikop const int height4x4; 935*09537850SAkhilesh Sanikop const BlockParameters* bp_top; 936*09537850SAkhilesh Sanikop const BlockParameters* bp_left; 937*09537850SAkhilesh Sanikop BlockParameters* bp; 938*09537850SAkhilesh Sanikop TileScratchBuffer* const scratch_buffer; 939*09537850SAkhilesh Sanikop ResidualPtr* const residual; 940*09537850SAkhilesh Sanikop BlockCdfContext* const top_context; 941*09537850SAkhilesh Sanikop const int top_context_index; 942*09537850SAkhilesh Sanikop const int left_context_index; 943*09537850SAkhilesh Sanikop }; 944*09537850SAkhilesh Sanikop 945*09537850SAkhilesh Sanikop extern template bool 946*09537850SAkhilesh Sanikop Tile::ProcessSuperBlockRow<kProcessingModeDecodeOnly, false>( 947*09537850SAkhilesh Sanikop int row4x4, TileScratchBuffer* scratch_buffer); 948*09537850SAkhilesh Sanikop extern template bool 949*09537850SAkhilesh Sanikop Tile::ProcessSuperBlockRow<kProcessingModeParseAndDecode, true>( 950*09537850SAkhilesh Sanikop int row4x4, TileScratchBuffer* scratch_buffer); 951*09537850SAkhilesh Sanikop 952*09537850SAkhilesh Sanikop } // namespace libgav1 953*09537850SAkhilesh Sanikop 954*09537850SAkhilesh Sanikop #endif // LIBGAV1_SRC_TILE_H_ 955