Commit d13c24a5 authored by hui su's avatar hui su Committed by Hui Su

palette-delta-encoding experiment

Transmit palette colors with delta encoding.
Coding gain on scrren_content testset:
overall 0.67%  keyframe 1.37%

Change-Id: I72ce9061dfddf933e9f7530f069955afcb07edf8
parent d8cd55f4
......@@ -616,9 +616,20 @@ static void read_palette_mode_info(AV1_COMMON *const cm, MACROBLOCKD *const xd,
ACCT_STR) +
2;
n = pmi->palette_size[0];
#if CONFIG_PALETTE_DELTA_ENCODING
const int min_bits = cm->bit_depth - 3;
int bits = min_bits + aom_read_literal(r, 2, ACCT_STR);
pmi->palette_colors[0] = aom_read_literal(r, cm->bit_depth, ACCT_STR);
for (i = 1; i < n; ++i) {
pmi->palette_colors[i] = pmi->palette_colors[i - 1] +
aom_read_literal(r, bits, ACCT_STR) + 1;
bits = AOMMIN(
bits, av1_ceil_log2((1 << cm->bit_depth) - pmi->palette_colors[i]));
}
#else
for (i = 0; i < n; ++i)
pmi->palette_colors[i] = aom_read_literal(r, cm->bit_depth, ACCT_STR);
#endif // CONFIG_PALETTE_DELTA_ENCODING
xd->plane[0].color_index_map[0] = read_uniform(r, n);
assert(xd->plane[0].color_index_map[0] < n);
}
......@@ -634,12 +645,50 @@ static void read_palette_mode_info(AV1_COMMON *const cm, MACROBLOCKD *const xd,
ACCT_STR) +
2;
n = pmi->palette_size[1];
#if CONFIG_PALETTE_DELTA_ENCODING
// U channel colors.
const int min_bits_u = cm->bit_depth - 3;
int bits = min_bits_u + aom_read_literal(r, 2, ACCT_STR);
pmi->palette_colors[PALETTE_MAX_SIZE] =
aom_read_literal(r, cm->bit_depth, ACCT_STR);
for (i = 1; i < n; ++i) {
pmi->palette_colors[PALETTE_MAX_SIZE + i] =
pmi->palette_colors[PALETTE_MAX_SIZE + i - 1] +
aom_read_literal(r, bits, ACCT_STR);
bits = AOMMIN(bits,
av1_ceil_log2(1 + (1 << cm->bit_depth) -
pmi->palette_colors[PALETTE_MAX_SIZE + i]));
}
// V channel colors.
if (aom_read_bit(r, ACCT_STR)) { // Delta encoding.
const int min_bits_v = cm->bit_depth - 4;
const int max_val = 1 << cm->bit_depth;
bits = min_bits_v + aom_read_literal(r, 2, ACCT_STR);
pmi->palette_colors[2 * PALETTE_MAX_SIZE] =
aom_read_literal(r, cm->bit_depth, ACCT_STR);
for (i = 1; i < n; ++i) {
int delta = aom_read_literal(r, bits, ACCT_STR);
if (delta && aom_read_bit(r, ACCT_STR)) delta = -delta;
int val =
(int)pmi->palette_colors[2 * PALETTE_MAX_SIZE + i - 1] + delta;
if (val < 0) val += max_val;
if (val >= max_val) val -= max_val;
pmi->palette_colors[2 * PALETTE_MAX_SIZE + i] = val;
}
} else {
for (i = 0; i < n; ++i) {
pmi->palette_colors[2 * PALETTE_MAX_SIZE + i] =
aom_read_literal(r, cm->bit_depth, ACCT_STR);
}
}
#else
for (i = 0; i < n; ++i) {
pmi->palette_colors[PALETTE_MAX_SIZE + i] =
aom_read_literal(r, cm->bit_depth, ACCT_STR);
pmi->palette_colors[2 * PALETTE_MAX_SIZE + i] =
aom_read_literal(r, cm->bit_depth, ACCT_STR);
}
#endif // CONFIG_PALETTE_DELTA_ENCODING
xd->plane[1].color_index_map[0] = read_uniform(r, n);
assert(xd->plane[1].color_index_map[0] < n);
}
......
......@@ -51,6 +51,9 @@
#include "av1/encoder/cost.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/mcomp.h"
#if CONFIG_PALETTE && CONFIG_PALETTE_DELTA_ENCODING
#include "av1/encoder/palette.h"
#endif // CONFIG_PALETTE && CONFIG_PALETTE_DELTA_ENCODING
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
......@@ -1368,6 +1371,82 @@ static void write_mb_interp_filter(AV1_COMP *cpi, const MACROBLOCKD *xd,
}
#if CONFIG_PALETTE
#if CONFIG_PALETTE_DELTA_ENCODING
// Write luma palette color values with delta encoding. Write the first value as
// literal, and the deltas between each value and the previous one. The luma
// palette is sorted so each delta is larger than 0.
static void write_palette_colors_y(const PALETTE_MODE_INFO *const pmi,
int bit_depth, aom_writer *w) {
const int n = pmi->palette_size[0];
int min_bits, i;
int bits = av1_get_palette_delta_bits_y(pmi, bit_depth, &min_bits);
aom_write_literal(w, bits - min_bits, 2);
aom_write_literal(w, pmi->palette_colors[0], bit_depth);
for (i = 1; i < n; ++i) {
aom_write_literal(
w, pmi->palette_colors[i] - pmi->palette_colors[i - 1] - 1, bits);
bits =
AOMMIN(bits, av1_ceil_log2((1 << bit_depth) - pmi->palette_colors[i]));
}
}
// Write chroma palette color values. Use delta encoding for u channel as its
// palette is sorted. For v channel, either use delta encoding or transmit
// raw values directly, whichever costs less.
static void write_palette_colors_uv(const PALETTE_MODE_INFO *const pmi,
int bit_depth, aom_writer *w) {
int i;
const int n = pmi->palette_size[1];
#if CONFIG_HIGHBITDEPTH
const uint16_t *colors_u = pmi->palette_colors + PALETTE_MAX_SIZE;
const uint16_t *colors_v = pmi->palette_colors + 2 * PALETTE_MAX_SIZE;
#else
const uint8_t *colors_u = pmi->palette_colors + PALETTE_MAX_SIZE;
const uint8_t *colors_v = pmi->palette_colors + 2 * PALETTE_MAX_SIZE;
#endif // CONFIG_HIGHBITDEPTH
// U channel colors.
int min_bits_u = 0;
int bits_u = av1_get_palette_delta_bits_u(pmi, bit_depth, &min_bits_u);
aom_write_literal(w, bits_u - min_bits_u, 2);
aom_write_literal(w, colors_u[0], bit_depth);
for (i = 1; i < n; ++i) {
aom_write_literal(w, colors_u[i] - colors_u[i - 1], bits_u);
bits_u = AOMMIN(bits_u, av1_ceil_log2(1 + (1 << bit_depth) - colors_u[i]));
}
// V channel colors.
const int max_val = 1 << bit_depth;
int zero_count = 0, min_bits_v = 0;
int bits_v =
av1_get_palette_delta_bits_v(pmi, bit_depth, &zero_count, &min_bits_v);
const int rate_using_delta =
2 + bit_depth + (bits_v + 1) * (n - 1) - zero_count;
const int rate_using_raw = bit_depth * n;
if (rate_using_delta < rate_using_raw) { // delta encoding
aom_write_bit(w, 1);
aom_write_literal(w, bits_v - min_bits_v, 2);
aom_write_literal(w, colors_v[0], bit_depth);
for (i = 1; i < n; ++i) {
if (colors_v[i] == colors_v[i - 1]) { // No need to signal sign bit.
aom_write_literal(w, 0, bits_v);
continue;
}
const int delta = abs((int)colors_v[i] - colors_v[i - 1]);
const int sign_bit = colors_v[i] < colors_v[i - 1];
if (delta <= max_val - delta) {
aom_write_literal(w, delta, bits_v);
aom_write_bit(w, sign_bit);
} else {
aom_write_literal(w, max_val - delta, bits_v);
aom_write_bit(w, !sign_bit);
}
}
} else { // Transmit raw values.
aom_write_bit(w, 0);
for (i = 0; i < n; ++i) aom_write_literal(w, colors_v[i], bit_depth);
}
}
#endif // CONFIG_PALETTE_DELTA_ENCODING
static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const MODE_INFO *const mi, aom_writer *w) {
const MB_MODE_INFO *const mbmi = &mi->mbmi;
......@@ -1375,7 +1454,6 @@ static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd,
const MODE_INFO *const left_mi = xd->left_mi;
const BLOCK_SIZE bsize = mbmi->sb_type;
const PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
int i;
if (mbmi->mode == DC_PRED) {
const int n = pmi->palette_size[0];
......@@ -1393,8 +1471,13 @@ static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd,
av1_write_token(w, av1_palette_size_tree,
av1_default_palette_y_size_prob[bsize - BLOCK_8X8],
&palette_size_encodings[n - PALETTE_MIN_SIZE]);
#if CONFIG_PALETTE_DELTA_ENCODING
write_palette_colors_y(pmi, cm->bit_depth, w);
#else
int i;
for (i = 0; i < n; ++i)
aom_write_literal(w, pmi->palette_colors[i], cm->bit_depth);
#endif // CONFIG_PALETTE_DELTA_ENCODING
write_uniform(w, n, pmi->palette_first_color_idx[0]);
}
}
......@@ -1407,12 +1490,17 @@ static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd,
av1_write_token(w, av1_palette_size_tree,
av1_default_palette_uv_size_prob[bsize - BLOCK_8X8],
&palette_size_encodings[n - PALETTE_MIN_SIZE]);
#if CONFIG_PALETTE_DELTA_ENCODING
write_palette_colors_uv(pmi, cm->bit_depth, w);
#else
int i;
for (i = 0; i < n; ++i) {
aom_write_literal(w, pmi->palette_colors[PALETTE_MAX_SIZE + i],
cm->bit_depth);
aom_write_literal(w, pmi->palette_colors[2 * PALETTE_MAX_SIZE + i],
cm->bit_depth);
}
#endif // CONFIG_PALETTE_DELTA_ENCODING
write_uniform(w, n, pmi->palette_first_color_idx[1]);
}
}
......
......@@ -11,6 +11,8 @@
#include <math.h>
#include <stdlib.h>
#include "av1/encoder/cost.h"
#include "av1/encoder/palette.h"
static float calc_dist(const float *p1, const float *p2, int dim) {
......@@ -164,6 +166,89 @@ int av1_count_colors(const uint8_t *src, int stride, int rows, int cols) {
return n;
}
#if CONFIG_PALETTE_DELTA_ENCODING
int av1_get_palette_delta_bits_y(const PALETTE_MODE_INFO *const pmi,
int bit_depth, int *min_bits) {
const int n = pmi->palette_size[0];
int max_d = 0, i;
*min_bits = bit_depth - 3;
for (i = 1; i < n; ++i) {
const int delta = pmi->palette_colors[i] - pmi->palette_colors[i - 1];
assert(delta > 0);
if (delta > max_d) max_d = delta;
}
return AOMMAX(av1_ceil_log2(max_d), *min_bits);
}
int av1_get_palette_delta_bits_u(const PALETTE_MODE_INFO *const pmi,
int bit_depth, int *min_bits) {
const int n = pmi->palette_size[1];
int max_d = 0, i;
*min_bits = bit_depth - 3;
for (i = 1; i < n; ++i) {
const int delta = pmi->palette_colors[PALETTE_MAX_SIZE + i] -
pmi->palette_colors[PALETTE_MAX_SIZE + i - 1];
assert(delta >= 0);
if (delta > max_d) max_d = delta;
}
return AOMMAX(av1_ceil_log2(max_d + 1), *min_bits);
}
int av1_get_palette_delta_bits_v(const PALETTE_MODE_INFO *const pmi,
int bit_depth, int *zero_count,
int *min_bits) {
const int n = pmi->palette_size[1];
const int max_val = 1 << bit_depth;
int max_d = 0, i;
*min_bits = bit_depth - 4;
*zero_count = 0;
for (i = 1; i < n; ++i) {
const int delta = pmi->palette_colors[2 * PALETTE_MAX_SIZE + i] -
pmi->palette_colors[2 * PALETTE_MAX_SIZE + i - 1];
const int v = abs(delta);
const int d = AOMMIN(v, max_val - v);
if (d > max_d) max_d = d;
if (d == 0) ++(*zero_count);
}
return AOMMAX(av1_ceil_log2(max_d + 1), *min_bits);
}
#endif // CONFIG_PALETTE_DELTA_ENCODING
int av1_palette_color_cost_y(const PALETTE_MODE_INFO *const pmi,
int bit_depth) {
const int n = pmi->palette_size[0];
#if CONFIG_PALETTE_DELTA_ENCODING
int min_bits = 0;
const int bits = av1_get_palette_delta_bits_y(pmi, bit_depth, &min_bits);
return av1_cost_bit(128, 0) * (2 + bit_depth + bits * (n - 1));
#else
return bit_depth * n * av1_cost_bit(128, 0);
#endif // CONFIG_PALETTE_DELTA_ENCODING
}
int av1_palette_color_cost_uv(const PALETTE_MODE_INFO *const pmi,
int bit_depth) {
const int n = pmi->palette_size[1];
#if CONFIG_PALETTE_DELTA_ENCODING
int cost = 0;
// U channel palette color cost.
int min_bits_u = 0;
const int bits_u = av1_get_palette_delta_bits_u(pmi, bit_depth, &min_bits_u);
cost += av1_cost_bit(128, 0) * (2 + bit_depth + bits_u * (n - 1));
// V channel palette color cost.
int zero_count = 0, min_bits_v = 0;
const int bits_v =
av1_get_palette_delta_bits_v(pmi, bit_depth, &zero_count, &min_bits_v);
const int bits_using_delta =
2 + bit_depth + (bits_v + 1) * (n - 1) - zero_count;
const int bits_using_raw = bit_depth * n;
cost += av1_cost_bit(128, 0) * (1 + AOMMIN(bits_using_delta, bits_using_raw));
return cost;
#else
return 2 * bit_depth * n * av1_cost_bit(128, 0);
#endif // CONFIG_PALETTE_DELTA_ENCODING
}
#if CONFIG_HIGHBITDEPTH
int av1_count_colors_highbd(const uint8_t *src8, int stride, int rows, int cols,
int bit_depth) {
......
......@@ -44,6 +44,28 @@ int av1_count_colors_highbd(const uint8_t *src8, int stride, int rows, int cols,
int bit_depth);
#endif // CONFIG_HIGHBITDEPTH
#if CONFIG_PALETTE_DELTA_ENCODING
// Return the number of bits used to transmit each luma palette color delta.
int av1_get_palette_delta_bits_y(const PALETTE_MODE_INFO *const pmi,
int bit_depth, int *min_bits);
// Return the number of bits used to transmit each U palette color delta.
int av1_get_palette_delta_bits_u(const PALETTE_MODE_INFO *const pmi,
int bit_depth, int *min_bits);
// Return the number of bits used to transmit each v palette color delta;
// assign zero_count with the number of deltas being 0.
int av1_get_palette_delta_bits_v(const PALETTE_MODE_INFO *const pmi,
int bit_depth, int *zero_count, int *min_bits);
#endif // CONFIG_PALETTE_DELTA_ENCODING
// Return the rate cost for transmitting luma palette color values.
int av1_palette_color_cost_y(const PALETTE_MODE_INFO *const pmi, int bit_depth);
// Return the rate cost for transmitting chroma palette color values.
int av1_palette_color_cost_uv(const PALETTE_MODE_INFO *const pmi,
int bit_depth);
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -2541,12 +2541,13 @@ static int rd_pick_palette_intra_sby(const AV1_COMP *const cpi, MACROBLOCK *x,
extend_palette_color_map(color_map, cols, rows, block_width,
block_height);
palette_mode_cost =
dc_mode_cost + cpi->common.bit_depth * k * av1_cost_bit(128, 0) +
dc_mode_cost +
cpi->palette_y_size_cost[bsize - BLOCK_8X8][k - PALETTE_MIN_SIZE] +
write_uniform_cost(k, color_map[0]) +
av1_cost_bit(
av1_default_palette_y_mode_prob[bsize - BLOCK_8X8][palette_ctx],
1);
palette_mode_cost += av1_palette_color_cost_y(pmi, cpi->common.bit_depth);
for (i = 0; i < rows; ++i) {
for (j = (i == 0 ? 1 : 0); j < cols; ++j) {
int color_idx;
......@@ -4585,6 +4586,22 @@ static void rd_pick_palette_intra_sbuv(const AV1_COMP *const cpi, MACROBLOCK *x,
centroids[i * 2 + 1] = lb_v + (2 * i + 1) * (ub_v - lb_v) / n / 2;
}
av1_k_means(data, centroids, color_map, rows * cols, n, 2, max_itr);
#if CONFIG_PALETTE_DELTA_ENCODING
// Sort the U channel colors in ascending order.
for (i = 0; i < 2 * (n - 1); i += 2) {
int min_idx = i;
float min_val = centroids[i];
for (j = i + 2; j < 2 * n; j += 2)
if (centroids[j] < min_val) min_val = centroids[j], min_idx = j;
if (min_idx != i) {
float temp_u = centroids[i], temp_v = centroids[i + 1];
centroids[i] = centroids[min_idx];
centroids[i + 1] = centroids[min_idx + 1];
centroids[min_idx] = temp_u, centroids[min_idx + 1] = temp_v;
}
}
av1_calc_indices(data, centroids, color_map, rows * cols, n, 2);
#endif // CONFIG_PALETTE_DELTA_ENCODING
extend_palette_color_map(color_map, cols, rows, plane_block_width,
plane_block_height);
pmi->palette_size[1] = n;
......@@ -4605,12 +4622,11 @@ static void rd_pick_palette_intra_sbuv(const AV1_COMP *const cpi, MACROBLOCK *x,
if (tokenonly_rd_stats.rate == INT_MAX) continue;
this_rate =
tokenonly_rd_stats.rate + dc_mode_cost +
2 * cpi->common.bit_depth * n * av1_cost_bit(128, 0) +
cpi->palette_uv_size_cost[bsize - BLOCK_8X8][n - PALETTE_MIN_SIZE] +
write_uniform_cost(n, color_map[0]) +
av1_cost_bit(
av1_default_palette_uv_mode_prob[pmi->palette_size[0] > 0], 1);
this_rate += av1_palette_color_cost_uv(pmi, cpi->common.bit_depth);
for (i = 0; i < rows; ++i) {
for (j = (i == 0 ? 1 : 0); j < cols; ++j) {
int color_idx;
......
......@@ -285,6 +285,7 @@ EXPERIMENT_LIST="
bitstream_debug
alt_intra
palette
palette_delta_encoding
daala_ec
rawbits
ec_smallmul
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment