• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <math.h>
13 #include <stdlib.h>
14 
15 #include "av1/common/pred_common.h"
16 
17 #include "av1/encoder/block.h"
18 #include "av1/encoder/cost.h"
19 #include "av1/encoder/encoder.h"
20 #include "av1/encoder/intra_mode_search.h"
21 #include "av1/encoder/intra_mode_search_utils.h"
22 #include "av1/encoder/palette.h"
23 #include "av1/encoder/random.h"
24 #include "av1/encoder/rdopt_utils.h"
25 #include "av1/encoder/tx_search.h"
26 
27 #define AV1_K_MEANS_DIM 1
28 #include "av1/encoder/k_means_template.h"
29 #undef AV1_K_MEANS_DIM
30 #define AV1_K_MEANS_DIM 2
31 #include "av1/encoder/k_means_template.h"
32 #undef AV1_K_MEANS_DIM
33 
int_comparer(const void * a,const void * b)34 static int int_comparer(const void *a, const void *b) {
35   return (*(int *)a - *(int *)b);
36 }
37 
av1_remove_duplicates(int * centroids,int num_centroids)38 int av1_remove_duplicates(int *centroids, int num_centroids) {
39   int num_unique;  // number of unique centroids
40   int i;
41   qsort(centroids, num_centroids, sizeof(*centroids), int_comparer);
42   // Remove duplicates.
43   num_unique = 1;
44   for (i = 1; i < num_centroids; ++i) {
45     if (centroids[i] != centroids[i - 1]) {  // found a new unique centroid
46       centroids[num_unique++] = centroids[i];
47     }
48   }
49   return num_unique;
50 }
51 
delta_encode_cost(const int * colors,int num,int bit_depth,int min_val)52 static int delta_encode_cost(const int *colors, int num, int bit_depth,
53                              int min_val) {
54   if (num <= 0) return 0;
55   int bits_cost = bit_depth;
56   if (num == 1) return bits_cost;
57   bits_cost += 2;
58   int max_delta = 0;
59   int deltas[PALETTE_MAX_SIZE];
60   const int min_bits = bit_depth - 3;
61   for (int i = 1; i < num; ++i) {
62     const int delta = colors[i] - colors[i - 1];
63     deltas[i - 1] = delta;
64     assert(delta >= min_val);
65     if (delta > max_delta) max_delta = delta;
66   }
67   int bits_per_delta = AOMMAX(av1_ceil_log2(max_delta + 1 - min_val), min_bits);
68   assert(bits_per_delta <= bit_depth);
69   int range = (1 << bit_depth) - colors[0] - min_val;
70   for (int i = 0; i < num - 1; ++i) {
71     bits_cost += bits_per_delta;
72     range -= deltas[i];
73     bits_per_delta = AOMMIN(bits_per_delta, av1_ceil_log2(range));
74   }
75   return bits_cost;
76 }
77 
av1_index_color_cache(const uint16_t * color_cache,int n_cache,const uint16_t * colors,int n_colors,uint8_t * cache_color_found,int * out_cache_colors)78 int av1_index_color_cache(const uint16_t *color_cache, int n_cache,
79                           const uint16_t *colors, int n_colors,
80                           uint8_t *cache_color_found, int *out_cache_colors) {
81   if (n_cache <= 0) {
82     for (int i = 0; i < n_colors; ++i) out_cache_colors[i] = colors[i];
83     return n_colors;
84   }
85   memset(cache_color_found, 0, n_cache * sizeof(*cache_color_found));
86   int n_in_cache = 0;
87   int in_cache_flags[PALETTE_MAX_SIZE];
88   memset(in_cache_flags, 0, sizeof(in_cache_flags));
89   for (int i = 0; i < n_cache && n_in_cache < n_colors; ++i) {
90     for (int j = 0; j < n_colors; ++j) {
91       if (colors[j] == color_cache[i]) {
92         in_cache_flags[j] = 1;
93         cache_color_found[i] = 1;
94         ++n_in_cache;
95         break;
96       }
97     }
98   }
99   int j = 0;
100   for (int i = 0; i < n_colors; ++i)
101     if (!in_cache_flags[i]) out_cache_colors[j++] = colors[i];
102   assert(j == n_colors - n_in_cache);
103   return j;
104 }
105 
av1_get_palette_delta_bits_v(const PALETTE_MODE_INFO * const pmi,int bit_depth,int * zero_count,int * min_bits)106 int av1_get_palette_delta_bits_v(const PALETTE_MODE_INFO *const pmi,
107                                  int bit_depth, int *zero_count,
108                                  int *min_bits) {
109   const int n = pmi->palette_size[1];
110   const int max_val = 1 << bit_depth;
111   int max_d = 0;
112   *min_bits = bit_depth - 4;
113   *zero_count = 0;
114   for (int i = 1; i < n; ++i) {
115     const int delta = pmi->palette_colors[2 * PALETTE_MAX_SIZE + i] -
116                       pmi->palette_colors[2 * PALETTE_MAX_SIZE + i - 1];
117     const int v = abs(delta);
118     const int d = AOMMIN(v, max_val - v);
119     if (d > max_d) max_d = d;
120     if (d == 0) ++(*zero_count);
121   }
122   return AOMMAX(av1_ceil_log2(max_d + 1), *min_bits);
123 }
124 
av1_palette_color_cost_y(const PALETTE_MODE_INFO * const pmi,const uint16_t * color_cache,int n_cache,int bit_depth)125 int av1_palette_color_cost_y(const PALETTE_MODE_INFO *const pmi,
126                              const uint16_t *color_cache, int n_cache,
127                              int bit_depth) {
128   const int n = pmi->palette_size[0];
129   int out_cache_colors[PALETTE_MAX_SIZE];
130   uint8_t cache_color_found[2 * PALETTE_MAX_SIZE];
131   const int n_out_cache =
132       av1_index_color_cache(color_cache, n_cache, pmi->palette_colors, n,
133                             cache_color_found, out_cache_colors);
134   const int total_bits =
135       n_cache + delta_encode_cost(out_cache_colors, n_out_cache, bit_depth, 1);
136   return av1_cost_literal(total_bits);
137 }
138 
av1_palette_color_cost_uv(const PALETTE_MODE_INFO * const pmi,const uint16_t * color_cache,int n_cache,int bit_depth)139 int av1_palette_color_cost_uv(const PALETTE_MODE_INFO *const pmi,
140                               const uint16_t *color_cache, int n_cache,
141                               int bit_depth) {
142   const int n = pmi->palette_size[1];
143   int total_bits = 0;
144   // U channel palette color cost.
145   int out_cache_colors[PALETTE_MAX_SIZE];
146   uint8_t cache_color_found[2 * PALETTE_MAX_SIZE];
147   const int n_out_cache = av1_index_color_cache(
148       color_cache, n_cache, pmi->palette_colors + PALETTE_MAX_SIZE, n,
149       cache_color_found, out_cache_colors);
150   total_bits +=
151       n_cache + delta_encode_cost(out_cache_colors, n_out_cache, bit_depth, 0);
152 
153   // V channel palette color cost.
154   int zero_count = 0, min_bits_v = 0;
155   const int bits_v =
156       av1_get_palette_delta_bits_v(pmi, bit_depth, &zero_count, &min_bits_v);
157   const int bits_using_delta =
158       2 + bit_depth + (bits_v + 1) * (n - 1) - zero_count;
159   const int bits_using_raw = bit_depth * n;
160   total_bits += 1 + AOMMIN(bits_using_delta, bits_using_raw);
161   return av1_cost_literal(total_bits);
162 }
163 
164 // Extends 'color_map' array from 'orig_width x orig_height' to 'new_width x
165 // new_height'. Extra rows and columns are filled in by copying last valid
166 // row/column.
extend_palette_color_map(uint8_t * const color_map,int orig_width,int orig_height,int new_width,int new_height)167 static AOM_INLINE void extend_palette_color_map(uint8_t *const color_map,
168                                                 int orig_width, int orig_height,
169                                                 int new_width, int new_height) {
170   int j;
171   assert(new_width >= orig_width);
172   assert(new_height >= orig_height);
173   if (new_width == orig_width && new_height == orig_height) return;
174 
175   for (j = orig_height - 1; j >= 0; --j) {
176     memmove(color_map + j * new_width, color_map + j * orig_width, orig_width);
177     // Copy last column to extra columns.
178     memset(color_map + j * new_width + orig_width,
179            color_map[j * new_width + orig_width - 1], new_width - orig_width);
180   }
181   // Copy last row to extra rows.
182   for (j = orig_height; j < new_height; ++j) {
183     memcpy(color_map + j * new_width, color_map + (orig_height - 1) * new_width,
184            new_width);
185   }
186 }
187 
188 // Bias toward using colors in the cache.
189 // TODO(huisu): Try other schemes to improve compression.
optimize_palette_colors(uint16_t * color_cache,int n_cache,int n_colors,int stride,int * centroids,int bit_depth)190 static AOM_INLINE void optimize_palette_colors(uint16_t *color_cache,
191                                                int n_cache, int n_colors,
192                                                int stride, int *centroids,
193                                                int bit_depth) {
194   if (n_cache <= 0) return;
195   for (int i = 0; i < n_colors * stride; i += stride) {
196     int min_diff = abs(centroids[i] - (int)color_cache[0]);
197     int idx = 0;
198     for (int j = 1; j < n_cache; ++j) {
199       const int this_diff = abs(centroids[i] - color_cache[j]);
200       if (this_diff < min_diff) {
201         min_diff = this_diff;
202         idx = j;
203       }
204     }
205     const int min_threshold = 4 << (bit_depth - 8);
206     if (min_diff <= min_threshold) centroids[i] = color_cache[idx];
207   }
208 }
209 
210 /*!\brief Calculate the luma palette cost from a given color palette
211  *
212  * \ingroup palette_mode_search
213  * \callergraph
214  * Given the base colors as specified in centroids[], calculate the RD cost
215  * of palette mode.
216  */
palette_rd_y(const AV1_COMP * const cpi,MACROBLOCK * x,MB_MODE_INFO * mbmi,BLOCK_SIZE bsize,int dc_mode_cost,const int * data,int * centroids,int n,uint16_t * color_cache,int n_cache,bool do_header_rd_based_gating,MB_MODE_INFO * best_mbmi,uint8_t * best_palette_color_map,int64_t * best_rd,int * rate,int * rate_tokenonly,int64_t * distortion,int * skippable,int * beat_best_rd,PICK_MODE_CONTEXT * ctx,uint8_t * blk_skip,uint8_t * tx_type_map,int * beat_best_palette_rd,bool * do_header_rd_based_breakout)217 static AOM_INLINE void palette_rd_y(
218     const AV1_COMP *const cpi, MACROBLOCK *x, MB_MODE_INFO *mbmi,
219     BLOCK_SIZE bsize, int dc_mode_cost, const int *data, int *centroids, int n,
220     uint16_t *color_cache, int n_cache, bool do_header_rd_based_gating,
221     MB_MODE_INFO *best_mbmi, uint8_t *best_palette_color_map, int64_t *best_rd,
222     int *rate, int *rate_tokenonly, int64_t *distortion, int *skippable,
223     int *beat_best_rd, PICK_MODE_CONTEXT *ctx, uint8_t *blk_skip,
224     uint8_t *tx_type_map, int *beat_best_palette_rd,
225     bool *do_header_rd_based_breakout) {
226   if (do_header_rd_based_breakout != NULL) *do_header_rd_based_breakout = false;
227   optimize_palette_colors(color_cache, n_cache, n, 1, centroids,
228                           cpi->common.seq_params->bit_depth);
229   const int num_unique_colors = av1_remove_duplicates(centroids, n);
230   if (num_unique_colors < PALETTE_MIN_SIZE) {
231     // Too few unique colors to create a palette. And DC_PRED will work
232     // well for that case anyway. So skip.
233     return;
234   }
235   PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
236   if (cpi->common.seq_params->use_highbitdepth) {
237     for (int i = 0; i < num_unique_colors; ++i) {
238       pmi->palette_colors[i] = clip_pixel_highbd(
239           (int)centroids[i], cpi->common.seq_params->bit_depth);
240     }
241   } else {
242     for (int i = 0; i < num_unique_colors; ++i) {
243       pmi->palette_colors[i] = clip_pixel(centroids[i]);
244     }
245   }
246   pmi->palette_size[0] = num_unique_colors;
247   MACROBLOCKD *const xd = &x->e_mbd;
248   uint8_t *const color_map = xd->plane[0].color_index_map;
249   int block_width, block_height, rows, cols;
250   av1_get_block_dimensions(bsize, 0, xd, &block_width, &block_height, &rows,
251                            &cols);
252   av1_calc_indices(data, centroids, color_map, rows * cols, num_unique_colors,
253                    1);
254   extend_palette_color_map(color_map, cols, rows, block_width, block_height);
255 
256   RD_STATS tokenonly_rd_stats;
257   int this_rate;
258 
259   if (do_header_rd_based_gating) {
260     assert(do_header_rd_based_breakout != NULL);
261     const int palette_mode_rate =
262         intra_mode_info_cost_y(cpi, x, mbmi, bsize, dc_mode_cost);
263     const int64_t header_rd = RDCOST(x->rdmult, palette_mode_rate, 0);
264     // Less aggressive pruning when prune_luma_palette_size_search_level == 1.
265     const int header_rd_shift =
266         (cpi->sf.intra_sf.prune_luma_palette_size_search_level == 1) ? 1 : 0;
267     // Terminate further palette_size search, if the header cost corresponding
268     // to lower palette_size is more than *best_rd << header_rd_shift. This
269     // logic is implemented with a right shift in the LHS to prevent a possible
270     // overflow with the left shift in RHS.
271     if ((header_rd >> header_rd_shift) > *best_rd) {
272       *do_header_rd_based_breakout = true;
273       return;
274     }
275     av1_pick_uniform_tx_size_type_yrd(cpi, x, &tokenonly_rd_stats, bsize,
276                                       *best_rd);
277     if (tokenonly_rd_stats.rate == INT_MAX) return;
278     this_rate = tokenonly_rd_stats.rate + palette_mode_rate;
279   } else {
280     av1_pick_uniform_tx_size_type_yrd(cpi, x, &tokenonly_rd_stats, bsize,
281                                       *best_rd);
282     if (tokenonly_rd_stats.rate == INT_MAX) return;
283     this_rate = tokenonly_rd_stats.rate +
284                 intra_mode_info_cost_y(cpi, x, mbmi, bsize, dc_mode_cost);
285   }
286 
287   int64_t this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
288   if (!xd->lossless[mbmi->segment_id] && block_signals_txsize(mbmi->bsize)) {
289     tokenonly_rd_stats.rate -= tx_size_cost(x, bsize, mbmi->tx_size);
290   }
291   // Collect mode stats for multiwinner mode processing
292   const int txfm_search_done = 1;
293   store_winner_mode_stats(
294       &cpi->common, x, mbmi, NULL, NULL, NULL, THR_DC, color_map, bsize,
295       this_rd, cpi->sf.winner_mode_sf.multi_winner_mode_type, txfm_search_done);
296   if (this_rd < *best_rd) {
297     *best_rd = this_rd;
298     // Setting beat_best_rd flag because current mode rd is better than best_rd.
299     // This flag need to be updated only for palette evaluation in key frames
300     if (beat_best_rd) *beat_best_rd = 1;
301     memcpy(best_palette_color_map, color_map,
302            block_width * block_height * sizeof(color_map[0]));
303     *best_mbmi = *mbmi;
304     memcpy(blk_skip, x->txfm_search_info.blk_skip,
305            sizeof(x->txfm_search_info.blk_skip[0]) * ctx->num_4x4_blk);
306     av1_copy_array(tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
307     if (rate) *rate = this_rate;
308     if (rate_tokenonly) *rate_tokenonly = tokenonly_rd_stats.rate;
309     if (distortion) *distortion = tokenonly_rd_stats.dist;
310     if (skippable) *skippable = tokenonly_rd_stats.skip_txfm;
311     if (beat_best_palette_rd) *beat_best_palette_rd = 1;
312   }
313 }
314 
is_iter_over(int curr_idx,int end_idx,int step_size)315 static AOM_INLINE int is_iter_over(int curr_idx, int end_idx, int step_size) {
316   assert(step_size != 0);
317   return (step_size > 0) ? curr_idx >= end_idx : curr_idx <= end_idx;
318 }
319 
320 // Performs count-based palette search with number of colors in interval
321 // [start_n, end_n) with step size step_size. If step_size < 0, then end_n can
322 // be less than start_n. Saves the last numbers searched in last_n_searched and
323 // returns the best number of colors found.
perform_top_color_palette_search(const AV1_COMP * const cpi,MACROBLOCK * x,MB_MODE_INFO * mbmi,BLOCK_SIZE bsize,int dc_mode_cost,const int * data,int * top_colors,int start_n,int end_n,int step_size,bool do_header_rd_based_gating,int * last_n_searched,uint16_t * color_cache,int n_cache,MB_MODE_INFO * best_mbmi,uint8_t * best_palette_color_map,int64_t * best_rd,int * rate,int * rate_tokenonly,int64_t * distortion,int * skippable,int * beat_best_rd,PICK_MODE_CONTEXT * ctx,uint8_t * best_blk_skip,uint8_t * tx_type_map)324 static AOM_INLINE int perform_top_color_palette_search(
325     const AV1_COMP *const cpi, MACROBLOCK *x, MB_MODE_INFO *mbmi,
326     BLOCK_SIZE bsize, int dc_mode_cost, const int *data, int *top_colors,
327     int start_n, int end_n, int step_size, bool do_header_rd_based_gating,
328     int *last_n_searched, uint16_t *color_cache, int n_cache,
329     MB_MODE_INFO *best_mbmi, uint8_t *best_palette_color_map, int64_t *best_rd,
330     int *rate, int *rate_tokenonly, int64_t *distortion, int *skippable,
331     int *beat_best_rd, PICK_MODE_CONTEXT *ctx, uint8_t *best_blk_skip,
332     uint8_t *tx_type_map) {
333   int centroids[PALETTE_MAX_SIZE];
334   int n = start_n;
335   int top_color_winner = end_n;
336   /* clang-format off */
337   assert(IMPLIES(step_size < 0, start_n > end_n));
338   /* clang-format on */
339   assert(IMPLIES(step_size > 0, start_n < end_n));
340   while (!is_iter_over(n, end_n, step_size)) {
341     int beat_best_palette_rd = 0;
342     bool do_header_rd_based_breakout = false;
343     memcpy(centroids, top_colors, n * sizeof(top_colors[0]));
344     palette_rd_y(cpi, x, mbmi, bsize, dc_mode_cost, data, centroids, n,
345                  color_cache, n_cache, do_header_rd_based_gating, best_mbmi,
346                  best_palette_color_map, best_rd, rate, rate_tokenonly,
347                  distortion, skippable, beat_best_rd, ctx, best_blk_skip,
348                  tx_type_map, &beat_best_palette_rd,
349                  &do_header_rd_based_breakout);
350     *last_n_searched = n;
351     if (do_header_rd_based_breakout) {
352       // Terminate palette_size search by setting last_n_searched to end_n.
353       *last_n_searched = end_n;
354       break;
355     }
356     if (beat_best_palette_rd) {
357       top_color_winner = n;
358     } else if (cpi->sf.intra_sf.prune_palette_search_level == 2) {
359       // At search level 2, we return immediately if we don't see an improvement
360       return top_color_winner;
361     }
362     n += step_size;
363   }
364   return top_color_winner;
365 }
366 
367 // Performs k-means based palette search with number of colors in interval
368 // [start_n, end_n) with step size step_size. If step_size < 0, then end_n can
369 // be less than start_n. Saves the last numbers searched in last_n_searched and
370 // returns the best number of colors found.
perform_k_means_palette_search(const AV1_COMP * const cpi,MACROBLOCK * x,MB_MODE_INFO * mbmi,BLOCK_SIZE bsize,int dc_mode_cost,const int * data,int lower_bound,int upper_bound,int start_n,int end_n,int step_size,bool do_header_rd_based_gating,int * last_n_searched,uint16_t * color_cache,int n_cache,MB_MODE_INFO * best_mbmi,uint8_t * best_palette_color_map,int64_t * best_rd,int * rate,int * rate_tokenonly,int64_t * distortion,int * skippable,int * beat_best_rd,PICK_MODE_CONTEXT * ctx,uint8_t * best_blk_skip,uint8_t * tx_type_map,uint8_t * color_map,int data_points)371 static AOM_INLINE int perform_k_means_palette_search(
372     const AV1_COMP *const cpi, MACROBLOCK *x, MB_MODE_INFO *mbmi,
373     BLOCK_SIZE bsize, int dc_mode_cost, const int *data, int lower_bound,
374     int upper_bound, int start_n, int end_n, int step_size,
375     bool do_header_rd_based_gating, int *last_n_searched, uint16_t *color_cache,
376     int n_cache, MB_MODE_INFO *best_mbmi, uint8_t *best_palette_color_map,
377     int64_t *best_rd, int *rate, int *rate_tokenonly, int64_t *distortion,
378     int *skippable, int *beat_best_rd, PICK_MODE_CONTEXT *ctx,
379     uint8_t *best_blk_skip, uint8_t *tx_type_map, uint8_t *color_map,
380     int data_points) {
381   int centroids[PALETTE_MAX_SIZE];
382   const int max_itr = 50;
383   int n = start_n;
384   int top_color_winner = end_n;
385   /* clang-format off */
386   assert(IMPLIES(step_size < 0, start_n > end_n));
387   /* clang-format on */
388   assert(IMPLIES(step_size > 0, start_n < end_n));
389   while (!is_iter_over(n, end_n, step_size)) {
390     int beat_best_palette_rd = 0;
391     bool do_header_rd_based_breakout = false;
392     for (int i = 0; i < n; ++i) {
393       centroids[i] =
394           lower_bound + (2 * i + 1) * (upper_bound - lower_bound) / n / 2;
395     }
396     av1_k_means(data, centroids, color_map, data_points, n, 1, max_itr);
397     palette_rd_y(cpi, x, mbmi, bsize, dc_mode_cost, data, centroids, n,
398                  color_cache, n_cache, do_header_rd_based_gating, best_mbmi,
399                  best_palette_color_map, best_rd, rate, rate_tokenonly,
400                  distortion, skippable, beat_best_rd, ctx, best_blk_skip,
401                  tx_type_map, &beat_best_palette_rd,
402                  &do_header_rd_based_breakout);
403     *last_n_searched = n;
404     if (do_header_rd_based_breakout) {
405       // Terminate palette_size search by setting last_n_searched to end_n.
406       *last_n_searched = end_n;
407       break;
408     }
409     if (beat_best_palette_rd) {
410       top_color_winner = n;
411     } else if (cpi->sf.intra_sf.prune_palette_search_level == 2) {
412       // At search level 2, we return immediately if we don't see an improvement
413       return top_color_winner;
414     }
415     n += step_size;
416   }
417   return top_color_winner;
418 }
419 
420 // Sets the parameters to search the current number of colors +- 1
set_stage2_params(int * min_n,int * max_n,int * step_size,int winner,int end_n)421 static AOM_INLINE void set_stage2_params(int *min_n, int *max_n, int *step_size,
422                                          int winner, int end_n) {
423   // Set min to winner - 1 unless we are already at the border, then we set it
424   // to winner + 1
425   *min_n = (winner == PALETTE_MIN_SIZE) ? (PALETTE_MIN_SIZE + 1)
426                                         : AOMMAX(winner - 1, PALETTE_MIN_SIZE);
427   // Set max to winner + 1 unless we are already at the border, then we set it
428   // to winner - 1
429   *max_n =
430       (winner == end_n) ? (winner - 1) : AOMMIN(winner + 1, PALETTE_MAX_SIZE);
431 
432   // Set the step size to max_n - min_n so we only search those two values.
433   // If max_n == min_n, then set step_size to 1 to avoid infinite loop later.
434   *step_size = AOMMAX(1, *max_n - *min_n);
435 }
436 
fill_data_and_get_bounds(const uint8_t * src,const int src_stride,const int rows,const int cols,const int is_high_bitdepth,int * data,int * lower_bound,int * upper_bound)437 static AOM_INLINE void fill_data_and_get_bounds(
438     const uint8_t *src, const int src_stride, const int rows, const int cols,
439     const int is_high_bitdepth, int *data, int *lower_bound, int *upper_bound) {
440   if (is_high_bitdepth) {
441     const uint16_t *src_ptr = CONVERT_TO_SHORTPTR(src);
442     *lower_bound = *upper_bound = src_ptr[0];
443     for (int r = 0; r < rows; ++r) {
444       for (int c = 0; c < cols; ++c) {
445         const int val = src_ptr[c];
446         data[c] = val;
447         *lower_bound = AOMMIN(*lower_bound, val);
448         *upper_bound = AOMMAX(*upper_bound, val);
449       }
450       src_ptr += src_stride;
451       data += cols;
452     }
453     return;
454   }
455 
456   // low bit depth
457   *lower_bound = *upper_bound = src[0];
458   for (int r = 0; r < rows; ++r) {
459     for (int c = 0; c < cols; ++c) {
460       const int val = src[c];
461       data[c] = val;
462       *lower_bound = AOMMIN(*lower_bound, val);
463       *upper_bound = AOMMAX(*upper_bound, val);
464     }
465     src += src_stride;
466     data += cols;
467   }
468 }
469 
av1_rd_pick_palette_intra_sby(const AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,int dc_mode_cost,MB_MODE_INFO * best_mbmi,uint8_t * best_palette_color_map,int64_t * best_rd,int * rate,int * rate_tokenonly,int64_t * distortion,int * skippable,int * beat_best_rd,PICK_MODE_CONTEXT * ctx,uint8_t * best_blk_skip,uint8_t * tx_type_map)470 void av1_rd_pick_palette_intra_sby(
471     const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int dc_mode_cost,
472     MB_MODE_INFO *best_mbmi, uint8_t *best_palette_color_map, int64_t *best_rd,
473     int *rate, int *rate_tokenonly, int64_t *distortion, int *skippable,
474     int *beat_best_rd, PICK_MODE_CONTEXT *ctx, uint8_t *best_blk_skip,
475     uint8_t *tx_type_map) {
476   MACROBLOCKD *const xd = &x->e_mbd;
477   MB_MODE_INFO *const mbmi = xd->mi[0];
478   assert(!is_inter_block(mbmi));
479   assert(av1_allow_palette(cpi->common.features.allow_screen_content_tools,
480                            bsize));
481   assert(PALETTE_MAX_SIZE == 8);
482   assert(PALETTE_MIN_SIZE == 2);
483 
484   const int src_stride = x->plane[0].src.stride;
485   const uint8_t *const src = x->plane[0].src.buf;
486   int block_width, block_height, rows, cols;
487   av1_get_block_dimensions(bsize, 0, xd, &block_width, &block_height, &rows,
488                            &cols);
489   const SequenceHeader *const seq_params = cpi->common.seq_params;
490   const int is_hbd = seq_params->use_highbitdepth;
491   const int bit_depth = seq_params->bit_depth;
492   int unused;
493 
494   int count_buf[1 << 12];      // Maximum (1 << 12) color levels.
495   int count_buf_8bit[1 << 8];  // Maximum (1 << 8) bins for hbd path.
496   int colors, colors_threshold = 0;
497   if (is_hbd) {
498     av1_count_colors_highbd(src, src_stride, rows, cols, bit_depth, count_buf,
499                             count_buf_8bit, &colors_threshold, &colors);
500   } else {
501     av1_count_colors(src, src_stride, rows, cols, count_buf, &colors);
502     colors_threshold = colors;
503   }
504 
505   uint8_t *const color_map = xd->plane[0].color_index_map;
506   if (colors_threshold > 1 && colors_threshold <= 64) {
507     int *const data = x->palette_buffer->kmeans_data_buf;
508     int centroids[PALETTE_MAX_SIZE];
509     int lower_bound, upper_bound;
510     fill_data_and_get_bounds(src, src_stride, rows, cols, is_hbd, data,
511                              &lower_bound, &upper_bound);
512 
513     mbmi->mode = DC_PRED;
514     mbmi->filter_intra_mode_info.use_filter_intra = 0;
515 
516     uint16_t color_cache[2 * PALETTE_MAX_SIZE];
517     const int n_cache = av1_get_palette_cache(xd, 0, color_cache);
518 
519     // Find the dominant colors, stored in top_colors[].
520     int top_colors[PALETTE_MAX_SIZE] = { 0 };
521     for (int i = 0; i < AOMMIN(colors, PALETTE_MAX_SIZE); ++i) {
522       int max_count = 0;
523       for (int j = 0; j < (1 << bit_depth); ++j) {
524         if (count_buf[j] > max_count) {
525           max_count = count_buf[j];
526           top_colors[i] = j;
527         }
528       }
529       assert(max_count > 0);
530       count_buf[top_colors[i]] = 0;
531     }
532 
533     // The following are the approaches used for header rdcost based gating
534     // for early termination for different values of prune_palette_search_level.
535     // 0: Pruning based on header rdcost for ascending order palette_size
536     // search.
537     // 1: When colors > PALETTE_MIN_SIZE, enabled only for coarse palette_size
538     // search and for finer search do_header_rd_based_gating parameter is
539     // explicitly passed as 'false'.
540     // 2: Enabled only for ascending order palette_size search and for
541     // descending order search do_header_rd_based_gating parameter is explicitly
542     // passed as 'false'.
543     const bool do_header_rd_based_gating =
544         cpi->sf.intra_sf.prune_luma_palette_size_search_level != 0;
545 
546     // TODO(huisu@google.com): Try to avoid duplicate computation in cases
547     // where the dominant colors and the k-means results are similar.
548     if ((cpi->sf.intra_sf.prune_palette_search_level == 1) &&
549         (colors > PALETTE_MIN_SIZE)) {
550       // Start index and step size below are chosen to evaluate unique
551       // candidates in neighbor search, in case a winner candidate is found in
552       // coarse search. Example,
553       // 1) 8 colors (end_n = 8): 2,3,4,5,6,7,8. start_n is chosen as 2 and step
554       // size is chosen as 3. Therefore, coarse search will evaluate 2, 5 and 8.
555       // If winner is found at 5, then 4 and 6 are evaluated. Similarly, for 2
556       // (3) and 8 (7).
557       // 2) 7 colors (end_n = 7): 2,3,4,5,6,7. If start_n is chosen as 2 (same
558       // as for 8 colors) then step size should also be 2, to cover all
559       // candidates. Coarse search will evaluate 2, 4 and 6. If winner is either
560       // 2 or 4, 3 will be evaluated. Instead, if start_n=3 and step_size=3,
561       // coarse search will evaluate 3 and 6. For the winner, unique neighbors
562       // (3: 2,4 or 6: 5,7) would be evaluated.
563 
564       // Start index for coarse palette search for dominant colors and k-means
565       const uint8_t start_n_lookup_table[PALETTE_MAX_SIZE + 1] = { 0, 0, 0,
566                                                                    3, 3, 2,
567                                                                    3, 3, 2 };
568       // Step size for coarse palette search for dominant colors and k-means
569       const uint8_t step_size_lookup_table[PALETTE_MAX_SIZE + 1] = { 0, 0, 0,
570                                                                      3, 3, 3,
571                                                                      3, 3, 3 };
572 
573       // Choose the start index and step size for coarse search based on number
574       // of colors
575       const int max_n = AOMMIN(colors, PALETTE_MAX_SIZE);
576       const int min_n = start_n_lookup_table[max_n];
577       const int step_size = step_size_lookup_table[max_n];
578       assert(min_n >= PALETTE_MIN_SIZE);
579       // Perform top color coarse palette search to find the winner candidate
580       const int top_color_winner = perform_top_color_palette_search(
581           cpi, x, mbmi, bsize, dc_mode_cost, data, top_colors, min_n, max_n + 1,
582           step_size, do_header_rd_based_gating, &unused, color_cache, n_cache,
583           best_mbmi, best_palette_color_map, best_rd, rate, rate_tokenonly,
584           distortion, skippable, beat_best_rd, ctx, best_blk_skip, tx_type_map);
585       // Evaluate neighbors for the winner color (if winner is found) in the
586       // above coarse search for dominant colors
587       if (top_color_winner <= max_n) {
588         int stage2_min_n, stage2_max_n, stage2_step_size;
589         set_stage2_params(&stage2_min_n, &stage2_max_n, &stage2_step_size,
590                           top_color_winner, max_n);
591         // perform finer search for the winner candidate
592         perform_top_color_palette_search(
593             cpi, x, mbmi, bsize, dc_mode_cost, data, top_colors, stage2_min_n,
594             stage2_max_n + 1, stage2_step_size,
595             /*do_header_rd_based_gating=*/false, &unused, color_cache, n_cache,
596             best_mbmi, best_palette_color_map, best_rd, rate, rate_tokenonly,
597             distortion, skippable, beat_best_rd, ctx, best_blk_skip,
598             tx_type_map);
599       }
600       // K-means clustering.
601       // Perform k-means coarse palette search to find the winner candidate
602       const int k_means_winner = perform_k_means_palette_search(
603           cpi, x, mbmi, bsize, dc_mode_cost, data, lower_bound, upper_bound,
604           min_n, max_n + 1, step_size, do_header_rd_based_gating, &unused,
605           color_cache, n_cache, best_mbmi, best_palette_color_map, best_rd,
606           rate, rate_tokenonly, distortion, skippable, beat_best_rd, ctx,
607           best_blk_skip, tx_type_map, color_map, rows * cols);
608       // Evaluate neighbors for the winner color (if winner is found) in the
609       // above coarse search for k-means
610       if (k_means_winner <= max_n) {
611         int start_n_stage2, end_n_stage2, step_size_stage2;
612         set_stage2_params(&start_n_stage2, &end_n_stage2, &step_size_stage2,
613                           k_means_winner, max_n);
614         // perform finer search for the winner candidate
615         perform_k_means_palette_search(
616             cpi, x, mbmi, bsize, dc_mode_cost, data, lower_bound, upper_bound,
617             start_n_stage2, end_n_stage2 + 1, step_size_stage2,
618             /*do_header_rd_based_gating=*/false, &unused, color_cache, n_cache,
619             best_mbmi, best_palette_color_map, best_rd, rate, rate_tokenonly,
620             distortion, skippable, beat_best_rd, ctx, best_blk_skip,
621             tx_type_map, color_map, rows * cols);
622       }
623     } else {
624       const int max_n = AOMMIN(colors, PALETTE_MAX_SIZE),
625                 min_n = PALETTE_MIN_SIZE;
626       // Perform top color palette search in ascending order
627       int last_n_searched = min_n;
628       perform_top_color_palette_search(
629           cpi, x, mbmi, bsize, dc_mode_cost, data, top_colors, min_n, max_n + 1,
630           1, do_header_rd_based_gating, &last_n_searched, color_cache, n_cache,
631           best_mbmi, best_palette_color_map, best_rd, rate, rate_tokenonly,
632           distortion, skippable, beat_best_rd, ctx, best_blk_skip, tx_type_map);
633       if (last_n_searched < max_n) {
634         // Search in descending order until we get to the previous best
635         perform_top_color_palette_search(
636             cpi, x, mbmi, bsize, dc_mode_cost, data, top_colors, max_n,
637             last_n_searched, -1, /*do_header_rd_based_gating=*/false, &unused,
638             color_cache, n_cache, best_mbmi, best_palette_color_map, best_rd,
639             rate, rate_tokenonly, distortion, skippable, beat_best_rd, ctx,
640             best_blk_skip, tx_type_map);
641       }
642       // K-means clustering.
643       if (colors == PALETTE_MIN_SIZE) {
644         // Special case: These colors automatically become the centroids.
645         assert(colors == 2);
646         centroids[0] = lower_bound;
647         centroids[1] = upper_bound;
648         palette_rd_y(cpi, x, mbmi, bsize, dc_mode_cost, data, centroids, colors,
649                      color_cache, n_cache, /*do_header_rd_based_gating=*/false,
650                      best_mbmi, best_palette_color_map, best_rd, rate,
651                      rate_tokenonly, distortion, skippable, beat_best_rd, ctx,
652                      best_blk_skip, tx_type_map, NULL, NULL);
653       } else {
654         // Perform k-means palette search in ascending order
655         last_n_searched = min_n;
656         perform_k_means_palette_search(
657             cpi, x, mbmi, bsize, dc_mode_cost, data, lower_bound, upper_bound,
658             min_n, max_n + 1, 1, do_header_rd_based_gating, &last_n_searched,
659             color_cache, n_cache, best_mbmi, best_palette_color_map, best_rd,
660             rate, rate_tokenonly, distortion, skippable, beat_best_rd, ctx,
661             best_blk_skip, tx_type_map, color_map, rows * cols);
662         if (last_n_searched < max_n) {
663           // Search in descending order until we get to the previous best
664           perform_k_means_palette_search(
665               cpi, x, mbmi, bsize, dc_mode_cost, data, lower_bound, upper_bound,
666               max_n, last_n_searched, -1, /*do_header_rd_based_gating=*/false,
667               &unused, color_cache, n_cache, best_mbmi, best_palette_color_map,
668               best_rd, rate, rate_tokenonly, distortion, skippable,
669               beat_best_rd, ctx, best_blk_skip, tx_type_map, color_map,
670               rows * cols);
671         }
672       }
673     }
674   }
675 
676   if (best_mbmi->palette_mode_info.palette_size[0] > 0) {
677     memcpy(color_map, best_palette_color_map,
678            block_width * block_height * sizeof(best_palette_color_map[0]));
679   }
680   *mbmi = *best_mbmi;
681 }
682 
av1_rd_pick_palette_intra_sbuv(const AV1_COMP * cpi,MACROBLOCK * x,int dc_mode_cost,uint8_t * best_palette_color_map,MB_MODE_INFO * const best_mbmi,int64_t * best_rd,int * rate,int * rate_tokenonly,int64_t * distortion,int * skippable)683 void av1_rd_pick_palette_intra_sbuv(const AV1_COMP *cpi, MACROBLOCK *x,
684                                     int dc_mode_cost,
685                                     uint8_t *best_palette_color_map,
686                                     MB_MODE_INFO *const best_mbmi,
687                                     int64_t *best_rd, int *rate,
688                                     int *rate_tokenonly, int64_t *distortion,
689                                     int *skippable) {
690   MACROBLOCKD *const xd = &x->e_mbd;
691   MB_MODE_INFO *const mbmi = xd->mi[0];
692   assert(!is_inter_block(mbmi));
693   assert(av1_allow_palette(cpi->common.features.allow_screen_content_tools,
694                            mbmi->bsize));
695   PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
696   const BLOCK_SIZE bsize = mbmi->bsize;
697   const SequenceHeader *const seq_params = cpi->common.seq_params;
698   int this_rate;
699   int64_t this_rd;
700   int colors_u, colors_v;
701   int colors_threshold_u = 0, colors_threshold_v = 0, colors_threshold = 0;
702   const int src_stride = x->plane[1].src.stride;
703   const uint8_t *const src_u = x->plane[1].src.buf;
704   const uint8_t *const src_v = x->plane[2].src.buf;
705   uint8_t *const color_map = xd->plane[1].color_index_map;
706   RD_STATS tokenonly_rd_stats;
707   int plane_block_width, plane_block_height, rows, cols;
708   av1_get_block_dimensions(bsize, 1, xd, &plane_block_width,
709                            &plane_block_height, &rows, &cols);
710 
711   mbmi->uv_mode = UV_DC_PRED;
712   int count_buf[1 << 12];      // Maximum (1 << 12) color levels.
713   int count_buf_8bit[1 << 8];  // Maximum (1 << 8) bins for hbd path.
714   if (seq_params->use_highbitdepth) {
715     av1_count_colors_highbd(src_u, src_stride, rows, cols,
716                             seq_params->bit_depth, count_buf, count_buf_8bit,
717                             &colors_threshold_u, &colors_u);
718     av1_count_colors_highbd(src_v, src_stride, rows, cols,
719                             seq_params->bit_depth, count_buf, count_buf_8bit,
720                             &colors_threshold_v, &colors_v);
721   } else {
722     av1_count_colors(src_u, src_stride, rows, cols, count_buf, &colors_u);
723     av1_count_colors(src_v, src_stride, rows, cols, count_buf, &colors_v);
724     colors_threshold_u = colors_u;
725     colors_threshold_v = colors_v;
726   }
727 
728   uint16_t color_cache[2 * PALETTE_MAX_SIZE];
729   const int n_cache = av1_get_palette_cache(xd, 1, color_cache);
730 
731   colors_threshold = colors_threshold_u > colors_threshold_v
732                          ? colors_threshold_u
733                          : colors_threshold_v;
734   if (colors_threshold > 1 && colors_threshold <= 64) {
735     int r, c, n, i, j;
736     const int max_itr = 50;
737     int lb_u, ub_u, val_u;
738     int lb_v, ub_v, val_v;
739     int *const data = x->palette_buffer->kmeans_data_buf;
740     int centroids[2 * PALETTE_MAX_SIZE];
741 
742     uint16_t *src_u16 = CONVERT_TO_SHORTPTR(src_u);
743     uint16_t *src_v16 = CONVERT_TO_SHORTPTR(src_v);
744     if (seq_params->use_highbitdepth) {
745       lb_u = src_u16[0];
746       ub_u = src_u16[0];
747       lb_v = src_v16[0];
748       ub_v = src_v16[0];
749     } else {
750       lb_u = src_u[0];
751       ub_u = src_u[0];
752       lb_v = src_v[0];
753       ub_v = src_v[0];
754     }
755 
756     for (r = 0; r < rows; ++r) {
757       for (c = 0; c < cols; ++c) {
758         if (seq_params->use_highbitdepth) {
759           val_u = src_u16[r * src_stride + c];
760           val_v = src_v16[r * src_stride + c];
761           data[(r * cols + c) * 2] = val_u;
762           data[(r * cols + c) * 2 + 1] = val_v;
763         } else {
764           val_u = src_u[r * src_stride + c];
765           val_v = src_v[r * src_stride + c];
766           data[(r * cols + c) * 2] = val_u;
767           data[(r * cols + c) * 2 + 1] = val_v;
768         }
769         if (val_u < lb_u)
770           lb_u = val_u;
771         else if (val_u > ub_u)
772           ub_u = val_u;
773         if (val_v < lb_v)
774           lb_v = val_v;
775         else if (val_v > ub_v)
776           ub_v = val_v;
777       }
778     }
779 
780     const int colors = colors_u > colors_v ? colors_u : colors_v;
781     const int max_colors =
782         colors > PALETTE_MAX_SIZE ? PALETTE_MAX_SIZE : colors;
783     for (n = PALETTE_MIN_SIZE; n <= max_colors; ++n) {
784       for (i = 0; i < n; ++i) {
785         centroids[i * 2] = lb_u + (2 * i + 1) * (ub_u - lb_u) / n / 2;
786         centroids[i * 2 + 1] = lb_v + (2 * i + 1) * (ub_v - lb_v) / n / 2;
787       }
788       av1_k_means(data, centroids, color_map, rows * cols, n, 2, max_itr);
789       optimize_palette_colors(color_cache, n_cache, n, 2, centroids,
790                               cpi->common.seq_params->bit_depth);
791       // Sort the U channel colors in ascending order.
792       for (i = 0; i < 2 * (n - 1); i += 2) {
793         int min_idx = i;
794         int min_val = centroids[i];
795         for (j = i + 2; j < 2 * n; j += 2)
796           if (centroids[j] < min_val) min_val = centroids[j], min_idx = j;
797         if (min_idx != i) {
798           int temp_u = centroids[i], temp_v = centroids[i + 1];
799           centroids[i] = centroids[min_idx];
800           centroids[i + 1] = centroids[min_idx + 1];
801           centroids[min_idx] = temp_u, centroids[min_idx + 1] = temp_v;
802         }
803       }
804       av1_calc_indices(data, centroids, color_map, rows * cols, n, 2);
805       extend_palette_color_map(color_map, cols, rows, plane_block_width,
806                                plane_block_height);
807       pmi->palette_size[1] = n;
808       for (i = 1; i < 3; ++i) {
809         for (j = 0; j < n; ++j) {
810           if (seq_params->use_highbitdepth)
811             pmi->palette_colors[i * PALETTE_MAX_SIZE + j] = clip_pixel_highbd(
812                 (int)centroids[j * 2 + i - 1], seq_params->bit_depth);
813           else
814             pmi->palette_colors[i * PALETTE_MAX_SIZE + j] =
815                 clip_pixel((int)centroids[j * 2 + i - 1]);
816         }
817       }
818 
819       if (cpi->sf.intra_sf.early_term_chroma_palette_size_search) {
820         const int palette_mode_rate =
821             intra_mode_info_cost_uv(cpi, x, mbmi, bsize, dc_mode_cost);
822         const int64_t header_rd = RDCOST(x->rdmult, palette_mode_rate, 0);
823         // Terminate further palette_size search, if header cost corresponding
824         // to lower palette_size is more than the best_rd.
825         if (header_rd >= *best_rd) break;
826         av1_txfm_uvrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
827         if (tokenonly_rd_stats.rate == INT_MAX) continue;
828         this_rate = tokenonly_rd_stats.rate + palette_mode_rate;
829       } else {
830         av1_txfm_uvrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
831         if (tokenonly_rd_stats.rate == INT_MAX) continue;
832         this_rate = tokenonly_rd_stats.rate +
833                     intra_mode_info_cost_uv(cpi, x, mbmi, bsize, dc_mode_cost);
834       }
835 
836       this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
837       if (this_rd < *best_rd) {
838         *best_rd = this_rd;
839         *best_mbmi = *mbmi;
840         memcpy(best_palette_color_map, color_map,
841                plane_block_width * plane_block_height *
842                    sizeof(best_palette_color_map[0]));
843         *rate = this_rate;
844         *distortion = tokenonly_rd_stats.dist;
845         *rate_tokenonly = tokenonly_rd_stats.rate;
846         *skippable = tokenonly_rd_stats.skip_txfm;
847       }
848     }
849   }
850   if (best_mbmi->palette_mode_info.palette_size[1] > 0) {
851     memcpy(color_map, best_palette_color_map,
852            plane_block_width * plane_block_height *
853                sizeof(best_palette_color_map[0]));
854   }
855 }
856 
av1_restore_uv_color_map(const AV1_COMP * cpi,MACROBLOCK * x)857 void av1_restore_uv_color_map(const AV1_COMP *cpi, MACROBLOCK *x) {
858   MACROBLOCKD *const xd = &x->e_mbd;
859   MB_MODE_INFO *const mbmi = xd->mi[0];
860   PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
861   const BLOCK_SIZE bsize = mbmi->bsize;
862   int src_stride = x->plane[1].src.stride;
863   const uint8_t *const src_u = x->plane[1].src.buf;
864   const uint8_t *const src_v = x->plane[2].src.buf;
865   int *const data = x->palette_buffer->kmeans_data_buf;
866   int centroids[2 * PALETTE_MAX_SIZE];
867   uint8_t *const color_map = xd->plane[1].color_index_map;
868   int r, c;
869   const uint16_t *const src_u16 = CONVERT_TO_SHORTPTR(src_u);
870   const uint16_t *const src_v16 = CONVERT_TO_SHORTPTR(src_v);
871   int plane_block_width, plane_block_height, rows, cols;
872   av1_get_block_dimensions(bsize, 1, xd, &plane_block_width,
873                            &plane_block_height, &rows, &cols);
874 
875   for (r = 0; r < rows; ++r) {
876     for (c = 0; c < cols; ++c) {
877       if (cpi->common.seq_params->use_highbitdepth) {
878         data[(r * cols + c) * 2] = src_u16[r * src_stride + c];
879         data[(r * cols + c) * 2 + 1] = src_v16[r * src_stride + c];
880       } else {
881         data[(r * cols + c) * 2] = src_u[r * src_stride + c];
882         data[(r * cols + c) * 2 + 1] = src_v[r * src_stride + c];
883       }
884     }
885   }
886 
887   for (r = 1; r < 3; ++r) {
888     for (c = 0; c < pmi->palette_size[1]; ++c) {
889       centroids[c * 2 + r - 1] = pmi->palette_colors[r * PALETTE_MAX_SIZE + c];
890     }
891   }
892 
893   av1_calc_indices(data, centroids, color_map, rows * cols,
894                    pmi->palette_size[1], 2);
895   extend_palette_color_map(color_map, cols, rows, plane_block_width,
896                            plane_block_height);
897 }
898