LCOV - code coverage report
Current view: top level - Codec - palette.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 399 0.0 %
Date: 2019-11-25 17:38:06 Functions: 0 25 0.0 %

          Line data    Source code
       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             : #include "EbDefinitions.h"
      15             : #include "EbModeDecisionProcess.h"
      16             : 
      17             : #if PAL_SUP
      18             : 
      19             : #define DIVIDE_AND_ROUND(x, y) (((x) + ((y) >> 1)) / (y))
      20             : 
      21             : // Generate a random number in the range [0, 32768).
      22           0 : static INLINE unsigned int lcg_rand16(unsigned int *state) {
      23           0 :     *state = (unsigned int)(*state * 1103515245ULL + 12345);
      24           0 :     return *state / 65536 % 32768;
      25             : }
      26             : 
      27             : #define AV1_K_MEANS_RENAME(func, dim) func##_dim##dim
      28             : 
      29             : void AV1_K_MEANS_RENAME(av1_calc_indices, 1)(const int *data,
      30             :     const int *centroids,
      31             :     uint8_t *indices, int n, int k);
      32             : void AV1_K_MEANS_RENAME(av1_calc_indices, 2)(const int *data,
      33             :     const int *centroids,
      34             :     uint8_t *indices, int n, int k);
      35             : void AV1_K_MEANS_RENAME(av1_k_means, 1)(const int *data, int *centroids,
      36             :     uint8_t *indices, int n, int k,
      37             :     int max_itr);
      38             : void AV1_K_MEANS_RENAME(av1_k_means, 2)(const int *data, int *centroids,
      39             :     uint8_t *indices, int n, int k,
      40             :     int max_itr);
      41             : 
      42             : // Given 'n' 'data' points and 'k' 'centroids' each of dimension 'dim',
      43             : // calculate the centroid 'indices' for the data points.
      44           0 : static inline void av1_calc_indices(const int *data, const int *centroids,
      45             :     uint8_t *indices, int n, int k, int dim) {
      46           0 :     if (dim == 1) {
      47           0 :         AV1_K_MEANS_RENAME(av1_calc_indices, 1)(data, centroids, indices, n, k);
      48             :     }
      49           0 :     else if (dim == 2) {
      50           0 :         AV1_K_MEANS_RENAME(av1_calc_indices, 2)(data, centroids, indices, n, k);
      51             :     }
      52             :     else {
      53           0 :         assert(0 && "Untemplated k means dimension");
      54             :     }
      55           0 : }
      56             : 
      57             : // Given 'n' 'data' points and an initial guess of 'k' 'centroids' each of
      58             : // dimension 'dim', runs up to 'max_itr' iterations of k-means algorithm to get
      59             : // updated 'centroids' and the centroid 'indices' for elements in 'data'.
      60             : // Note: the output centroids are rounded off to nearest integers.
      61           0 : static inline void av1_k_means(const int *data, int *centroids,
      62             :     uint8_t *indices, int n, int k, int dim,
      63             :     int max_itr) {
      64           0 :     if (dim == 1) {
      65           0 :         AV1_K_MEANS_RENAME(av1_k_means, 1)(data, centroids, indices, n, k, max_itr);
      66             :     }
      67           0 :     else if (dim == 2) {
      68           0 :         AV1_K_MEANS_RENAME(av1_k_means, 2)(data, centroids, indices, n, k, max_itr);
      69             :     }
      70             :     else {
      71           0 :         assert(0 && "Untemplated k means dimension");
      72             :     }
      73           0 : }
      74             : 
      75             : 
      76             : #define AV1_K_MEANS_DIM 1
      77             : #include "k_means_template.h"
      78             : #undef AV1_K_MEANS_DIM
      79             : #define AV1_K_MEANS_DIM 2
      80             : #include "k_means_template.h"
      81             : #undef AV1_K_MEANS_DIM
      82             : 
      83           0 : static int int_comparer(const void *a, const void *b) {
      84           0 :   return (*(int *)a - *(int *)b);
      85             : }
      86             : 
      87           0 : int av1_remove_duplicates(int *centroids, int num_centroids) {
      88             :   int num_unique;  // number of unique centroids
      89             :   int i;
      90           0 :   qsort(centroids, num_centroids, sizeof(*centroids), int_comparer);
      91             :   // Remove duplicates.
      92           0 :   num_unique = 1;
      93           0 :   for (i = 1; i < num_centroids; ++i) {
      94           0 :     if (centroids[i] != centroids[i - 1]) {  // found a new unique centroid
      95           0 :       centroids[num_unique++] = centroids[i];
      96             :     }
      97             :   }
      98           0 :   return num_unique;
      99             : }
     100             : 
     101           0 : static int delta_encode_cost(const int *colors, int num, int bit_depth,
     102             :                              int min_val) {
     103           0 :   if (num <= 0) return 0;
     104           0 :   int bits_cost = bit_depth;
     105           0 :   if (num == 1) return bits_cost;
     106           0 :   bits_cost += 2;
     107           0 :   int max_delta = 0;
     108             :   int deltas[PALETTE_MAX_SIZE];
     109           0 :   const int min_bits = bit_depth - 3;
     110           0 :   for (int i = 1; i < num; ++i) {
     111           0 :     const int delta = colors[i] - colors[i - 1];
     112           0 :     deltas[i - 1] = delta;
     113           0 :     assert(delta >= min_val);
     114           0 :     if (delta > max_delta) max_delta = delta;
     115             :   }
     116           0 :   int bits_per_delta = AOMMAX(av1_ceil_log2(max_delta + 1 - min_val), min_bits);
     117           0 :   assert(bits_per_delta <= bit_depth);
     118           0 :   int range = (1 << bit_depth) - colors[0] - min_val;
     119           0 :   for (int i = 0; i < num - 1; ++i) {
     120           0 :     bits_cost += bits_per_delta;
     121           0 :     range -= deltas[i];
     122           0 :     bits_per_delta = AOMMIN(bits_per_delta, av1_ceil_log2(range));
     123             :   }
     124           0 :   return bits_cost;
     125             : }
     126             : 
     127           0 : int av1_index_color_cache(const uint16_t *color_cache, int n_cache,
     128             :                           const uint16_t *colors, int n_colors,
     129             :                           uint8_t *cache_color_found, int *out_cache_colors) {
     130           0 :   if (n_cache <= 0) {
     131           0 :     for (int i = 0; i < n_colors; ++i) out_cache_colors[i] = colors[i];
     132           0 :     return n_colors;
     133             :   }
     134           0 :   memset(cache_color_found, 0, n_cache * sizeof(*cache_color_found));
     135           0 :   int n_in_cache = 0;
     136             :   int in_cache_flags[PALETTE_MAX_SIZE];
     137           0 :   memset(in_cache_flags, 0, sizeof(in_cache_flags));
     138           0 :   for (int i = 0; i < n_cache && n_in_cache < n_colors; ++i) {
     139           0 :     for (int j = 0; j < n_colors; ++j) {
     140           0 :       if (colors[j] == color_cache[i]) {
     141           0 :         in_cache_flags[j] = 1;
     142           0 :         cache_color_found[i] = 1;
     143           0 :         ++n_in_cache;
     144           0 :         break;
     145             :       }
     146             :     }
     147             :   }
     148           0 :   int j = 0;
     149           0 :   for (int i = 0; i < n_colors; ++i)
     150           0 :     if (!in_cache_flags[i]) out_cache_colors[j++] = colors[i];
     151           0 :   assert(j == n_colors - n_in_cache);
     152           0 :   return j;
     153             : }
     154             : 
     155             : 
     156           0 : int av1_get_palette_delta_bits_v(const PaletteModeInfo *const pmi,
     157             :                                  int bit_depth, int *zero_count,
     158             :                                  int *min_bits) {
     159           0 :   const int n = pmi->palette_size[1];
     160           0 :   const int max_val = 1 << bit_depth;
     161           0 :   int max_d = 0;
     162           0 :   *min_bits = bit_depth - 4;
     163           0 :   *zero_count = 0;
     164           0 :   for (int i = 1; i < n; ++i) {
     165           0 :     const int delta = pmi->palette_colors[2 * PALETTE_MAX_SIZE + i] -
     166           0 :                       pmi->palette_colors[2 * PALETTE_MAX_SIZE + i - 1];
     167           0 :     const int v = abs(delta);
     168           0 :     const int d = AOMMIN(v, max_val - v);
     169           0 :     if (d > max_d) max_d = d;
     170           0 :     if (d == 0) ++(*zero_count);
     171             :   }
     172           0 :   return AOMMAX(av1_ceil_log2(max_d + 1), *min_bits);
     173             : }
     174             : 
     175           0 : int av1_palette_color_cost_y(const PaletteModeInfo *const pmi,
     176             :                              uint16_t *color_cache, int n_cache,
     177             :                              int bit_depth) {
     178           0 :   const int n = pmi->palette_size[0];
     179             :   int out_cache_colors[PALETTE_MAX_SIZE];
     180             :   uint8_t cache_color_found[2 * PALETTE_MAX_SIZE];
     181             :   const int n_out_cache =
     182           0 :       av1_index_color_cache(color_cache, n_cache, pmi->palette_colors, n,
     183             :                             cache_color_found, out_cache_colors);
     184           0 :   const int total_bits =
     185           0 :       n_cache + delta_encode_cost(out_cache_colors, n_out_cache, bit_depth, 1);
     186           0 :   return av1_cost_literal(total_bits);
     187             : }
     188             : 
     189           0 : int av1_palette_color_cost_uv(const PaletteModeInfo *const pmi,
     190             :                               uint16_t *color_cache, int n_cache,
     191             :                               int bit_depth) {
     192           0 :   const int n = pmi->palette_size[1];
     193           0 :   int total_bits = 0;
     194             :   // U channel palette color cost.
     195             :   int out_cache_colors[PALETTE_MAX_SIZE];
     196             :   uint8_t cache_color_found[2 * PALETTE_MAX_SIZE];
     197           0 :   const int n_out_cache = av1_index_color_cache(
     198           0 :       color_cache, n_cache, pmi->palette_colors + PALETTE_MAX_SIZE, n,
     199             :       cache_color_found, out_cache_colors);
     200           0 :   total_bits +=
     201           0 :       n_cache + delta_encode_cost(out_cache_colors, n_out_cache, bit_depth, 0);
     202             : 
     203             :   // V channel palette color cost.
     204           0 :   int zero_count = 0, min_bits_v = 0;
     205             :   const int bits_v =
     206           0 :       av1_get_palette_delta_bits_v(pmi, bit_depth, &zero_count, &min_bits_v);
     207           0 :   const int bits_using_delta =
     208           0 :       2 + bit_depth + (bits_v + 1) * (n - 1) - zero_count;
     209           0 :   const int bits_using_raw = bit_depth * n;
     210           0 :   total_bits += 1 + AOMMIN(bits_using_delta, bits_using_raw);
     211           0 :   return av1_cost_literal(total_bits);
     212             : }
     213             : 
     214             : 
     215           0 : static void palette_add_to_cache(uint16_t *cache, int *n, uint16_t val) {
     216             :     // Do not add an already existing value
     217           0 :     if (*n > 0 && val == cache[*n - 1]) return;
     218             : 
     219           0 :     cache[(*n)++] = val;
     220             : }
     221             : 
     222           0 : int eb_get_palette_cache(const MacroBlockD *const xd, int plane,
     223             :     uint16_t *cache) {
     224           0 :     const int row = -xd->mb_to_top_edge >> 3;
     225             :     // Do not refer to above SB row when on SB boundary.
     226           0 :     const MbModeInfo *const above_mi =
     227           0 :         (row % (1 << MIN_SB_SIZE_LOG2)) ? xd->above_mbmi : NULL;
     228           0 :     const MbModeInfo *const left_mi = xd->left_mbmi;
     229           0 :     int above_n = 0, left_n = 0;
     230           0 :     if (above_mi) above_n = above_mi->palette_mode_info.palette_size[plane != 0];
     231           0 :     if (left_mi) left_n = left_mi->palette_mode_info.palette_size[plane != 0];
     232           0 :     if (above_n == 0 && left_n == 0) return 0;
     233           0 :     int above_idx = plane * PALETTE_MAX_SIZE;
     234           0 :     int left_idx = plane * PALETTE_MAX_SIZE;
     235           0 :     int n = 0;
     236           0 :     const uint16_t *above_colors =
     237           0 :         above_mi ? above_mi->palette_mode_info.palette_colors : NULL;
     238           0 :     const uint16_t *left_colors =
     239           0 :         left_mi ? left_mi->palette_mode_info.palette_colors : NULL;
     240             :     // Merge the sorted lists of base colors from above and left to get
     241             :     // combined sorted color cache.
     242           0 :     while (above_n > 0 && left_n > 0) {
     243           0 :         uint16_t v_above = above_colors[above_idx];
     244           0 :         uint16_t v_left = left_colors[left_idx];
     245           0 :         if (v_left < v_above) {
     246           0 :             palette_add_to_cache(cache, &n, v_left);
     247           0 :             ++left_idx, --left_n;
     248             :         }
     249             :         else {
     250           0 :             palette_add_to_cache(cache, &n, v_above);
     251           0 :             ++above_idx, --above_n;
     252           0 :             if (v_left == v_above) ++left_idx, --left_n;
     253             :         }
     254             :     }
     255           0 :     while (above_n-- > 0) {
     256           0 :         uint16_t val = above_colors[above_idx++];
     257           0 :         palette_add_to_cache(cache, &n, val);
     258             :     }
     259           0 :     while (left_n-- > 0) {
     260           0 :         uint16_t val = left_colors[left_idx++];
     261           0 :         palette_add_to_cache(cache, &n, val);
     262             :     }
     263           0 :     assert(n <= 2 * PALETTE_MAX_SIZE);
     264           0 :     return n;
     265             : }
     266             : // Returns sub-sampled dimensions of the given block.
     267             : // The output values for 'rows_within_bounds' and 'cols_within_bounds' will
     268             : // differ from 'height' and 'width' when part of the block is outside the
     269             : // right
     270             : // and/or bottom image boundary.
     271           0 :  void av1_get_block_dimensions(BlockSize bsize, int plane,
     272             :     const MacroBlockD *xd, int *width,
     273             :     int *height,
     274             :     int *rows_within_bounds,
     275             :     int *cols_within_bounds) {
     276           0 :     const int block_height = block_size_high[bsize];
     277           0 :     const int block_width = block_size_wide[bsize];
     278           0 :     const int block_rows = (xd->mb_to_bottom_edge >= 0)
     279             :         ? block_height
     280           0 :         : (xd->mb_to_bottom_edge >> 3) + block_height;
     281           0 :     const int block_cols = (xd->mb_to_right_edge >= 0)
     282             :         ? block_width
     283           0 :         : (xd->mb_to_right_edge >> 3) + block_width;
     284             : 
     285           0 :     uint8_t subsampling_x = plane == 0 ? 0 : 1;
     286           0 :     uint8_t subsampling_y = plane == 0 ? 0 : 1;
     287             : 
     288           0 :     assert(block_width >= block_cols);
     289           0 :     assert(block_height >= block_rows);
     290           0 :     const int plane_block_width = block_width >> subsampling_x;
     291           0 :     const int plane_block_height = block_height >> subsampling_y;
     292             :     // Special handling for chroma sub8x8.
     293           0 :     const int is_chroma_sub8_x = plane > 0 && plane_block_width < 4;
     294           0 :     const int is_chroma_sub8_y = plane > 0 && plane_block_height < 4;
     295           0 :     if (width) *width = plane_block_width + 2 * is_chroma_sub8_x;
     296           0 :     if (height) *height = plane_block_height + 2 * is_chroma_sub8_y;
     297           0 :     if (rows_within_bounds) {
     298           0 :         *rows_within_bounds =
     299           0 :             (block_rows >> subsampling_y) + 2 * is_chroma_sub8_y;
     300             :     }
     301           0 :     if (cols_within_bounds) {
     302           0 :         *cols_within_bounds =
     303           0 :             (block_cols >> subsampling_x) + 2 * is_chroma_sub8_x;
     304             :     }
     305           0 : }
     306             : 
     307             : int av1_remove_duplicates(int *centroids, int num_centroids);
     308             : // Bias toward using colors in the cache.
     309             : // TODO: Try other schemes to improve compression.
     310           0 : static AOM_INLINE void optimize_palette_colors(uint16_t *color_cache,
     311             :     int n_cache, int n_colors,
     312             :     int stride, int *centroids) {
     313           0 :     if (n_cache <= 0) return;
     314           0 :     for (int i = 0; i < n_colors * stride; i += stride) {
     315           0 :         int min_diff = abs(centroids[i] - (int)color_cache[0]);
     316           0 :         int idx = 0;
     317           0 :         for (int j = 1; j < n_cache; ++j) {
     318           0 :             const int this_diff = abs(centroids[i] - color_cache[j]);
     319           0 :             if (this_diff < min_diff) {
     320           0 :                 min_diff = this_diff;
     321           0 :                 idx = j;
     322             :             }
     323             :         }
     324           0 :         if (min_diff <= 1) centroids[i] = color_cache[idx];
     325             :     }
     326             : }
     327             : // Extends 'color_map' array from 'orig_width x orig_height' to 'new_width x
     328             : // new_height'. Extra rows and columns are filled in by copying last valid
     329             : // row/column.
     330           0 : static AOM_INLINE void extend_palette_color_map(uint8_t *const color_map,
     331             :     int orig_width, int orig_height,
     332             :     int new_width, int new_height) {
     333             :     int j;
     334           0 :     assert(new_width >= orig_width);
     335           0 :     assert(new_height >= orig_height);
     336           0 :     if (new_width == orig_width && new_height == orig_height) return;
     337             : 
     338           0 :     for (j = orig_height - 1; j >= 0; --j) {
     339           0 :         memmove(color_map + j * new_width, color_map + j * orig_width, orig_width);
     340             :         // Copy last column to extra columns.
     341           0 :         memset(color_map + j * new_width + orig_width,
     342           0 :             color_map[j * new_width + orig_width - 1], new_width - orig_width);
     343             :     }
     344             :     // Copy last row to extra rows.
     345           0 :     for (j = orig_height; j < new_height; ++j) {
     346           0 :         memcpy(color_map + j * new_width, color_map + (orig_height - 1) * new_width,
     347             :             new_width);
     348             :     }
     349             : }
     350           0 :  void palette_rd_y(
     351             :      PaletteInfo                 *palette_info,
     352             :     ModeDecisionContext          *context_ptr,
     353             :      BlockSize bsize,
     354             :     const int *data,
     355             :     int *centroids, int n, uint16_t *color_cache, int n_cache
     356             : )
     357             : {
     358           0 :     optimize_palette_colors(color_cache, n_cache, n, 1, centroids);
     359           0 :     int k = av1_remove_duplicates(centroids, n);
     360           0 :     if (k < PALETTE_MIN_SIZE) {
     361             :         // Too few unique colors to create a palette. And DC_PRED will work
     362             :         // well for that case anyway. So skip.
     363           0 :         palette_info->pmi.palette_size[0] = 0;
     364           0 :         return;
     365             :     }
     366             : 
     367             :      //if (cpi->common.seq_params.use_highbitdepth)
     368             :      //    for (int i = 0; i < k; ++i)
     369             :      //        pmi->palette_colors[i] = clip_pixel_highbd(
     370             :      //        (int)centroids[i], cpi->common.seq_params.bit_depth);
     371             :      //else
     372           0 :     for (int i = 0; i < k; ++i)
     373           0 :         palette_info->pmi.palette_colors[i] = clip_pixel(centroids[i]);
     374           0 :     palette_info->pmi.palette_size[0] = k;
     375             : 
     376           0 :     uint8_t *const color_map = palette_info->color_idx_map;
     377             :     int block_width, block_height, rows, cols;
     378           0 :     av1_get_block_dimensions(bsize, 0, context_ptr->cu_ptr->av1xd, &block_width, &block_height, &rows,
     379             :         &cols);
     380           0 :     av1_calc_indices(data, centroids, color_map, rows * cols, k, 1);
     381           0 :     extend_palette_color_map(color_map, cols, rows, block_width, block_height);
     382             : }
     383             : 
     384             : int eb_av1_count_colors(const uint8_t *src, int stride, int rows, int cols,
     385             :      int *val_count);
     386             : int av1_count_colors_highbd(uint16_t *src, int stride, int rows, int cols,
     387             :     int bit_depth, int *val_count);
     388             :  /****************************************
     389             :    determine all palette luma candidates
     390             :  ****************************************/
     391           0 :  void  search_palette_luma(
     392             :      PictureControlSet            *picture_control_set_ptr,
     393             :      ModeDecisionContext          *context_ptr,
     394             :      PaletteInfo                 *palette_cand,
     395             :      uint32_t                     *tot_palette_cands)
     396             :  {
     397             :      int colors, n;
     398           0 :      EbPictureBufferDesc   *src_pic = picture_control_set_ptr->parent_pcs_ptr->enhanced_picture_ptr;
     399           0 :      const int src_stride = src_pic->stride_y;
     400           0 :      uint16_t * src16 = 0;
     401           0 :      const uint8_t *const src = src_pic->buffer_y + (context_ptr->cu_origin_x + src_pic->origin_x) + (context_ptr->cu_origin_y + src_pic->origin_y) * src_pic->stride_y;
     402             :      int block_width, block_height, rows, cols;
     403           0 :      uint8_t hbd_md = 0;
     404             : 
     405           0 :      Av1Common  *cm = picture_control_set_ptr->parent_pcs_ptr->av1_cm;
     406           0 :      MacroBlockD  *xd = context_ptr->cu_ptr->av1xd;
     407           0 :      TileInfo * tile = &context_ptr->sb_ptr->tile_info;
     408           0 :      BlockSize bsize = context_ptr->blk_geom->bsize;
     409           0 :      int32_t mirow = context_ptr->cu_origin_y >> 2;
     410           0 :      int32_t micol = context_ptr->cu_origin_x >> 2;
     411           0 :      xd->up_available = (mirow > tile->mi_row_start);
     412           0 :      xd->left_available = (micol > tile->mi_col_start);
     413           0 :      const int32_t bw = mi_size_wide[bsize];
     414           0 :      const int32_t bh = mi_size_high[bsize];
     415           0 :      xd->mb_to_top_edge = -((mirow * MI_SIZE) * 8);
     416           0 :      xd->mb_to_bottom_edge = ((cm->mi_rows - bh - mirow) * MI_SIZE) * 8;
     417           0 :      xd->mb_to_left_edge = -((micol * MI_SIZE) * 8);
     418           0 :      xd->mb_to_right_edge = ((cm->mi_cols - bw - micol) * MI_SIZE) * 8;
     419           0 :      xd->tile.mi_col_start = tile->mi_col_start;
     420           0 :      xd->tile.mi_col_end = tile->mi_col_end;
     421           0 :      xd->tile.mi_row_start = tile->mi_row_start;
     422           0 :      xd->tile.mi_row_end = tile->mi_row_end;
     423           0 :      xd->n8_h = bh;
     424           0 :      xd->n8_w = bw;
     425           0 :      xd->is_sec_rect = 0;
     426           0 :      if (xd->n8_w < xd->n8_h) {
     427             :          // Only mark is_sec_rect as 1 for the last block.
     428             :          // For PARTITION_VERT_4, it would be (0, 0, 0, 1);
     429             :          // For other partitions, it would be (0, 1).
     430           0 :          if (!((micol + xd->n8_w) & (xd->n8_h - 1))) xd->is_sec_rect = 1;
     431             :      }
     432             : 
     433           0 :      if (xd->n8_w > xd->n8_h)
     434           0 :          if (mirow & (xd->n8_w - 1)) xd->is_sec_rect = 1;
     435             : 
     436           0 :      int mi_stride = cm->mi_stride;
     437           0 :      const int32_t offset = mirow * mi_stride + micol;
     438           0 :      xd->mi = cm->pcs_ptr->mi_grid_base + offset;
     439           0 :      ModeInfo *miPtr = *xd->mi;
     440           0 :      if (xd->up_available) {
     441           0 :          xd->above_mbmi = &miPtr[-mi_stride].mbmi;
     442             :      }
     443             :      else
     444           0 :          xd->above_mbmi = NULL;
     445           0 :      if (xd->left_available) {
     446           0 :          xd->left_mbmi = &miPtr[-1].mbmi;
     447             :      }
     448             :      else
     449           0 :          xd->left_mbmi = NULL;
     450             : 
     451             : 
     452           0 :      av1_get_block_dimensions(context_ptr->blk_geom->bsize, 0, context_ptr->cu_ptr->av1xd, &block_width, &block_height, &rows,
     453             :          &cols);
     454             : 
     455             :      int count_buf[1 << 12];  // Maximum (1 << 12) color levels.
     456             : 
     457           0 :      if(hbd_md)
     458           0 :           colors = av1_count_colors_highbd(src16, src_stride, rows, cols, picture_control_set_ptr->parent_pcs_ptr->sequence_control_set_ptr->encoder_bit_depth, count_buf);
     459             :      else
     460           0 :           colors = eb_av1_count_colors(src, src_stride, rows, cols, count_buf);
     461             : 
     462           0 :      if (colors > 1 && colors <= 64) {
     463             :          int r, c, i;
     464           0 :          const int max_itr = 50;
     465           0 :          int *const data = context_ptr->palette_buffer.kmeans_data_buf;
     466             :          int centroids[PALETTE_MAX_SIZE];
     467             :          int lb, ub, val;
     468           0 :          lb = ub = src[0];
     469             :          {
     470           0 :              for (r = 0; r < rows; ++r) {
     471           0 :                  for (c = 0; c < cols; ++c) {
     472           0 :                      val = src[r * src_stride + c];
     473           0 :                      data[r * cols + c] = val;
     474           0 :                      if (val < lb)
     475           0 :                          lb = val;
     476           0 :                      else if (val > ub)
     477           0 :                          ub = val;
     478             :                  }
     479             :              }
     480             :          }
     481             : 
     482             :          uint16_t color_cache[2 * PALETTE_MAX_SIZE];
     483           0 :          const int n_cache = eb_get_palette_cache(xd, 0, color_cache);
     484             : 
     485             :          // Find the dominant colors, stored in top_colors[].
     486           0 :          int top_colors[PALETTE_MAX_SIZE] = { 0 };
     487           0 :          for (i = 0; i < AOMMIN(colors, PALETTE_MAX_SIZE); ++i) {
     488           0 :              int max_count = 0;
     489           0 :              for (int j = 0; j < (1 << EB_8BIT); ++j) {
     490           0 :                  if (count_buf[j] > max_count) {
     491           0 :                      max_count = count_buf[j];
     492           0 :                      top_colors[i] = j;
     493             :                  }
     494             :              }
     495           0 :              assert(max_count > 0);
     496           0 :              count_buf[top_colors[i]] = 0;
     497             :          }
     498             : 
     499             :          // Try the dominant colors directly.
     500             :          // TODO: Try to avoid duplicate computation in cases
     501             :          // where the dominant colors and the k-means results are similar.
     502             : 
     503           0 :          int step = (picture_control_set_ptr->parent_pcs_ptr->palette_mode == 6 && picture_control_set_ptr->temporal_layer_index > 0) ? 2 : 1;
     504           0 :          for (n = AOMMIN(colors, PALETTE_MAX_SIZE); n >= 2; n-=step) {
     505             : 
     506           0 :              for (i = 0; i < n; ++i)
     507           0 :                  centroids[i] = top_colors[i];
     508             : 
     509           0 :              palette_rd_y(&palette_cand[*tot_palette_cands], context_ptr, bsize, data, centroids, n, color_cache, n_cache);
     510             : 
     511             :              //consider this candidate if it has some non zero palette
     512           0 :              if(palette_cand[*tot_palette_cands].pmi.palette_size[0]>2)
     513           0 :                  (*tot_palette_cands)++;
     514           0 :              assert((*tot_palette_cands) <= 14);
     515             :          }
     516             : 
     517           0 :          if (picture_control_set_ptr->parent_pcs_ptr->palette_mode == 3)
     518           0 :              if (picture_control_set_ptr->parent_pcs_ptr->is_used_as_reference_flag == 0)
     519           0 :                  return;
     520             : 
     521           0 :          if (picture_control_set_ptr->parent_pcs_ptr->palette_mode == 5 || picture_control_set_ptr->parent_pcs_ptr->palette_mode == 6)
     522           0 :              if (picture_control_set_ptr->temporal_layer_index > 0)
     523           0 :                  return;
     524             : 
     525             :          // K-means clustering.
     526           0 :          for (n = AOMMIN(colors, PALETTE_MAX_SIZE); n >= 2; --n) {
     527           0 :              if (colors == PALETTE_MIN_SIZE) {
     528             :                  // Special case: These colors automatically become the centroids.
     529           0 :                  assert(colors == n);
     530           0 :                  assert(colors == 2);
     531           0 :                  centroids[0] = lb;
     532           0 :                  centroids[1] = ub;
     533             :              }
     534             :              else {
     535           0 :                  for (i = 0; i < n; ++i) {
     536           0 :                      centroids[i] = lb + (2 * i + 1) * (ub - lb) / n / 2;
     537             :                  }
     538           0 :                  uint8_t *const color_map = palette_cand[*tot_palette_cands].color_idx_map;
     539           0 :                  av1_k_means(data, centroids, color_map, rows * cols, n, 1, max_itr);
     540             :              }
     541             : 
     542           0 :              palette_rd_y(&palette_cand[*tot_palette_cands], context_ptr, bsize, data, centroids, n, color_cache, n_cache);
     543             : 
     544             :              //consider this candidate if it has some non zero palette
     545           0 :              if (palette_cand[*tot_palette_cands].pmi.palette_size[0] > 2)
     546           0 :                  (*tot_palette_cands)++;
     547             : 
     548           0 :              assert((*tot_palette_cands) <= 14);
     549             :          }
     550             :      }
     551             :  }
     552             : 
     553             :  /* clang-format off */
     554             :  typedef AomCdfProb(*MapCdf)[PALETTE_COLOR_INDEX_CONTEXTS]
     555             :      [CDF_SIZE(PALETTE_COLORS)];
     556             :  typedef const int(*ColorCost)[PALETTE_SIZES][PALETTE_COLOR_INDEX_CONTEXTS]
     557             :      [PALETTE_COLORS];
     558             :  /* clang-format on */
     559             : 
     560             :  typedef struct {
     561             :      int rows;
     562             :      int cols;
     563             :      int n_colors;
     564             :      int plane_width;
     565             :      int plane_height;
     566             :      uint8_t *color_map;
     567             :      MapCdf map_cdf;
     568             :      ColorCost color_cost;
     569             :  } Av1ColorMapParam;
     570             : 
     571           0 :  static void get_palette_params(FRAME_CONTEXT *frame_context, CodingUnit*cu_ptr, int plane,
     572             :      BlockSize bsize, Av1ColorMapParam *params) {
     573           0 :      const MacroBlockD *const xd = cu_ptr->av1xd;
     574           0 :      MbModeInfo * mbmi = &(xd->mi[0]->mbmi);
     575           0 :      const PaletteModeInfo *const pmi = &mbmi->palette_mode_info;
     576           0 :      params->color_map = cu_ptr->palette_info.color_idx_map;
     577           0 :      params->map_cdf = plane ? frame_context->palette_uv_color_index_cdf
     578           0 :          : frame_context->palette_y_color_index_cdf;
     579           0 :      params->color_cost = NULL;
     580           0 :      params->n_colors = pmi->palette_size[plane];
     581           0 :      av1_get_block_dimensions(bsize, plane, xd, &params->plane_width, NULL,
     582             :          &params->rows, &params->cols);
     583           0 :  }
     584             : 
     585           0 :  static void get_color_map_params(FRAME_CONTEXT *frame_context, CodingUnit*cu_ptr , int plane,
     586             :      BlockSize bsize, TxSize tx_size,
     587             :      COLOR_MAP_TYPE type,
     588             :      Av1ColorMapParam *params) {
     589             :      (void)tx_size;
     590           0 :      memset(params, 0, sizeof(*params));
     591           0 :      switch (type) {
     592           0 :      case PALETTE_MAP: get_palette_params(frame_context, cu_ptr, plane, bsize, params); break;
     593           0 :      default: assert(0 && "Invalid color map type"); return;
     594             :      }
     595             :  }
     596           0 :  static void get_palette_params_rate(PaletteInfo *palette_info, MdRateEstimationContext  *rate_table, CodingUnit*cu_ptr, int plane,
     597             :      BlockSize bsize, Av1ColorMapParam *params) {
     598           0 :      const MacroBlockD *const xd = cu_ptr->av1xd;
     599           0 :      const PaletteModeInfo *const pmi = &palette_info->pmi;
     600             : 
     601           0 :      params->color_map = palette_info->color_idx_map;
     602           0 :      params->map_cdf = NULL;
     603           0 :      params->color_cost =   plane ? NULL  : &rate_table->palette_ycolor_fac_bitss;
     604           0 :      params->n_colors = pmi->palette_size[plane];
     605             : 
     606           0 :      av1_get_block_dimensions(bsize, plane, xd, &params->plane_width, NULL,
     607             :          &params->rows, &params->cols);
     608           0 :  }
     609             : 
     610           0 :  static void get_color_map_params_rate(PaletteInfo *palette_info, MdRateEstimationContext  *rate_table,/*const MACROBLOCK *const x*/ CodingUnit*cu_ptr, int plane,
     611             :      BlockSize bsize,
     612             :      COLOR_MAP_TYPE type,
     613             :      Av1ColorMapParam *params) {
     614           0 :      memset(params, 0, sizeof(*params));
     615           0 :      switch (type) {
     616           0 :      case PALETTE_MAP: get_palette_params_rate(palette_info, rate_table, cu_ptr, plane, bsize, params); break;
     617           0 :      default: assert(0 && "Invalid color map type"); return;
     618             :      }
     619             :  }
     620             : #define MAX_COLOR_CONTEXT_HASH 8
     621             :  // Negative values are invalid
     622             :  int palette_color_index_context_lookup[MAX_COLOR_CONTEXT_HASH +
     623             :      1] = { -1, -1, 0, -1, -1,
     624             :             4,  3,  2, 1 };
     625             : 
     626             : #define NUM_PALETTE_NEIGHBORS 3  // left, top-left and top.
     627           0 :  int av1_get_palette_color_index_context(const uint8_t *color_map, int stride,
     628             :      int r, int c, int palette_size,
     629             :      uint8_t *color_order, int *color_idx) {
     630           0 :      assert(palette_size <= PALETTE_MAX_SIZE);
     631           0 :      assert(r > 0 || c > 0);
     632             : 
     633             :      // Get color indices of neighbors.
     634             :      int color_neighbors[NUM_PALETTE_NEIGHBORS];
     635           0 :      color_neighbors[0] = (c - 1 >= 0) ? color_map[r * stride + c - 1] : -1;
     636           0 :      color_neighbors[1] =
     637           0 :          (c - 1 >= 0 && r - 1 >= 0) ? color_map[(r - 1) * stride + c - 1] : -1;
     638           0 :      color_neighbors[2] = (r - 1 >= 0) ? color_map[(r - 1) * stride + c] : -1;
     639             : 
     640             :      // The +10 below should not be needed. But we get a warning "array subscript
     641             :      // is above array bounds [-Werror=array-bounds]" without it, possibly due to
     642             :      // this (or similar) bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
     643           0 :      int scores[PALETTE_MAX_SIZE + 10] = { 0 };
     644             :      int i;
     645             :      static const int weights[NUM_PALETTE_NEIGHBORS] = { 2, 1, 2 };
     646           0 :      for (i = 0; i < NUM_PALETTE_NEIGHBORS; ++i) {
     647           0 :          if (color_neighbors[i] >= 0) {
     648           0 :              scores[color_neighbors[i]] += weights[i];
     649             :          }
     650             :      }
     651             : 
     652             :      int inverse_color_order[PALETTE_MAX_SIZE];
     653           0 :      for (i = 0; i < PALETTE_MAX_SIZE; ++i) {
     654           0 :          color_order[i] = i;
     655           0 :          inverse_color_order[i] = i;
     656             :      }
     657             : 
     658             :      // Get the top NUM_PALETTE_NEIGHBORS scores (sorted from large to small).
     659           0 :      for (i = 0; i < NUM_PALETTE_NEIGHBORS; ++i) {
     660           0 :          int max = scores[i];
     661           0 :          int max_idx = i;
     662           0 :          for (int j = i + 1; j < palette_size; ++j) {
     663           0 :              if (scores[j] > max) {
     664           0 :                  max = scores[j];
     665           0 :                  max_idx = j;
     666             :              }
     667             :          }
     668           0 :          if (max_idx != i) {
     669             :              // Move the score at index 'max_idx' to index 'i', and shift the scores
     670             :              // from 'i' to 'max_idx - 1' by 1.
     671           0 :              const int max_score = scores[max_idx];
     672           0 :              const uint8_t max_color_order = color_order[max_idx];
     673           0 :              for (int k = max_idx; k > i; --k) {
     674           0 :                  scores[k] = scores[k - 1];
     675           0 :                  color_order[k] = color_order[k - 1];
     676           0 :                  inverse_color_order[color_order[k]] = k;
     677             :              }
     678           0 :              scores[i] = max_score;
     679           0 :              color_order[i] = max_color_order;
     680           0 :              inverse_color_order[color_order[i]] = i;
     681             :          }
     682             :      }
     683             : 
     684           0 :      if (color_idx != NULL)
     685           0 :          *color_idx = inverse_color_order[color_map[r * stride + c]];
     686             : 
     687             :      // Get hash value of context.
     688           0 :      int color_index_ctx_hash = 0;
     689             :      static const int hash_multipliers[NUM_PALETTE_NEIGHBORS] = { 1, 2, 2 };
     690           0 :      for (i = 0; i < NUM_PALETTE_NEIGHBORS; ++i) {
     691           0 :          color_index_ctx_hash += scores[i] * hash_multipliers[i];
     692             :      }
     693           0 :      assert(color_index_ctx_hash > 0);
     694           0 :      assert(color_index_ctx_hash <= MAX_COLOR_CONTEXT_HASH);
     695             : 
     696             :      // Lookup context from hash.
     697           0 :      const int color_index_ctx =
     698             :          palette_color_index_context_lookup[color_index_ctx_hash];
     699           0 :      assert(color_index_ctx >= 0);
     700           0 :      assert(color_index_ctx < PALETTE_COLOR_INDEX_CONTEXTS);
     701           0 :      return color_index_ctx;
     702             :  }
     703             : #undef NUM_PALETTE_NEIGHBORS
     704             : #undef MAX_COLOR_CONTEXT_HASH
     705           0 :  static int cost_and_tokenize_map(Av1ColorMapParam *param, TOKENEXTRA **t,
     706             :      int plane, int calc_rate, int allow_update_cdf,
     707             :      MapCdf map_pb_cdf) {
     708           0 :      const uint8_t *const color_map = param->color_map;
     709           0 :      MapCdf map_cdf = param->map_cdf;
     710           0 :      ColorCost color_cost = param->color_cost;
     711           0 :      const int plane_block_width = param->plane_width;
     712           0 :      const int rows = param->rows;
     713           0 :      const int cols = param->cols;
     714           0 :      const int n = param->n_colors;
     715           0 :      const int palette_size_idx = n - PALETTE_MIN_SIZE;
     716           0 :      int this_rate = 0;
     717             :      uint8_t color_order[PALETTE_MAX_SIZE];
     718             : 
     719             :      (void)plane;
     720             : 
     721           0 :      for (int k = 1; k < rows + cols - 1; ++k) {
     722           0 :          for (int j = AOMMIN(k, cols - 1); j >= AOMMAX(0, k - rows + 1); --j) {
     723           0 :              int i = k - j;
     724             :              int color_new_idx;
     725           0 :              const int color_ctx = av1_get_palette_color_index_context(
     726             :                  color_map, plane_block_width, i, j, n, color_order, &color_new_idx);
     727           0 :              assert(color_new_idx >= 0 && color_new_idx < n);
     728           0 :              if (calc_rate) {
     729           0 :                  this_rate += (*color_cost)[palette_size_idx][color_ctx][color_new_idx];
     730             :              }
     731             :              else {
     732           0 :                  (*t)->token = color_new_idx;
     733           0 :                  (*t)->color_map_cdf = map_pb_cdf[palette_size_idx][color_ctx];
     734           0 :                  ++(*t);
     735           0 :                  if (allow_update_cdf)
     736           0 :                      update_cdf(map_cdf[palette_size_idx][color_ctx], color_new_idx, n);
     737             : #if CONFIG_ENTROPY_STATS
     738             :                  if (plane) {
     739             :                      ++counts->palette_uv_color_index[palette_size_idx][color_ctx]
     740             :                          [color_new_idx];
     741             :                  }
     742             :                  else {
     743             :                      ++counts->palette_y_color_index[palette_size_idx][color_ctx]
     744             :                          [color_new_idx];
     745             :                  }
     746             : #endif
     747             :              }
     748             :          }
     749             :      }
     750           0 :      if (calc_rate) return this_rate;
     751           0 :      return 0;
     752             :  }
     753             : 
     754           0 :  void av1_tokenize_color_map(FRAME_CONTEXT *frameContext,CodingUnit*cu_ptr, int plane,
     755             :      TOKENEXTRA **t, BlockSize bsize, TxSize tx_size,
     756             :      COLOR_MAP_TYPE type, int allow_update_cdf) {
     757           0 :      assert(plane == 0 || plane == 1);
     758             :      Av1ColorMapParam color_map_params;
     759           0 :      get_color_map_params(frameContext, cu_ptr, plane, bsize, tx_size, type, &color_map_params);
     760             :      // The first color index does not use context or entropy.
     761           0 :      (*t)->token = color_map_params.color_map[0];
     762           0 :      (*t)->color_map_cdf = NULL;
     763           0 :      ++(*t);
     764           0 :      MapCdf map_pb_cdf = plane ? frameContext->palette_uv_color_index_cdf
     765           0 :          : frameContext->palette_y_color_index_cdf;
     766           0 :      cost_and_tokenize_map(&color_map_params, t, plane, 0, allow_update_cdf,
     767             :          map_pb_cdf);
     768           0 :  }
     769           0 :  int av1_cost_color_map(PaletteInfo *palette_info, MdRateEstimationContext  *rate_table, CodingUnit*cu_ptr, int plane, BlockSize bsize,
     770             :       COLOR_MAP_TYPE type) {
     771           0 :      assert(plane == 0 || plane == 1);
     772             :      Av1ColorMapParam color_map_params;
     773           0 :      get_color_map_params_rate(palette_info,rate_table, cu_ptr, plane, bsize, type, &color_map_params);
     774           0 :      MapCdf map_pb_cdf = NULL;
     775           0 :      return cost_and_tokenize_map(&color_map_params, NULL, plane, 1, 0,
     776             :          map_pb_cdf);
     777             :  }
     778             : #endif

Generated by: LCOV version 1.14