xref: /aosp_15_r20/external/libgav1/src/tile/bitstream/mode_info.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop // Copyright 2019 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop //      http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop 
15*09537850SAkhilesh Sanikop #include <algorithm>
16*09537850SAkhilesh Sanikop #include <array>
17*09537850SAkhilesh Sanikop #include <cassert>
18*09537850SAkhilesh Sanikop #include <cstdint>
19*09537850SAkhilesh Sanikop #include <cstdlib>
20*09537850SAkhilesh Sanikop #include <cstring>
21*09537850SAkhilesh Sanikop #include <memory>
22*09537850SAkhilesh Sanikop #include <vector>
23*09537850SAkhilesh Sanikop 
24*09537850SAkhilesh Sanikop #include "src/buffer_pool.h"
25*09537850SAkhilesh Sanikop #include "src/dsp/constants.h"
26*09537850SAkhilesh Sanikop #include "src/motion_vector.h"
27*09537850SAkhilesh Sanikop #include "src/obu_parser.h"
28*09537850SAkhilesh Sanikop #include "src/prediction_mask.h"
29*09537850SAkhilesh Sanikop #include "src/symbol_decoder_context.h"
30*09537850SAkhilesh Sanikop #include "src/tile.h"
31*09537850SAkhilesh Sanikop #include "src/utils/array_2d.h"
32*09537850SAkhilesh Sanikop #include "src/utils/bit_mask_set.h"
33*09537850SAkhilesh Sanikop #include "src/utils/block_parameters_holder.h"
34*09537850SAkhilesh Sanikop #include "src/utils/common.h"
35*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
36*09537850SAkhilesh Sanikop #include "src/utils/entropy_decoder.h"
37*09537850SAkhilesh Sanikop #include "src/utils/logging.h"
38*09537850SAkhilesh Sanikop #include "src/utils/segmentation.h"
39*09537850SAkhilesh Sanikop #include "src/utils/segmentation_map.h"
40*09537850SAkhilesh Sanikop #include "src/utils/types.h"
41*09537850SAkhilesh Sanikop 
42*09537850SAkhilesh Sanikop namespace libgav1 {
43*09537850SAkhilesh Sanikop namespace {
44*09537850SAkhilesh Sanikop 
45*09537850SAkhilesh Sanikop constexpr int kDeltaQSmall = 3;
46*09537850SAkhilesh Sanikop constexpr int kDeltaLfSmall = 3;
47*09537850SAkhilesh Sanikop 
48*09537850SAkhilesh Sanikop constexpr uint8_t kIntraYModeContext[kIntraPredictionModesY] = {
49*09537850SAkhilesh Sanikop     0, 1, 2, 3, 4, 4, 4, 4, 3, 0, 1, 2, 0};
50*09537850SAkhilesh Sanikop 
51*09537850SAkhilesh Sanikop constexpr uint8_t kSizeGroup[kMaxBlockSizes] = {
52*09537850SAkhilesh Sanikop     0, 0, 0, 0, 1, 1, 1, 0, 1, 2, 2, 2, 1, 2, 3, 3, 2, 3, 3, 3, 3, 3};
53*09537850SAkhilesh Sanikop 
54*09537850SAkhilesh Sanikop constexpr int kCompoundModeNewMvContexts = 5;
55*09537850SAkhilesh Sanikop constexpr uint8_t kCompoundModeContextMap[3][kCompoundModeNewMvContexts] = {
56*09537850SAkhilesh Sanikop     {0, 1, 1, 1, 1}, {1, 2, 3, 4, 4}, {4, 4, 5, 6, 7}};
57*09537850SAkhilesh Sanikop 
58*09537850SAkhilesh Sanikop enum CflSign : uint8_t {
59*09537850SAkhilesh Sanikop   kCflSignZero = 0,
60*09537850SAkhilesh Sanikop   kCflSignNegative = 1,
61*09537850SAkhilesh Sanikop   kCflSignPositive = 2
62*09537850SAkhilesh Sanikop };
63*09537850SAkhilesh Sanikop 
64*09537850SAkhilesh Sanikop // For each possible value of the combined signs (which is read from the
65*09537850SAkhilesh Sanikop // bitstream), this array stores the following: sign_u, sign_v, alpha_u_context,
66*09537850SAkhilesh Sanikop // alpha_v_context. Only positive entries are used. Entry at index i is computed
67*09537850SAkhilesh Sanikop // as follows:
68*09537850SAkhilesh Sanikop // sign_u = i / 3
69*09537850SAkhilesh Sanikop // sign_v = i % 3
70*09537850SAkhilesh Sanikop // alpha_u_context = i - 2
71*09537850SAkhilesh Sanikop // alpha_v_context = (sign_v - 1) * 3 + sign_u
72*09537850SAkhilesh Sanikop constexpr int8_t kCflAlphaLookup[kCflAlphaSignsSymbolCount][4] = {
73*09537850SAkhilesh Sanikop     {0, 1, -2, 0}, {0, 2, -1, 3}, {1, 0, 0, -2}, {1, 1, 1, 1},
74*09537850SAkhilesh Sanikop     {1, 2, 2, 4},  {2, 0, 3, -1}, {2, 1, 4, 2},  {2, 2, 5, 5},
75*09537850SAkhilesh Sanikop };
76*09537850SAkhilesh Sanikop 
77*09537850SAkhilesh Sanikop constexpr BitMaskSet kPredictionModeHasNearMvMask(kPredictionModeNearMv,
78*09537850SAkhilesh Sanikop                                                   kPredictionModeNearNearMv,
79*09537850SAkhilesh Sanikop                                                   kPredictionModeNearNewMv,
80*09537850SAkhilesh Sanikop                                                   kPredictionModeNewNearMv);
81*09537850SAkhilesh Sanikop 
82*09537850SAkhilesh Sanikop constexpr BitMaskSet kIsInterIntraModeAllowedMask(kBlock8x8, kBlock8x16,
83*09537850SAkhilesh Sanikop                                                   kBlock16x8, kBlock16x16,
84*09537850SAkhilesh Sanikop                                                   kBlock16x32, kBlock32x16,
85*09537850SAkhilesh Sanikop                                                   kBlock32x32);
86*09537850SAkhilesh Sanikop 
IsBackwardReference(ReferenceFrameType type)87*09537850SAkhilesh Sanikop bool IsBackwardReference(ReferenceFrameType type) {
88*09537850SAkhilesh Sanikop   return type >= kReferenceFrameBackward && type <= kReferenceFrameAlternate;
89*09537850SAkhilesh Sanikop }
90*09537850SAkhilesh Sanikop 
IsSameDirectionReferencePair(ReferenceFrameType type1,ReferenceFrameType type2)91*09537850SAkhilesh Sanikop bool IsSameDirectionReferencePair(ReferenceFrameType type1,
92*09537850SAkhilesh Sanikop                                   ReferenceFrameType type2) {
93*09537850SAkhilesh Sanikop   return (type1 >= kReferenceFrameBackward) ==
94*09537850SAkhilesh Sanikop          (type2 >= kReferenceFrameBackward);
95*09537850SAkhilesh Sanikop }
96*09537850SAkhilesh Sanikop 
97*09537850SAkhilesh Sanikop // This is called neg_deinterleave() in the spec.
DecodeSegmentId(int diff,int reference,int max)98*09537850SAkhilesh Sanikop int DecodeSegmentId(int diff, int reference, int max) {
99*09537850SAkhilesh Sanikop   if (reference == 0) return diff;
100*09537850SAkhilesh Sanikop   if (reference >= max - 1) return max - diff - 1;
101*09537850SAkhilesh Sanikop   const int value = ((diff & 1) != 0) ? reference + ((diff + 1) >> 1)
102*09537850SAkhilesh Sanikop                                       : reference - (diff >> 1);
103*09537850SAkhilesh Sanikop   const int reference2 = (reference << 1);
104*09537850SAkhilesh Sanikop   if (reference2 < max) {
105*09537850SAkhilesh Sanikop     return (diff <= reference2) ? value : diff;
106*09537850SAkhilesh Sanikop   }
107*09537850SAkhilesh Sanikop   return (diff <= ((max - reference - 1) << 1)) ? value : max - (diff + 1);
108*09537850SAkhilesh Sanikop }
109*09537850SAkhilesh Sanikop 
110*09537850SAkhilesh Sanikop // This is called DrlCtxStack in section 7.10.2.14 of the spec.
111*09537850SAkhilesh Sanikop // In the spec, the weights of all the nearest mvs are incremented by a bonus
112*09537850SAkhilesh Sanikop // weight which is larger than any natural weight, and the weights of the mvs
113*09537850SAkhilesh Sanikop // are compared with this bonus weight to determine their contexts. We replace
114*09537850SAkhilesh Sanikop // this procedure by introducing |nearest_mv_count| in PredictionParameters,
115*09537850SAkhilesh Sanikop // which records the count of the nearest mvs. Since all the nearest mvs are in
116*09537850SAkhilesh Sanikop // the beginning of the mv stack, the |index| of a mv in the mv stack can be
117*09537850SAkhilesh Sanikop // compared with |nearest_mv_count| to get that mv's context.
GetRefMvIndexContext(int nearest_mv_count,int index)118*09537850SAkhilesh Sanikop int GetRefMvIndexContext(int nearest_mv_count, int index) {
119*09537850SAkhilesh Sanikop   if (index + 1 < nearest_mv_count) {
120*09537850SAkhilesh Sanikop     return 0;
121*09537850SAkhilesh Sanikop   }
122*09537850SAkhilesh Sanikop   if (index + 1 == nearest_mv_count) {
123*09537850SAkhilesh Sanikop     return 1;
124*09537850SAkhilesh Sanikop   }
125*09537850SAkhilesh Sanikop   return 2;
126*09537850SAkhilesh Sanikop }
127*09537850SAkhilesh Sanikop 
128*09537850SAkhilesh Sanikop // Returns true if both the width and height of the block is less than 64.
IsBlockDimensionLessThan64(BlockSize size)129*09537850SAkhilesh Sanikop bool IsBlockDimensionLessThan64(BlockSize size) {
130*09537850SAkhilesh Sanikop   return size <= kBlock32x32 && size != kBlock16x64;
131*09537850SAkhilesh Sanikop }
132*09537850SAkhilesh Sanikop 
GetUseCompoundReferenceContext(const Tile::Block & block)133*09537850SAkhilesh Sanikop int GetUseCompoundReferenceContext(const Tile::Block& block) {
134*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY] && block.left_available[kPlaneY]) {
135*09537850SAkhilesh Sanikop     if (block.IsTopSingle() && block.IsLeftSingle()) {
136*09537850SAkhilesh Sanikop       return static_cast<int>(IsBackwardReference(block.TopReference(0))) ^
137*09537850SAkhilesh Sanikop              static_cast<int>(IsBackwardReference(block.LeftReference(0)));
138*09537850SAkhilesh Sanikop     }
139*09537850SAkhilesh Sanikop     if (block.IsTopSingle()) {
140*09537850SAkhilesh Sanikop       return 2 + static_cast<int>(IsBackwardReference(block.TopReference(0)) ||
141*09537850SAkhilesh Sanikop                                   block.IsTopIntra());
142*09537850SAkhilesh Sanikop     }
143*09537850SAkhilesh Sanikop     if (block.IsLeftSingle()) {
144*09537850SAkhilesh Sanikop       return 2 + static_cast<int>(IsBackwardReference(block.LeftReference(0)) ||
145*09537850SAkhilesh Sanikop                                   block.IsLeftIntra());
146*09537850SAkhilesh Sanikop     }
147*09537850SAkhilesh Sanikop     return 4;
148*09537850SAkhilesh Sanikop   }
149*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY]) {
150*09537850SAkhilesh Sanikop     return block.IsTopSingle()
151*09537850SAkhilesh Sanikop                ? static_cast<int>(IsBackwardReference(block.TopReference(0)))
152*09537850SAkhilesh Sanikop                : 3;
153*09537850SAkhilesh Sanikop   }
154*09537850SAkhilesh Sanikop   if (block.left_available[kPlaneY]) {
155*09537850SAkhilesh Sanikop     return block.IsLeftSingle()
156*09537850SAkhilesh Sanikop                ? static_cast<int>(IsBackwardReference(block.LeftReference(0)))
157*09537850SAkhilesh Sanikop                : 3;
158*09537850SAkhilesh Sanikop   }
159*09537850SAkhilesh Sanikop   return 1;
160*09537850SAkhilesh Sanikop }
161*09537850SAkhilesh Sanikop 
162*09537850SAkhilesh Sanikop // Calculates count0 by calling block.CountReferences() on the frame types from
163*09537850SAkhilesh Sanikop // type0_start to type0_end, inclusive, and summing the results.
164*09537850SAkhilesh Sanikop // Calculates count1 by calling block.CountReferences() on the frame types from
165*09537850SAkhilesh Sanikop // type1_start to type1_end, inclusive, and summing the results.
166*09537850SAkhilesh Sanikop // Compares count0 with count1 and returns 0, 1 or 2.
167*09537850SAkhilesh Sanikop //
168*09537850SAkhilesh Sanikop // See count_refs and ref_count_ctx in 8.3.2.
GetReferenceContext(const Tile::Block & block,ReferenceFrameType type0_start,ReferenceFrameType type0_end,ReferenceFrameType type1_start,ReferenceFrameType type1_end)169*09537850SAkhilesh Sanikop int GetReferenceContext(const Tile::Block& block,
170*09537850SAkhilesh Sanikop                         ReferenceFrameType type0_start,
171*09537850SAkhilesh Sanikop                         ReferenceFrameType type0_end,
172*09537850SAkhilesh Sanikop                         ReferenceFrameType type1_start,
173*09537850SAkhilesh Sanikop                         ReferenceFrameType type1_end) {
174*09537850SAkhilesh Sanikop   int count0 = 0;
175*09537850SAkhilesh Sanikop   int count1 = 0;
176*09537850SAkhilesh Sanikop   for (int type = type0_start; type <= type0_end; ++type) {
177*09537850SAkhilesh Sanikop     count0 += block.CountReferences(static_cast<ReferenceFrameType>(type));
178*09537850SAkhilesh Sanikop   }
179*09537850SAkhilesh Sanikop   for (int type = type1_start; type <= type1_end; ++type) {
180*09537850SAkhilesh Sanikop     count1 += block.CountReferences(static_cast<ReferenceFrameType>(type));
181*09537850SAkhilesh Sanikop   }
182*09537850SAkhilesh Sanikop   return (count0 < count1) ? 0 : (count0 == count1 ? 1 : 2);
183*09537850SAkhilesh Sanikop }
184*09537850SAkhilesh Sanikop 
185*09537850SAkhilesh Sanikop }  // namespace
186*09537850SAkhilesh Sanikop 
ReadSegmentId(const Block & block)187*09537850SAkhilesh Sanikop bool Tile::ReadSegmentId(const Block& block) {
188*09537850SAkhilesh Sanikop   // These two asserts ensure that current_frame_.segmentation_map() is not
189*09537850SAkhilesh Sanikop   // nullptr.
190*09537850SAkhilesh Sanikop   assert(frame_header_.segmentation.enabled);
191*09537850SAkhilesh Sanikop   assert(frame_header_.segmentation.update_map);
192*09537850SAkhilesh Sanikop   const SegmentationMap& map = *current_frame_.segmentation_map();
193*09537850SAkhilesh Sanikop   int top_left = -1;
194*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY] && block.left_available[kPlaneY]) {
195*09537850SAkhilesh Sanikop     top_left = map.segment_id(block.row4x4 - 1, block.column4x4 - 1);
196*09537850SAkhilesh Sanikop   }
197*09537850SAkhilesh Sanikop   int top = -1;
198*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY]) {
199*09537850SAkhilesh Sanikop     top = map.segment_id(block.row4x4 - 1, block.column4x4);
200*09537850SAkhilesh Sanikop   }
201*09537850SAkhilesh Sanikop   int left = -1;
202*09537850SAkhilesh Sanikop   if (block.left_available[kPlaneY]) {
203*09537850SAkhilesh Sanikop     left = map.segment_id(block.row4x4, block.column4x4 - 1);
204*09537850SAkhilesh Sanikop   }
205*09537850SAkhilesh Sanikop   int pred;
206*09537850SAkhilesh Sanikop   if (top == -1) {
207*09537850SAkhilesh Sanikop     pred = (left == -1) ? 0 : left;
208*09537850SAkhilesh Sanikop   } else if (left == -1) {
209*09537850SAkhilesh Sanikop     pred = top;
210*09537850SAkhilesh Sanikop   } else {
211*09537850SAkhilesh Sanikop     pred = (top_left == top) ? top : left;
212*09537850SAkhilesh Sanikop   }
213*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
214*09537850SAkhilesh Sanikop   if (bp.skip) {
215*09537850SAkhilesh Sanikop     bp.prediction_parameters->segment_id = pred;
216*09537850SAkhilesh Sanikop     return true;
217*09537850SAkhilesh Sanikop   }
218*09537850SAkhilesh Sanikop   int context = 0;
219*09537850SAkhilesh Sanikop   if (top_left < 0) {
220*09537850SAkhilesh Sanikop     context = 0;
221*09537850SAkhilesh Sanikop   } else if (top_left == top && top_left == left) {
222*09537850SAkhilesh Sanikop     context = 2;
223*09537850SAkhilesh Sanikop   } else if (top_left == top || top_left == left || top == left) {
224*09537850SAkhilesh Sanikop     context = 1;
225*09537850SAkhilesh Sanikop   }
226*09537850SAkhilesh Sanikop   uint16_t* const segment_id_cdf =
227*09537850SAkhilesh Sanikop       symbol_decoder_context_.segment_id_cdf[context];
228*09537850SAkhilesh Sanikop   const int encoded_segment_id =
229*09537850SAkhilesh Sanikop       reader_.ReadSymbol<kMaxSegments>(segment_id_cdf);
230*09537850SAkhilesh Sanikop   bp.prediction_parameters->segment_id =
231*09537850SAkhilesh Sanikop       DecodeSegmentId(encoded_segment_id, pred,
232*09537850SAkhilesh Sanikop                       frame_header_.segmentation.last_active_segment_id + 1);
233*09537850SAkhilesh Sanikop   // Check the bitstream conformance requirement in Section 6.10.8 of the spec.
234*09537850SAkhilesh Sanikop   if (bp.prediction_parameters->segment_id < 0 ||
235*09537850SAkhilesh Sanikop       bp.prediction_parameters->segment_id >
236*09537850SAkhilesh Sanikop           frame_header_.segmentation.last_active_segment_id) {
237*09537850SAkhilesh Sanikop     LIBGAV1_DLOG(
238*09537850SAkhilesh Sanikop         ERROR,
239*09537850SAkhilesh Sanikop         "Corrupted segment_ids: encoded %d, last active %d, postprocessed %d",
240*09537850SAkhilesh Sanikop         encoded_segment_id, frame_header_.segmentation.last_active_segment_id,
241*09537850SAkhilesh Sanikop         bp.prediction_parameters->segment_id);
242*09537850SAkhilesh Sanikop     return false;
243*09537850SAkhilesh Sanikop   }
244*09537850SAkhilesh Sanikop   return true;
245*09537850SAkhilesh Sanikop }
246*09537850SAkhilesh Sanikop 
ReadIntraSegmentId(const Block & block)247*09537850SAkhilesh Sanikop bool Tile::ReadIntraSegmentId(const Block& block) {
248*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
249*09537850SAkhilesh Sanikop   if (!frame_header_.segmentation.enabled) {
250*09537850SAkhilesh Sanikop     bp.prediction_parameters->segment_id = 0;
251*09537850SAkhilesh Sanikop     return true;
252*09537850SAkhilesh Sanikop   }
253*09537850SAkhilesh Sanikop   return ReadSegmentId(block);
254*09537850SAkhilesh Sanikop }
255*09537850SAkhilesh Sanikop 
ReadSkip(const Block & block)256*09537850SAkhilesh Sanikop void Tile::ReadSkip(const Block& block) {
257*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
258*09537850SAkhilesh Sanikop   if (frame_header_.segmentation.segment_id_pre_skip &&
259*09537850SAkhilesh Sanikop       frame_header_.segmentation.FeatureActive(
260*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id, kSegmentFeatureSkip)) {
261*09537850SAkhilesh Sanikop     bp.skip = true;
262*09537850SAkhilesh Sanikop     return;
263*09537850SAkhilesh Sanikop   }
264*09537850SAkhilesh Sanikop   int context = 0;
265*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY] && block.bp_top->skip) {
266*09537850SAkhilesh Sanikop     ++context;
267*09537850SAkhilesh Sanikop   }
268*09537850SAkhilesh Sanikop   if (block.left_available[kPlaneY] && block.bp_left->skip) {
269*09537850SAkhilesh Sanikop     ++context;
270*09537850SAkhilesh Sanikop   }
271*09537850SAkhilesh Sanikop   uint16_t* const skip_cdf = symbol_decoder_context_.skip_cdf[context];
272*09537850SAkhilesh Sanikop   bp.skip = reader_.ReadSymbol(skip_cdf);
273*09537850SAkhilesh Sanikop }
274*09537850SAkhilesh Sanikop 
ReadSkipMode(const Block & block)275*09537850SAkhilesh Sanikop bool Tile::ReadSkipMode(const Block& block) {
276*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
277*09537850SAkhilesh Sanikop   if (!frame_header_.skip_mode_present ||
278*09537850SAkhilesh Sanikop       frame_header_.segmentation.FeatureActive(
279*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id, kSegmentFeatureSkip) ||
280*09537850SAkhilesh Sanikop       frame_header_.segmentation.FeatureActive(
281*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id,
282*09537850SAkhilesh Sanikop           kSegmentFeatureReferenceFrame) ||
283*09537850SAkhilesh Sanikop       frame_header_.segmentation.FeatureActive(
284*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id, kSegmentFeatureGlobalMv) ||
285*09537850SAkhilesh Sanikop       IsBlockDimension4(block.size)) {
286*09537850SAkhilesh Sanikop     return false;
287*09537850SAkhilesh Sanikop   }
288*09537850SAkhilesh Sanikop   const int context =
289*09537850SAkhilesh Sanikop       (block.left_available[kPlaneY]
290*09537850SAkhilesh Sanikop            ? static_cast<int>(left_context_.skip_mode[block.left_context_index])
291*09537850SAkhilesh Sanikop            : 0) +
292*09537850SAkhilesh Sanikop       (block.top_available[kPlaneY]
293*09537850SAkhilesh Sanikop            ? static_cast<int>(
294*09537850SAkhilesh Sanikop                  block.top_context->skip_mode[block.top_context_index])
295*09537850SAkhilesh Sanikop            : 0);
296*09537850SAkhilesh Sanikop   return reader_.ReadSymbol(symbol_decoder_context_.skip_mode_cdf[context]);
297*09537850SAkhilesh Sanikop }
298*09537850SAkhilesh Sanikop 
ReadCdef(const Block & block)299*09537850SAkhilesh Sanikop void Tile::ReadCdef(const Block& block) {
300*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
301*09537850SAkhilesh Sanikop   if (bp.skip || frame_header_.coded_lossless ||
302*09537850SAkhilesh Sanikop       !sequence_header_.enable_cdef || frame_header_.allow_intrabc ||
303*09537850SAkhilesh Sanikop       frame_header_.cdef.bits == 0) {
304*09537850SAkhilesh Sanikop     return;
305*09537850SAkhilesh Sanikop   }
306*09537850SAkhilesh Sanikop   int8_t* const cdef_index =
307*09537850SAkhilesh Sanikop       &cdef_index_[DivideBy16(block.row4x4)][DivideBy16(block.column4x4)];
308*09537850SAkhilesh Sanikop   int stride = cdef_index_.columns();
309*09537850SAkhilesh Sanikop   if (cdef_index[0] == -1) {
310*09537850SAkhilesh Sanikop     cdef_index[0] =
311*09537850SAkhilesh Sanikop         static_cast<int8_t>(reader_.ReadLiteral(frame_header_.cdef.bits));
312*09537850SAkhilesh Sanikop     if (block.size == kBlock128x128) {
313*09537850SAkhilesh Sanikop       // This condition is shorthand for block.width4x4 > 16 && block.height4x4
314*09537850SAkhilesh Sanikop       // > 16.
315*09537850SAkhilesh Sanikop       cdef_index[1] = cdef_index[0];
316*09537850SAkhilesh Sanikop       cdef_index[stride] = cdef_index[0];
317*09537850SAkhilesh Sanikop       cdef_index[stride + 1] = cdef_index[0];
318*09537850SAkhilesh Sanikop     } else if (block.width4x4 > 16) {
319*09537850SAkhilesh Sanikop       cdef_index[1] = cdef_index[0];
320*09537850SAkhilesh Sanikop     } else if (block.height4x4 > 16) {
321*09537850SAkhilesh Sanikop       cdef_index[stride] = cdef_index[0];
322*09537850SAkhilesh Sanikop     }
323*09537850SAkhilesh Sanikop   }
324*09537850SAkhilesh Sanikop }
325*09537850SAkhilesh Sanikop 
ReadAndClipDelta(uint16_t * const cdf,int delta_small,int scale,int min_value,int max_value,int value)326*09537850SAkhilesh Sanikop int Tile::ReadAndClipDelta(uint16_t* const cdf, int delta_small, int scale,
327*09537850SAkhilesh Sanikop                            int min_value, int max_value, int value) {
328*09537850SAkhilesh Sanikop   int abs = reader_.ReadSymbol<kDeltaSymbolCount>(cdf);
329*09537850SAkhilesh Sanikop   if (abs == delta_small) {
330*09537850SAkhilesh Sanikop     const int remaining_bit_count =
331*09537850SAkhilesh Sanikop         static_cast<int>(reader_.ReadLiteral(3)) + 1;
332*09537850SAkhilesh Sanikop     const int abs_remaining_bits =
333*09537850SAkhilesh Sanikop         static_cast<int>(reader_.ReadLiteral(remaining_bit_count));
334*09537850SAkhilesh Sanikop     abs = abs_remaining_bits + (1 << remaining_bit_count) + 1;
335*09537850SAkhilesh Sanikop   }
336*09537850SAkhilesh Sanikop   if (abs != 0) {
337*09537850SAkhilesh Sanikop     const bool sign = reader_.ReadBit() != 0;
338*09537850SAkhilesh Sanikop     const int scaled_abs = abs << scale;
339*09537850SAkhilesh Sanikop     const int reduced_delta = sign ? -scaled_abs : scaled_abs;
340*09537850SAkhilesh Sanikop     value += reduced_delta;
341*09537850SAkhilesh Sanikop     value = Clip3(value, min_value, max_value);
342*09537850SAkhilesh Sanikop   }
343*09537850SAkhilesh Sanikop   return value;
344*09537850SAkhilesh Sanikop }
345*09537850SAkhilesh Sanikop 
ReadQuantizerIndexDelta(const Block & block)346*09537850SAkhilesh Sanikop void Tile::ReadQuantizerIndexDelta(const Block& block) {
347*09537850SAkhilesh Sanikop   assert(read_deltas_);
348*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
349*09537850SAkhilesh Sanikop   if ((block.size == SuperBlockSize() && bp.skip)) {
350*09537850SAkhilesh Sanikop     return;
351*09537850SAkhilesh Sanikop   }
352*09537850SAkhilesh Sanikop   current_quantizer_index_ =
353*09537850SAkhilesh Sanikop       ReadAndClipDelta(symbol_decoder_context_.delta_q_cdf, kDeltaQSmall,
354*09537850SAkhilesh Sanikop                        frame_header_.delta_q.scale, kMinLossyQuantizer,
355*09537850SAkhilesh Sanikop                        kMaxQuantizer, current_quantizer_index_);
356*09537850SAkhilesh Sanikop }
357*09537850SAkhilesh Sanikop 
ReadLoopFilterDelta(const Block & block)358*09537850SAkhilesh Sanikop void Tile::ReadLoopFilterDelta(const Block& block) {
359*09537850SAkhilesh Sanikop   assert(read_deltas_);
360*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
361*09537850SAkhilesh Sanikop   if (!frame_header_.delta_lf.present ||
362*09537850SAkhilesh Sanikop       (block.size == SuperBlockSize() && bp.skip)) {
363*09537850SAkhilesh Sanikop     return;
364*09537850SAkhilesh Sanikop   }
365*09537850SAkhilesh Sanikop   int frame_lf_count = 1;
366*09537850SAkhilesh Sanikop   if (frame_header_.delta_lf.multi) {
367*09537850SAkhilesh Sanikop     frame_lf_count = kFrameLfCount - (PlaneCount() > 1 ? 0 : 2);
368*09537850SAkhilesh Sanikop   }
369*09537850SAkhilesh Sanikop   bool recompute_deblock_filter_levels = false;
370*09537850SAkhilesh Sanikop   for (int i = 0; i < frame_lf_count; ++i) {
371*09537850SAkhilesh Sanikop     uint16_t* const delta_lf_abs_cdf =
372*09537850SAkhilesh Sanikop         frame_header_.delta_lf.multi
373*09537850SAkhilesh Sanikop             ? symbol_decoder_context_.delta_lf_multi_cdf[i]
374*09537850SAkhilesh Sanikop             : symbol_decoder_context_.delta_lf_cdf;
375*09537850SAkhilesh Sanikop     const int8_t old_delta_lf = delta_lf_[i];
376*09537850SAkhilesh Sanikop     delta_lf_[i] = ReadAndClipDelta(
377*09537850SAkhilesh Sanikop         delta_lf_abs_cdf, kDeltaLfSmall, frame_header_.delta_lf.scale,
378*09537850SAkhilesh Sanikop         -kMaxLoopFilterValue, kMaxLoopFilterValue, delta_lf_[i]);
379*09537850SAkhilesh Sanikop     recompute_deblock_filter_levels =
380*09537850SAkhilesh Sanikop         recompute_deblock_filter_levels || (old_delta_lf != delta_lf_[i]);
381*09537850SAkhilesh Sanikop   }
382*09537850SAkhilesh Sanikop   delta_lf_all_zero_ =
383*09537850SAkhilesh Sanikop       (delta_lf_[0] | delta_lf_[1] | delta_lf_[2] | delta_lf_[3]) == 0;
384*09537850SAkhilesh Sanikop   if (!delta_lf_all_zero_ && recompute_deblock_filter_levels) {
385*09537850SAkhilesh Sanikop     post_filter_.ComputeDeblockFilterLevels(delta_lf_, deblock_filter_levels_);
386*09537850SAkhilesh Sanikop   }
387*09537850SAkhilesh Sanikop }
388*09537850SAkhilesh Sanikop 
ReadPredictionModeY(const Block & block,bool intra_y_mode)389*09537850SAkhilesh Sanikop void Tile::ReadPredictionModeY(const Block& block, bool intra_y_mode) {
390*09537850SAkhilesh Sanikop   uint16_t* cdf;
391*09537850SAkhilesh Sanikop   if (intra_y_mode) {
392*09537850SAkhilesh Sanikop     const PredictionMode top_mode =
393*09537850SAkhilesh Sanikop         block.top_available[kPlaneY] ? block.bp_top->y_mode : kPredictionModeDc;
394*09537850SAkhilesh Sanikop     const PredictionMode left_mode = block.left_available[kPlaneY]
395*09537850SAkhilesh Sanikop                                          ? block.bp_left->y_mode
396*09537850SAkhilesh Sanikop                                          : kPredictionModeDc;
397*09537850SAkhilesh Sanikop     const int top_context = kIntraYModeContext[top_mode];
398*09537850SAkhilesh Sanikop     const int left_context = kIntraYModeContext[left_mode];
399*09537850SAkhilesh Sanikop     cdf = symbol_decoder_context_
400*09537850SAkhilesh Sanikop               .intra_frame_y_mode_cdf[top_context][left_context];
401*09537850SAkhilesh Sanikop   } else {
402*09537850SAkhilesh Sanikop     cdf = symbol_decoder_context_.y_mode_cdf[kSizeGroup[block.size]];
403*09537850SAkhilesh Sanikop   }
404*09537850SAkhilesh Sanikop   block.bp->y_mode = static_cast<PredictionMode>(
405*09537850SAkhilesh Sanikop       reader_.ReadSymbol<kIntraPredictionModesY>(cdf));
406*09537850SAkhilesh Sanikop }
407*09537850SAkhilesh Sanikop 
ReadIntraAngleInfo(const Block & block,PlaneType plane_type)408*09537850SAkhilesh Sanikop void Tile::ReadIntraAngleInfo(const Block& block, PlaneType plane_type) {
409*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
410*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
411*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
412*09537850SAkhilesh Sanikop   prediction_parameters.angle_delta[plane_type] = 0;
413*09537850SAkhilesh Sanikop   const PredictionMode mode = (plane_type == kPlaneTypeY)
414*09537850SAkhilesh Sanikop                                   ? bp.y_mode
415*09537850SAkhilesh Sanikop                                   : bp.prediction_parameters->uv_mode;
416*09537850SAkhilesh Sanikop   if (IsBlockSmallerThan8x8(block.size) || !IsDirectionalMode(mode)) return;
417*09537850SAkhilesh Sanikop   uint16_t* const cdf =
418*09537850SAkhilesh Sanikop       symbol_decoder_context_.angle_delta_cdf[mode - kPredictionModeVertical];
419*09537850SAkhilesh Sanikop   prediction_parameters.angle_delta[plane_type] =
420*09537850SAkhilesh Sanikop       reader_.ReadSymbol<kAngleDeltaSymbolCount>(cdf);
421*09537850SAkhilesh Sanikop   prediction_parameters.angle_delta[plane_type] -= kMaxAngleDelta;
422*09537850SAkhilesh Sanikop }
423*09537850SAkhilesh Sanikop 
ReadCflAlpha(const Block & block)424*09537850SAkhilesh Sanikop void Tile::ReadCflAlpha(const Block& block) {
425*09537850SAkhilesh Sanikop   const int signs = reader_.ReadSymbol<kCflAlphaSignsSymbolCount>(
426*09537850SAkhilesh Sanikop       symbol_decoder_context_.cfl_alpha_signs_cdf);
427*09537850SAkhilesh Sanikop   const int8_t* const cfl_lookup = kCflAlphaLookup[signs];
428*09537850SAkhilesh Sanikop   const auto sign_u = static_cast<CflSign>(cfl_lookup[0]);
429*09537850SAkhilesh Sanikop   const auto sign_v = static_cast<CflSign>(cfl_lookup[1]);
430*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
431*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
432*09537850SAkhilesh Sanikop   prediction_parameters.cfl_alpha_u = 0;
433*09537850SAkhilesh Sanikop   if (sign_u != kCflSignZero) {
434*09537850SAkhilesh Sanikop     assert(cfl_lookup[2] >= 0);
435*09537850SAkhilesh Sanikop     prediction_parameters.cfl_alpha_u =
436*09537850SAkhilesh Sanikop         reader_.ReadSymbol<kCflAlphaSymbolCount>(
437*09537850SAkhilesh Sanikop             symbol_decoder_context_.cfl_alpha_cdf[cfl_lookup[2]]) +
438*09537850SAkhilesh Sanikop         1;
439*09537850SAkhilesh Sanikop     if (sign_u == kCflSignNegative) prediction_parameters.cfl_alpha_u *= -1;
440*09537850SAkhilesh Sanikop   }
441*09537850SAkhilesh Sanikop   prediction_parameters.cfl_alpha_v = 0;
442*09537850SAkhilesh Sanikop   if (sign_v != kCflSignZero) {
443*09537850SAkhilesh Sanikop     assert(cfl_lookup[3] >= 0);
444*09537850SAkhilesh Sanikop     prediction_parameters.cfl_alpha_v =
445*09537850SAkhilesh Sanikop         reader_.ReadSymbol<kCflAlphaSymbolCount>(
446*09537850SAkhilesh Sanikop             symbol_decoder_context_.cfl_alpha_cdf[cfl_lookup[3]]) +
447*09537850SAkhilesh Sanikop         1;
448*09537850SAkhilesh Sanikop     if (sign_v == kCflSignNegative) prediction_parameters.cfl_alpha_v *= -1;
449*09537850SAkhilesh Sanikop   }
450*09537850SAkhilesh Sanikop }
451*09537850SAkhilesh Sanikop 
ReadPredictionModeUV(const Block & block)452*09537850SAkhilesh Sanikop void Tile::ReadPredictionModeUV(const Block& block) {
453*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
454*09537850SAkhilesh Sanikop   bool chroma_from_luma_allowed;
455*09537850SAkhilesh Sanikop   if (frame_header_.segmentation
456*09537850SAkhilesh Sanikop           .lossless[bp.prediction_parameters->segment_id]) {
457*09537850SAkhilesh Sanikop     chroma_from_luma_allowed = block.residual_size[kPlaneU] == kBlock4x4;
458*09537850SAkhilesh Sanikop   } else {
459*09537850SAkhilesh Sanikop     chroma_from_luma_allowed = IsBlockDimensionLessThan64(block.size);
460*09537850SAkhilesh Sanikop   }
461*09537850SAkhilesh Sanikop   uint16_t* const cdf =
462*09537850SAkhilesh Sanikop       symbol_decoder_context_
463*09537850SAkhilesh Sanikop           .uv_mode_cdf[static_cast<int>(chroma_from_luma_allowed)][bp.y_mode];
464*09537850SAkhilesh Sanikop   if (chroma_from_luma_allowed) {
465*09537850SAkhilesh Sanikop     bp.prediction_parameters->uv_mode = static_cast<PredictionMode>(
466*09537850SAkhilesh Sanikop         reader_.ReadSymbol<kIntraPredictionModesUV>(cdf));
467*09537850SAkhilesh Sanikop   } else {
468*09537850SAkhilesh Sanikop     bp.prediction_parameters->uv_mode = static_cast<PredictionMode>(
469*09537850SAkhilesh Sanikop         reader_.ReadSymbol<kIntraPredictionModesUV - 1>(cdf));
470*09537850SAkhilesh Sanikop   }
471*09537850SAkhilesh Sanikop }
472*09537850SAkhilesh Sanikop 
ReadMotionVectorComponent(const Block & block,const int component)473*09537850SAkhilesh Sanikop int Tile::ReadMotionVectorComponent(const Block& block, const int component) {
474*09537850SAkhilesh Sanikop   const int context =
475*09537850SAkhilesh Sanikop       static_cast<int>(block.bp->prediction_parameters->use_intra_block_copy);
476*09537850SAkhilesh Sanikop   const bool sign = reader_.ReadSymbol(
477*09537850SAkhilesh Sanikop       symbol_decoder_context_.mv_sign_cdf[component][context]);
478*09537850SAkhilesh Sanikop   const int mv_class = reader_.ReadSymbol<kMvClassSymbolCount>(
479*09537850SAkhilesh Sanikop       symbol_decoder_context_.mv_class_cdf[component][context]);
480*09537850SAkhilesh Sanikop   int magnitude = 1;
481*09537850SAkhilesh Sanikop   int value;
482*09537850SAkhilesh Sanikop   uint16_t* fraction_cdf;
483*09537850SAkhilesh Sanikop   uint16_t* precision_cdf;
484*09537850SAkhilesh Sanikop   if (mv_class == 0) {
485*09537850SAkhilesh Sanikop     value = static_cast<int>(reader_.ReadSymbol(
486*09537850SAkhilesh Sanikop         symbol_decoder_context_.mv_class0_bit_cdf[component][context]));
487*09537850SAkhilesh Sanikop     fraction_cdf = symbol_decoder_context_
488*09537850SAkhilesh Sanikop                        .mv_class0_fraction_cdf[component][context][value];
489*09537850SAkhilesh Sanikop     precision_cdf = symbol_decoder_context_
490*09537850SAkhilesh Sanikop                         .mv_class0_high_precision_cdf[component][context];
491*09537850SAkhilesh Sanikop   } else {
492*09537850SAkhilesh Sanikop     assert(mv_class <= kMvBitSymbolCount);
493*09537850SAkhilesh Sanikop     value = 0;
494*09537850SAkhilesh Sanikop     for (int i = 0; i < mv_class; ++i) {
495*09537850SAkhilesh Sanikop       const int bit = static_cast<int>(reader_.ReadSymbol(
496*09537850SAkhilesh Sanikop           symbol_decoder_context_.mv_bit_cdf[component][context][i]));
497*09537850SAkhilesh Sanikop       value |= bit << i;
498*09537850SAkhilesh Sanikop     }
499*09537850SAkhilesh Sanikop     magnitude += 2 << (mv_class + 2);
500*09537850SAkhilesh Sanikop     fraction_cdf = symbol_decoder_context_.mv_fraction_cdf[component][context];
501*09537850SAkhilesh Sanikop     precision_cdf =
502*09537850SAkhilesh Sanikop         symbol_decoder_context_.mv_high_precision_cdf[component][context];
503*09537850SAkhilesh Sanikop   }
504*09537850SAkhilesh Sanikop   const int fraction =
505*09537850SAkhilesh Sanikop       (frame_header_.force_integer_mv == 0)
506*09537850SAkhilesh Sanikop           ? reader_.ReadSymbol<kMvFractionSymbolCount>(fraction_cdf)
507*09537850SAkhilesh Sanikop           : 3;
508*09537850SAkhilesh Sanikop   const int precision =
509*09537850SAkhilesh Sanikop       frame_header_.allow_high_precision_mv
510*09537850SAkhilesh Sanikop           ? static_cast<int>(reader_.ReadSymbol(precision_cdf))
511*09537850SAkhilesh Sanikop           : 1;
512*09537850SAkhilesh Sanikop   magnitude += (value << 3) | (fraction << 1) | precision;
513*09537850SAkhilesh Sanikop   return sign ? -magnitude : magnitude;
514*09537850SAkhilesh Sanikop }
515*09537850SAkhilesh Sanikop 
ReadMotionVector(const Block & block,int index)516*09537850SAkhilesh Sanikop void Tile::ReadMotionVector(const Block& block, int index) {
517*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
518*09537850SAkhilesh Sanikop   const int context =
519*09537850SAkhilesh Sanikop       static_cast<int>(block.bp->prediction_parameters->use_intra_block_copy);
520*09537850SAkhilesh Sanikop   const auto mv_joint =
521*09537850SAkhilesh Sanikop       static_cast<MvJointType>(reader_.ReadSymbol<kNumMvJointTypes>(
522*09537850SAkhilesh Sanikop           symbol_decoder_context_.mv_joint_cdf[context]));
523*09537850SAkhilesh Sanikop   if (mv_joint == kMvJointTypeHorizontalZeroVerticalNonZero ||
524*09537850SAkhilesh Sanikop       mv_joint == kMvJointTypeNonZero) {
525*09537850SAkhilesh Sanikop     bp.mv.mv[index].mv[0] = ReadMotionVectorComponent(block, 0);
526*09537850SAkhilesh Sanikop   }
527*09537850SAkhilesh Sanikop   if (mv_joint == kMvJointTypeHorizontalNonZeroVerticalZero ||
528*09537850SAkhilesh Sanikop       mv_joint == kMvJointTypeNonZero) {
529*09537850SAkhilesh Sanikop     bp.mv.mv[index].mv[1] = ReadMotionVectorComponent(block, 1);
530*09537850SAkhilesh Sanikop   }
531*09537850SAkhilesh Sanikop }
532*09537850SAkhilesh Sanikop 
ReadFilterIntraModeInfo(const Block & block)533*09537850SAkhilesh Sanikop void Tile::ReadFilterIntraModeInfo(const Block& block) {
534*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
535*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
536*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
537*09537850SAkhilesh Sanikop   prediction_parameters.use_filter_intra = false;
538*09537850SAkhilesh Sanikop   if (!sequence_header_.enable_filter_intra || bp.y_mode != kPredictionModeDc ||
539*09537850SAkhilesh Sanikop       bp.prediction_parameters->palette_mode_info.size[kPlaneTypeY] != 0 ||
540*09537850SAkhilesh Sanikop       !IsBlockDimensionLessThan64(block.size)) {
541*09537850SAkhilesh Sanikop     return;
542*09537850SAkhilesh Sanikop   }
543*09537850SAkhilesh Sanikop   prediction_parameters.use_filter_intra = reader_.ReadSymbol(
544*09537850SAkhilesh Sanikop       symbol_decoder_context_.use_filter_intra_cdf[block.size]);
545*09537850SAkhilesh Sanikop   if (prediction_parameters.use_filter_intra) {
546*09537850SAkhilesh Sanikop     prediction_parameters.filter_intra_mode = static_cast<FilterIntraPredictor>(
547*09537850SAkhilesh Sanikop         reader_.ReadSymbol<kNumFilterIntraPredictors>(
548*09537850SAkhilesh Sanikop             symbol_decoder_context_.filter_intra_mode_cdf));
549*09537850SAkhilesh Sanikop   }
550*09537850SAkhilesh Sanikop }
551*09537850SAkhilesh Sanikop 
DecodeIntraModeInfo(const Block & block)552*09537850SAkhilesh Sanikop bool Tile::DecodeIntraModeInfo(const Block& block) {
553*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
554*09537850SAkhilesh Sanikop   bp.skip = false;
555*09537850SAkhilesh Sanikop   if (frame_header_.segmentation.segment_id_pre_skip &&
556*09537850SAkhilesh Sanikop       !ReadIntraSegmentId(block)) {
557*09537850SAkhilesh Sanikop     return false;
558*09537850SAkhilesh Sanikop   }
559*09537850SAkhilesh Sanikop   SetCdfContextSkipMode(block, false);
560*09537850SAkhilesh Sanikop   ReadSkip(block);
561*09537850SAkhilesh Sanikop   if (!frame_header_.segmentation.segment_id_pre_skip &&
562*09537850SAkhilesh Sanikop       !ReadIntraSegmentId(block)) {
563*09537850SAkhilesh Sanikop     return false;
564*09537850SAkhilesh Sanikop   }
565*09537850SAkhilesh Sanikop   ReadCdef(block);
566*09537850SAkhilesh Sanikop   if (read_deltas_) {
567*09537850SAkhilesh Sanikop     ReadQuantizerIndexDelta(block);
568*09537850SAkhilesh Sanikop     ReadLoopFilterDelta(block);
569*09537850SAkhilesh Sanikop     read_deltas_ = false;
570*09537850SAkhilesh Sanikop   }
571*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
572*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
573*09537850SAkhilesh Sanikop   prediction_parameters.use_intra_block_copy = false;
574*09537850SAkhilesh Sanikop   if (frame_header_.allow_intrabc) {
575*09537850SAkhilesh Sanikop     prediction_parameters.use_intra_block_copy =
576*09537850SAkhilesh Sanikop         reader_.ReadSymbol(symbol_decoder_context_.intra_block_copy_cdf);
577*09537850SAkhilesh Sanikop   }
578*09537850SAkhilesh Sanikop   if (prediction_parameters.use_intra_block_copy) {
579*09537850SAkhilesh Sanikop     bp.is_inter = true;
580*09537850SAkhilesh Sanikop     bp.reference_frame[0] = kReferenceFrameIntra;
581*09537850SAkhilesh Sanikop     bp.reference_frame[1] = kReferenceFrameNone;
582*09537850SAkhilesh Sanikop     bp.y_mode = kPredictionModeDc;
583*09537850SAkhilesh Sanikop     bp.prediction_parameters->uv_mode = kPredictionModeDc;
584*09537850SAkhilesh Sanikop     SetCdfContextUVMode(block);
585*09537850SAkhilesh Sanikop     prediction_parameters.motion_mode = kMotionModeSimple;
586*09537850SAkhilesh Sanikop     prediction_parameters.compound_prediction_type =
587*09537850SAkhilesh Sanikop         kCompoundPredictionTypeAverage;
588*09537850SAkhilesh Sanikop     bp.prediction_parameters->palette_mode_info.size[kPlaneTypeY] = 0;
589*09537850SAkhilesh Sanikop     bp.prediction_parameters->palette_mode_info.size[kPlaneTypeUV] = 0;
590*09537850SAkhilesh Sanikop     SetCdfContextPaletteSize(block);
591*09537850SAkhilesh Sanikop     bp.interpolation_filter[0] = kInterpolationFilterBilinear;
592*09537850SAkhilesh Sanikop     bp.interpolation_filter[1] = kInterpolationFilterBilinear;
593*09537850SAkhilesh Sanikop     MvContexts dummy_mode_contexts;
594*09537850SAkhilesh Sanikop     FindMvStack(block, /*is_compound=*/false, &dummy_mode_contexts);
595*09537850SAkhilesh Sanikop     return AssignIntraMv(block);
596*09537850SAkhilesh Sanikop   }
597*09537850SAkhilesh Sanikop   bp.is_inter = false;
598*09537850SAkhilesh Sanikop   return ReadIntraBlockModeInfo(block, /*intra_y_mode=*/true);
599*09537850SAkhilesh Sanikop }
600*09537850SAkhilesh Sanikop 
ComputePredictedSegmentId(const Block & block) const601*09537850SAkhilesh Sanikop int8_t Tile::ComputePredictedSegmentId(const Block& block) const {
602*09537850SAkhilesh Sanikop   // If prev_segment_ids_ is null, treat it as if it pointed to a segmentation
603*09537850SAkhilesh Sanikop   // map containing all 0s.
604*09537850SAkhilesh Sanikop   if (prev_segment_ids_ == nullptr) return 0;
605*09537850SAkhilesh Sanikop 
606*09537850SAkhilesh Sanikop   const int x_limit = std::min(frame_header_.columns4x4 - block.column4x4,
607*09537850SAkhilesh Sanikop                                static_cast<int>(block.width4x4));
608*09537850SAkhilesh Sanikop   const int y_limit = std::min(frame_header_.rows4x4 - block.row4x4,
609*09537850SAkhilesh Sanikop                                static_cast<int>(block.height4x4));
610*09537850SAkhilesh Sanikop   int8_t id = 7;
611*09537850SAkhilesh Sanikop   for (int y = 0; y < y_limit; ++y) {
612*09537850SAkhilesh Sanikop     for (int x = 0; x < x_limit; ++x) {
613*09537850SAkhilesh Sanikop       const int8_t prev_segment_id =
614*09537850SAkhilesh Sanikop           prev_segment_ids_->segment_id(block.row4x4 + y, block.column4x4 + x);
615*09537850SAkhilesh Sanikop       id = std::min(id, prev_segment_id);
616*09537850SAkhilesh Sanikop     }
617*09537850SAkhilesh Sanikop   }
618*09537850SAkhilesh Sanikop   return id;
619*09537850SAkhilesh Sanikop }
620*09537850SAkhilesh Sanikop 
SetCdfContextUsePredictedSegmentId(const Block & block,bool use_predicted_segment_id)621*09537850SAkhilesh Sanikop void Tile::SetCdfContextUsePredictedSegmentId(const Block& block,
622*09537850SAkhilesh Sanikop                                               bool use_predicted_segment_id) {
623*09537850SAkhilesh Sanikop   memset(left_context_.use_predicted_segment_id + block.left_context_index,
624*09537850SAkhilesh Sanikop          static_cast<int>(use_predicted_segment_id), block.height4x4);
625*09537850SAkhilesh Sanikop   memset(block.top_context->use_predicted_segment_id + block.top_context_index,
626*09537850SAkhilesh Sanikop          static_cast<int>(use_predicted_segment_id), block.width4x4);
627*09537850SAkhilesh Sanikop }
628*09537850SAkhilesh Sanikop 
ReadInterSegmentId(const Block & block,bool pre_skip)629*09537850SAkhilesh Sanikop bool Tile::ReadInterSegmentId(const Block& block, bool pre_skip) {
630*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
631*09537850SAkhilesh Sanikop   if (!frame_header_.segmentation.enabled) {
632*09537850SAkhilesh Sanikop     bp.prediction_parameters->segment_id = 0;
633*09537850SAkhilesh Sanikop     return true;
634*09537850SAkhilesh Sanikop   }
635*09537850SAkhilesh Sanikop   if (!frame_header_.segmentation.update_map) {
636*09537850SAkhilesh Sanikop     bp.prediction_parameters->segment_id = ComputePredictedSegmentId(block);
637*09537850SAkhilesh Sanikop     return true;
638*09537850SAkhilesh Sanikop   }
639*09537850SAkhilesh Sanikop   if (pre_skip) {
640*09537850SAkhilesh Sanikop     if (!frame_header_.segmentation.segment_id_pre_skip) {
641*09537850SAkhilesh Sanikop       bp.prediction_parameters->segment_id = 0;
642*09537850SAkhilesh Sanikop       return true;
643*09537850SAkhilesh Sanikop     }
644*09537850SAkhilesh Sanikop   } else if (bp.skip) {
645*09537850SAkhilesh Sanikop     SetCdfContextUsePredictedSegmentId(block, false);
646*09537850SAkhilesh Sanikop     return ReadSegmentId(block);
647*09537850SAkhilesh Sanikop   }
648*09537850SAkhilesh Sanikop   if (frame_header_.segmentation.temporal_update) {
649*09537850SAkhilesh Sanikop     const int context =
650*09537850SAkhilesh Sanikop         (block.left_available[kPlaneY]
651*09537850SAkhilesh Sanikop              ? static_cast<int>(
652*09537850SAkhilesh Sanikop                    left_context_
653*09537850SAkhilesh Sanikop                        .use_predicted_segment_id[block.left_context_index])
654*09537850SAkhilesh Sanikop              : 0) +
655*09537850SAkhilesh Sanikop         (block.top_available[kPlaneY]
656*09537850SAkhilesh Sanikop              ? static_cast<int>(
657*09537850SAkhilesh Sanikop                    block.top_context
658*09537850SAkhilesh Sanikop                        ->use_predicted_segment_id[block.top_context_index])
659*09537850SAkhilesh Sanikop              : 0);
660*09537850SAkhilesh Sanikop     const bool use_predicted_segment_id = reader_.ReadSymbol(
661*09537850SAkhilesh Sanikop         symbol_decoder_context_.use_predicted_segment_id_cdf[context]);
662*09537850SAkhilesh Sanikop     SetCdfContextUsePredictedSegmentId(block, use_predicted_segment_id);
663*09537850SAkhilesh Sanikop     if (use_predicted_segment_id) {
664*09537850SAkhilesh Sanikop       bp.prediction_parameters->segment_id = ComputePredictedSegmentId(block);
665*09537850SAkhilesh Sanikop       return true;
666*09537850SAkhilesh Sanikop     }
667*09537850SAkhilesh Sanikop   }
668*09537850SAkhilesh Sanikop   return ReadSegmentId(block);
669*09537850SAkhilesh Sanikop }
670*09537850SAkhilesh Sanikop 
ReadIsInter(const Block & block,bool skip_mode)671*09537850SAkhilesh Sanikop void Tile::ReadIsInter(const Block& block, bool skip_mode) {
672*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
673*09537850SAkhilesh Sanikop   if (skip_mode) {
674*09537850SAkhilesh Sanikop     bp.is_inter = true;
675*09537850SAkhilesh Sanikop     return;
676*09537850SAkhilesh Sanikop   }
677*09537850SAkhilesh Sanikop   if (frame_header_.segmentation.FeatureActive(
678*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id,
679*09537850SAkhilesh Sanikop           kSegmentFeatureReferenceFrame)) {
680*09537850SAkhilesh Sanikop     bp.is_inter = frame_header_.segmentation
681*09537850SAkhilesh Sanikop                       .feature_data[bp.prediction_parameters->segment_id]
682*09537850SAkhilesh Sanikop                                    [kSegmentFeatureReferenceFrame] !=
683*09537850SAkhilesh Sanikop                   kReferenceFrameIntra;
684*09537850SAkhilesh Sanikop     return;
685*09537850SAkhilesh Sanikop   }
686*09537850SAkhilesh Sanikop   if (frame_header_.segmentation.FeatureActive(
687*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id, kSegmentFeatureGlobalMv)) {
688*09537850SAkhilesh Sanikop     bp.is_inter = true;
689*09537850SAkhilesh Sanikop     return;
690*09537850SAkhilesh Sanikop   }
691*09537850SAkhilesh Sanikop   int context = 0;
692*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY] && block.left_available[kPlaneY]) {
693*09537850SAkhilesh Sanikop     context = (block.IsTopIntra() && block.IsLeftIntra())
694*09537850SAkhilesh Sanikop                   ? 3
695*09537850SAkhilesh Sanikop                   : static_cast<int>(block.IsTopIntra() || block.IsLeftIntra());
696*09537850SAkhilesh Sanikop   } else if (block.top_available[kPlaneY] || block.left_available[kPlaneY]) {
697*09537850SAkhilesh Sanikop     context = 2 * static_cast<int>(block.top_available[kPlaneY]
698*09537850SAkhilesh Sanikop                                        ? block.IsTopIntra()
699*09537850SAkhilesh Sanikop                                        : block.IsLeftIntra());
700*09537850SAkhilesh Sanikop   }
701*09537850SAkhilesh Sanikop   bp.is_inter =
702*09537850SAkhilesh Sanikop       reader_.ReadSymbol(symbol_decoder_context_.is_inter_cdf[context]);
703*09537850SAkhilesh Sanikop }
704*09537850SAkhilesh Sanikop 
SetCdfContextPaletteSize(const Block & block)705*09537850SAkhilesh Sanikop void Tile::SetCdfContextPaletteSize(const Block& block) {
706*09537850SAkhilesh Sanikop   const PaletteModeInfo& palette_mode_info =
707*09537850SAkhilesh Sanikop       block.bp->prediction_parameters->palette_mode_info;
708*09537850SAkhilesh Sanikop   for (int plane_type = kPlaneTypeY; plane_type <= kPlaneTypeUV; ++plane_type) {
709*09537850SAkhilesh Sanikop     memset(left_context_.palette_size[plane_type] + block.left_context_index,
710*09537850SAkhilesh Sanikop            palette_mode_info.size[plane_type], block.height4x4);
711*09537850SAkhilesh Sanikop     memset(
712*09537850SAkhilesh Sanikop         block.top_context->palette_size[plane_type] + block.top_context_index,
713*09537850SAkhilesh Sanikop         palette_mode_info.size[plane_type], block.width4x4);
714*09537850SAkhilesh Sanikop     if (palette_mode_info.size[plane_type] == 0) continue;
715*09537850SAkhilesh Sanikop     for (int i = block.left_context_index;
716*09537850SAkhilesh Sanikop          i < block.left_context_index + block.height4x4; ++i) {
717*09537850SAkhilesh Sanikop       memcpy(left_context_.palette_color[i][plane_type],
718*09537850SAkhilesh Sanikop              palette_mode_info.color[plane_type],
719*09537850SAkhilesh Sanikop              kMaxPaletteSize * sizeof(palette_mode_info.color[0][0]));
720*09537850SAkhilesh Sanikop     }
721*09537850SAkhilesh Sanikop     for (int i = block.top_context_index;
722*09537850SAkhilesh Sanikop          i < block.top_context_index + block.width4x4; ++i) {
723*09537850SAkhilesh Sanikop       memcpy(block.top_context->palette_color[i][plane_type],
724*09537850SAkhilesh Sanikop              palette_mode_info.color[plane_type],
725*09537850SAkhilesh Sanikop              kMaxPaletteSize * sizeof(palette_mode_info.color[0][0]));
726*09537850SAkhilesh Sanikop     }
727*09537850SAkhilesh Sanikop   }
728*09537850SAkhilesh Sanikop }
729*09537850SAkhilesh Sanikop 
SetCdfContextUVMode(const Block & block)730*09537850SAkhilesh Sanikop void Tile::SetCdfContextUVMode(const Block& block) {
731*09537850SAkhilesh Sanikop   // BlockCdfContext.uv_mode is only used to compute is_smooth_prediction for
732*09537850SAkhilesh Sanikop   // the intra edge upsamplers in the subsequent blocks. They have some special
733*09537850SAkhilesh Sanikop   // rules for subsampled UV planes. For subsampled UV planes, update left
734*09537850SAkhilesh Sanikop   // context only if current block contains the last odd column and update top
735*09537850SAkhilesh Sanikop   // context only if current block contains the last odd row.
736*09537850SAkhilesh Sanikop   if (subsampling_x_[kPlaneU] == 0 || (block.column4x4 & 1) == 1 ||
737*09537850SAkhilesh Sanikop       block.width4x4 > 1) {
738*09537850SAkhilesh Sanikop     memset(left_context_.uv_mode + block.left_context_index,
739*09537850SAkhilesh Sanikop            block.bp->prediction_parameters->uv_mode, block.height4x4);
740*09537850SAkhilesh Sanikop   }
741*09537850SAkhilesh Sanikop   if (subsampling_y_[kPlaneU] == 0 || (block.row4x4 & 1) == 1 ||
742*09537850SAkhilesh Sanikop       block.height4x4 > 1) {
743*09537850SAkhilesh Sanikop     memset(block.top_context->uv_mode + block.top_context_index,
744*09537850SAkhilesh Sanikop            block.bp->prediction_parameters->uv_mode, block.width4x4);
745*09537850SAkhilesh Sanikop   }
746*09537850SAkhilesh Sanikop }
747*09537850SAkhilesh Sanikop 
ReadIntraBlockModeInfo(const Block & block,bool intra_y_mode)748*09537850SAkhilesh Sanikop bool Tile::ReadIntraBlockModeInfo(const Block& block, bool intra_y_mode) {
749*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
750*09537850SAkhilesh Sanikop   bp.reference_frame[0] = kReferenceFrameIntra;
751*09537850SAkhilesh Sanikop   bp.reference_frame[1] = kReferenceFrameNone;
752*09537850SAkhilesh Sanikop   ReadPredictionModeY(block, intra_y_mode);
753*09537850SAkhilesh Sanikop   ReadIntraAngleInfo(block, kPlaneTypeY);
754*09537850SAkhilesh Sanikop   if (block.HasChroma()) {
755*09537850SAkhilesh Sanikop     ReadPredictionModeUV(block);
756*09537850SAkhilesh Sanikop     if (bp.prediction_parameters->uv_mode == kPredictionModeChromaFromLuma) {
757*09537850SAkhilesh Sanikop       ReadCflAlpha(block);
758*09537850SAkhilesh Sanikop     }
759*09537850SAkhilesh Sanikop     if (block.left_available[kPlaneU]) {
760*09537850SAkhilesh Sanikop       const int smooth_row =
761*09537850SAkhilesh Sanikop           block.row4x4 + (~block.row4x4 & subsampling_y_[kPlaneU]);
762*09537850SAkhilesh Sanikop       const int smooth_column =
763*09537850SAkhilesh Sanikop           block.column4x4 - 1 - (block.column4x4 & subsampling_x_[kPlaneU]);
764*09537850SAkhilesh Sanikop       const BlockParameters& bp_left =
765*09537850SAkhilesh Sanikop           *block_parameters_holder_.Find(smooth_row, smooth_column);
766*09537850SAkhilesh Sanikop       bp.prediction_parameters->chroma_left_uses_smooth_prediction =
767*09537850SAkhilesh Sanikop           (bp_left.reference_frame[0] <= kReferenceFrameIntra) &&
768*09537850SAkhilesh Sanikop           kPredictionModeSmoothMask.Contains(
769*09537850SAkhilesh Sanikop               left_context_.uv_mode[CdfContextIndex(smooth_row)]);
770*09537850SAkhilesh Sanikop     }
771*09537850SAkhilesh Sanikop     if (block.top_available[kPlaneU]) {
772*09537850SAkhilesh Sanikop       const int smooth_row =
773*09537850SAkhilesh Sanikop           block.row4x4 - 1 - (block.row4x4 & subsampling_y_[kPlaneU]);
774*09537850SAkhilesh Sanikop       const int smooth_column =
775*09537850SAkhilesh Sanikop           block.column4x4 + (~block.column4x4 & subsampling_x_[kPlaneU]);
776*09537850SAkhilesh Sanikop       const BlockParameters& bp_top =
777*09537850SAkhilesh Sanikop           *block_parameters_holder_.Find(smooth_row, smooth_column);
778*09537850SAkhilesh Sanikop       bp.prediction_parameters->chroma_top_uses_smooth_prediction =
779*09537850SAkhilesh Sanikop           (bp_top.reference_frame[0] <= kReferenceFrameIntra) &&
780*09537850SAkhilesh Sanikop           kPredictionModeSmoothMask.Contains(
781*09537850SAkhilesh Sanikop               top_context_.get()[SuperBlockColumnIndex(smooth_column)]
782*09537850SAkhilesh Sanikop                   .uv_mode[CdfContextIndex(smooth_column)]);
783*09537850SAkhilesh Sanikop     }
784*09537850SAkhilesh Sanikop     SetCdfContextUVMode(block);
785*09537850SAkhilesh Sanikop     ReadIntraAngleInfo(block, kPlaneTypeUV);
786*09537850SAkhilesh Sanikop   }
787*09537850SAkhilesh Sanikop   ReadPaletteModeInfo(block);
788*09537850SAkhilesh Sanikop   SetCdfContextPaletteSize(block);
789*09537850SAkhilesh Sanikop   ReadFilterIntraModeInfo(block);
790*09537850SAkhilesh Sanikop   return true;
791*09537850SAkhilesh Sanikop }
792*09537850SAkhilesh Sanikop 
ReadCompoundReferenceType(const Block & block)793*09537850SAkhilesh Sanikop CompoundReferenceType Tile::ReadCompoundReferenceType(const Block& block) {
794*09537850SAkhilesh Sanikop   // compound and inter.
795*09537850SAkhilesh Sanikop   const bool top_comp_inter = block.top_available[kPlaneY] &&
796*09537850SAkhilesh Sanikop                               !block.IsTopIntra() && !block.IsTopSingle();
797*09537850SAkhilesh Sanikop   const bool left_comp_inter = block.left_available[kPlaneY] &&
798*09537850SAkhilesh Sanikop                                !block.IsLeftIntra() && !block.IsLeftSingle();
799*09537850SAkhilesh Sanikop   // unidirectional compound.
800*09537850SAkhilesh Sanikop   const bool top_uni_comp =
801*09537850SAkhilesh Sanikop       top_comp_inter && IsSameDirectionReferencePair(block.TopReference(0),
802*09537850SAkhilesh Sanikop                                                      block.TopReference(1));
803*09537850SAkhilesh Sanikop   const bool left_uni_comp =
804*09537850SAkhilesh Sanikop       left_comp_inter && IsSameDirectionReferencePair(block.LeftReference(0),
805*09537850SAkhilesh Sanikop                                                       block.LeftReference(1));
806*09537850SAkhilesh Sanikop   int context;
807*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY] && !block.IsTopIntra() &&
808*09537850SAkhilesh Sanikop       block.left_available[kPlaneY] && !block.IsLeftIntra()) {
809*09537850SAkhilesh Sanikop     const int same_direction = static_cast<int>(IsSameDirectionReferencePair(
810*09537850SAkhilesh Sanikop         block.TopReference(0), block.LeftReference(0)));
811*09537850SAkhilesh Sanikop     if (!top_comp_inter && !left_comp_inter) {
812*09537850SAkhilesh Sanikop       context = 1 + MultiplyBy2(same_direction);
813*09537850SAkhilesh Sanikop     } else if (!top_comp_inter) {
814*09537850SAkhilesh Sanikop       context = left_uni_comp ? 3 + same_direction : 1;
815*09537850SAkhilesh Sanikop     } else if (!left_comp_inter) {
816*09537850SAkhilesh Sanikop       context = top_uni_comp ? 3 + same_direction : 1;
817*09537850SAkhilesh Sanikop     } else {
818*09537850SAkhilesh Sanikop       if (!top_uni_comp && !left_uni_comp) {
819*09537850SAkhilesh Sanikop         context = 0;
820*09537850SAkhilesh Sanikop       } else if (!top_uni_comp || !left_uni_comp) {
821*09537850SAkhilesh Sanikop         context = 2;
822*09537850SAkhilesh Sanikop       } else {
823*09537850SAkhilesh Sanikop         context = 3 + static_cast<int>(
824*09537850SAkhilesh Sanikop                           (block.TopReference(0) == kReferenceFrameBackward) ==
825*09537850SAkhilesh Sanikop                           (block.LeftReference(0) == kReferenceFrameBackward));
826*09537850SAkhilesh Sanikop       }
827*09537850SAkhilesh Sanikop     }
828*09537850SAkhilesh Sanikop   } else if (block.top_available[kPlaneY] && block.left_available[kPlaneY]) {
829*09537850SAkhilesh Sanikop     if (top_comp_inter) {
830*09537850SAkhilesh Sanikop       context = 1 + MultiplyBy2(static_cast<int>(top_uni_comp));
831*09537850SAkhilesh Sanikop     } else if (left_comp_inter) {
832*09537850SAkhilesh Sanikop       context = 1 + MultiplyBy2(static_cast<int>(left_uni_comp));
833*09537850SAkhilesh Sanikop     } else {
834*09537850SAkhilesh Sanikop       context = 2;
835*09537850SAkhilesh Sanikop     }
836*09537850SAkhilesh Sanikop   } else if (top_comp_inter) {
837*09537850SAkhilesh Sanikop     context = MultiplyBy4(static_cast<int>(top_uni_comp));
838*09537850SAkhilesh Sanikop   } else if (left_comp_inter) {
839*09537850SAkhilesh Sanikop     context = MultiplyBy4(static_cast<int>(left_uni_comp));
840*09537850SAkhilesh Sanikop   } else {
841*09537850SAkhilesh Sanikop     context = 2;
842*09537850SAkhilesh Sanikop   }
843*09537850SAkhilesh Sanikop   return static_cast<CompoundReferenceType>(reader_.ReadSymbol(
844*09537850SAkhilesh Sanikop       symbol_decoder_context_.compound_reference_type_cdf[context]));
845*09537850SAkhilesh Sanikop }
846*09537850SAkhilesh Sanikop 
847*09537850SAkhilesh Sanikop template <bool is_single, bool is_backward, int index>
GetReferenceCdf(const Block & block,CompoundReferenceType type)848*09537850SAkhilesh Sanikop uint16_t* Tile::GetReferenceCdf(
849*09537850SAkhilesh Sanikop     const Block& block,
850*09537850SAkhilesh Sanikop     CompoundReferenceType type /*= kNumCompoundReferenceTypes*/) {
851*09537850SAkhilesh Sanikop   int context = 0;
852*09537850SAkhilesh Sanikop   if ((type == kCompoundReferenceUnidirectional && index == 0) ||
853*09537850SAkhilesh Sanikop       (is_single && index == 1)) {
854*09537850SAkhilesh Sanikop     // uni_comp_ref and single_ref_p1.
855*09537850SAkhilesh Sanikop     context =
856*09537850SAkhilesh Sanikop         GetReferenceContext(block, kReferenceFrameLast, kReferenceFrameGolden,
857*09537850SAkhilesh Sanikop                             kReferenceFrameBackward, kReferenceFrameAlternate);
858*09537850SAkhilesh Sanikop   } else if (type == kCompoundReferenceUnidirectional && index == 1) {
859*09537850SAkhilesh Sanikop     // uni_comp_ref_p1.
860*09537850SAkhilesh Sanikop     context =
861*09537850SAkhilesh Sanikop         GetReferenceContext(block, kReferenceFrameLast2, kReferenceFrameLast2,
862*09537850SAkhilesh Sanikop                             kReferenceFrameLast3, kReferenceFrameGolden);
863*09537850SAkhilesh Sanikop   } else if ((type == kCompoundReferenceUnidirectional && index == 2) ||
864*09537850SAkhilesh Sanikop              (type == kCompoundReferenceBidirectional && index == 2) ||
865*09537850SAkhilesh Sanikop              (is_single && index == 5)) {
866*09537850SAkhilesh Sanikop     // uni_comp_ref_p2, comp_ref_p2 and single_ref_p5.
867*09537850SAkhilesh Sanikop     context =
868*09537850SAkhilesh Sanikop         GetReferenceContext(block, kReferenceFrameLast3, kReferenceFrameLast3,
869*09537850SAkhilesh Sanikop                             kReferenceFrameGolden, kReferenceFrameGolden);
870*09537850SAkhilesh Sanikop   } else if ((type == kCompoundReferenceBidirectional && index == 0) ||
871*09537850SAkhilesh Sanikop              (is_single && index == 3)) {
872*09537850SAkhilesh Sanikop     // comp_ref and single_ref_p3.
873*09537850SAkhilesh Sanikop     context =
874*09537850SAkhilesh Sanikop         GetReferenceContext(block, kReferenceFrameLast, kReferenceFrameLast2,
875*09537850SAkhilesh Sanikop                             kReferenceFrameLast3, kReferenceFrameGolden);
876*09537850SAkhilesh Sanikop   } else if ((type == kCompoundReferenceBidirectional && index == 1) ||
877*09537850SAkhilesh Sanikop              (is_single && index == 4)) {
878*09537850SAkhilesh Sanikop     // comp_ref_p1 and single_ref_p4.
879*09537850SAkhilesh Sanikop     context =
880*09537850SAkhilesh Sanikop         GetReferenceContext(block, kReferenceFrameLast, kReferenceFrameLast,
881*09537850SAkhilesh Sanikop                             kReferenceFrameLast2, kReferenceFrameLast2);
882*09537850SAkhilesh Sanikop   } else if ((is_single && index == 2) || (is_backward && index == 0)) {
883*09537850SAkhilesh Sanikop     // single_ref_p2 and comp_bwdref.
884*09537850SAkhilesh Sanikop     context = GetReferenceContext(
885*09537850SAkhilesh Sanikop         block, kReferenceFrameBackward, kReferenceFrameAlternate2,
886*09537850SAkhilesh Sanikop         kReferenceFrameAlternate, kReferenceFrameAlternate);
887*09537850SAkhilesh Sanikop   } else if ((is_single && index == 6) || (is_backward && index == 1)) {
888*09537850SAkhilesh Sanikop     // single_ref_p6 and comp_bwdref_p1.
889*09537850SAkhilesh Sanikop     context = GetReferenceContext(
890*09537850SAkhilesh Sanikop         block, kReferenceFrameBackward, kReferenceFrameBackward,
891*09537850SAkhilesh Sanikop         kReferenceFrameAlternate2, kReferenceFrameAlternate2);
892*09537850SAkhilesh Sanikop   }
893*09537850SAkhilesh Sanikop   // When using GCC 12.x for some targets the compiler reports a false positive
894*09537850SAkhilesh Sanikop   // with the context subscript when is_single=false, is_backward=false and
895*09537850SAkhilesh Sanikop   // index=0. GetReferenceContext() can only return values between 0 and 2.
896*09537850SAkhilesh Sanikop #ifdef __GNUC__
897*09537850SAkhilesh Sanikop #pragma GCC diagnostic push
898*09537850SAkhilesh Sanikop #pragma GCC diagnostic ignored "-Warray-bounds"
899*09537850SAkhilesh Sanikop #endif
900*09537850SAkhilesh Sanikop   assert(context >= 0 && context <= 2);
901*09537850SAkhilesh Sanikop   if (is_single) {
902*09537850SAkhilesh Sanikop     // The index parameter for single references is offset by one since the spec
903*09537850SAkhilesh Sanikop     // uses 1-based index for these elements.
904*09537850SAkhilesh Sanikop     return symbol_decoder_context_.single_reference_cdf[context][index - 1];
905*09537850SAkhilesh Sanikop   }
906*09537850SAkhilesh Sanikop   if (is_backward) {
907*09537850SAkhilesh Sanikop     return symbol_decoder_context_
908*09537850SAkhilesh Sanikop         .compound_backward_reference_cdf[context][index];
909*09537850SAkhilesh Sanikop   }
910*09537850SAkhilesh Sanikop   return symbol_decoder_context_.compound_reference_cdf[type][context][index];
911*09537850SAkhilesh Sanikop #ifdef __GNUC__
912*09537850SAkhilesh Sanikop #pragma GCC diagnostic pop
913*09537850SAkhilesh Sanikop #endif
914*09537850SAkhilesh Sanikop }
915*09537850SAkhilesh Sanikop 
ReadReferenceFrames(const Block & block,bool skip_mode)916*09537850SAkhilesh Sanikop void Tile::ReadReferenceFrames(const Block& block, bool skip_mode) {
917*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
918*09537850SAkhilesh Sanikop   if (skip_mode) {
919*09537850SAkhilesh Sanikop     bp.reference_frame[0] = frame_header_.skip_mode_frame[0];
920*09537850SAkhilesh Sanikop     bp.reference_frame[1] = frame_header_.skip_mode_frame[1];
921*09537850SAkhilesh Sanikop     return;
922*09537850SAkhilesh Sanikop   }
923*09537850SAkhilesh Sanikop   if (frame_header_.segmentation.FeatureActive(
924*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id,
925*09537850SAkhilesh Sanikop           kSegmentFeatureReferenceFrame)) {
926*09537850SAkhilesh Sanikop     bp.reference_frame[0] = static_cast<ReferenceFrameType>(
927*09537850SAkhilesh Sanikop         frame_header_.segmentation
928*09537850SAkhilesh Sanikop             .feature_data[bp.prediction_parameters->segment_id]
929*09537850SAkhilesh Sanikop                          [kSegmentFeatureReferenceFrame]);
930*09537850SAkhilesh Sanikop     bp.reference_frame[1] = kReferenceFrameNone;
931*09537850SAkhilesh Sanikop     return;
932*09537850SAkhilesh Sanikop   }
933*09537850SAkhilesh Sanikop   if (frame_header_.segmentation.FeatureActive(
934*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id, kSegmentFeatureSkip) ||
935*09537850SAkhilesh Sanikop       frame_header_.segmentation.FeatureActive(
936*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id, kSegmentFeatureGlobalMv)) {
937*09537850SAkhilesh Sanikop     bp.reference_frame[0] = kReferenceFrameLast;
938*09537850SAkhilesh Sanikop     bp.reference_frame[1] = kReferenceFrameNone;
939*09537850SAkhilesh Sanikop     return;
940*09537850SAkhilesh Sanikop   }
941*09537850SAkhilesh Sanikop   const bool use_compound_reference =
942*09537850SAkhilesh Sanikop       frame_header_.reference_mode_select &&
943*09537850SAkhilesh Sanikop       std::min(block.width4x4, block.height4x4) >= 2 &&
944*09537850SAkhilesh Sanikop       reader_.ReadSymbol(symbol_decoder_context_.use_compound_reference_cdf
945*09537850SAkhilesh Sanikop                              [GetUseCompoundReferenceContext(block)]);
946*09537850SAkhilesh Sanikop   if (use_compound_reference) {
947*09537850SAkhilesh Sanikop     CompoundReferenceType reference_type = ReadCompoundReferenceType(block);
948*09537850SAkhilesh Sanikop     if (reference_type == kCompoundReferenceUnidirectional) {
949*09537850SAkhilesh Sanikop       // uni_comp_ref.
950*09537850SAkhilesh Sanikop       if (reader_.ReadSymbol(
951*09537850SAkhilesh Sanikop               GetReferenceCdf<false, false, 0>(block, reference_type))) {
952*09537850SAkhilesh Sanikop         bp.reference_frame[0] = kReferenceFrameBackward;
953*09537850SAkhilesh Sanikop         bp.reference_frame[1] = kReferenceFrameAlternate;
954*09537850SAkhilesh Sanikop         return;
955*09537850SAkhilesh Sanikop       }
956*09537850SAkhilesh Sanikop       // uni_comp_ref_p1.
957*09537850SAkhilesh Sanikop       if (!reader_.ReadSymbol(
958*09537850SAkhilesh Sanikop               GetReferenceCdf<false, false, 1>(block, reference_type))) {
959*09537850SAkhilesh Sanikop         bp.reference_frame[0] = kReferenceFrameLast;
960*09537850SAkhilesh Sanikop         bp.reference_frame[1] = kReferenceFrameLast2;
961*09537850SAkhilesh Sanikop         return;
962*09537850SAkhilesh Sanikop       }
963*09537850SAkhilesh Sanikop       // uni_comp_ref_p2.
964*09537850SAkhilesh Sanikop       if (reader_.ReadSymbol(
965*09537850SAkhilesh Sanikop               GetReferenceCdf<false, false, 2>(block, reference_type))) {
966*09537850SAkhilesh Sanikop         bp.reference_frame[0] = kReferenceFrameLast;
967*09537850SAkhilesh Sanikop         bp.reference_frame[1] = kReferenceFrameGolden;
968*09537850SAkhilesh Sanikop         return;
969*09537850SAkhilesh Sanikop       }
970*09537850SAkhilesh Sanikop       bp.reference_frame[0] = kReferenceFrameLast;
971*09537850SAkhilesh Sanikop       bp.reference_frame[1] = kReferenceFrameLast3;
972*09537850SAkhilesh Sanikop       return;
973*09537850SAkhilesh Sanikop     }
974*09537850SAkhilesh Sanikop     assert(reference_type == kCompoundReferenceBidirectional);
975*09537850SAkhilesh Sanikop     // comp_ref.
976*09537850SAkhilesh Sanikop     if (reader_.ReadSymbol(
977*09537850SAkhilesh Sanikop             GetReferenceCdf<false, false, 0>(block, reference_type))) {
978*09537850SAkhilesh Sanikop       // comp_ref_p2.
979*09537850SAkhilesh Sanikop       bp.reference_frame[0] =
980*09537850SAkhilesh Sanikop           reader_.ReadSymbol(
981*09537850SAkhilesh Sanikop               GetReferenceCdf<false, false, 2>(block, reference_type))
982*09537850SAkhilesh Sanikop               ? kReferenceFrameGolden
983*09537850SAkhilesh Sanikop               : kReferenceFrameLast3;
984*09537850SAkhilesh Sanikop     } else {
985*09537850SAkhilesh Sanikop       // comp_ref_p1.
986*09537850SAkhilesh Sanikop       bp.reference_frame[0] =
987*09537850SAkhilesh Sanikop           reader_.ReadSymbol(
988*09537850SAkhilesh Sanikop               GetReferenceCdf<false, false, 1>(block, reference_type))
989*09537850SAkhilesh Sanikop               ? kReferenceFrameLast2
990*09537850SAkhilesh Sanikop               : kReferenceFrameLast;
991*09537850SAkhilesh Sanikop     }
992*09537850SAkhilesh Sanikop     // comp_bwdref.
993*09537850SAkhilesh Sanikop     if (reader_.ReadSymbol(GetReferenceCdf<false, true, 0>(block))) {
994*09537850SAkhilesh Sanikop       bp.reference_frame[1] = kReferenceFrameAlternate;
995*09537850SAkhilesh Sanikop     } else {
996*09537850SAkhilesh Sanikop       // comp_bwdref_p1.
997*09537850SAkhilesh Sanikop       bp.reference_frame[1] =
998*09537850SAkhilesh Sanikop           reader_.ReadSymbol(GetReferenceCdf<false, true, 1>(block))
999*09537850SAkhilesh Sanikop               ? kReferenceFrameAlternate2
1000*09537850SAkhilesh Sanikop               : kReferenceFrameBackward;
1001*09537850SAkhilesh Sanikop     }
1002*09537850SAkhilesh Sanikop     return;
1003*09537850SAkhilesh Sanikop   }
1004*09537850SAkhilesh Sanikop   assert(!use_compound_reference);
1005*09537850SAkhilesh Sanikop   bp.reference_frame[1] = kReferenceFrameNone;
1006*09537850SAkhilesh Sanikop   // single_ref_p1.
1007*09537850SAkhilesh Sanikop   if (reader_.ReadSymbol(GetReferenceCdf<true, false, 1>(block))) {
1008*09537850SAkhilesh Sanikop     // single_ref_p2.
1009*09537850SAkhilesh Sanikop     if (reader_.ReadSymbol(GetReferenceCdf<true, false, 2>(block))) {
1010*09537850SAkhilesh Sanikop       bp.reference_frame[0] = kReferenceFrameAlternate;
1011*09537850SAkhilesh Sanikop       return;
1012*09537850SAkhilesh Sanikop     }
1013*09537850SAkhilesh Sanikop     // single_ref_p6.
1014*09537850SAkhilesh Sanikop     bp.reference_frame[0] =
1015*09537850SAkhilesh Sanikop         reader_.ReadSymbol(GetReferenceCdf<true, false, 6>(block))
1016*09537850SAkhilesh Sanikop             ? kReferenceFrameAlternate2
1017*09537850SAkhilesh Sanikop             : kReferenceFrameBackward;
1018*09537850SAkhilesh Sanikop     return;
1019*09537850SAkhilesh Sanikop   }
1020*09537850SAkhilesh Sanikop   // single_ref_p3.
1021*09537850SAkhilesh Sanikop   if (reader_.ReadSymbol(GetReferenceCdf<true, false, 3>(block))) {
1022*09537850SAkhilesh Sanikop     // single_ref_p5.
1023*09537850SAkhilesh Sanikop     bp.reference_frame[0] =
1024*09537850SAkhilesh Sanikop         reader_.ReadSymbol(GetReferenceCdf<true, false, 5>(block))
1025*09537850SAkhilesh Sanikop             ? kReferenceFrameGolden
1026*09537850SAkhilesh Sanikop             : kReferenceFrameLast3;
1027*09537850SAkhilesh Sanikop     return;
1028*09537850SAkhilesh Sanikop   }
1029*09537850SAkhilesh Sanikop   // single_ref_p4.
1030*09537850SAkhilesh Sanikop   bp.reference_frame[0] =
1031*09537850SAkhilesh Sanikop       reader_.ReadSymbol(GetReferenceCdf<true, false, 4>(block))
1032*09537850SAkhilesh Sanikop           ? kReferenceFrameLast2
1033*09537850SAkhilesh Sanikop           : kReferenceFrameLast;
1034*09537850SAkhilesh Sanikop }
1035*09537850SAkhilesh Sanikop 
ReadInterPredictionModeY(const Block & block,const MvContexts & mode_contexts,bool skip_mode)1036*09537850SAkhilesh Sanikop void Tile::ReadInterPredictionModeY(const Block& block,
1037*09537850SAkhilesh Sanikop                                     const MvContexts& mode_contexts,
1038*09537850SAkhilesh Sanikop                                     bool skip_mode) {
1039*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
1040*09537850SAkhilesh Sanikop   if (skip_mode) {
1041*09537850SAkhilesh Sanikop     bp.y_mode = kPredictionModeNearestNearestMv;
1042*09537850SAkhilesh Sanikop     return;
1043*09537850SAkhilesh Sanikop   }
1044*09537850SAkhilesh Sanikop   if (frame_header_.segmentation.FeatureActive(
1045*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id, kSegmentFeatureSkip) ||
1046*09537850SAkhilesh Sanikop       frame_header_.segmentation.FeatureActive(
1047*09537850SAkhilesh Sanikop           bp.prediction_parameters->segment_id, kSegmentFeatureGlobalMv)) {
1048*09537850SAkhilesh Sanikop     bp.y_mode = kPredictionModeGlobalMv;
1049*09537850SAkhilesh Sanikop     return;
1050*09537850SAkhilesh Sanikop   }
1051*09537850SAkhilesh Sanikop   if (bp.reference_frame[1] > kReferenceFrameIntra) {
1052*09537850SAkhilesh Sanikop     const int idx0 = mode_contexts.reference_mv >> 1;
1053*09537850SAkhilesh Sanikop     const int idx1 =
1054*09537850SAkhilesh Sanikop         std::min(mode_contexts.new_mv, kCompoundModeNewMvContexts - 1);
1055*09537850SAkhilesh Sanikop     const int context = kCompoundModeContextMap[idx0][idx1];
1056*09537850SAkhilesh Sanikop     const int offset = reader_.ReadSymbol<kNumCompoundInterPredictionModes>(
1057*09537850SAkhilesh Sanikop         symbol_decoder_context_.compound_prediction_mode_cdf[context]);
1058*09537850SAkhilesh Sanikop     bp.y_mode =
1059*09537850SAkhilesh Sanikop         static_cast<PredictionMode>(kPredictionModeNearestNearestMv + offset);
1060*09537850SAkhilesh Sanikop     return;
1061*09537850SAkhilesh Sanikop   }
1062*09537850SAkhilesh Sanikop   // new_mv.
1063*09537850SAkhilesh Sanikop   if (!reader_.ReadSymbol(
1064*09537850SAkhilesh Sanikop           symbol_decoder_context_.new_mv_cdf[mode_contexts.new_mv])) {
1065*09537850SAkhilesh Sanikop     bp.y_mode = kPredictionModeNewMv;
1066*09537850SAkhilesh Sanikop     return;
1067*09537850SAkhilesh Sanikop   }
1068*09537850SAkhilesh Sanikop   // zero_mv.
1069*09537850SAkhilesh Sanikop   if (!reader_.ReadSymbol(
1070*09537850SAkhilesh Sanikop           symbol_decoder_context_.zero_mv_cdf[mode_contexts.zero_mv])) {
1071*09537850SAkhilesh Sanikop     bp.y_mode = kPredictionModeGlobalMv;
1072*09537850SAkhilesh Sanikop     return;
1073*09537850SAkhilesh Sanikop   }
1074*09537850SAkhilesh Sanikop   // ref_mv.
1075*09537850SAkhilesh Sanikop   bp.y_mode =
1076*09537850SAkhilesh Sanikop       reader_.ReadSymbol(
1077*09537850SAkhilesh Sanikop           symbol_decoder_context_.reference_mv_cdf[mode_contexts.reference_mv])
1078*09537850SAkhilesh Sanikop           ? kPredictionModeNearMv
1079*09537850SAkhilesh Sanikop           : kPredictionModeNearestMv;
1080*09537850SAkhilesh Sanikop }
1081*09537850SAkhilesh Sanikop 
ReadRefMvIndex(const Block & block)1082*09537850SAkhilesh Sanikop void Tile::ReadRefMvIndex(const Block& block) {
1083*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
1084*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
1085*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
1086*09537850SAkhilesh Sanikop   prediction_parameters.ref_mv_index = 0;
1087*09537850SAkhilesh Sanikop   if (bp.y_mode != kPredictionModeNewMv &&
1088*09537850SAkhilesh Sanikop       bp.y_mode != kPredictionModeNewNewMv &&
1089*09537850SAkhilesh Sanikop       !kPredictionModeHasNearMvMask.Contains(bp.y_mode)) {
1090*09537850SAkhilesh Sanikop     return;
1091*09537850SAkhilesh Sanikop   }
1092*09537850SAkhilesh Sanikop   const int start =
1093*09537850SAkhilesh Sanikop       static_cast<int>(kPredictionModeHasNearMvMask.Contains(bp.y_mode));
1094*09537850SAkhilesh Sanikop   prediction_parameters.ref_mv_index = start;
1095*09537850SAkhilesh Sanikop   for (int i = start; i < start + 2; ++i) {
1096*09537850SAkhilesh Sanikop     if (prediction_parameters.ref_mv_count <= i + 1) break;
1097*09537850SAkhilesh Sanikop     // drl_mode in the spec.
1098*09537850SAkhilesh Sanikop     const bool ref_mv_index_bit = reader_.ReadSymbol(
1099*09537850SAkhilesh Sanikop         symbol_decoder_context_.ref_mv_index_cdf[GetRefMvIndexContext(
1100*09537850SAkhilesh Sanikop             prediction_parameters.nearest_mv_count, i)]);
1101*09537850SAkhilesh Sanikop     prediction_parameters.ref_mv_index = i + static_cast<int>(ref_mv_index_bit);
1102*09537850SAkhilesh Sanikop     if (!ref_mv_index_bit) return;
1103*09537850SAkhilesh Sanikop   }
1104*09537850SAkhilesh Sanikop }
1105*09537850SAkhilesh Sanikop 
ReadInterIntraMode(const Block & block,bool is_compound,bool skip_mode)1106*09537850SAkhilesh Sanikop void Tile::ReadInterIntraMode(const Block& block, bool is_compound,
1107*09537850SAkhilesh Sanikop                               bool skip_mode) {
1108*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
1109*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
1110*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
1111*09537850SAkhilesh Sanikop   prediction_parameters.inter_intra_mode = kNumInterIntraModes;
1112*09537850SAkhilesh Sanikop   prediction_parameters.is_wedge_inter_intra = false;
1113*09537850SAkhilesh Sanikop   if (skip_mode || !sequence_header_.enable_interintra_compound ||
1114*09537850SAkhilesh Sanikop       is_compound || !kIsInterIntraModeAllowedMask.Contains(block.size)) {
1115*09537850SAkhilesh Sanikop     return;
1116*09537850SAkhilesh Sanikop   }
1117*09537850SAkhilesh Sanikop   // kSizeGroup[block.size] is guaranteed to be non-zero because of the block
1118*09537850SAkhilesh Sanikop   // size constraint enforced in the above condition.
1119*09537850SAkhilesh Sanikop   assert(kSizeGroup[block.size] - 1 >= 0);
1120*09537850SAkhilesh Sanikop   if (!reader_.ReadSymbol(
1121*09537850SAkhilesh Sanikop           symbol_decoder_context_
1122*09537850SAkhilesh Sanikop               .is_inter_intra_cdf[kSizeGroup[block.size] - 1])) {
1123*09537850SAkhilesh Sanikop     prediction_parameters.inter_intra_mode = kNumInterIntraModes;
1124*09537850SAkhilesh Sanikop     return;
1125*09537850SAkhilesh Sanikop   }
1126*09537850SAkhilesh Sanikop   prediction_parameters.inter_intra_mode =
1127*09537850SAkhilesh Sanikop       static_cast<InterIntraMode>(reader_.ReadSymbol<kNumInterIntraModes>(
1128*09537850SAkhilesh Sanikop           symbol_decoder_context_
1129*09537850SAkhilesh Sanikop               .inter_intra_mode_cdf[kSizeGroup[block.size] - 1]));
1130*09537850SAkhilesh Sanikop   bp.reference_frame[1] = kReferenceFrameIntra;
1131*09537850SAkhilesh Sanikop   prediction_parameters.angle_delta[kPlaneTypeY] = 0;
1132*09537850SAkhilesh Sanikop   prediction_parameters.angle_delta[kPlaneTypeUV] = 0;
1133*09537850SAkhilesh Sanikop   prediction_parameters.use_filter_intra = false;
1134*09537850SAkhilesh Sanikop   prediction_parameters.is_wedge_inter_intra = reader_.ReadSymbol(
1135*09537850SAkhilesh Sanikop       symbol_decoder_context_.is_wedge_inter_intra_cdf[block.size]);
1136*09537850SAkhilesh Sanikop   if (!prediction_parameters.is_wedge_inter_intra) return;
1137*09537850SAkhilesh Sanikop   prediction_parameters.wedge_index =
1138*09537850SAkhilesh Sanikop       reader_.ReadSymbol<kWedgeIndexSymbolCount>(
1139*09537850SAkhilesh Sanikop           symbol_decoder_context_.wedge_index_cdf[block.size]);
1140*09537850SAkhilesh Sanikop   prediction_parameters.wedge_sign = 0;
1141*09537850SAkhilesh Sanikop }
1142*09537850SAkhilesh Sanikop 
ReadMotionMode(const Block & block,bool is_compound,bool skip_mode)1143*09537850SAkhilesh Sanikop void Tile::ReadMotionMode(const Block& block, bool is_compound,
1144*09537850SAkhilesh Sanikop                           bool skip_mode) {
1145*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
1146*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
1147*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
1148*09537850SAkhilesh Sanikop   const auto global_motion_type =
1149*09537850SAkhilesh Sanikop       frame_header_.global_motion[bp.reference_frame[0]].type;
1150*09537850SAkhilesh Sanikop   if (skip_mode || !frame_header_.is_motion_mode_switchable ||
1151*09537850SAkhilesh Sanikop       IsBlockDimension4(block.size) ||
1152*09537850SAkhilesh Sanikop       (frame_header_.force_integer_mv == 0 &&
1153*09537850SAkhilesh Sanikop        (bp.y_mode == kPredictionModeGlobalMv ||
1154*09537850SAkhilesh Sanikop         bp.y_mode == kPredictionModeGlobalGlobalMv) &&
1155*09537850SAkhilesh Sanikop        global_motion_type > kGlobalMotionTransformationTypeTranslation) ||
1156*09537850SAkhilesh Sanikop       is_compound || bp.reference_frame[1] == kReferenceFrameIntra ||
1157*09537850SAkhilesh Sanikop       !block.HasOverlappableCandidates()) {
1158*09537850SAkhilesh Sanikop     prediction_parameters.motion_mode = kMotionModeSimple;
1159*09537850SAkhilesh Sanikop     return;
1160*09537850SAkhilesh Sanikop   }
1161*09537850SAkhilesh Sanikop   prediction_parameters.num_warp_samples = 0;
1162*09537850SAkhilesh Sanikop   int num_samples_scanned = 0;
1163*09537850SAkhilesh Sanikop   memset(prediction_parameters.warp_estimate_candidates, 0,
1164*09537850SAkhilesh Sanikop          sizeof(prediction_parameters.warp_estimate_candidates));
1165*09537850SAkhilesh Sanikop   FindWarpSamples(block, &prediction_parameters.num_warp_samples,
1166*09537850SAkhilesh Sanikop                   &num_samples_scanned,
1167*09537850SAkhilesh Sanikop                   prediction_parameters.warp_estimate_candidates);
1168*09537850SAkhilesh Sanikop   if (frame_header_.force_integer_mv != 0 ||
1169*09537850SAkhilesh Sanikop       prediction_parameters.num_warp_samples == 0 ||
1170*09537850SAkhilesh Sanikop       !frame_header_.allow_warped_motion || IsScaled(bp.reference_frame[0])) {
1171*09537850SAkhilesh Sanikop     prediction_parameters.motion_mode =
1172*09537850SAkhilesh Sanikop         reader_.ReadSymbol(symbol_decoder_context_.use_obmc_cdf[block.size])
1173*09537850SAkhilesh Sanikop             ? kMotionModeObmc
1174*09537850SAkhilesh Sanikop             : kMotionModeSimple;
1175*09537850SAkhilesh Sanikop     return;
1176*09537850SAkhilesh Sanikop   }
1177*09537850SAkhilesh Sanikop   prediction_parameters.motion_mode =
1178*09537850SAkhilesh Sanikop       static_cast<MotionMode>(reader_.ReadSymbol<kNumMotionModes>(
1179*09537850SAkhilesh Sanikop           symbol_decoder_context_.motion_mode_cdf[block.size]));
1180*09537850SAkhilesh Sanikop }
1181*09537850SAkhilesh Sanikop 
GetIsExplicitCompoundTypeCdf(const Block & block)1182*09537850SAkhilesh Sanikop uint16_t* Tile::GetIsExplicitCompoundTypeCdf(const Block& block) {
1183*09537850SAkhilesh Sanikop   int context = 0;
1184*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY]) {
1185*09537850SAkhilesh Sanikop     if (!block.IsTopSingle()) {
1186*09537850SAkhilesh Sanikop       context += static_cast<int>(
1187*09537850SAkhilesh Sanikop           block.top_context
1188*09537850SAkhilesh Sanikop               ->is_explicit_compound_type[block.top_context_index]);
1189*09537850SAkhilesh Sanikop     } else if (block.TopReference(0) == kReferenceFrameAlternate) {
1190*09537850SAkhilesh Sanikop       context += 3;
1191*09537850SAkhilesh Sanikop     }
1192*09537850SAkhilesh Sanikop   }
1193*09537850SAkhilesh Sanikop   if (block.left_available[kPlaneY]) {
1194*09537850SAkhilesh Sanikop     if (!block.IsLeftSingle()) {
1195*09537850SAkhilesh Sanikop       context += static_cast<int>(
1196*09537850SAkhilesh Sanikop           left_context_.is_explicit_compound_type[block.left_context_index]);
1197*09537850SAkhilesh Sanikop     } else if (block.LeftReference(0) == kReferenceFrameAlternate) {
1198*09537850SAkhilesh Sanikop       context += 3;
1199*09537850SAkhilesh Sanikop     }
1200*09537850SAkhilesh Sanikop   }
1201*09537850SAkhilesh Sanikop   return symbol_decoder_context_.is_explicit_compound_type_cdf[std::min(
1202*09537850SAkhilesh Sanikop       context, kIsExplicitCompoundTypeContexts - 1)];
1203*09537850SAkhilesh Sanikop }
1204*09537850SAkhilesh Sanikop 
GetIsCompoundTypeAverageCdf(const Block & block)1205*09537850SAkhilesh Sanikop uint16_t* Tile::GetIsCompoundTypeAverageCdf(const Block& block) {
1206*09537850SAkhilesh Sanikop   const BlockParameters& bp = *block.bp;
1207*09537850SAkhilesh Sanikop   const ReferenceInfo& reference_info = *current_frame_.reference_info();
1208*09537850SAkhilesh Sanikop   const int forward =
1209*09537850SAkhilesh Sanikop       std::abs(reference_info.relative_distance_from[bp.reference_frame[0]]);
1210*09537850SAkhilesh Sanikop   const int backward =
1211*09537850SAkhilesh Sanikop       std::abs(reference_info.relative_distance_from[bp.reference_frame[1]]);
1212*09537850SAkhilesh Sanikop   int context = (forward == backward) ? 3 : 0;
1213*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY]) {
1214*09537850SAkhilesh Sanikop     if (!block.IsTopSingle()) {
1215*09537850SAkhilesh Sanikop       context += static_cast<int>(
1216*09537850SAkhilesh Sanikop           block.top_context->is_compound_type_average[block.top_context_index]);
1217*09537850SAkhilesh Sanikop     } else if (block.TopReference(0) == kReferenceFrameAlternate) {
1218*09537850SAkhilesh Sanikop       ++context;
1219*09537850SAkhilesh Sanikop     }
1220*09537850SAkhilesh Sanikop   }
1221*09537850SAkhilesh Sanikop   if (block.left_available[kPlaneY]) {
1222*09537850SAkhilesh Sanikop     if (!block.IsLeftSingle()) {
1223*09537850SAkhilesh Sanikop       context += static_cast<int>(
1224*09537850SAkhilesh Sanikop           left_context_.is_compound_type_average[block.left_context_index]);
1225*09537850SAkhilesh Sanikop     } else if (block.LeftReference(0) == kReferenceFrameAlternate) {
1226*09537850SAkhilesh Sanikop       ++context;
1227*09537850SAkhilesh Sanikop     }
1228*09537850SAkhilesh Sanikop   }
1229*09537850SAkhilesh Sanikop   return symbol_decoder_context_.is_compound_type_average_cdf[context];
1230*09537850SAkhilesh Sanikop }
1231*09537850SAkhilesh Sanikop 
ReadCompoundType(const Block & block,bool is_compound,bool skip_mode,bool * const is_explicit_compound_type,bool * const is_compound_type_average)1232*09537850SAkhilesh Sanikop void Tile::ReadCompoundType(const Block& block, bool is_compound,
1233*09537850SAkhilesh Sanikop                             bool skip_mode,
1234*09537850SAkhilesh Sanikop                             bool* const is_explicit_compound_type,
1235*09537850SAkhilesh Sanikop                             bool* const is_compound_type_average) {
1236*09537850SAkhilesh Sanikop   *is_explicit_compound_type = false;
1237*09537850SAkhilesh Sanikop   *is_compound_type_average = true;
1238*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
1239*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
1240*09537850SAkhilesh Sanikop   if (skip_mode) {
1241*09537850SAkhilesh Sanikop     prediction_parameters.compound_prediction_type =
1242*09537850SAkhilesh Sanikop         kCompoundPredictionTypeAverage;
1243*09537850SAkhilesh Sanikop     return;
1244*09537850SAkhilesh Sanikop   }
1245*09537850SAkhilesh Sanikop   if (is_compound) {
1246*09537850SAkhilesh Sanikop     if (sequence_header_.enable_masked_compound) {
1247*09537850SAkhilesh Sanikop       *is_explicit_compound_type =
1248*09537850SAkhilesh Sanikop           reader_.ReadSymbol(GetIsExplicitCompoundTypeCdf(block));
1249*09537850SAkhilesh Sanikop     }
1250*09537850SAkhilesh Sanikop     if (*is_explicit_compound_type) {
1251*09537850SAkhilesh Sanikop       if (kIsWedgeCompoundModeAllowed.Contains(block.size)) {
1252*09537850SAkhilesh Sanikop         // Only kCompoundPredictionTypeWedge and
1253*09537850SAkhilesh Sanikop         // kCompoundPredictionTypeDiffWeighted are signaled explicitly.
1254*09537850SAkhilesh Sanikop         prediction_parameters.compound_prediction_type =
1255*09537850SAkhilesh Sanikop             static_cast<CompoundPredictionType>(reader_.ReadSymbol(
1256*09537850SAkhilesh Sanikop                 symbol_decoder_context_.compound_type_cdf[block.size]));
1257*09537850SAkhilesh Sanikop       } else {
1258*09537850SAkhilesh Sanikop         prediction_parameters.compound_prediction_type =
1259*09537850SAkhilesh Sanikop             kCompoundPredictionTypeDiffWeighted;
1260*09537850SAkhilesh Sanikop       }
1261*09537850SAkhilesh Sanikop     } else {
1262*09537850SAkhilesh Sanikop       if (sequence_header_.enable_jnt_comp) {
1263*09537850SAkhilesh Sanikop         *is_compound_type_average =
1264*09537850SAkhilesh Sanikop             reader_.ReadSymbol(GetIsCompoundTypeAverageCdf(block));
1265*09537850SAkhilesh Sanikop         prediction_parameters.compound_prediction_type =
1266*09537850SAkhilesh Sanikop             *is_compound_type_average ? kCompoundPredictionTypeAverage
1267*09537850SAkhilesh Sanikop                                       : kCompoundPredictionTypeDistance;
1268*09537850SAkhilesh Sanikop       } else {
1269*09537850SAkhilesh Sanikop         prediction_parameters.compound_prediction_type =
1270*09537850SAkhilesh Sanikop             kCompoundPredictionTypeAverage;
1271*09537850SAkhilesh Sanikop         return;
1272*09537850SAkhilesh Sanikop       }
1273*09537850SAkhilesh Sanikop     }
1274*09537850SAkhilesh Sanikop     if (prediction_parameters.compound_prediction_type ==
1275*09537850SAkhilesh Sanikop         kCompoundPredictionTypeWedge) {
1276*09537850SAkhilesh Sanikop       prediction_parameters.wedge_index =
1277*09537850SAkhilesh Sanikop           reader_.ReadSymbol<kWedgeIndexSymbolCount>(
1278*09537850SAkhilesh Sanikop               symbol_decoder_context_.wedge_index_cdf[block.size]);
1279*09537850SAkhilesh Sanikop       prediction_parameters.wedge_sign = static_cast<int>(reader_.ReadBit());
1280*09537850SAkhilesh Sanikop     } else if (prediction_parameters.compound_prediction_type ==
1281*09537850SAkhilesh Sanikop                kCompoundPredictionTypeDiffWeighted) {
1282*09537850SAkhilesh Sanikop       prediction_parameters.mask_is_inverse = reader_.ReadBit() != 0;
1283*09537850SAkhilesh Sanikop     }
1284*09537850SAkhilesh Sanikop     return;
1285*09537850SAkhilesh Sanikop   }
1286*09537850SAkhilesh Sanikop   if (prediction_parameters.inter_intra_mode != kNumInterIntraModes) {
1287*09537850SAkhilesh Sanikop     prediction_parameters.compound_prediction_type =
1288*09537850SAkhilesh Sanikop         prediction_parameters.is_wedge_inter_intra
1289*09537850SAkhilesh Sanikop             ? kCompoundPredictionTypeWedge
1290*09537850SAkhilesh Sanikop             : kCompoundPredictionTypeIntra;
1291*09537850SAkhilesh Sanikop     return;
1292*09537850SAkhilesh Sanikop   }
1293*09537850SAkhilesh Sanikop   prediction_parameters.compound_prediction_type =
1294*09537850SAkhilesh Sanikop       kCompoundPredictionTypeAverage;
1295*09537850SAkhilesh Sanikop }
1296*09537850SAkhilesh Sanikop 
GetInterpolationFilterCdf(const Block & block,int direction)1297*09537850SAkhilesh Sanikop uint16_t* Tile::GetInterpolationFilterCdf(const Block& block, int direction) {
1298*09537850SAkhilesh Sanikop   const BlockParameters& bp = *block.bp;
1299*09537850SAkhilesh Sanikop   int context = MultiplyBy8(direction) +
1300*09537850SAkhilesh Sanikop                 MultiplyBy4(static_cast<int>(bp.reference_frame[1] >
1301*09537850SAkhilesh Sanikop                                              kReferenceFrameIntra));
1302*09537850SAkhilesh Sanikop   int top_type = kNumExplicitInterpolationFilters;
1303*09537850SAkhilesh Sanikop   if (block.top_available[kPlaneY]) {
1304*09537850SAkhilesh Sanikop     if (block.bp_top->reference_frame[0] == bp.reference_frame[0] ||
1305*09537850SAkhilesh Sanikop         block.bp_top->reference_frame[1] == bp.reference_frame[0]) {
1306*09537850SAkhilesh Sanikop       top_type = block.bp_top->interpolation_filter[direction];
1307*09537850SAkhilesh Sanikop     }
1308*09537850SAkhilesh Sanikop   }
1309*09537850SAkhilesh Sanikop   int left_type = kNumExplicitInterpolationFilters;
1310*09537850SAkhilesh Sanikop   if (block.left_available[kPlaneY]) {
1311*09537850SAkhilesh Sanikop     if (block.bp_left->reference_frame[0] == bp.reference_frame[0] ||
1312*09537850SAkhilesh Sanikop         block.bp_left->reference_frame[1] == bp.reference_frame[0]) {
1313*09537850SAkhilesh Sanikop       left_type = block.bp_left->interpolation_filter[direction];
1314*09537850SAkhilesh Sanikop     }
1315*09537850SAkhilesh Sanikop   }
1316*09537850SAkhilesh Sanikop   if (left_type == top_type) {
1317*09537850SAkhilesh Sanikop     context += left_type;
1318*09537850SAkhilesh Sanikop   } else if (left_type == kNumExplicitInterpolationFilters) {
1319*09537850SAkhilesh Sanikop     context += top_type;
1320*09537850SAkhilesh Sanikop   } else if (top_type == kNumExplicitInterpolationFilters) {
1321*09537850SAkhilesh Sanikop     context += left_type;
1322*09537850SAkhilesh Sanikop   } else {
1323*09537850SAkhilesh Sanikop     context += kNumExplicitInterpolationFilters;
1324*09537850SAkhilesh Sanikop   }
1325*09537850SAkhilesh Sanikop   return symbol_decoder_context_.interpolation_filter_cdf[context];
1326*09537850SAkhilesh Sanikop }
1327*09537850SAkhilesh Sanikop 
ReadInterpolationFilter(const Block & block,bool skip_mode)1328*09537850SAkhilesh Sanikop void Tile::ReadInterpolationFilter(const Block& block, bool skip_mode) {
1329*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
1330*09537850SAkhilesh Sanikop   if (frame_header_.interpolation_filter != kInterpolationFilterSwitchable) {
1331*09537850SAkhilesh Sanikop     static_assert(
1332*09537850SAkhilesh Sanikop         sizeof(bp.interpolation_filter) / sizeof(bp.interpolation_filter[0]) ==
1333*09537850SAkhilesh Sanikop             2,
1334*09537850SAkhilesh Sanikop         "Interpolation filter array size is not 2");
1335*09537850SAkhilesh Sanikop     for (auto& interpolation_filter : bp.interpolation_filter) {
1336*09537850SAkhilesh Sanikop       interpolation_filter = frame_header_.interpolation_filter;
1337*09537850SAkhilesh Sanikop     }
1338*09537850SAkhilesh Sanikop     return;
1339*09537850SAkhilesh Sanikop   }
1340*09537850SAkhilesh Sanikop   bool interpolation_filter_present = true;
1341*09537850SAkhilesh Sanikop   if (skip_mode ||
1342*09537850SAkhilesh Sanikop       block.bp->prediction_parameters->motion_mode == kMotionModeLocalWarp) {
1343*09537850SAkhilesh Sanikop     interpolation_filter_present = false;
1344*09537850SAkhilesh Sanikop   } else if (!IsBlockDimension4(block.size) &&
1345*09537850SAkhilesh Sanikop              bp.y_mode == kPredictionModeGlobalMv) {
1346*09537850SAkhilesh Sanikop     interpolation_filter_present =
1347*09537850SAkhilesh Sanikop         frame_header_.global_motion[bp.reference_frame[0]].type ==
1348*09537850SAkhilesh Sanikop         kGlobalMotionTransformationTypeTranslation;
1349*09537850SAkhilesh Sanikop   } else if (!IsBlockDimension4(block.size) &&
1350*09537850SAkhilesh Sanikop              bp.y_mode == kPredictionModeGlobalGlobalMv) {
1351*09537850SAkhilesh Sanikop     interpolation_filter_present =
1352*09537850SAkhilesh Sanikop         frame_header_.global_motion[bp.reference_frame[0]].type ==
1353*09537850SAkhilesh Sanikop             kGlobalMotionTransformationTypeTranslation ||
1354*09537850SAkhilesh Sanikop         frame_header_.global_motion[bp.reference_frame[1]].type ==
1355*09537850SAkhilesh Sanikop             kGlobalMotionTransformationTypeTranslation;
1356*09537850SAkhilesh Sanikop   }
1357*09537850SAkhilesh Sanikop   for (int i = 0; i < (sequence_header_.enable_dual_filter ? 2 : 1); ++i) {
1358*09537850SAkhilesh Sanikop     bp.interpolation_filter[i] =
1359*09537850SAkhilesh Sanikop         interpolation_filter_present
1360*09537850SAkhilesh Sanikop             ? static_cast<InterpolationFilter>(
1361*09537850SAkhilesh Sanikop                   reader_.ReadSymbol<kNumExplicitInterpolationFilters>(
1362*09537850SAkhilesh Sanikop                       GetInterpolationFilterCdf(block, i)))
1363*09537850SAkhilesh Sanikop             : kInterpolationFilterEightTap;
1364*09537850SAkhilesh Sanikop   }
1365*09537850SAkhilesh Sanikop   if (!sequence_header_.enable_dual_filter) {
1366*09537850SAkhilesh Sanikop     bp.interpolation_filter[1] = bp.interpolation_filter[0];
1367*09537850SAkhilesh Sanikop   }
1368*09537850SAkhilesh Sanikop }
1369*09537850SAkhilesh Sanikop 
SetCdfContextCompoundType(const Block & block,bool is_explicit_compound_type,bool is_compound_type_average)1370*09537850SAkhilesh Sanikop void Tile::SetCdfContextCompoundType(const Block& block,
1371*09537850SAkhilesh Sanikop                                      bool is_explicit_compound_type,
1372*09537850SAkhilesh Sanikop                                      bool is_compound_type_average) {
1373*09537850SAkhilesh Sanikop   memset(left_context_.is_explicit_compound_type + block.left_context_index,
1374*09537850SAkhilesh Sanikop          static_cast<int>(is_explicit_compound_type), block.height4x4);
1375*09537850SAkhilesh Sanikop   memset(left_context_.is_compound_type_average + block.left_context_index,
1376*09537850SAkhilesh Sanikop          static_cast<int>(is_compound_type_average), block.height4x4);
1377*09537850SAkhilesh Sanikop   memset(block.top_context->is_explicit_compound_type + block.top_context_index,
1378*09537850SAkhilesh Sanikop          static_cast<int>(is_explicit_compound_type), block.width4x4);
1379*09537850SAkhilesh Sanikop   memset(block.top_context->is_compound_type_average + block.top_context_index,
1380*09537850SAkhilesh Sanikop          static_cast<int>(is_compound_type_average), block.width4x4);
1381*09537850SAkhilesh Sanikop }
1382*09537850SAkhilesh Sanikop 
ReadInterBlockModeInfo(const Block & block,bool skip_mode)1383*09537850SAkhilesh Sanikop bool Tile::ReadInterBlockModeInfo(const Block& block, bool skip_mode) {
1384*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
1385*09537850SAkhilesh Sanikop   bp.prediction_parameters->palette_mode_info.size[kPlaneTypeY] = 0;
1386*09537850SAkhilesh Sanikop   bp.prediction_parameters->palette_mode_info.size[kPlaneTypeUV] = 0;
1387*09537850SAkhilesh Sanikop   SetCdfContextPaletteSize(block);
1388*09537850SAkhilesh Sanikop   ReadReferenceFrames(block, skip_mode);
1389*09537850SAkhilesh Sanikop   const bool is_compound = bp.reference_frame[1] > kReferenceFrameIntra;
1390*09537850SAkhilesh Sanikop   MvContexts mode_contexts;
1391*09537850SAkhilesh Sanikop   FindMvStack(block, is_compound, &mode_contexts);
1392*09537850SAkhilesh Sanikop   ReadInterPredictionModeY(block, mode_contexts, skip_mode);
1393*09537850SAkhilesh Sanikop   ReadRefMvIndex(block);
1394*09537850SAkhilesh Sanikop   if (!AssignInterMv(block, is_compound)) return false;
1395*09537850SAkhilesh Sanikop   ReadInterIntraMode(block, is_compound, skip_mode);
1396*09537850SAkhilesh Sanikop   ReadMotionMode(block, is_compound, skip_mode);
1397*09537850SAkhilesh Sanikop   bool is_explicit_compound_type;
1398*09537850SAkhilesh Sanikop   bool is_compound_type_average;
1399*09537850SAkhilesh Sanikop   ReadCompoundType(block, is_compound, skip_mode, &is_explicit_compound_type,
1400*09537850SAkhilesh Sanikop                    &is_compound_type_average);
1401*09537850SAkhilesh Sanikop   SetCdfContextCompoundType(block, is_explicit_compound_type,
1402*09537850SAkhilesh Sanikop                             is_compound_type_average);
1403*09537850SAkhilesh Sanikop   ReadInterpolationFilter(block, skip_mode);
1404*09537850SAkhilesh Sanikop   return true;
1405*09537850SAkhilesh Sanikop }
1406*09537850SAkhilesh Sanikop 
SetCdfContextSkipMode(const Block & block,bool skip_mode)1407*09537850SAkhilesh Sanikop void Tile::SetCdfContextSkipMode(const Block& block, bool skip_mode) {
1408*09537850SAkhilesh Sanikop   memset(left_context_.skip_mode + block.left_context_index,
1409*09537850SAkhilesh Sanikop          static_cast<int>(skip_mode), block.height4x4);
1410*09537850SAkhilesh Sanikop   memset(block.top_context->skip_mode + block.top_context_index,
1411*09537850SAkhilesh Sanikop          static_cast<int>(skip_mode), block.width4x4);
1412*09537850SAkhilesh Sanikop }
1413*09537850SAkhilesh Sanikop 
DecodeInterModeInfo(const Block & block)1414*09537850SAkhilesh Sanikop bool Tile::DecodeInterModeInfo(const Block& block) {
1415*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
1416*09537850SAkhilesh Sanikop   block.bp->prediction_parameters->use_intra_block_copy = false;
1417*09537850SAkhilesh Sanikop   bp.skip = false;
1418*09537850SAkhilesh Sanikop   if (!ReadInterSegmentId(block, /*pre_skip=*/true)) return false;
1419*09537850SAkhilesh Sanikop   bool skip_mode = ReadSkipMode(block);
1420*09537850SAkhilesh Sanikop   SetCdfContextSkipMode(block, skip_mode);
1421*09537850SAkhilesh Sanikop   if (skip_mode) {
1422*09537850SAkhilesh Sanikop     bp.skip = true;
1423*09537850SAkhilesh Sanikop   } else {
1424*09537850SAkhilesh Sanikop     ReadSkip(block);
1425*09537850SAkhilesh Sanikop   }
1426*09537850SAkhilesh Sanikop   if (!frame_header_.segmentation.segment_id_pre_skip &&
1427*09537850SAkhilesh Sanikop       !ReadInterSegmentId(block, /*pre_skip=*/false)) {
1428*09537850SAkhilesh Sanikop     return false;
1429*09537850SAkhilesh Sanikop   }
1430*09537850SAkhilesh Sanikop   ReadCdef(block);
1431*09537850SAkhilesh Sanikop   if (read_deltas_) {
1432*09537850SAkhilesh Sanikop     ReadQuantizerIndexDelta(block);
1433*09537850SAkhilesh Sanikop     ReadLoopFilterDelta(block);
1434*09537850SAkhilesh Sanikop     read_deltas_ = false;
1435*09537850SAkhilesh Sanikop   }
1436*09537850SAkhilesh Sanikop   ReadIsInter(block, skip_mode);
1437*09537850SAkhilesh Sanikop   return bp.is_inter ? ReadInterBlockModeInfo(block, skip_mode)
1438*09537850SAkhilesh Sanikop                      : ReadIntraBlockModeInfo(block, /*intra_y_mode=*/false);
1439*09537850SAkhilesh Sanikop }
1440*09537850SAkhilesh Sanikop 
DecodeModeInfo(const Block & block)1441*09537850SAkhilesh Sanikop bool Tile::DecodeModeInfo(const Block& block) {
1442*09537850SAkhilesh Sanikop   return IsIntraFrame(frame_header_.frame_type) ? DecodeIntraModeInfo(block)
1443*09537850SAkhilesh Sanikop                                                 : DecodeInterModeInfo(block);
1444*09537850SAkhilesh Sanikop }
1445*09537850SAkhilesh Sanikop 
1446*09537850SAkhilesh Sanikop }  // namespace libgav1
1447