xref: /aosp_15_r20/external/libgav1/src/tile.h (revision 095378508e87ed692bf8dfeb34008b65b3735891)
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