xref: /aosp_15_r20/external/libgav1/src/tile/bitstream/palette.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 <cassert>
17*09537850SAkhilesh Sanikop #include <cstdint>
18*09537850SAkhilesh Sanikop #include <cstring>
19*09537850SAkhilesh Sanikop #include <iterator>
20*09537850SAkhilesh Sanikop #include <memory>
21*09537850SAkhilesh Sanikop 
22*09537850SAkhilesh Sanikop #include "src/obu_parser.h"
23*09537850SAkhilesh Sanikop #include "src/symbol_decoder_context.h"
24*09537850SAkhilesh Sanikop #include "src/tile.h"
25*09537850SAkhilesh Sanikop #include "src/utils/bit_mask_set.h"
26*09537850SAkhilesh Sanikop #include "src/utils/common.h"
27*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
28*09537850SAkhilesh Sanikop #include "src/utils/entropy_decoder.h"
29*09537850SAkhilesh Sanikop #include "src/utils/memory.h"
30*09537850SAkhilesh Sanikop #include "src/utils/types.h"
31*09537850SAkhilesh Sanikop 
32*09537850SAkhilesh Sanikop namespace libgav1 {
33*09537850SAkhilesh Sanikop 
GetPaletteCache(const Block & block,PlaneType plane_type,uint16_t * const cache)34*09537850SAkhilesh Sanikop int Tile::GetPaletteCache(const Block& block, PlaneType plane_type,
35*09537850SAkhilesh Sanikop                           uint16_t* const cache) {
36*09537850SAkhilesh Sanikop   const int top_size =
37*09537850SAkhilesh Sanikop       (block.top_available[kPlaneY] && Mod64(MultiplyBy4(block.row4x4)) != 0)
38*09537850SAkhilesh Sanikop           ? block.top_context->palette_size[plane_type][block.top_context_index]
39*09537850SAkhilesh Sanikop           : 0;
40*09537850SAkhilesh Sanikop   const int left_size =
41*09537850SAkhilesh Sanikop       block.left_available[kPlaneY]
42*09537850SAkhilesh Sanikop           ? left_context_.palette_size[plane_type][block.left_context_index]
43*09537850SAkhilesh Sanikop           : 0;
44*09537850SAkhilesh Sanikop   if (left_size == 0 && top_size == 0) return 0;
45*09537850SAkhilesh Sanikop   // Merge the left and top colors in sorted order and store them in |cache|.
46*09537850SAkhilesh Sanikop   uint16_t empty_palette[1];
47*09537850SAkhilesh Sanikop   const uint16_t* top =
48*09537850SAkhilesh Sanikop       (top_size > 0) ? block.top_context
49*09537850SAkhilesh Sanikop                            ->palette_color[block.top_context_index][plane_type]
50*09537850SAkhilesh Sanikop                      : empty_palette;
51*09537850SAkhilesh Sanikop   const uint16_t* left =
52*09537850SAkhilesh Sanikop       (left_size > 0)
53*09537850SAkhilesh Sanikop           ? left_context_.palette_color[block.left_context_index][plane_type]
54*09537850SAkhilesh Sanikop           : empty_palette;
55*09537850SAkhilesh Sanikop   std::merge(top, top + top_size, left, left + left_size, cache);
56*09537850SAkhilesh Sanikop   // Deduplicate the entries in |cache| and return the number of unique
57*09537850SAkhilesh Sanikop   // entries.
58*09537850SAkhilesh Sanikop   return static_cast<int>(
59*09537850SAkhilesh Sanikop       std::distance(cache, std::unique(cache, cache + left_size + top_size)));
60*09537850SAkhilesh Sanikop }
61*09537850SAkhilesh Sanikop 
ReadPaletteColors(const Block & block,Plane plane)62*09537850SAkhilesh Sanikop void Tile::ReadPaletteColors(const Block& block, Plane plane) {
63*09537850SAkhilesh Sanikop   const PlaneType plane_type = GetPlaneType(plane);
64*09537850SAkhilesh Sanikop   uint16_t cache[2 * kMaxPaletteSize];
65*09537850SAkhilesh Sanikop   const int n = GetPaletteCache(block, plane_type, cache);
66*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
67*09537850SAkhilesh Sanikop   const uint8_t palette_size =
68*09537850SAkhilesh Sanikop       bp.prediction_parameters->palette_mode_info.size[plane_type];
69*09537850SAkhilesh Sanikop   uint16_t* const palette_color =
70*09537850SAkhilesh Sanikop       bp.prediction_parameters->palette_mode_info.color[plane];
71*09537850SAkhilesh Sanikop   const int8_t bitdepth = sequence_header_.color_config.bitdepth;
72*09537850SAkhilesh Sanikop   int index = 0;
73*09537850SAkhilesh Sanikop   for (int i = 0; i < n && index < palette_size; ++i) {
74*09537850SAkhilesh Sanikop     if (reader_.ReadBit() != 0) {  // use_palette_color_cache.
75*09537850SAkhilesh Sanikop       palette_color[index++] = cache[i];
76*09537850SAkhilesh Sanikop     }
77*09537850SAkhilesh Sanikop   }
78*09537850SAkhilesh Sanikop   const int merge_pivot = index;
79*09537850SAkhilesh Sanikop   if (index < palette_size) {
80*09537850SAkhilesh Sanikop     palette_color[index++] =
81*09537850SAkhilesh Sanikop         static_cast<uint16_t>(reader_.ReadLiteral(bitdepth));
82*09537850SAkhilesh Sanikop   }
83*09537850SAkhilesh Sanikop   const int max_value = (1 << bitdepth) - 1;
84*09537850SAkhilesh Sanikop   if (index < palette_size) {
85*09537850SAkhilesh Sanikop     int bits = bitdepth - 3 + static_cast<int>(reader_.ReadLiteral(2));
86*09537850SAkhilesh Sanikop     do {
87*09537850SAkhilesh Sanikop       const int delta = static_cast<int>(reader_.ReadLiteral(bits)) +
88*09537850SAkhilesh Sanikop                         (plane_type == kPlaneTypeY ? 1 : 0);
89*09537850SAkhilesh Sanikop       palette_color[index] =
90*09537850SAkhilesh Sanikop           std::min(palette_color[index - 1] + delta, max_value);
91*09537850SAkhilesh Sanikop       if (palette_color[index] + (plane_type == kPlaneTypeY ? 1 : 0) >=
92*09537850SAkhilesh Sanikop           max_value) {
93*09537850SAkhilesh Sanikop         // Once the color exceeds max_value, all others can be set to max_value
94*09537850SAkhilesh Sanikop         // (since they are computed as a delta on top of the current color and
95*09537850SAkhilesh Sanikop         // then clipped).
96*09537850SAkhilesh Sanikop         Memset(&palette_color[index + 1], max_value, palette_size - index - 1);
97*09537850SAkhilesh Sanikop         break;
98*09537850SAkhilesh Sanikop       }
99*09537850SAkhilesh Sanikop       const int range = (1 << bitdepth) - palette_color[index] -
100*09537850SAkhilesh Sanikop                         (plane_type == kPlaneTypeY ? 1 : 0);
101*09537850SAkhilesh Sanikop       bits = std::min(bits, CeilLog2(range));
102*09537850SAkhilesh Sanikop     } while (++index < palette_size);
103*09537850SAkhilesh Sanikop   }
104*09537850SAkhilesh Sanikop   // Palette colors are generated using two ascending arrays. So sorting them is
105*09537850SAkhilesh Sanikop   // simply a matter of merging the two sorted portions of the array.
106*09537850SAkhilesh Sanikop   std::inplace_merge(palette_color, palette_color + merge_pivot,
107*09537850SAkhilesh Sanikop                      palette_color + palette_size);
108*09537850SAkhilesh Sanikop   if (plane_type == kPlaneTypeUV) {
109*09537850SAkhilesh Sanikop     uint16_t* const palette_color_v =
110*09537850SAkhilesh Sanikop         bp.prediction_parameters->palette_mode_info.color[kPlaneV];
111*09537850SAkhilesh Sanikop     if (reader_.ReadBit() != 0) {  // delta_encode_palette_colors_v.
112*09537850SAkhilesh Sanikop       const int bits = bitdepth - 4 + static_cast<int>(reader_.ReadLiteral(2));
113*09537850SAkhilesh Sanikop       palette_color_v[0] = reader_.ReadLiteral(bitdepth);
114*09537850SAkhilesh Sanikop       for (int i = 1; i < palette_size; ++i) {
115*09537850SAkhilesh Sanikop         int delta = static_cast<int>(reader_.ReadLiteral(bits));
116*09537850SAkhilesh Sanikop         if (delta != 0 && reader_.ReadBit() != 0) delta = -delta;
117*09537850SAkhilesh Sanikop         // This line is equivalent to the following lines in the spec:
118*09537850SAkhilesh Sanikop         // val = palette_colors_v[ idx - 1 ] + palette_delta_v
119*09537850SAkhilesh Sanikop         // if ( val < 0 ) val += maxVal
120*09537850SAkhilesh Sanikop         // if ( val >= maxVal ) val -= maxVal
121*09537850SAkhilesh Sanikop         // palette_colors_v[ idx ] = Clip1( val )
122*09537850SAkhilesh Sanikop         //
123*09537850SAkhilesh Sanikop         // The difference is that in the code, max_value is (1 << bitdepth) - 1.
124*09537850SAkhilesh Sanikop         // So "& max_value" has the desired effect of computing both the "if"
125*09537850SAkhilesh Sanikop         // conditions and the Clip.
126*09537850SAkhilesh Sanikop         palette_color_v[i] = (palette_color_v[i - 1] + delta) & max_value;
127*09537850SAkhilesh Sanikop       }
128*09537850SAkhilesh Sanikop     } else {
129*09537850SAkhilesh Sanikop       for (int i = 0; i < palette_size; ++i) {
130*09537850SAkhilesh Sanikop         palette_color_v[i] =
131*09537850SAkhilesh Sanikop             static_cast<uint16_t>(reader_.ReadLiteral(bitdepth));
132*09537850SAkhilesh Sanikop       }
133*09537850SAkhilesh Sanikop     }
134*09537850SAkhilesh Sanikop   }
135*09537850SAkhilesh Sanikop }
136*09537850SAkhilesh Sanikop 
ReadPaletteModeInfo(const Block & block)137*09537850SAkhilesh Sanikop void Tile::ReadPaletteModeInfo(const Block& block) {
138*09537850SAkhilesh Sanikop   BlockParameters& bp = *block.bp;
139*09537850SAkhilesh Sanikop   bp.prediction_parameters->palette_mode_info.size[kPlaneTypeY] = 0;
140*09537850SAkhilesh Sanikop   bp.prediction_parameters->palette_mode_info.size[kPlaneTypeUV] = 0;
141*09537850SAkhilesh Sanikop   if (IsBlockSmallerThan8x8(block.size) || block.size > kBlock64x64 ||
142*09537850SAkhilesh Sanikop       !frame_header_.allow_screen_content_tools) {
143*09537850SAkhilesh Sanikop     return;
144*09537850SAkhilesh Sanikop   }
145*09537850SAkhilesh Sanikop   const int block_size_context =
146*09537850SAkhilesh Sanikop       k4x4WidthLog2[block.size] + k4x4HeightLog2[block.size] - 2;
147*09537850SAkhilesh Sanikop   if (bp.y_mode == kPredictionModeDc) {
148*09537850SAkhilesh Sanikop     const int context =
149*09537850SAkhilesh Sanikop         static_cast<int>(
150*09537850SAkhilesh Sanikop             block.top_available[kPlaneY] &&
151*09537850SAkhilesh Sanikop             block.top_context
152*09537850SAkhilesh Sanikop                     ->palette_size[kPlaneTypeY][block.top_context_index] > 0) +
153*09537850SAkhilesh Sanikop         static_cast<int>(
154*09537850SAkhilesh Sanikop             block.left_available[kPlaneY] &&
155*09537850SAkhilesh Sanikop             left_context_.palette_size[kPlaneTypeY][block.left_context_index] >
156*09537850SAkhilesh Sanikop                 0);
157*09537850SAkhilesh Sanikop     const bool has_palette_y = reader_.ReadSymbol(
158*09537850SAkhilesh Sanikop         symbol_decoder_context_.has_palette_y_cdf[block_size_context][context]);
159*09537850SAkhilesh Sanikop     if (has_palette_y) {
160*09537850SAkhilesh Sanikop       bp.prediction_parameters->palette_mode_info.size[kPlaneTypeY] =
161*09537850SAkhilesh Sanikop           kMinPaletteSize +
162*09537850SAkhilesh Sanikop           reader_.ReadSymbol<kPaletteSizeSymbolCount>(
163*09537850SAkhilesh Sanikop               symbol_decoder_context_.palette_y_size_cdf[block_size_context]);
164*09537850SAkhilesh Sanikop       ReadPaletteColors(block, kPlaneY);
165*09537850SAkhilesh Sanikop     }
166*09537850SAkhilesh Sanikop   }
167*09537850SAkhilesh Sanikop   if (block.HasChroma() &&
168*09537850SAkhilesh Sanikop       bp.prediction_parameters->uv_mode == kPredictionModeDc) {
169*09537850SAkhilesh Sanikop     const int context = static_cast<int>(
170*09537850SAkhilesh Sanikop         bp.prediction_parameters->palette_mode_info.size[kPlaneTypeY] > 0);
171*09537850SAkhilesh Sanikop     const bool has_palette_uv =
172*09537850SAkhilesh Sanikop         reader_.ReadSymbol(symbol_decoder_context_.has_palette_uv_cdf[context]);
173*09537850SAkhilesh Sanikop     if (has_palette_uv) {
174*09537850SAkhilesh Sanikop       bp.prediction_parameters->palette_mode_info.size[kPlaneTypeUV] =
175*09537850SAkhilesh Sanikop           kMinPaletteSize +
176*09537850SAkhilesh Sanikop           reader_.ReadSymbol<kPaletteSizeSymbolCount>(
177*09537850SAkhilesh Sanikop               symbol_decoder_context_.palette_uv_size_cdf[block_size_context]);
178*09537850SAkhilesh Sanikop       ReadPaletteColors(block, kPlaneU);
179*09537850SAkhilesh Sanikop     }
180*09537850SAkhilesh Sanikop   }
181*09537850SAkhilesh Sanikop }
182*09537850SAkhilesh Sanikop 
PopulatePaletteColorContexts(const Block & block,PlaneType plane_type,int i,int start,int end,uint8_t color_order[kMaxPaletteSquare][kMaxPaletteSize],uint8_t color_context[kMaxPaletteSquare])183*09537850SAkhilesh Sanikop void Tile::PopulatePaletteColorContexts(
184*09537850SAkhilesh Sanikop     const Block& block, PlaneType plane_type, int i, int start, int end,
185*09537850SAkhilesh Sanikop     uint8_t color_order[kMaxPaletteSquare][kMaxPaletteSize],
186*09537850SAkhilesh Sanikop     uint8_t color_context[kMaxPaletteSquare]) {
187*09537850SAkhilesh Sanikop   const PredictionParameters& prediction_parameters =
188*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
189*09537850SAkhilesh Sanikop   for (int column = start, counter = 0; column >= end; --column, ++counter) {
190*09537850SAkhilesh Sanikop     const int row = i - column;
191*09537850SAkhilesh Sanikop     assert(row > 0 || column > 0);
192*09537850SAkhilesh Sanikop     const uint8_t top =
193*09537850SAkhilesh Sanikop         (row > 0)
194*09537850SAkhilesh Sanikop             ? prediction_parameters.color_index_map[plane_type][row - 1][column]
195*09537850SAkhilesh Sanikop             : 0;
196*09537850SAkhilesh Sanikop     const uint8_t left =
197*09537850SAkhilesh Sanikop         (column > 0)
198*09537850SAkhilesh Sanikop             ? prediction_parameters.color_index_map[plane_type][row][column - 1]
199*09537850SAkhilesh Sanikop             : 0;
200*09537850SAkhilesh Sanikop     uint8_t index_mask;
201*09537850SAkhilesh Sanikop     static_assert(kMaxPaletteSize <= 8, "");
202*09537850SAkhilesh Sanikop     int index;
203*09537850SAkhilesh Sanikop     if (column <= 0) {
204*09537850SAkhilesh Sanikop       color_context[counter] = 0;
205*09537850SAkhilesh Sanikop       color_order[counter][0] = top;
206*09537850SAkhilesh Sanikop       index_mask = 1 << top;
207*09537850SAkhilesh Sanikop       index = 1;
208*09537850SAkhilesh Sanikop     } else if (row <= 0) {
209*09537850SAkhilesh Sanikop       color_context[counter] = 0;
210*09537850SAkhilesh Sanikop       color_order[counter][0] = left;
211*09537850SAkhilesh Sanikop       index_mask = 1 << left;
212*09537850SAkhilesh Sanikop       index = 1;
213*09537850SAkhilesh Sanikop     } else {
214*09537850SAkhilesh Sanikop       const uint8_t top_left =
215*09537850SAkhilesh Sanikop           prediction_parameters
216*09537850SAkhilesh Sanikop               .color_index_map[plane_type][row - 1][column - 1];
217*09537850SAkhilesh Sanikop       index_mask = (1 << top) | (1 << left) | (1 << top_left);
218*09537850SAkhilesh Sanikop       if (top == left && top == top_left) {
219*09537850SAkhilesh Sanikop         color_context[counter] = 4;
220*09537850SAkhilesh Sanikop         color_order[counter][0] = top;
221*09537850SAkhilesh Sanikop         index = 1;
222*09537850SAkhilesh Sanikop       } else if (top == left) {
223*09537850SAkhilesh Sanikop         color_context[counter] = 3;
224*09537850SAkhilesh Sanikop         color_order[counter][0] = top;
225*09537850SAkhilesh Sanikop         color_order[counter][1] = top_left;
226*09537850SAkhilesh Sanikop         index = 2;
227*09537850SAkhilesh Sanikop       } else if (top == top_left) {
228*09537850SAkhilesh Sanikop         color_context[counter] = 2;
229*09537850SAkhilesh Sanikop         color_order[counter][0] = top_left;
230*09537850SAkhilesh Sanikop         color_order[counter][1] = left;
231*09537850SAkhilesh Sanikop         index = 2;
232*09537850SAkhilesh Sanikop       } else if (left == top_left) {
233*09537850SAkhilesh Sanikop         color_context[counter] = 2;
234*09537850SAkhilesh Sanikop         color_order[counter][0] = top_left;
235*09537850SAkhilesh Sanikop         color_order[counter][1] = top;
236*09537850SAkhilesh Sanikop         index = 2;
237*09537850SAkhilesh Sanikop       } else {
238*09537850SAkhilesh Sanikop         color_context[counter] = 1;
239*09537850SAkhilesh Sanikop         color_order[counter][0] = std::min(top, left);
240*09537850SAkhilesh Sanikop         color_order[counter][1] = std::max(top, left);
241*09537850SAkhilesh Sanikop         color_order[counter][2] = top_left;
242*09537850SAkhilesh Sanikop         index = 3;
243*09537850SAkhilesh Sanikop       }
244*09537850SAkhilesh Sanikop     }
245*09537850SAkhilesh Sanikop     // Even though only the first |palette_size| entries of this array are ever
246*09537850SAkhilesh Sanikop     // used, it is faster to populate all 8 because of the vectorization of the
247*09537850SAkhilesh Sanikop     // constant sized loop.
248*09537850SAkhilesh Sanikop     for (uint8_t j = 0; j < kMaxPaletteSize; ++j) {
249*09537850SAkhilesh Sanikop       if (BitMaskSet::MaskContainsValue(index_mask, j)) continue;
250*09537850SAkhilesh Sanikop       color_order[counter][index++] = j;
251*09537850SAkhilesh Sanikop     }
252*09537850SAkhilesh Sanikop   }
253*09537850SAkhilesh Sanikop }
254*09537850SAkhilesh Sanikop 
ReadPaletteTokens(const Block & block)255*09537850SAkhilesh Sanikop bool Tile::ReadPaletteTokens(const Block& block) {
256*09537850SAkhilesh Sanikop   const PaletteModeInfo& palette_mode_info =
257*09537850SAkhilesh Sanikop       block.bp->prediction_parameters->palette_mode_info;
258*09537850SAkhilesh Sanikop   PredictionParameters& prediction_parameters =
259*09537850SAkhilesh Sanikop       *block.bp->prediction_parameters;
260*09537850SAkhilesh Sanikop   for (int plane_type = kPlaneTypeY;
261*09537850SAkhilesh Sanikop        plane_type < (block.HasChroma() ? kNumPlaneTypes : kPlaneTypeUV);
262*09537850SAkhilesh Sanikop        ++plane_type) {
263*09537850SAkhilesh Sanikop     const int palette_size = palette_mode_info.size[plane_type];
264*09537850SAkhilesh Sanikop     if (palette_size == 0) continue;
265*09537850SAkhilesh Sanikop     int block_height = block.height;
266*09537850SAkhilesh Sanikop     int block_width = block.width;
267*09537850SAkhilesh Sanikop     int screen_height = std::min(
268*09537850SAkhilesh Sanikop         block_height, MultiplyBy4(frame_header_.rows4x4 - block.row4x4));
269*09537850SAkhilesh Sanikop     int screen_width = std::min(
270*09537850SAkhilesh Sanikop         block_width, MultiplyBy4(frame_header_.columns4x4 - block.column4x4));
271*09537850SAkhilesh Sanikop     if (plane_type == kPlaneTypeUV) {
272*09537850SAkhilesh Sanikop       block_height >>= sequence_header_.color_config.subsampling_y;
273*09537850SAkhilesh Sanikop       block_width >>= sequence_header_.color_config.subsampling_x;
274*09537850SAkhilesh Sanikop       screen_height >>= sequence_header_.color_config.subsampling_y;
275*09537850SAkhilesh Sanikop       screen_width >>= sequence_header_.color_config.subsampling_x;
276*09537850SAkhilesh Sanikop       if (block_height < 4) {
277*09537850SAkhilesh Sanikop         block_height += 2;
278*09537850SAkhilesh Sanikop         screen_height += 2;
279*09537850SAkhilesh Sanikop       }
280*09537850SAkhilesh Sanikop       if (block_width < 4) {
281*09537850SAkhilesh Sanikop         block_width += 2;
282*09537850SAkhilesh Sanikop         screen_width += 2;
283*09537850SAkhilesh Sanikop       }
284*09537850SAkhilesh Sanikop     }
285*09537850SAkhilesh Sanikop     if (!prediction_parameters.color_index_map[plane_type].Reset(
286*09537850SAkhilesh Sanikop             block_height, block_width, /*zero_initialize=*/false)) {
287*09537850SAkhilesh Sanikop       return false;
288*09537850SAkhilesh Sanikop     }
289*09537850SAkhilesh Sanikop     int first_value = 0;
290*09537850SAkhilesh Sanikop     reader_.DecodeUniform(palette_size, &first_value);
291*09537850SAkhilesh Sanikop     prediction_parameters.color_index_map[plane_type][0][0] = first_value;
292*09537850SAkhilesh Sanikop     for (int i = 1; i < screen_height + screen_width - 1; ++i) {
293*09537850SAkhilesh Sanikop       const int start = std::min(i, screen_width - 1);
294*09537850SAkhilesh Sanikop       const int end = std::max(0, i - screen_height + 1);
295*09537850SAkhilesh Sanikop       uint8_t color_order[kMaxPaletteSquare][kMaxPaletteSize];
296*09537850SAkhilesh Sanikop       uint8_t color_context[kMaxPaletteSquare];
297*09537850SAkhilesh Sanikop       PopulatePaletteColorContexts(block, static_cast<PlaneType>(plane_type), i,
298*09537850SAkhilesh Sanikop                                    start, end, color_order, color_context);
299*09537850SAkhilesh Sanikop       for (int j = start, counter = 0; j >= end; --j, ++counter) {
300*09537850SAkhilesh Sanikop         uint16_t* const cdf =
301*09537850SAkhilesh Sanikop             symbol_decoder_context_
302*09537850SAkhilesh Sanikop                 .palette_color_index_cdf[plane_type]
303*09537850SAkhilesh Sanikop                                         [palette_size - kMinPaletteSize]
304*09537850SAkhilesh Sanikop                                         [color_context[counter]];
305*09537850SAkhilesh Sanikop         const int color_order_index = reader_.ReadSymbol(cdf, palette_size);
306*09537850SAkhilesh Sanikop         prediction_parameters.color_index_map[plane_type][i - j][j] =
307*09537850SAkhilesh Sanikop             color_order[counter][color_order_index];
308*09537850SAkhilesh Sanikop       }
309*09537850SAkhilesh Sanikop     }
310*09537850SAkhilesh Sanikop     if (screen_width < block_width) {
311*09537850SAkhilesh Sanikop       for (int i = 0; i < screen_height; ++i) {
312*09537850SAkhilesh Sanikop         memset(
313*09537850SAkhilesh Sanikop             &prediction_parameters.color_index_map[plane_type][i][screen_width],
314*09537850SAkhilesh Sanikop             prediction_parameters
315*09537850SAkhilesh Sanikop                 .color_index_map[plane_type][i][screen_width - 1],
316*09537850SAkhilesh Sanikop             block_width - screen_width);
317*09537850SAkhilesh Sanikop       }
318*09537850SAkhilesh Sanikop     }
319*09537850SAkhilesh Sanikop     for (int i = screen_height; i < block_height; ++i) {
320*09537850SAkhilesh Sanikop       memcpy(
321*09537850SAkhilesh Sanikop           prediction_parameters.color_index_map[plane_type][i],
322*09537850SAkhilesh Sanikop           prediction_parameters.color_index_map[plane_type][screen_height - 1],
323*09537850SAkhilesh Sanikop           block_width);
324*09537850SAkhilesh Sanikop     }
325*09537850SAkhilesh Sanikop   }
326*09537850SAkhilesh Sanikop   return true;
327*09537850SAkhilesh Sanikop }
328*09537850SAkhilesh Sanikop 
329*09537850SAkhilesh Sanikop }  // namespace libgav1
330