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
int16_comparer(const void * a,const void * b)34 static int int16_comparer(const void *a, const void *b) {
35 return (*(int16_t *)a - *(int16_t *)b);
36 }
37
av1_remove_duplicates(int16_t * centroids,int num_centroids)38 int av1_remove_duplicates(int16_t *centroids, int num_centroids) {
39 int num_unique; // number of unique centroids
40 int i;
41 qsort(centroids, num_centroids, sizeof(*centroids), int16_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,int16_t * 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, int16_t *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((int)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((int)centroids[i] - (int)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 int16_t * data,int16_t * 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,uint8_t * 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,int discount_color_cost)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 int16_t *data, int16_t *centroids,
220 int n, 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, uint8_t *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, int discount_color_cost) {
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 = intra_mode_info_cost_y(
262 cpi, x, mbmi, bsize, dc_mode_cost, discount_color_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 discount_color_cost);
286 }
287
288 int64_t this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
289 if (!xd->lossless[mbmi->segment_id] && block_signals_txsize(mbmi->bsize)) {
290 tokenonly_rd_stats.rate -= tx_size_cost(x, bsize, mbmi->tx_size);
291 }
292 // Collect mode stats for multiwinner mode processing
293 const int txfm_search_done = 1;
294 store_winner_mode_stats(
295 &cpi->common, x, mbmi, NULL, NULL, NULL, THR_DC, color_map, bsize,
296 this_rd, cpi->sf.winner_mode_sf.multi_winner_mode_type, txfm_search_done);
297 if (this_rd < *best_rd) {
298 *best_rd = this_rd;
299 // Setting beat_best_rd flag because current mode rd is better than best_rd.
300 // This flag need to be updated only for palette evaluation in key frames
301 if (beat_best_rd) *beat_best_rd = 1;
302 memcpy(best_palette_color_map, color_map,
303 block_width * block_height * sizeof(color_map[0]));
304 *best_mbmi = *mbmi;
305 memcpy(blk_skip, x->txfm_search_info.blk_skip,
306 sizeof(x->txfm_search_info.blk_skip[0]) * ctx->num_4x4_blk);
307 av1_copy_array(tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
308 if (rate) *rate = this_rate;
309 if (rate_tokenonly) *rate_tokenonly = tokenonly_rd_stats.rate;
310 if (distortion) *distortion = tokenonly_rd_stats.dist;
311 if (skippable) *skippable = tokenonly_rd_stats.skip_txfm;
312 if (beat_best_palette_rd) *beat_best_palette_rd = 1;
313 }
314 }
315
is_iter_over(int curr_idx,int end_idx,int step_size)316 static AOM_INLINE int is_iter_over(int curr_idx, int end_idx, int step_size) {
317 assert(step_size != 0);
318 return (step_size > 0) ? curr_idx >= end_idx : curr_idx <= end_idx;
319 }
320
321 // Performs count-based palette search with number of colors in interval
322 // [start_n, end_n) with step size step_size. If step_size < 0, then end_n can
323 // be less than start_n. Saves the last numbers searched in last_n_searched and
324 // 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 int16_t * data,int16_t * 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,uint8_t * skippable,int * beat_best_rd,PICK_MODE_CONTEXT * ctx,uint8_t * best_blk_skip,uint8_t * tx_type_map,int discount_color_cost)325 static AOM_INLINE int perform_top_color_palette_search(
326 const AV1_COMP *const cpi, MACROBLOCK *x, MB_MODE_INFO *mbmi,
327 BLOCK_SIZE bsize, int dc_mode_cost, const int16_t *data,
328 int16_t *top_colors, int start_n, int end_n, int step_size,
329 bool do_header_rd_based_gating, int *last_n_searched, uint16_t *color_cache,
330 int n_cache, MB_MODE_INFO *best_mbmi, uint8_t *best_palette_color_map,
331 int64_t *best_rd, int *rate, int *rate_tokenonly, int64_t *distortion,
332 uint8_t *skippable, int *beat_best_rd, PICK_MODE_CONTEXT *ctx,
333 uint8_t *best_blk_skip, uint8_t *tx_type_map, int discount_color_cost) {
334 int16_t centroids[PALETTE_MAX_SIZE];
335 int n = start_n;
336 int top_color_winner = end_n;
337 /* clang-format off */
338 assert(IMPLIES(step_size < 0, start_n > end_n));
339 /* clang-format on */
340 assert(IMPLIES(step_size > 0, start_n < end_n));
341 while (!is_iter_over(n, end_n, step_size)) {
342 int beat_best_palette_rd = 0;
343 bool do_header_rd_based_breakout = false;
344 memcpy(centroids, top_colors, n * sizeof(top_colors[0]));
345 palette_rd_y(cpi, x, mbmi, bsize, dc_mode_cost, data, centroids, n,
346 color_cache, n_cache, do_header_rd_based_gating, best_mbmi,
347 best_palette_color_map, best_rd, rate, rate_tokenonly,
348 distortion, skippable, beat_best_rd, ctx, best_blk_skip,
349 tx_type_map, &beat_best_palette_rd,
350 &do_header_rd_based_breakout, discount_color_cost);
351 *last_n_searched = n;
352 if (do_header_rd_based_breakout) {
353 // Terminate palette_size search by setting last_n_searched to end_n.
354 *last_n_searched = end_n;
355 break;
356 }
357 if (beat_best_palette_rd) {
358 top_color_winner = n;
359 } else if (cpi->sf.intra_sf.prune_palette_search_level == 2) {
360 // At search level 2, we return immediately if we don't see an improvement
361 return top_color_winner;
362 }
363 n += step_size;
364 }
365 return top_color_winner;
366 }
367
368 // Performs k-means based palette search with number of colors in interval
369 // [start_n, end_n) with step size step_size. If step_size < 0, then end_n can
370 // be less than start_n. Saves the last numbers searched in last_n_searched and
371 // 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 int16_t * 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,uint8_t * 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,int discount_color_cost)372 static AOM_INLINE int perform_k_means_palette_search(
373 const AV1_COMP *const cpi, MACROBLOCK *x, MB_MODE_INFO *mbmi,
374 BLOCK_SIZE bsize, int dc_mode_cost, const int16_t *data, int lower_bound,
375 int upper_bound, int start_n, int end_n, int step_size,
376 bool do_header_rd_based_gating, int *last_n_searched, uint16_t *color_cache,
377 int n_cache, MB_MODE_INFO *best_mbmi, uint8_t *best_palette_color_map,
378 int64_t *best_rd, int *rate, int *rate_tokenonly, int64_t *distortion,
379 uint8_t *skippable, int *beat_best_rd, PICK_MODE_CONTEXT *ctx,
380 uint8_t *best_blk_skip, uint8_t *tx_type_map, uint8_t *color_map,
381 int data_points, int discount_color_cost) {
382 int16_t centroids[PALETTE_MAX_SIZE];
383 const int max_itr = 50;
384 int n = start_n;
385 int top_color_winner = end_n;
386 /* clang-format off */
387 assert(IMPLIES(step_size < 0, start_n > end_n));
388 /* clang-format on */
389 assert(IMPLIES(step_size > 0, start_n < end_n));
390 while (!is_iter_over(n, end_n, step_size)) {
391 int beat_best_palette_rd = 0;
392 bool do_header_rd_based_breakout = false;
393 for (int i = 0; i < n; ++i) {
394 centroids[i] =
395 lower_bound + (2 * i + 1) * (upper_bound - lower_bound) / n / 2;
396 }
397 av1_k_means(data, centroids, color_map, data_points, n, 1, max_itr);
398 palette_rd_y(cpi, x, mbmi, bsize, dc_mode_cost, data, centroids, n,
399 color_cache, n_cache, do_header_rd_based_gating, best_mbmi,
400 best_palette_color_map, best_rd, rate, rate_tokenonly,
401 distortion, skippable, beat_best_rd, ctx, best_blk_skip,
402 tx_type_map, &beat_best_palette_rd,
403 &do_header_rd_based_breakout, discount_color_cost);
404 *last_n_searched = n;
405 if (do_header_rd_based_breakout) {
406 // Terminate palette_size search by setting last_n_searched to end_n.
407 *last_n_searched = end_n;
408 break;
409 }
410 if (beat_best_palette_rd) {
411 top_color_winner = n;
412 } else if (cpi->sf.intra_sf.prune_palette_search_level == 2) {
413 // At search level 2, we return immediately if we don't see an improvement
414 return top_color_winner;
415 }
416 n += step_size;
417 }
418 return top_color_winner;
419 }
420
421 // 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)422 static AOM_INLINE void set_stage2_params(int *min_n, int *max_n, int *step_size,
423 int winner, int end_n) {
424 // Set min to winner - 1 unless we are already at the border, then we set it
425 // to winner + 1
426 *min_n = (winner == PALETTE_MIN_SIZE) ? (PALETTE_MIN_SIZE + 1)
427 : AOMMAX(winner - 1, PALETTE_MIN_SIZE);
428 // Set max to winner + 1 unless we are already at the border, then we set it
429 // to winner - 1
430 *max_n =
431 (winner == end_n) ? (winner - 1) : AOMMIN(winner + 1, PALETTE_MAX_SIZE);
432
433 // Set the step size to max_n - min_n so we only search those two values.
434 // If max_n == min_n, then set step_size to 1 to avoid infinite loop later.
435 *step_size = AOMMAX(1, *max_n - *min_n);
436 }
437
fill_data_and_get_bounds(const uint8_t * src,const int src_stride,const int rows,const int cols,const int is_high_bitdepth,int16_t * data,int * lower_bound,int * upper_bound)438 static AOM_INLINE void fill_data_and_get_bounds(const uint8_t *src,
439 const int src_stride,
440 const int rows, const int cols,
441 const int is_high_bitdepth,
442 int16_t *data, int *lower_bound,
443 int *upper_bound) {
444 if (is_high_bitdepth) {
445 const uint16_t *src_ptr = CONVERT_TO_SHORTPTR(src);
446 *lower_bound = *upper_bound = src_ptr[0];
447 for (int r = 0; r < rows; ++r) {
448 for (int c = 0; c < cols; ++c) {
449 const int val = src_ptr[c];
450 data[c] = (int16_t)val;
451 *lower_bound = AOMMIN(*lower_bound, val);
452 *upper_bound = AOMMAX(*upper_bound, val);
453 }
454 src_ptr += src_stride;
455 data += cols;
456 }
457 return;
458 }
459
460 // low bit depth
461 *lower_bound = *upper_bound = src[0];
462 for (int r = 0; r < rows; ++r) {
463 for (int c = 0; c < cols; ++c) {
464 const int val = src[c];
465 data[c] = (int16_t)val;
466 *lower_bound = AOMMIN(*lower_bound, val);
467 *upper_bound = AOMMAX(*upper_bound, val);
468 }
469 src += src_stride;
470 data += cols;
471 }
472 }
473
474 /*! \brief Colors are sorted by their count: the higher the better.
475 */
476 struct ColorCount {
477 //! Color index in the histogram.
478 int index;
479 //! Histogram count.
480 int count;
481 };
482
color_count_comp(const void * c1,const void * c2)483 int color_count_comp(const void *c1, const void *c2) {
484 const struct ColorCount *color_count1 = (const struct ColorCount *)c1;
485 const struct ColorCount *color_count2 = (const struct ColorCount *)c2;
486 if (color_count1->count > color_count2->count) return -1;
487 if (color_count1->count < color_count2->count) return 1;
488 if (color_count1->index < color_count2->index) return -1;
489 return 1;
490 }
491
find_top_colors(const int * const count_buf,int bit_depth,int n_colors,int16_t * top_colors)492 static void find_top_colors(const int *const count_buf, int bit_depth,
493 int n_colors, int16_t *top_colors) {
494 // Top color array, serving as a priority queue if more than n_colors are
495 // found.
496 struct ColorCount top_color_counts[PALETTE_MAX_SIZE] = { { 0 } };
497 int n_color_count = 0;
498 for (int i = 0; i < (1 << bit_depth); ++i) {
499 if (count_buf[i] > 0) {
500 if (n_color_count < n_colors) {
501 // Keep adding to the top colors.
502 top_color_counts[n_color_count].index = i;
503 top_color_counts[n_color_count].count = count_buf[i];
504 ++n_color_count;
505 if (n_color_count == n_colors) {
506 qsort(top_color_counts, n_colors, sizeof(top_color_counts[0]),
507 color_count_comp);
508 }
509 } else {
510 // Check the worst in the sorted top.
511 if (count_buf[i] > top_color_counts[n_colors - 1].count) {
512 int j = n_colors - 1;
513 // Move up to the best one.
514 while (j >= 1 && count_buf[i] > top_color_counts[j - 1].count) --j;
515 memmove(top_color_counts + j + 1, top_color_counts + j,
516 (n_colors - j - 1) * sizeof(top_color_counts[0]));
517 top_color_counts[j].index = i;
518 top_color_counts[j].count = count_buf[i];
519 }
520 }
521 }
522 }
523 assert(n_color_count == n_colors);
524
525 for (int i = 0; i < n_colors; ++i) {
526 top_colors[i] = top_color_counts[i].index;
527 }
528 }
529
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,uint8_t * skippable,int * beat_best_rd,PICK_MODE_CONTEXT * ctx,uint8_t * best_blk_skip,uint8_t * tx_type_map)530 void av1_rd_pick_palette_intra_sby(
531 const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int dc_mode_cost,
532 MB_MODE_INFO *best_mbmi, uint8_t *best_palette_color_map, int64_t *best_rd,
533 int *rate, int *rate_tokenonly, int64_t *distortion, uint8_t *skippable,
534 int *beat_best_rd, PICK_MODE_CONTEXT *ctx, uint8_t *best_blk_skip,
535 uint8_t *tx_type_map) {
536 MACROBLOCKD *const xd = &x->e_mbd;
537 MB_MODE_INFO *const mbmi = xd->mi[0];
538 assert(!is_inter_block(mbmi));
539 assert(av1_allow_palette(cpi->common.features.allow_screen_content_tools,
540 bsize));
541 assert(PALETTE_MAX_SIZE == 8);
542 assert(PALETTE_MIN_SIZE == 2);
543
544 const int src_stride = x->plane[0].src.stride;
545 const uint8_t *const src = x->plane[0].src.buf;
546 int block_width, block_height, rows, cols;
547 av1_get_block_dimensions(bsize, 0, xd, &block_width, &block_height, &rows,
548 &cols);
549 const SequenceHeader *const seq_params = cpi->common.seq_params;
550 const int is_hbd = seq_params->use_highbitdepth;
551 const int bit_depth = seq_params->bit_depth;
552 const int discount_color_cost = cpi->sf.rt_sf.use_nonrd_pick_mode;
553 int unused;
554
555 int count_buf[1 << 12]; // Maximum (1 << 12) color levels.
556 int colors, colors_threshold = 0;
557 if (is_hbd) {
558 int count_buf_8bit[1 << 8]; // Maximum (1 << 8) bins for hbd path.
559 av1_count_colors_highbd(src, src_stride, rows, cols, bit_depth, count_buf,
560 count_buf_8bit, &colors_threshold, &colors);
561 } else {
562 av1_count_colors(src, src_stride, rows, cols, count_buf, &colors);
563 colors_threshold = colors;
564 }
565
566 uint8_t *const color_map = xd->plane[0].color_index_map;
567 if (colors_threshold > 1 && colors_threshold <= 64) {
568 int16_t *const data = x->palette_buffer->kmeans_data_buf;
569 int16_t centroids[PALETTE_MAX_SIZE];
570 int lower_bound, upper_bound;
571 fill_data_and_get_bounds(src, src_stride, rows, cols, is_hbd, data,
572 &lower_bound, &upper_bound);
573
574 mbmi->mode = DC_PRED;
575 mbmi->filter_intra_mode_info.use_filter_intra = 0;
576
577 uint16_t color_cache[2 * PALETTE_MAX_SIZE];
578 const int n_cache = av1_get_palette_cache(xd, 0, color_cache);
579
580 // Find the dominant colors, stored in top_colors[].
581 int16_t top_colors[PALETTE_MAX_SIZE] = { 0 };
582 find_top_colors(count_buf, bit_depth, AOMMIN(colors, PALETTE_MAX_SIZE),
583 top_colors);
584
585 // The following are the approaches used for header rdcost based gating
586 // for early termination for different values of prune_palette_search_level.
587 // 0: Pruning based on header rdcost for ascending order palette_size
588 // search.
589 // 1: When colors > PALETTE_MIN_SIZE, enabled only for coarse palette_size
590 // search and for finer search do_header_rd_based_gating parameter is
591 // explicitly passed as 'false'.
592 // 2: Enabled only for ascending order palette_size search and for
593 // descending order search do_header_rd_based_gating parameter is explicitly
594 // passed as 'false'.
595 const bool do_header_rd_based_gating =
596 cpi->sf.intra_sf.prune_luma_palette_size_search_level != 0;
597
598 // TODO(huisu@google.com): Try to avoid duplicate computation in cases
599 // where the dominant colors and the k-means results are similar.
600 if ((cpi->sf.intra_sf.prune_palette_search_level == 1) &&
601 (colors > PALETTE_MIN_SIZE)) {
602 // Start index and step size below are chosen to evaluate unique
603 // candidates in neighbor search, in case a winner candidate is found in
604 // coarse search. Example,
605 // 1) 8 colors (end_n = 8): 2,3,4,5,6,7,8. start_n is chosen as 2 and step
606 // size is chosen as 3. Therefore, coarse search will evaluate 2, 5 and 8.
607 // If winner is found at 5, then 4 and 6 are evaluated. Similarly, for 2
608 // (3) and 8 (7).
609 // 2) 7 colors (end_n = 7): 2,3,4,5,6,7. If start_n is chosen as 2 (same
610 // as for 8 colors) then step size should also be 2, to cover all
611 // candidates. Coarse search will evaluate 2, 4 and 6. If winner is either
612 // 2 or 4, 3 will be evaluated. Instead, if start_n=3 and step_size=3,
613 // coarse search will evaluate 3 and 6. For the winner, unique neighbors
614 // (3: 2,4 or 6: 5,7) would be evaluated.
615
616 // Start index for coarse palette search for dominant colors and k-means
617 const uint8_t start_n_lookup_table[PALETTE_MAX_SIZE + 1] = { 0, 0, 0,
618 3, 3, 2,
619 3, 3, 2 };
620 // Step size for coarse palette search for dominant colors and k-means
621 const uint8_t step_size_lookup_table[PALETTE_MAX_SIZE + 1] = { 0, 0, 0,
622 3, 3, 3,
623 3, 3, 3 };
624
625 // Choose the start index and step size for coarse search based on number
626 // of colors
627 const int max_n = AOMMIN(colors, PALETTE_MAX_SIZE);
628 const int min_n = start_n_lookup_table[max_n];
629 const int step_size = step_size_lookup_table[max_n];
630 assert(min_n >= PALETTE_MIN_SIZE);
631 // Perform top color coarse palette search to find the winner candidate
632 const int top_color_winner = perform_top_color_palette_search(
633 cpi, x, mbmi, bsize, dc_mode_cost, data, top_colors, min_n, max_n + 1,
634 step_size, do_header_rd_based_gating, &unused, color_cache, n_cache,
635 best_mbmi, best_palette_color_map, best_rd, rate, rate_tokenonly,
636 distortion, skippable, beat_best_rd, ctx, best_blk_skip, tx_type_map,
637 discount_color_cost);
638 // Evaluate neighbors for the winner color (if winner is found) in the
639 // above coarse search for dominant colors
640 if (top_color_winner <= max_n) {
641 int stage2_min_n, stage2_max_n, stage2_step_size;
642 set_stage2_params(&stage2_min_n, &stage2_max_n, &stage2_step_size,
643 top_color_winner, max_n);
644 // perform finer search for the winner candidate
645 perform_top_color_palette_search(
646 cpi, x, mbmi, bsize, dc_mode_cost, data, top_colors, stage2_min_n,
647 stage2_max_n + 1, stage2_step_size,
648 /*do_header_rd_based_gating=*/false, &unused, color_cache, n_cache,
649 best_mbmi, best_palette_color_map, best_rd, rate, rate_tokenonly,
650 distortion, skippable, beat_best_rd, ctx, best_blk_skip,
651 tx_type_map, discount_color_cost);
652 }
653 // K-means clustering.
654 // Perform k-means coarse palette search to find the winner candidate
655 const int k_means_winner = perform_k_means_palette_search(
656 cpi, x, mbmi, bsize, dc_mode_cost, data, lower_bound, upper_bound,
657 min_n, max_n + 1, step_size, do_header_rd_based_gating, &unused,
658 color_cache, n_cache, best_mbmi, best_palette_color_map, best_rd,
659 rate, rate_tokenonly, distortion, skippable, beat_best_rd, ctx,
660 best_blk_skip, tx_type_map, color_map, rows * cols,
661 discount_color_cost);
662 // Evaluate neighbors for the winner color (if winner is found) in the
663 // above coarse search for k-means
664 if (k_means_winner <= max_n) {
665 int start_n_stage2, end_n_stage2, step_size_stage2;
666 set_stage2_params(&start_n_stage2, &end_n_stage2, &step_size_stage2,
667 k_means_winner, max_n);
668 // perform finer search for the winner candidate
669 perform_k_means_palette_search(
670 cpi, x, mbmi, bsize, dc_mode_cost, data, lower_bound, upper_bound,
671 start_n_stage2, end_n_stage2 + 1, step_size_stage2,
672 /*do_header_rd_based_gating=*/false, &unused, color_cache, n_cache,
673 best_mbmi, best_palette_color_map, best_rd, rate, rate_tokenonly,
674 distortion, skippable, beat_best_rd, ctx, best_blk_skip,
675 tx_type_map, color_map, rows * cols, discount_color_cost);
676 }
677 } else {
678 const int max_n = AOMMIN(colors, PALETTE_MAX_SIZE),
679 min_n = PALETTE_MIN_SIZE;
680 // Perform top color palette search in ascending order
681 int last_n_searched = min_n;
682 perform_top_color_palette_search(
683 cpi, x, mbmi, bsize, dc_mode_cost, data, top_colors, min_n, max_n + 1,
684 1, do_header_rd_based_gating, &last_n_searched, color_cache, n_cache,
685 best_mbmi, best_palette_color_map, best_rd, rate, rate_tokenonly,
686 distortion, skippable, beat_best_rd, ctx, best_blk_skip, tx_type_map,
687 discount_color_cost);
688 if (last_n_searched < max_n) {
689 // Search in descending order until we get to the previous best
690 perform_top_color_palette_search(
691 cpi, x, mbmi, bsize, dc_mode_cost, data, top_colors, max_n,
692 last_n_searched, -1, /*do_header_rd_based_gating=*/false, &unused,
693 color_cache, n_cache, best_mbmi, best_palette_color_map, best_rd,
694 rate, rate_tokenonly, distortion, skippable, beat_best_rd, ctx,
695 best_blk_skip, tx_type_map, discount_color_cost);
696 }
697 // K-means clustering.
698 if (colors == PALETTE_MIN_SIZE) {
699 // Special case: These colors automatically become the centroids.
700 assert(colors == 2);
701 centroids[0] = lower_bound;
702 centroids[1] = upper_bound;
703 palette_rd_y(cpi, x, mbmi, bsize, dc_mode_cost, data, centroids, colors,
704 color_cache, n_cache, /*do_header_rd_based_gating=*/false,
705 best_mbmi, best_palette_color_map, best_rd, rate,
706 rate_tokenonly, distortion, skippable, beat_best_rd, ctx,
707 best_blk_skip, tx_type_map, NULL, NULL,
708 discount_color_cost);
709 } else {
710 // Perform k-means palette search in ascending order
711 last_n_searched = min_n;
712 perform_k_means_palette_search(
713 cpi, x, mbmi, bsize, dc_mode_cost, data, lower_bound, upper_bound,
714 min_n, max_n + 1, 1, do_header_rd_based_gating, &last_n_searched,
715 color_cache, n_cache, best_mbmi, best_palette_color_map, best_rd,
716 rate, rate_tokenonly, distortion, skippable, beat_best_rd, ctx,
717 best_blk_skip, tx_type_map, color_map, rows * cols,
718 discount_color_cost);
719 if (last_n_searched < max_n) {
720 // Search in descending order until we get to the previous best
721 perform_k_means_palette_search(
722 cpi, x, mbmi, bsize, dc_mode_cost, data, lower_bound, upper_bound,
723 max_n, last_n_searched, -1, /*do_header_rd_based_gating=*/false,
724 &unused, color_cache, n_cache, best_mbmi, best_palette_color_map,
725 best_rd, rate, rate_tokenonly, distortion, skippable,
726 beat_best_rd, ctx, best_blk_skip, tx_type_map, color_map,
727 rows * cols, discount_color_cost);
728 }
729 }
730 }
731 }
732
733 if (best_mbmi->palette_mode_info.palette_size[0] > 0) {
734 memcpy(color_map, best_palette_color_map,
735 block_width * block_height * sizeof(best_palette_color_map[0]));
736 }
737 *mbmi = *best_mbmi;
738 }
739
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,uint8_t * skippable)740 void av1_rd_pick_palette_intra_sbuv(const AV1_COMP *cpi, MACROBLOCK *x,
741 int dc_mode_cost,
742 uint8_t *best_palette_color_map,
743 MB_MODE_INFO *const best_mbmi,
744 int64_t *best_rd, int *rate,
745 int *rate_tokenonly, int64_t *distortion,
746 uint8_t *skippable) {
747 MACROBLOCKD *const xd = &x->e_mbd;
748 MB_MODE_INFO *const mbmi = xd->mi[0];
749 assert(!is_inter_block(mbmi));
750 assert(av1_allow_palette(cpi->common.features.allow_screen_content_tools,
751 mbmi->bsize));
752 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
753 const BLOCK_SIZE bsize = mbmi->bsize;
754 const SequenceHeader *const seq_params = cpi->common.seq_params;
755 int this_rate;
756 int64_t this_rd;
757 int colors_u, colors_v;
758 int colors_threshold_u = 0, colors_threshold_v = 0, colors_threshold = 0;
759 const int src_stride = x->plane[1].src.stride;
760 const uint8_t *const src_u = x->plane[1].src.buf;
761 const uint8_t *const src_v = x->plane[2].src.buf;
762 uint8_t *const color_map = xd->plane[1].color_index_map;
763 RD_STATS tokenonly_rd_stats;
764 int plane_block_width, plane_block_height, rows, cols;
765 av1_get_block_dimensions(bsize, 1, xd, &plane_block_width,
766 &plane_block_height, &rows, &cols);
767
768 mbmi->uv_mode = UV_DC_PRED;
769 if (seq_params->use_highbitdepth) {
770 int count_buf[1 << 12]; // Maximum (1 << 12) color levels.
771 int count_buf_8bit[1 << 8]; // Maximum (1 << 8) bins for hbd path.
772 av1_count_colors_highbd(src_u, src_stride, rows, cols,
773 seq_params->bit_depth, count_buf, count_buf_8bit,
774 &colors_threshold_u, &colors_u);
775 av1_count_colors_highbd(src_v, src_stride, rows, cols,
776 seq_params->bit_depth, count_buf, count_buf_8bit,
777 &colors_threshold_v, &colors_v);
778 } else {
779 int count_buf[1 << 8];
780 av1_count_colors(src_u, src_stride, rows, cols, count_buf, &colors_u);
781 av1_count_colors(src_v, src_stride, rows, cols, count_buf, &colors_v);
782 colors_threshold_u = colors_u;
783 colors_threshold_v = colors_v;
784 }
785
786 uint16_t color_cache[2 * PALETTE_MAX_SIZE];
787 const int n_cache = av1_get_palette_cache(xd, 1, color_cache);
788
789 colors_threshold = colors_threshold_u > colors_threshold_v
790 ? colors_threshold_u
791 : colors_threshold_v;
792 if (colors_threshold > 1 && colors_threshold <= 64) {
793 int r, c, n, i, j;
794 const int max_itr = 50;
795 int lb_u, ub_u, val_u;
796 int lb_v, ub_v, val_v;
797 int16_t *const data = x->palette_buffer->kmeans_data_buf;
798 int16_t centroids[2 * PALETTE_MAX_SIZE];
799
800 uint16_t *src_u16 = CONVERT_TO_SHORTPTR(src_u);
801 uint16_t *src_v16 = CONVERT_TO_SHORTPTR(src_v);
802 if (seq_params->use_highbitdepth) {
803 lb_u = src_u16[0];
804 ub_u = src_u16[0];
805 lb_v = src_v16[0];
806 ub_v = src_v16[0];
807 } else {
808 lb_u = src_u[0];
809 ub_u = src_u[0];
810 lb_v = src_v[0];
811 ub_v = src_v[0];
812 }
813
814 for (r = 0; r < rows; ++r) {
815 for (c = 0; c < cols; ++c) {
816 if (seq_params->use_highbitdepth) {
817 val_u = src_u16[r * src_stride + c];
818 val_v = src_v16[r * src_stride + c];
819 data[(r * cols + c) * 2] = val_u;
820 data[(r * cols + c) * 2 + 1] = val_v;
821 } else {
822 val_u = src_u[r * src_stride + c];
823 val_v = src_v[r * src_stride + c];
824 data[(r * cols + c) * 2] = val_u;
825 data[(r * cols + c) * 2 + 1] = val_v;
826 }
827 if (val_u < lb_u)
828 lb_u = val_u;
829 else if (val_u > ub_u)
830 ub_u = val_u;
831 if (val_v < lb_v)
832 lb_v = val_v;
833 else if (val_v > ub_v)
834 ub_v = val_v;
835 }
836 }
837
838 const int colors = colors_u > colors_v ? colors_u : colors_v;
839 const int max_colors =
840 colors > PALETTE_MAX_SIZE ? PALETTE_MAX_SIZE : colors;
841 for (n = PALETTE_MIN_SIZE; n <= max_colors; ++n) {
842 for (i = 0; i < n; ++i) {
843 centroids[i * 2] = lb_u + (2 * i + 1) * (ub_u - lb_u) / n / 2;
844 centroids[i * 2 + 1] = lb_v + (2 * i + 1) * (ub_v - lb_v) / n / 2;
845 }
846 av1_k_means(data, centroids, color_map, rows * cols, n, 2, max_itr);
847 optimize_palette_colors(color_cache, n_cache, n, 2, centroids,
848 cpi->common.seq_params->bit_depth);
849 // Sort the U channel colors in ascending order.
850 for (i = 0; i < 2 * (n - 1); i += 2) {
851 int min_idx = i;
852 int min_val = centroids[i];
853 for (j = i + 2; j < 2 * n; j += 2)
854 if (centroids[j] < min_val) min_val = centroids[j], min_idx = j;
855 if (min_idx != i) {
856 int temp_u = centroids[i], temp_v = centroids[i + 1];
857 centroids[i] = centroids[min_idx];
858 centroids[i + 1] = centroids[min_idx + 1];
859 centroids[min_idx] = temp_u, centroids[min_idx + 1] = temp_v;
860 }
861 }
862 av1_calc_indices(data, centroids, color_map, rows * cols, n, 2);
863 extend_palette_color_map(color_map, cols, rows, plane_block_width,
864 plane_block_height);
865 pmi->palette_size[1] = n;
866 for (i = 1; i < 3; ++i) {
867 for (j = 0; j < n; ++j) {
868 if (seq_params->use_highbitdepth)
869 pmi->palette_colors[i * PALETTE_MAX_SIZE + j] = clip_pixel_highbd(
870 (int)centroids[j * 2 + i - 1], seq_params->bit_depth);
871 else
872 pmi->palette_colors[i * PALETTE_MAX_SIZE + j] =
873 clip_pixel((int)centroids[j * 2 + i - 1]);
874 }
875 }
876
877 if (cpi->sf.intra_sf.early_term_chroma_palette_size_search) {
878 const int palette_mode_rate =
879 intra_mode_info_cost_uv(cpi, x, mbmi, bsize, dc_mode_cost);
880 const int64_t header_rd = RDCOST(x->rdmult, palette_mode_rate, 0);
881 // Terminate further palette_size search, if header cost corresponding
882 // to lower palette_size is more than the best_rd.
883 if (header_rd >= *best_rd) break;
884 av1_txfm_uvrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
885 if (tokenonly_rd_stats.rate == INT_MAX) continue;
886 this_rate = tokenonly_rd_stats.rate + palette_mode_rate;
887 } else {
888 av1_txfm_uvrd(cpi, x, &tokenonly_rd_stats, bsize, *best_rd);
889 if (tokenonly_rd_stats.rate == INT_MAX) continue;
890 this_rate = tokenonly_rd_stats.rate +
891 intra_mode_info_cost_uv(cpi, x, mbmi, bsize, dc_mode_cost);
892 }
893
894 this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
895 if (this_rd < *best_rd) {
896 *best_rd = this_rd;
897 *best_mbmi = *mbmi;
898 memcpy(best_palette_color_map, color_map,
899 plane_block_width * plane_block_height *
900 sizeof(best_palette_color_map[0]));
901 *rate = this_rate;
902 *distortion = tokenonly_rd_stats.dist;
903 *rate_tokenonly = tokenonly_rd_stats.rate;
904 *skippable = tokenonly_rd_stats.skip_txfm;
905 }
906 }
907 }
908 if (best_mbmi->palette_mode_info.palette_size[1] > 0) {
909 memcpy(color_map, best_palette_color_map,
910 plane_block_width * plane_block_height *
911 sizeof(best_palette_color_map[0]));
912 }
913 }
914
av1_restore_uv_color_map(const AV1_COMP * cpi,MACROBLOCK * x)915 void av1_restore_uv_color_map(const AV1_COMP *cpi, MACROBLOCK *x) {
916 MACROBLOCKD *const xd = &x->e_mbd;
917 MB_MODE_INFO *const mbmi = xd->mi[0];
918 PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
919 const BLOCK_SIZE bsize = mbmi->bsize;
920 int src_stride = x->plane[1].src.stride;
921 const uint8_t *const src_u = x->plane[1].src.buf;
922 const uint8_t *const src_v = x->plane[2].src.buf;
923 int16_t *const data = x->palette_buffer->kmeans_data_buf;
924 int16_t centroids[2 * PALETTE_MAX_SIZE];
925 uint8_t *const color_map = xd->plane[1].color_index_map;
926 int r, c;
927 const uint16_t *const src_u16 = CONVERT_TO_SHORTPTR(src_u);
928 const uint16_t *const src_v16 = CONVERT_TO_SHORTPTR(src_v);
929 int plane_block_width, plane_block_height, rows, cols;
930 av1_get_block_dimensions(bsize, 1, xd, &plane_block_width,
931 &plane_block_height, &rows, &cols);
932
933 for (r = 0; r < rows; ++r) {
934 for (c = 0; c < cols; ++c) {
935 if (cpi->common.seq_params->use_highbitdepth) {
936 data[(r * cols + c) * 2] = src_u16[r * src_stride + c];
937 data[(r * cols + c) * 2 + 1] = src_v16[r * src_stride + c];
938 } else {
939 data[(r * cols + c) * 2] = src_u[r * src_stride + c];
940 data[(r * cols + c) * 2 + 1] = src_v[r * src_stride + c];
941 }
942 }
943 }
944
945 for (r = 1; r < 3; ++r) {
946 for (c = 0; c < pmi->palette_size[1]; ++c) {
947 centroids[c * 2 + r - 1] = pmi->palette_colors[r * PALETTE_MAX_SIZE + c];
948 }
949 }
950
951 av1_calc_indices(data, centroids, color_map, rows * cols,
952 pmi->palette_size[1], 2);
953 extend_palette_color_map(color_map, cols, rows, plane_block_width,
954 plane_block_height);
955 }
956