From 523f1f470c814ba8ecf5f04a712fd74d7842a095 Mon Sep 17 00:00:00 2001 From: Angie Chiang Date: Mon, 11 Mar 2019 18:40:53 -0700 Subject: [PATCH] Add vp9_kmeans() Change-Id: I753920a65fb14a252617444f49feb40dc332d766 --- vp9/encoder/vp9_encodeframe.c | 91 +++++++++++++++++++++++++++++++++++++++++++ vp9/encoder/vp9_encodeframe.h | 3 ++ 2 files changed, 94 insertions(+) diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 8449474..3a526fe 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -5673,6 +5673,97 @@ static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats, } #endif +#define MAX_KMEANS_GROUPS 8 + +typedef struct KMEANS_DATA { + int64_t value; + int pos; + int group_idx; +} KMEANS_DATA; + +static int compare_kmeans_data(const void *a, const void *b) { + if (((const KMEANS_DATA *)a)->value > ((const KMEANS_DATA *)b)->value) { + return 1; + } else if (((const KMEANS_DATA *)a)->value < + ((const KMEANS_DATA *)b)->value) { + return -1; + } else { + return 0; + } +} + +void vp9_kmeans(double *ctr_ls, int k, KMEANS_DATA *arr, int size) { + int64_t min, max; + double step; + int i, j; + int itr; + double boundary_ls[MAX_KMEANS_GROUPS] = { 0 }; + int group_idx; + double sum; + int count; + + vpx_clear_system_state(); + + assert(k >= 2 && k <= MAX_KMEANS_GROUPS); + + qsort(arr, size, sizeof(*arr), compare_kmeans_data); + + min = arr[0].value; + max = arr[size - 1].value; + + // initialize the center points + step = (max - min) * 1. / k; + for (j = 0; j < k; ++j) { + ctr_ls[j] = min + j * step + step / 2; + } + + for (itr = 0; itr < 10; ++itr) { + for (j = 0; j < k - 1; ++j) { + boundary_ls[j] = (ctr_ls[j] + ctr_ls[j + 1]) / 2.; + } + boundary_ls[k - 1] = max + 1; + + group_idx = 0; + count = 0; + sum = 0; + for (i = 0; i < size; ++i) { + while (arr[i].value >= boundary_ls[group_idx]) { + ++group_idx; + if (group_idx == k - 1) { + break; + } + } + + sum += arr[i].value; + ++count; + + if (i + 1 == size || arr[i + 1].value >= boundary_ls[group_idx]) { + if (count > 0) { + ctr_ls[group_idx] = sum / count; + } + count = 0; + sum = 0; + } + } + } + + // compute group_idx + for (j = 0; j < k - 1; ++j) { + boundary_ls[j] = (ctr_ls[j] + ctr_ls[j + 1]) / 2.; + } + boundary_ls[k - 1] = max + 1; + group_idx = 0; + for (i = 0; i < size; ++i) { + while (arr[i].value >= boundary_ls[group_idx]) { + ++group_idx; + if (group_idx == k - 1) { + break; + } + } + arr[i].group_idx = group_idx; + } +} + static void encode_frame_internal(VP9_COMP *cpi) { SPEED_FEATURES *const sf = &cpi->sf; ThreadData *const td = &cpi->td; diff --git a/vp9/encoder/vp9_encodeframe.h b/vp9/encoder/vp9_encodeframe.h index 1798c00..a761ae6 100644 --- a/vp9/encoder/vp9_encodeframe.h +++ b/vp9/encoder/vp9_encodeframe.h @@ -45,6 +45,9 @@ void vp9_encode_sb_row(struct VP9_COMP *cpi, struct ThreadData *td, void vp9_set_variance_partition_thresholds(struct VP9_COMP *cpi, int q, int content_state); +struct KMEANS_DATA; +void vp9_kmeans(double *ctr_ls, int k, struct KMEANS_DATA *arr, int size); + #ifdef __cplusplus } // extern "C" #endif -- 2.7.4