Palette-based coding experiment
Added palette coding option for Y channel only, key frame only. Palette colors are obtained with k-means clustering algorithm. Run-length coding is used to compress the color indices. On screen_content: --enable-palette + 5.75% --enable-palette --enable-tx_skip +15.04% (was 13.3%) On derflr: --enable-palette - 0.03% with all the other expriments + 5.95% (was 5.98%) Change-Id: I6d1cf45c889be764d14083170fdf14a424bd31b5
This commit is contained in:
1
configure
vendored
1
configure
vendored
@@ -292,6 +292,7 @@ EXPERIMENT_LIST="
|
||||
wedge_partition
|
||||
compound_modes
|
||||
global_motion
|
||||
palette
|
||||
"
|
||||
CONFIG_LIST="
|
||||
external_build
|
||||
|
||||
@@ -34,6 +34,13 @@ extern "C" {
|
||||
#define COPY_MODE_CONTEXTS 5
|
||||
#endif // CONFIG_COPY_MODE
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
#define PALETTE_BUF_SIZE 16
|
||||
#define PALETTE_MAX_SIZE 8
|
||||
#define PALETTE_DELTA_BIT 0
|
||||
#define PALETTE_MAX_RUNS 128
|
||||
#endif // CONFIG_PALETTE
|
||||
|
||||
/* Segment Feature Masks */
|
||||
#define MAX_MV_REF_CANDIDATES 2
|
||||
|
||||
@@ -101,6 +108,16 @@ typedef enum {
|
||||
} COPY_MODE;
|
||||
#endif // CONFIG_COPY_MODE
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
typedef enum {
|
||||
H_SCAN,
|
||||
V_SCAN,
|
||||
SPIN_SCAN,
|
||||
ZZ_SCAN,
|
||||
PALETTE_SCAN_ORDERS
|
||||
} PALETTE_SCAN_ORDER;
|
||||
#endif
|
||||
|
||||
static INLINE int is_inter_mode(PREDICTION_MODE mode) {
|
||||
return mode >= NEARESTMV && mode <= NEWMV;
|
||||
}
|
||||
@@ -181,7 +198,7 @@ typedef struct {
|
||||
#if CONFIG_TX_SKIP
|
||||
int tx_skip[PLANE_TYPES];
|
||||
int tx_skip_shift;
|
||||
#endif
|
||||
#endif // CONFIG_TX_SKIP
|
||||
#if CONFIG_COPY_MODE
|
||||
COPY_MODE copy_mode;
|
||||
int inter_ref_count;
|
||||
@@ -199,6 +216,21 @@ typedef struct {
|
||||
int use_wedge_interinter;
|
||||
int interinter_wedge_index;
|
||||
#endif // CONFIG_WEDGE_PARTITION
|
||||
#if CONFIG_PALETTE
|
||||
int palette_enabled;
|
||||
int palette_size;
|
||||
int palette_indexed_size;
|
||||
int palette_literal_size;
|
||||
int palette_run_length;
|
||||
int current_palette_size;
|
||||
int palette_delta_bitdepth;
|
||||
uint8_t palette_colors[PALETTE_MAX_SIZE];
|
||||
uint8_t palette_indexed_colors[PALETTE_MAX_SIZE];
|
||||
int8_t palette_color_delta[PALETTE_MAX_SIZE];
|
||||
uint8_t palette_literal_colors[PALETTE_MAX_SIZE];
|
||||
uint16_t palette_runs[PALETTE_MAX_RUNS];
|
||||
PALETTE_SCAN_ORDER palette_scan_order;
|
||||
#endif // CONFIG_PALETTE
|
||||
} MB_MODE_INFO;
|
||||
|
||||
typedef struct MODE_INFO {
|
||||
@@ -260,6 +292,9 @@ struct macroblockd_plane {
|
||||
const int16_t *dequant;
|
||||
ENTROPY_CONTEXT *above_context;
|
||||
ENTROPY_CONTEXT *left_context;
|
||||
#if CONFIG_PALETTE
|
||||
uint8_t *color_index_map;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define BLOCK_OFFSET(x, i) ((x) + (i) * 16)
|
||||
@@ -308,6 +343,9 @@ typedef struct macroblockd {
|
||||
int corrupted;
|
||||
|
||||
DECLARE_ALIGNED(16, tran_low_t, dqcoeff[MAX_MB_PLANE][64 * 64]);
|
||||
#if CONFIG_PALETTE
|
||||
DECLARE_ALIGNED(16, uint8_t, color_index_map[64 * 64]);
|
||||
#endif
|
||||
|
||||
ENTROPY_CONTEXT *above_context[MAX_MB_PLANE];
|
||||
ENTROPY_CONTEXT left_context[MAX_MB_PLANE][16];
|
||||
|
||||
@@ -363,6 +363,54 @@ static const vp9_prob default_ext_tx_prob[3][EXT_TX_TYPES - 1] = {
|
||||
};
|
||||
#endif // CONFIG_EXT_TX
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
const vp9_tree_index vp9_palette_size_tree[TREE_SIZE(PALETTE_SIZES)] = {
|
||||
-TWO_COLORS, 2,
|
||||
-THREE_COLORS, 4,
|
||||
-FOUR_COLORS, 6,
|
||||
-FIVE_COLORS, 8,
|
||||
-SIX_COLORS, 10,
|
||||
-SEVEN_COLORS, -EIGHT_COLORS
|
||||
};
|
||||
|
||||
const vp9_tree_index vp9_palette_run_length_tree[TREE_SIZE(PALETTE_RUN_LENGTHS)]
|
||||
= {
|
||||
-ONE_BITS, 2,
|
||||
-TWO_BITS, 4,
|
||||
-THREE_BITS, 6,
|
||||
-FOUR_BITS, 8,
|
||||
-FIVE_BITS, 10,
|
||||
-SIX_BITS, -MAX_BITS
|
||||
};
|
||||
|
||||
static const vp9_prob default_palette_size_prob[10][PALETTE_SIZES - 1] = {
|
||||
{ 54, 82, 96, 100, 117, 139},
|
||||
{ 11, 10, 30, 20, 45, 82},
|
||||
{ 11, 10, 30, 20, 45, 82},
|
||||
{ 16, 13, 29, 9, 34, 93},
|
||||
{ 128, 40, 50, 46, 62, 77},
|
||||
{ 128, 40, 50, 46, 62, 77},
|
||||
{ 92, 177, 193, 78, 28, 40},
|
||||
{ 160, 30, 228, 64, 105, 180},
|
||||
{ 160, 30, 228, 64, 105, 180},
|
||||
{ 32, 84, 227, 45, 12, 232},
|
||||
};
|
||||
|
||||
static const vp9_prob
|
||||
default_palette_run_length_prob[10][PALETTE_RUN_LENGTHS - 1] = {
|
||||
{ 10, 91, 148, 95, 121, 254},
|
||||
{ 170, 70, 110, 125, 120, 130},
|
||||
{ 170, 70, 110, 125, 120, 130},
|
||||
{ 153, 33, 43, 147, 60, 67},
|
||||
{ 90, 18, 21, 75, 85, 65},
|
||||
{ 90, 18, 21, 75, 85, 65},
|
||||
{ 44, 38, 17, 30, 125, 18},
|
||||
{ 30, 12, 14, 18, 75, 75},
|
||||
{ 30, 12, 14, 18, 75, 75},
|
||||
{ 72, 34, 32, 42, 42, 108},
|
||||
};
|
||||
#endif // CONFIG_PALETTE
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
static const vp9_prob default_supertx_prob[PARTITION_SUPERTX_CONTEXTS]
|
||||
[TX_SIZES] = {
|
||||
@@ -493,6 +541,10 @@ void vp9_init_mode_probs(FRAME_CONTEXT *fc) {
|
||||
#if CONFIG_EXT_TX
|
||||
vp9_copy(fc->ext_tx_prob, default_ext_tx_prob);
|
||||
#endif // CONFIG_EXT_TX
|
||||
#if CONFIG_PALETTE
|
||||
vp9_copy(fc->palette_size_prob, default_palette_size_prob);
|
||||
vp9_copy(fc->palette_run_length_prob, default_palette_run_length_prob);
|
||||
#endif // CONFIG_PALETTE
|
||||
#if CONFIG_SUPERTX
|
||||
vp9_copy(fc->supertx_prob, default_supertx_prob);
|
||||
#endif // CONFIG_SUPERTX
|
||||
|
||||
@@ -66,6 +66,10 @@ typedef struct frame_contexts {
|
||||
#if CONFIG_EXT_TX
|
||||
vp9_prob ext_tx_prob[3][EXT_TX_TYPES - 1];
|
||||
#endif // CONFIG_EXT_TX
|
||||
#if CONFIG_PALETTE
|
||||
vp9_prob palette_size_prob[10][PALETTE_SIZES - 1];
|
||||
vp9_prob palette_run_length_prob[10][PALETTE_RUN_LENGTHS - 1];
|
||||
#endif // CONFIG_PALETTE
|
||||
#if CONFIG_SUPERTX
|
||||
vp9_prob supertx_prob[PARTITION_SUPERTX_CONTEXTS][TX_SIZES];
|
||||
#endif // CONFIG_SUPERTX
|
||||
@@ -152,6 +156,11 @@ extern const vp9_tree_index vp9_switchable_interp_tree
|
||||
#if CONFIG_EXT_TX
|
||||
extern const vp9_tree_index vp9_ext_tx_tree[TREE_SIZE(EXT_TX_TYPES)];
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
extern const vp9_tree_index vp9_palette_size_tree[TREE_SIZE(PALETTE_SIZES)];
|
||||
extern const vp9_tree_index
|
||||
vp9_palette_run_length_tree[TREE_SIZE(PALETTE_RUN_LENGTHS)];
|
||||
#endif
|
||||
#if CONFIG_COPY_MODE
|
||||
extern const vp9_tree_index vp9_copy_mode_tree_l2[TREE_SIZE(2)];
|
||||
extern const vp9_tree_index vp9_copy_mode_tree[TREE_SIZE(COPY_MODE_COUNT - 1)];
|
||||
|
||||
@@ -127,6 +127,30 @@ typedef enum {
|
||||
} EXT_TX_TYPE;
|
||||
#endif
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
typedef enum {
|
||||
TWO_COLORS,
|
||||
THREE_COLORS,
|
||||
FOUR_COLORS,
|
||||
FIVE_COLORS,
|
||||
SIX_COLORS,
|
||||
SEVEN_COLORS,
|
||||
EIGHT_COLORS,
|
||||
PALETTE_SIZES
|
||||
} PALETTE_SIZE;
|
||||
|
||||
typedef enum {
|
||||
ONE_BITS,
|
||||
TWO_BITS,
|
||||
THREE_BITS,
|
||||
FOUR_BITS,
|
||||
FIVE_BITS,
|
||||
SIX_BITS,
|
||||
MAX_BITS,
|
||||
PALETTE_RUN_LENGTHS
|
||||
} PALETTE_RUN_LENGTH;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN = 0,
|
||||
BT_601 = 1, // YUV
|
||||
|
||||
@@ -200,6 +200,15 @@ typedef struct VP9Common {
|
||||
|
||||
PARTITION_CONTEXT *above_seg_context;
|
||||
ENTROPY_CONTEXT *above_context;
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
uint8_t current_palette_colors[PALETTE_BUF_SIZE];
|
||||
int current_palette_size;
|
||||
int current_palette_count[PALETTE_BUF_SIZE];
|
||||
int allow_palette_mode;
|
||||
int palette_counter;
|
||||
int block_counter;
|
||||
#endif
|
||||
} VP9_COMMON;
|
||||
|
||||
static INLINE YV12_BUFFER_CONFIG *get_ref_frame(VP9_COMMON *cm, int index) {
|
||||
@@ -250,6 +259,10 @@ static INLINE void init_macroblockd(VP9_COMMON *cm, MACROBLOCKD *xd) {
|
||||
i * sizeof(*cm->above_context) * 2 * mi_cols_aligned_to_sb(cm->mi_cols);
|
||||
}
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
xd->plane[0].color_index_map = xd->color_index_map;
|
||||
#endif
|
||||
|
||||
xd->above_seg_context = cm->above_seg_context;
|
||||
xd->mi_stride = cm->mi_stride;
|
||||
}
|
||||
|
||||
396
vp9/common/vp9_palette.c
Normal file
396
vp9/common/vp9_palette.c
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "vp9/common/vp9_palette.h"
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
void insertion_sort(double *data, int n) {
|
||||
int i, j, k;
|
||||
double val;
|
||||
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
val = data[i];
|
||||
j = 0;
|
||||
while (val > data[j] && j < i)
|
||||
j++;
|
||||
|
||||
if (j == i)
|
||||
continue;
|
||||
|
||||
for (k = i; k > j; k--)
|
||||
data[k] = data[k - 1];
|
||||
data[j] = val;
|
||||
}
|
||||
}
|
||||
|
||||
int count_colors(const uint8_t *src, int stride, int rows, int cols) {
|
||||
int n = 0, r, c, i, val_count[256];
|
||||
uint8_t val;
|
||||
memset(val_count, 0, sizeof(val_count));
|
||||
|
||||
for (r = 0; r < rows; r++) {
|
||||
for (c = 0; c < cols; c++) {
|
||||
val = src[r * stride + c];
|
||||
val_count[val]++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (val_count[i]) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int run_lengh_encoding(uint8_t *seq, int n, uint16_t *runs, int max_run) {
|
||||
int this_run, i, l = 0;
|
||||
uint8_t symbol;
|
||||
|
||||
for (i = 0; i < n; ) {
|
||||
if ((l + 2) > (2 * max_run - 1))
|
||||
return 0;
|
||||
|
||||
symbol = seq[i];
|
||||
runs[l++] = symbol;
|
||||
this_run = 1;
|
||||
i++;
|
||||
while (seq[i] == symbol && i < n) {
|
||||
i++;
|
||||
this_run++;
|
||||
}
|
||||
runs[l++] = this_run;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
int run_lengh_decoding(uint16_t *runs, int l, uint8_t *seq) {
|
||||
int i, j = 0;
|
||||
|
||||
for (i = 0; i < l; i += 2) {
|
||||
memset(seq + j, runs[i], runs[i + 1]);
|
||||
j += runs[i + 1];
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
void transpose_block(uint8_t *seq_in, uint8_t *seq_out, int rows, int cols) {
|
||||
int r, c;
|
||||
uint8_t seq_dup[4096];
|
||||
memcpy(seq_dup, seq_in, rows * cols);
|
||||
|
||||
for (r = 0; r < cols; r++) {
|
||||
for (c = 0; c < rows; c++) {
|
||||
seq_out[r * rows + c] = seq_dup[c * cols + r];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void palette_color_insertion(uint8_t *old_colors, int *m, int *count,
|
||||
MB_MODE_INFO *mbmi) {
|
||||
int k = *m, n = mbmi->palette_literal_size;
|
||||
int i, j, l, idx, min_idx = -1;
|
||||
uint8_t *new_colors = mbmi->palette_literal_colors;
|
||||
uint8_t val;
|
||||
|
||||
if (mbmi->palette_indexed_size > 0) {
|
||||
for (i = 0; i < mbmi->palette_indexed_size; i++)
|
||||
count[mbmi->palette_indexed_colors[i]] +=
|
||||
(8 - abs(mbmi->palette_color_delta[i]));
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < k) {
|
||||
count[i] -= 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (n <= 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
val = new_colors[i];
|
||||
j = 0;
|
||||
while (val > old_colors[j] && j < k)
|
||||
j++;
|
||||
if (j < k && val == old_colors[j]) {
|
||||
count[j] += 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
idx = j;
|
||||
k++;
|
||||
if (k > PALETTE_BUF_SIZE) {
|
||||
k--;
|
||||
min_idx = 0;
|
||||
for (l = 1; l < k; l++) {
|
||||
if (count[l] < count[min_idx])
|
||||
min_idx = l;
|
||||
}
|
||||
|
||||
l = min_idx;
|
||||
while (l < k - 1) {
|
||||
old_colors[l] = old_colors[l + 1];
|
||||
count[l] = count[l + 1];
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
if (min_idx < 0 || idx <= min_idx)
|
||||
j = idx;
|
||||
else
|
||||
j = idx - 1;
|
||||
|
||||
if (j == k - 1) {
|
||||
old_colors[k - 1] = val;
|
||||
count[k - 1] = 8;
|
||||
} else {
|
||||
for (l = k - 1; l > j; l--) {
|
||||
old_colors[l] = old_colors[l - 1];
|
||||
count[l] = count[l - 1];
|
||||
}
|
||||
old_colors[j] = val;
|
||||
count[j] = 8;
|
||||
}
|
||||
}
|
||||
*m = k;
|
||||
}
|
||||
|
||||
int palette_color_lookup(uint8_t *dic, int n, uint8_t val, int bits) {
|
||||
int j, min, arg_min = 0, i = 1;
|
||||
|
||||
if (n < 1)
|
||||
return -1;
|
||||
|
||||
min = abs(val - dic[0]);
|
||||
arg_min = 0;
|
||||
while (i < n) {
|
||||
j = abs(val - dic[i]);
|
||||
if (j < min) {
|
||||
min = j;
|
||||
arg_min = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (min < (1 << bits))
|
||||
return arg_min;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int get_bit_depth(int n) {
|
||||
int i = 1, p = 2;
|
||||
while (p < n) {
|
||||
i++;
|
||||
p = p << 1;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int palette_max_run(BLOCK_SIZE bsize) {
|
||||
int table[BLOCK_SIZES] = {
|
||||
16, 16, 16, 32, // BLOCK_4X4, BLOCK_4X8, BLOCK_8X4, BLOCK_8X8
|
||||
64, 64, 64, 64, // BLOCK_8X16, BLOCK_16X8, BLOCK_16X16, BLOCK_16X32
|
||||
64, 64, 64, 64, // BLOCK_32X16, BLOCK_32X32, BLOCK_32X64, BLOCK_64X32
|
||||
64 // BLOCK_64X64
|
||||
};
|
||||
|
||||
return table[bsize];
|
||||
}
|
||||
|
||||
double calc_dist(double *p1, double *p2, int dim) {
|
||||
double dist = 0;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < dim; i++) {
|
||||
dist = dist + (p1[i] - p2[i]) * (p1[i] - p2[i]);
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
void calc_indices(double *data, double *centroids, int *indices,
|
||||
int n, int k, int dim) {
|
||||
int i, j;
|
||||
double min_dist, this_dist;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
min_dist = calc_dist(data + i * dim, centroids, dim);
|
||||
indices[i] = 0;
|
||||
for (j = 0; j < k; j++) {
|
||||
this_dist = calc_dist(data + i * dim, centroids + j * dim, dim);
|
||||
if (this_dist < min_dist) {
|
||||
min_dist = this_dist;
|
||||
indices[i] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void calc_centroids(double *data, double *centroids, int *indices,
|
||||
int n, int k, int dim) {
|
||||
int i, j, index;
|
||||
int count[256];
|
||||
unsigned int seed = time(NULL);
|
||||
memset(count, 0, sizeof(count[0]) * k);
|
||||
memset(centroids, 0, sizeof(centroids[0]) * k * dim);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
index = indices[i];
|
||||
count[index]++;
|
||||
for (j = 0; j < dim; j++) {
|
||||
centroids[index * dim + j] += data[i * dim + j];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < k; i++) {
|
||||
if (!count[i])
|
||||
memcpy(centroids + i * dim, data + (rand_r(&seed) % n) * dim,
|
||||
sizeof(centroids[0]) * dim);
|
||||
else
|
||||
for (j = 0; j < dim; j++)
|
||||
centroids[i * dim + j] /= count[i];
|
||||
}
|
||||
}
|
||||
|
||||
double calc_total_dist(double *data, double *centroids, int *indices,
|
||||
int n, int k, int dim) {
|
||||
double dist = 0;
|
||||
int i;
|
||||
(void) k;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
dist += calc_dist(data + i * dim, centroids + indices[i] * dim, dim);
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
int k_means(double *data, double *centroids, int *indices,
|
||||
int n, int k, int dim, int max_itr) {
|
||||
int i = 0;
|
||||
int pre_indices[4096];
|
||||
double pre_total_dist, cur_total_dist;
|
||||
double pre_centroids[256];
|
||||
|
||||
calc_indices(data, centroids, indices, n, k, dim);
|
||||
pre_total_dist = calc_total_dist(data, centroids, indices, n, k, dim);
|
||||
memcpy(pre_centroids, centroids, sizeof(pre_centroids[0]) * k * dim);
|
||||
memcpy(pre_indices, indices, sizeof(pre_indices[0]) * n);
|
||||
while (i < max_itr) {
|
||||
calc_centroids(data, centroids, indices, n, k, dim);
|
||||
calc_indices(data, centroids, indices, n, k, dim);
|
||||
cur_total_dist = calc_total_dist(data, centroids, indices, n, k, dim);
|
||||
|
||||
if (cur_total_dist > pre_total_dist && 0) {
|
||||
memcpy(centroids, pre_centroids, sizeof(pre_centroids[0]) * k * dim);
|
||||
memcpy(indices, pre_indices, sizeof(pre_indices[0]) * n);
|
||||
break;
|
||||
}
|
||||
if (!memcmp(centroids, pre_centroids, sizeof(pre_centroids[0]) * k * dim))
|
||||
break;
|
||||
|
||||
memcpy(pre_centroids, centroids, sizeof(pre_centroids[0]) * k * dim);
|
||||
memcpy(pre_indices, indices, sizeof(pre_indices[0]) * n);
|
||||
pre_total_dist = cur_total_dist;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int is_in_boundary(int rows, int cols, int r, int c) {
|
||||
if (r < 0 || r >= rows || c < 0 || c >= cols)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void zz_scan_order(int *order, int rows, int cols) {
|
||||
int r, c, dir, idx;
|
||||
|
||||
memset(order, 0, sizeof(order[0]) * rows * cols);
|
||||
r = 0;
|
||||
c = 0;
|
||||
dir = 1;
|
||||
idx = 0;
|
||||
while (r != (rows - 1) || c != (cols - 1)) {
|
||||
order[idx++] = r * cols + c;
|
||||
if (dir == -1) {
|
||||
if (is_in_boundary(rows, cols, r + 1, c - 1)) {
|
||||
r = r + 1;
|
||||
c = c - 1;
|
||||
} else if (is_in_boundary(rows, cols, r + 1, c)) {
|
||||
r = r + 1;
|
||||
dir *= -1;
|
||||
} else if (is_in_boundary(rows, cols, r, c + 1)) {
|
||||
c = c + 1;
|
||||
dir *= -1;
|
||||
}
|
||||
} else {
|
||||
if (is_in_boundary(rows, cols, r - 1, c + 1)) {
|
||||
r = r - 1;
|
||||
c = c + 1;
|
||||
} else if (is_in_boundary(rows, cols, r, c + 1)) {
|
||||
c = c + 1;
|
||||
dir *= -1;
|
||||
} else if (is_in_boundary(rows, cols, r + 1, c)) {
|
||||
r = r + 1;
|
||||
dir *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
order[idx] = (rows - 1) * cols + cols - 1;
|
||||
}
|
||||
|
||||
void spin_order(int *order, int cols, int r_start, int c_start,
|
||||
int h, int w, int idx) {
|
||||
int r, c;
|
||||
|
||||
if (h <= 0 && w <= 0) {
|
||||
return;
|
||||
} else if (h <= 0) {
|
||||
for (c = 0; c < w; c++)
|
||||
order[idx++] = r_start * cols + c + c_start;
|
||||
return;
|
||||
} else if (w <= 0) {
|
||||
for (r = 0; r < h; r++)
|
||||
order[idx++] = (r + r_start) * cols;
|
||||
return;
|
||||
}
|
||||
|
||||
for (r = 0; r < h; r++)
|
||||
order[idx++] = (r + r_start) * cols + c_start;
|
||||
|
||||
for (c = 0; c < w; c++)
|
||||
order[idx++] = (h + r_start) * cols + c + c_start;
|
||||
|
||||
for (r = 0; r < h; r++)
|
||||
order[idx++] = (h - r + r_start) * cols + w + c_start;
|
||||
|
||||
for (c = 0; c < w; c++)
|
||||
order[idx++] = r_start * cols + w - c + c_start;
|
||||
|
||||
spin_order(order, cols, r_start + 1, c_start + 1, h - 2, w - 2, idx);
|
||||
}
|
||||
|
||||
void spin_scan_order(int *order, int rows, int cols) {
|
||||
spin_order(order, cols, 0, 0, rows - 1, cols - 1, 0);
|
||||
}
|
||||
#endif
|
||||
35
vp9/common/vp9_palette.h
Normal file
35
vp9/common/vp9_palette.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef VP9_COMMON_VP9_PALETTE_H_
|
||||
#define VP9_COMMON_VP9_PALETTE_H_
|
||||
|
||||
#include "vp9/common/vp9_blockd.h"
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
int count_colors(const uint8_t *src, int stride, int rows, int cols);
|
||||
void insertion_sort(double *data, int n);
|
||||
int run_lengh_encoding(uint8_t *seq, int n, uint16_t *runs, int max_run);
|
||||
int run_lengh_decoding(uint16_t *runs, int l, uint8_t *seq);
|
||||
void transpose_block(uint8_t *seq_in, uint8_t *seq_out, int rows, int cols);
|
||||
void palette_color_insertion(uint8_t *old_colors, int *m, int *count,
|
||||
MB_MODE_INFO *mbmi);
|
||||
int palette_color_lookup(uint8_t *dic, int n, uint8_t val, int bits);
|
||||
int palette_max_run(BLOCK_SIZE bsize);
|
||||
int get_bit_depth(int n);
|
||||
int k_means(double *data, double *centroids, int *indices,
|
||||
int n, int k, int dim, int max_itr);
|
||||
void calc_indices(double *data, double *centroids, int *indices,
|
||||
int n, int k, int dim);
|
||||
void zz_scan_order(int *order, int rows, int cols);
|
||||
void spin_scan_order(int *order, int rows, int cols);
|
||||
#endif
|
||||
|
||||
#endif // VP9_COMMON_VP9_PALETTE_H_
|
||||
@@ -1155,7 +1155,7 @@ void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
|
||||
#if CONFIG_FILTERINTRA
|
||||
int filterbit,
|
||||
#endif
|
||||
const uint8_t *ref, int ref_stride,
|
||||
const uint8_t *ref, int ref_stride,
|
||||
uint8_t *dst, int dst_stride,
|
||||
int aoff, int loff, int plane) {
|
||||
const int bwl = bwl_in - tx_size;
|
||||
@@ -1168,7 +1168,7 @@ void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
|
||||
#if CONFIG_FILTERINTRA
|
||||
const int filterflag = is_filter_allowed(mode) && is_filter_enabled(tx_size)
|
||||
&& filterbit;
|
||||
#endif
|
||||
#endif // CONFIG_FILTERINTRA
|
||||
|
||||
assert(bwl >= 0);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
@@ -1181,7 +1181,22 @@ void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
|
||||
#endif
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (!filterflag) {
|
||||
#endif
|
||||
#endif // CONFIG_FILTERINTRA
|
||||
#if CONFIG_PALETTE
|
||||
if (xd->mi[0].src_mi->mbmi.palette_enabled && !plane) {
|
||||
uint8_t *palette = xd->mi[0].src_mi->mbmi.palette_colors;
|
||||
int bs = 4 * (1 << tx_size);
|
||||
uint8_t *map = xd->plane[0].color_index_map;
|
||||
int r, c, stride = 4 * (1 << bwl_in);
|
||||
|
||||
for (r = 0; r < bs; r++) {
|
||||
for (c = 0; c < bs; c++) {
|
||||
dst[r * dst_stride + c] = palette[map[(r + y) * stride + c + x]];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif // CONFIG_PALETTE
|
||||
build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode, tx_size,
|
||||
have_top, have_left, have_right, x, y, plane);
|
||||
#if CONFIG_FILTERINTRA
|
||||
|
||||
@@ -2296,6 +2296,10 @@ static int read_compressed_header(VP9Decoder *pbi, const uint8_t *data,
|
||||
}
|
||||
#endif // CONFIG_WEDGE_PARTITION
|
||||
}
|
||||
#if CONFIG_PALETTE
|
||||
if (frame_is_intra_only(cm))
|
||||
cm->allow_palette_mode = vp9_read_bit(&r);
|
||||
#endif
|
||||
|
||||
return vp9_reader_has_error(&r);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include "vp9/common/vp9_entropymode.h"
|
||||
#include "vp9/common/vp9_entropymv.h"
|
||||
#include "vp9/common/vp9_mvref_common.h"
|
||||
#if CONFIG_PALETTE
|
||||
#include "vp9/common/vp9_palette.h"
|
||||
#endif
|
||||
#include "vp9/common/vp9_pred_common.h"
|
||||
#include "vp9/common/vp9_reconinter.h"
|
||||
#include "vp9/common/vp9_seg_common.h"
|
||||
@@ -219,7 +222,139 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm,
|
||||
|
||||
mbmi->segment_id = read_intra_segment_id(cm, xd, mi_row, mi_col, r);
|
||||
mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
|
||||
#if CONFIG_PALETTE
|
||||
if (bsize >= BLOCK_8X8 && cm->allow_palette_mode)
|
||||
mbmi->palette_enabled = vp9_read_bit(r);
|
||||
else
|
||||
mbmi->palette_enabled = 0;
|
||||
if (mbmi->palette_enabled) {
|
||||
int i, j, k;
|
||||
int m1, m2, d;
|
||||
int rows = 4 * num_4x4_blocks_high_lookup[bsize];
|
||||
int cols = 4 * num_4x4_blocks_wide_lookup[bsize];
|
||||
int c1, c2;
|
||||
int scan_order[4096];
|
||||
uint8_t map[4096];
|
||||
PALETTE_RUN_LENGTH bits;
|
||||
|
||||
mbmi->mode = DC_PRED;
|
||||
mbmi->palette_size =
|
||||
vp9_read_tree(r, vp9_palette_size_tree,
|
||||
cm->fc.palette_size_prob[bsize - BLOCK_8X8]);
|
||||
mbmi->palette_size += 2;
|
||||
mbmi->palette_indexed_size =
|
||||
vp9_decode_uniform(r, MIN(mbmi->palette_size + 1, 8));
|
||||
mbmi->palette_literal_size = mbmi->palette_size -
|
||||
mbmi->palette_indexed_size;
|
||||
|
||||
if (PALETTE_DELTA_BIT)
|
||||
mbmi->palette_delta_bitdepth =
|
||||
vp9_read_literal(r, PALETTE_DELTA_BIT);
|
||||
else
|
||||
mbmi->palette_delta_bitdepth = 0;
|
||||
|
||||
mbmi->palette_run_length =
|
||||
vp9_read_literal(r, get_bit_depth(palette_max_run(bsize)));
|
||||
mbmi->palette_run_length = (mbmi->palette_run_length) << 1;
|
||||
mbmi->palette_scan_order = vp9_read_literal(r, 2);
|
||||
m1 = mbmi->palette_indexed_size;
|
||||
m2 = mbmi->palette_literal_size;
|
||||
|
||||
if (m1 > 0) {
|
||||
for (i = 0; i < m1; i++)
|
||||
mbmi->palette_indexed_colors[i] =
|
||||
vp9_read_literal(r, get_bit_depth(cm->current_palette_size));
|
||||
if (mbmi->palette_delta_bitdepth > 0) {
|
||||
int s;
|
||||
for (i = 0; i < m1; i++) {
|
||||
s = vp9_read_bit(r);
|
||||
s = 1 - 2 * s;
|
||||
mbmi->palette_color_delta[i] =
|
||||
s * vp9_read_literal(r, mbmi->palette_delta_bitdepth);
|
||||
}
|
||||
} else {
|
||||
memset(mbmi->palette_color_delta, 0,
|
||||
m1 * sizeof(mbmi->palette_color_delta[0]));
|
||||
}
|
||||
}
|
||||
|
||||
if (m2 > 0) {
|
||||
for (i = 0; i < m2; i++)
|
||||
mbmi->palette_literal_colors[i] = vp9_read_literal(r, 8);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
k = 0;
|
||||
for (i = 0; i < mbmi->palette_size; i++) {
|
||||
if (j < m1) {
|
||||
c1 = cm->current_palette_colors[mbmi->palette_indexed_colors[j]];
|
||||
if (mbmi->palette_color_delta[j])
|
||||
c1 += mbmi->palette_color_delta[j];
|
||||
} else {
|
||||
c1 = 256;
|
||||
}
|
||||
|
||||
if (k < m2)
|
||||
c2 = mbmi->palette_literal_colors[k];
|
||||
else
|
||||
c2 = 256;
|
||||
|
||||
if (c1 < c2) {
|
||||
mbmi->palette_colors[i] = c1;
|
||||
j++;
|
||||
} else if (c2 < c1) {
|
||||
mbmi->palette_colors[i] = c2;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
d = get_bit_depth(rows * cols);
|
||||
for (i = 0; i < mbmi->palette_run_length; i += 2) {
|
||||
mbmi->palette_runs[i] =
|
||||
vp9_read_literal(r, get_bit_depth(m1 + m2));
|
||||
|
||||
bits = vp9_read_tree(r, vp9_palette_run_length_tree,
|
||||
cm->fc.palette_run_length_prob[bsize - BLOCK_8X8]);
|
||||
if (bits == MAX_BITS)
|
||||
mbmi->palette_runs[i + 1] = vp9_read_literal(r, d);
|
||||
else
|
||||
mbmi->palette_runs[i + 1] = vp9_read_literal(r, bits - ONE_BITS + 1);
|
||||
mbmi->palette_runs[i + 1] += 1;
|
||||
}
|
||||
|
||||
palette_color_insertion(cm->current_palette_colors,
|
||||
&cm ->current_palette_size,
|
||||
cm->current_palette_count, mbmi);
|
||||
|
||||
run_lengh_decoding(mbmi->palette_runs, mbmi->palette_run_length, map);
|
||||
switch (mbmi->palette_scan_order) {
|
||||
case H_SCAN:
|
||||
memcpy(xd->plane[0].color_index_map, map, rows * cols);
|
||||
break;
|
||||
case V_SCAN:
|
||||
transpose_block(map, xd->plane[0].color_index_map, cols, rows);
|
||||
break;
|
||||
case SPIN_SCAN:
|
||||
spin_scan_order(scan_order, rows, cols);
|
||||
for (i = 0; i < rows * cols; i++)
|
||||
xd->plane[0].color_index_map[scan_order[i]] = map[i];
|
||||
break;
|
||||
case ZZ_SCAN:
|
||||
zz_scan_order(scan_order, rows, cols);
|
||||
for (i = 0; i < rows * cols; i++)
|
||||
xd->plane[0].color_index_map[scan_order[i]] = map[i];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mbmi->tx_size = MIN(max_txsize_lookup[bsize],
|
||||
tx_mode_to_biggest_tx_size[cm->tx_mode]);
|
||||
} else {
|
||||
mbmi->tx_size = read_tx_size(cm, xd, cm->tx_mode, bsize, 1, r);
|
||||
}
|
||||
#else
|
||||
mbmi->tx_size = read_tx_size(cm, xd, cm->tx_mode, bsize, 1, r);
|
||||
#endif
|
||||
mbmi->ref_frame[0] = INTRA_FRAME;
|
||||
mbmi->ref_frame[1] = NONE;
|
||||
|
||||
@@ -315,15 +450,25 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm,
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
#if CONFIG_PALETTE
|
||||
if (!mbmi->palette_enabled)
|
||||
mbmi->mode = read_intra_mode(r,
|
||||
get_y_mode_probs(mi, above_mi, left_mi, 0));
|
||||
#else
|
||||
mbmi->mode = read_intra_mode(r,
|
||||
get_y_mode_probs(mi, above_mi, left_mi, 0));
|
||||
#endif // CONFIG_PALETTE
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_enabled(mbmi->tx_size) && is_filter_allowed(mbmi->mode))
|
||||
if (is_filter_enabled(mbmi->tx_size) && is_filter_allowed(mbmi->mode)
|
||||
#if CONFIG_PALETTE
|
||||
&& !mbmi->palette_enabled
|
||||
#endif // CONFIG_PALETTE
|
||||
)
|
||||
mbmi->filterbit = vp9_read(r,
|
||||
cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
|
||||
else
|
||||
mbmi->filterbit = 0;
|
||||
#endif
|
||||
#endif // CONFIG_FILTERINTRA
|
||||
}
|
||||
|
||||
mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
|
||||
@@ -564,7 +709,11 @@ static void read_intra_block_mode_info(VP9_COMMON *const cm, MODE_INFO *mi,
|
||||
} else {
|
||||
mbmi->uv_filterbit = 0;
|
||||
}
|
||||
#endif
|
||||
#endif // CONFIG_FILTERINTRA
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
mbmi->palette_enabled = 0;
|
||||
#endif // CONFIG_PALETTE
|
||||
}
|
||||
|
||||
static INLINE int is_mv_valid(const MV *mv) {
|
||||
|
||||
@@ -263,6 +263,14 @@ int vp9_receive_compressed_data(VP9Decoder *pbi,
|
||||
|
||||
cm->error.setjmp = 1;
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
if (frame_is_intra_only(cm)) {
|
||||
cm->current_palette_size = 0;
|
||||
memset(cm->current_palette_count, 0,
|
||||
PALETTE_BUF_SIZE * sizeof(cm->current_palette_count[0]));
|
||||
}
|
||||
#endif
|
||||
|
||||
vp9_decode_frame(pbi, source, source + size, psource);
|
||||
|
||||
swap_frame_buffers(pbi);
|
||||
|
||||
@@ -112,6 +112,19 @@ static INLINE int vp9_read_tree(vp9_reader *r, const vp9_tree_index *tree,
|
||||
return -i;
|
||||
}
|
||||
|
||||
static INLINE int vp9_decode_uniform(vp9_reader *r, int n) {
|
||||
int l = get_unsigned_bits(n);
|
||||
int m = (1 << l) - n;
|
||||
int v= vp9_read_literal(r, l-1);
|
||||
|
||||
if (l == 0)
|
||||
return 0;
|
||||
if (v < m)
|
||||
return v;
|
||||
else
|
||||
return (v << 1) - m + vp9_read_literal(r, 1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#include "vp9/common/vp9_entropymode.h"
|
||||
#include "vp9/common/vp9_entropymv.h"
|
||||
#include "vp9/common/vp9_mvref_common.h"
|
||||
#if CONFIG_PALETTE
|
||||
#include "vp9/common/vp9_palette.h"
|
||||
#endif
|
||||
#include "vp9/common/vp9_pred_common.h"
|
||||
#include "vp9/common/vp9_seg_common.h"
|
||||
#include "vp9/common/vp9_systemdependent.h"
|
||||
@@ -41,6 +44,10 @@ static struct vp9_token inter_mode_encodings[INTER_MODES];
|
||||
#if CONFIG_EXT_TX
|
||||
static struct vp9_token ext_tx_encodings[EXT_TX_TYPES];
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
static struct vp9_token palette_size_encodings[PALETTE_SIZES];
|
||||
static struct vp9_token palette_run_length_encodings[PALETTE_RUN_LENGTHS];
|
||||
#endif
|
||||
#if CONFIG_COPY_MODE
|
||||
static struct vp9_token copy_mode_encodings_l2[2];
|
||||
static struct vp9_token copy_mode_encodings[COPY_MODE_COUNT - 1];
|
||||
@@ -69,6 +76,11 @@ void vp9_entropy_mode_init() {
|
||||
#if CONFIG_EXT_TX
|
||||
vp9_tokens_from_tree(ext_tx_encodings, vp9_ext_tx_tree);
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
vp9_tokens_from_tree(palette_size_encodings, vp9_palette_size_tree);
|
||||
vp9_tokens_from_tree(palette_run_length_encodings,
|
||||
vp9_palette_run_length_tree);
|
||||
#endif
|
||||
#if CONFIG_COMPOUND_MODES
|
||||
vp9_tokens_from_tree(inter_compound_mode_encodings,
|
||||
vp9_inter_compound_mode_tree);
|
||||
@@ -707,7 +719,68 @@ static void write_mb_modes_kf(const VP9_COMMON *cm, const MACROBLOCKD *xd,
|
||||
|
||||
write_skip(cm, xd, mbmi->segment_id, mi, w);
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
if (bsize >= BLOCK_8X8 && cm->allow_palette_mode) {
|
||||
int l, m1, m2, i, d, bits;
|
||||
int rows = 4 * num_4x4_blocks_high_lookup[bsize];
|
||||
int cols = 4 * num_4x4_blocks_wide_lookup[bsize];
|
||||
|
||||
vp9_write_bit(w, mbmi->palette_enabled);
|
||||
if (mbmi->palette_enabled) {
|
||||
m1 = mbmi->palette_indexed_size;
|
||||
m2 = mbmi->palette_literal_size;
|
||||
l = mbmi->palette_run_length;
|
||||
|
||||
vp9_write_token(w, vp9_palette_size_tree,
|
||||
cm->fc.palette_size_prob[bsize - BLOCK_8X8],
|
||||
&palette_size_encodings[mbmi->palette_size - 2]);
|
||||
vp9_encode_uniform(w, MIN(mbmi->palette_size + 1, 8),
|
||||
mbmi->palette_indexed_size);
|
||||
|
||||
if (PALETTE_DELTA_BIT)
|
||||
vp9_write_literal(w, mbmi->palette_delta_bitdepth, PALETTE_DELTA_BIT);
|
||||
vp9_write_literal(w, (l >> 1),
|
||||
get_bit_depth(palette_max_run(bsize)));
|
||||
vp9_write_literal(w, mbmi->palette_scan_order, 2);
|
||||
|
||||
if (m1 > 0) {
|
||||
for (i = 0; i < m1; i++)
|
||||
vp9_write_literal(w, mbmi->palette_indexed_colors[i],
|
||||
get_bit_depth(mbmi->current_palette_size));
|
||||
if (mbmi->palette_delta_bitdepth > 0) {
|
||||
for (i = 0; i < m1; i++) {
|
||||
vp9_write_bit(w, mbmi->palette_color_delta[i] < 0);
|
||||
vp9_write_literal(w, abs(mbmi->palette_color_delta[i]),
|
||||
mbmi->palette_delta_bitdepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m2 > 0) {
|
||||
for (i = 0; i < m2; i++)
|
||||
vp9_write_literal(w, mbmi->palette_literal_colors[i], 8);
|
||||
}
|
||||
|
||||
d = get_bit_depth(rows * cols);
|
||||
for (i = 0; i < l; i += 2) {
|
||||
vp9_write_literal(w, mbmi->palette_runs[i],
|
||||
get_bit_depth(m1 + m2));
|
||||
bits = get_bit_depth(mbmi->palette_runs[i + 1]);
|
||||
vp9_write_token(w, vp9_palette_run_length_tree,
|
||||
cm->fc.palette_run_length_prob[bsize - BLOCK_8X8],
|
||||
&palette_run_length_encodings[bits > 6 ?
|
||||
6 : bits - 1]);
|
||||
vp9_write_literal(w, mbmi->palette_runs[i + 1] - 1,
|
||||
bits > 6 ? d : bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT &&
|
||||
!mbmi->palette_enabled)
|
||||
#else
|
||||
if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT)
|
||||
#endif
|
||||
write_selected_tx_size(cm, xd, mbmi->tx_size, bsize, w);
|
||||
|
||||
#if CONFIG_TX_SKIP
|
||||
@@ -731,12 +804,22 @@ static void write_mb_modes_kf(const VP9_COMMON *cm, const MACROBLOCKD *xd,
|
||||
#endif
|
||||
|
||||
if (bsize >= BLOCK_8X8) {
|
||||
#if CONFIG_PALETTE
|
||||
if (!mbmi->palette_enabled)
|
||||
write_intra_mode(w, mbmi->mode,
|
||||
get_y_mode_probs(mi, above_mi, left_mi, 0));
|
||||
#else
|
||||
write_intra_mode(w, mbmi->mode, get_y_mode_probs(mi, above_mi, left_mi, 0));
|
||||
#endif // CONFIG_PALETTE
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size))
|
||||
if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size)
|
||||
#if CONFIG_PALETTE
|
||||
&& !mbmi->palette_enabled
|
||||
#endif // CONFIG_PALETTE
|
||||
)
|
||||
vp9_write(w, mbmi->filterbit,
|
||||
cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
|
||||
#endif
|
||||
#endif // CONFIG_FILTERINTRA
|
||||
} else {
|
||||
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
|
||||
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
|
||||
@@ -1792,6 +1875,11 @@ static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) {
|
||||
#endif // CONFIG_WEDGE_PARTITION
|
||||
}
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
if (frame_is_intra_only(cm))
|
||||
vp9_write_bit(&header_bc, cm->allow_palette_mode);
|
||||
#endif
|
||||
|
||||
vp9_stop_encode(&header_bc);
|
||||
assert(header_bc.pos <= 0xffff);
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ static void alloc_mode_context(VP9_COMMON *cm, int num_4x4_blk,
|
||||
ctx->eobs_pbuf[i][k] = ctx->eobs[i][k];
|
||||
}
|
||||
}
|
||||
#if CONFIG_PALETTE
|
||||
CHECK_MEM_ERROR(cm, ctx->color_index_map,
|
||||
vpx_memalign(16, num_pix * sizeof(ctx->color_index_map[0])));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void free_mode_context(PICK_MODE_CONTEXT *ctx) {
|
||||
@@ -61,6 +65,11 @@ static void free_mode_context(PICK_MODE_CONTEXT *ctx) {
|
||||
ctx->eobs[i][k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
vpx_free(ctx->color_index_map);
|
||||
ctx->color_index_map = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void alloc_tree_contexts(VP9_COMMON *cm, PC_TREE *tree,
|
||||
|
||||
@@ -30,6 +30,12 @@ typedef struct {
|
||||
tran_low_t *qcoeff_pbuf[MAX_MB_PLANE][3];
|
||||
tran_low_t *dqcoeff_pbuf[MAX_MB_PLANE][3];
|
||||
uint16_t *eobs_pbuf[MAX_MB_PLANE][3];
|
||||
#if CONFIG_PALETTE
|
||||
uint8_t *color_index_map;
|
||||
uint8_t palette_colors_buf[PALETTE_BUF_SIZE];
|
||||
int palette_buf_size;
|
||||
int palette_count_buf[PALETTE_BUF_SIZE];
|
||||
#endif
|
||||
|
||||
int is_coded;
|
||||
int num_4x4_blk;
|
||||
@@ -72,6 +78,9 @@ typedef struct PC_TREE {
|
||||
struct PC_TREE *split[4];
|
||||
PICK_MODE_CONTEXT *leaf_split[4];
|
||||
};
|
||||
#if CONFIG_PALETTE
|
||||
PICK_MODE_CONTEXT current;
|
||||
#endif
|
||||
} PC_TREE;
|
||||
|
||||
void vp9_setup_pc_tree(struct VP9Common *cm, struct VP9_COMP *cpi);
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
#include "vp9/common/vp9_entropymode.h"
|
||||
#include "vp9/common/vp9_idct.h"
|
||||
#include "vp9/common/vp9_mvref_common.h"
|
||||
#if CONFIG_PALETTE
|
||||
#include "vp9/common/vp9_palette.h"
|
||||
#endif
|
||||
#include "vp9/common/vp9_pred_common.h"
|
||||
#include "vp9/common/vp9_quant_common.h"
|
||||
#include "vp9/common/vp9_reconintra.h"
|
||||
@@ -354,6 +357,16 @@ static void set_offsets_extend(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
}
|
||||
#endif // CONFIG_SUPERTX
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
void copy_palette_info(PICK_MODE_CONTEXT *c, PICK_MODE_CONTEXT *p) {
|
||||
c->palette_buf_size = p->palette_buf_size;
|
||||
memcpy(c->palette_colors_buf, p->palette_colors_buf,
|
||||
c->palette_buf_size * sizeof(c->palette_colors_buf[0]));
|
||||
memcpy(c->palette_count_buf, p->palette_count_buf,
|
||||
c->palette_buf_size * sizeof(c->palette_count_buf[0]));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void duplicate_mode_info_in_sb(VP9_COMMON *cm, MACROBLOCKD *xd,
|
||||
int mi_row, int mi_col,
|
||||
BLOCK_SIZE bsize) {
|
||||
@@ -769,6 +782,10 @@ static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
|
||||
p[i].eobs = ctx->eobs_pbuf[i][2];
|
||||
}
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
pd[0].color_index_map = ctx->color_index_map;
|
||||
#endif
|
||||
|
||||
// Restore the coding context of the MB to that that was in place
|
||||
// when the mode was picked for it
|
||||
for (y = 0; y < mi_height; y++)
|
||||
@@ -1094,7 +1111,7 @@ static void update_supertx_param(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
|
||||
#if CONFIG_TX_SKIP
|
||||
ctx->mic.mbmi.tx_skip[0] = 0;
|
||||
ctx->mic.mbmi.tx_skip[1] = 0;
|
||||
#endif // CONFIG_EXT_TX
|
||||
#endif // CONFIG_TX_SKIP
|
||||
}
|
||||
|
||||
static void update_supertx_param_sb(VP9_COMP *cpi, int mi_row, int mi_col,
|
||||
@@ -1267,6 +1284,9 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][0];
|
||||
p[i].eobs = ctx->eobs_pbuf[i][0];
|
||||
}
|
||||
#if CONFIG_PALETTE
|
||||
pd[0].color_index_map = ctx->color_index_map;
|
||||
#endif
|
||||
ctx->is_coded = 0;
|
||||
ctx->skippable = 0;
|
||||
ctx->pred_pixel_ready = 0;
|
||||
@@ -1325,7 +1345,25 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
// Find best coding mode & reconstruct the MB so it is available
|
||||
// as a predictor for MBs that follow in the SB
|
||||
if (frame_is_intra_only(cm)) {
|
||||
#if CONFIG_PALETTE
|
||||
int n = cpi->common.current_palette_size;
|
||||
uint8_t palette[PALETTE_BUF_SIZE];
|
||||
int count[PALETTE_BUF_SIZE];
|
||||
|
||||
memcpy(palette, cpi->common.current_palette_colors, n * sizeof(palette[0]));
|
||||
memcpy(count, cpi->common.current_palette_count, n * sizeof(count[0]));
|
||||
cpi->common.current_palette_size = ctx->palette_buf_size;
|
||||
memcpy(cpi->common.current_palette_colors, ctx->palette_colors_buf,
|
||||
ctx->palette_buf_size * sizeof(ctx->palette_colors_buf[0]));
|
||||
memcpy(cpi->common.current_palette_count, ctx->palette_count_buf,
|
||||
ctx->palette_buf_size * sizeof(ctx->palette_count_buf[0]));
|
||||
#endif
|
||||
vp9_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, best_rd);
|
||||
#if CONFIG_PALETTE
|
||||
cpi->common.current_palette_size = n;
|
||||
memcpy(cpi->common.current_palette_colors, palette, n * sizeof(palette[0]));
|
||||
memcpy(cpi->common.current_palette_count, count, n * sizeof(count[0]));
|
||||
#endif
|
||||
#if CONFIG_SUPERTX
|
||||
*totalrate_nocoef = 0;
|
||||
#endif
|
||||
@@ -2752,6 +2790,11 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
bsize >= BLOCK_8X8;
|
||||
int partition_vert_allowed = !force_horz_split && xss <= yss &&
|
||||
bsize >= BLOCK_8X8;
|
||||
#if CONFIG_PALETTE
|
||||
PICK_MODE_CONTEXT *c, *p;
|
||||
int previous_size, previous_count[PALETTE_BUF_SIZE];
|
||||
uint8_t previous_colors[PALETTE_BUF_SIZE];
|
||||
#endif
|
||||
(void) *tp_orig;
|
||||
|
||||
assert(num_8x8_blocks_wide_lookup[bsize] ==
|
||||
@@ -2764,6 +2807,28 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
|
||||
set_offsets(cpi, tile, mi_row, mi_col, bsize);
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
if (bsize == BLOCK_64X64) {
|
||||
c = &pc_tree->current;
|
||||
c->palette_buf_size = cm->current_palette_size;
|
||||
memcpy(c->palette_colors_buf, cm->current_palette_colors,
|
||||
c->palette_buf_size * sizeof(cm->current_palette_colors[0]));
|
||||
memcpy(c->palette_count_buf, cm->current_palette_count,
|
||||
c->palette_buf_size * sizeof(cm->current_palette_count[0]));
|
||||
}
|
||||
|
||||
c = &pc_tree->current;
|
||||
previous_size = c->palette_buf_size;
|
||||
memcpy(previous_colors, c->palette_colors_buf,
|
||||
previous_size * sizeof(previous_colors[0]));
|
||||
memcpy(previous_count, c->palette_count_buf,
|
||||
previous_size * sizeof(previous_count[0]));
|
||||
|
||||
c = &pc_tree->none;
|
||||
p = &pc_tree->current;
|
||||
copy_palette_info(c, p);
|
||||
#endif
|
||||
|
||||
if (bsize == BLOCK_16X16 && cpi->oxcf.aq_mode)
|
||||
x->mb_energy = vp9_block_energy(cpi, x, bsize);
|
||||
|
||||
@@ -2943,6 +3008,11 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
c = &pc_tree->current;
|
||||
p = &pc_tree->none;
|
||||
copy_palette_info(c, p);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -2957,6 +3027,9 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
// TODO(jingning): use the motion vectors given by the above search as
|
||||
// the starting point of motion search in the following partition type check.
|
||||
if (do_split) {
|
||||
#if CONFIG_PALETTE
|
||||
int last = -1;
|
||||
#endif
|
||||
subsize = get_subsize(bsize, PARTITION_SPLIT);
|
||||
if (bsize == BLOCK_8X8) {
|
||||
i = 4;
|
||||
@@ -3043,6 +3116,22 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
load_pred_mv(x, ctx);
|
||||
|
||||
pc_tree->split[i]->index = i;
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
c = &pc_tree->split[i]->current;
|
||||
if (last < 0) {
|
||||
c->palette_buf_size = previous_size;
|
||||
memcpy(c->palette_colors_buf, previous_colors,
|
||||
previous_size * sizeof(previous_colors[0]));
|
||||
memcpy(c->palette_count_buf, previous_count,
|
||||
previous_size * sizeof(previous_count[0]));
|
||||
} else {
|
||||
p = &pc_tree->split[last]->current;
|
||||
copy_palette_info(c, p);
|
||||
}
|
||||
last = i;
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
rd_pick_partition(cpi, tile, tp, mi_row + y_idx, mi_col + x_idx,
|
||||
subsize, &this_rdc, &this_rate_nocoef,
|
||||
@@ -3133,6 +3222,20 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
assert(best_rate_nocoef >= 0);
|
||||
#endif
|
||||
pc_tree->partitioning = PARTITION_SPLIT;
|
||||
#if CONFIG_PALETTE
|
||||
if (bsize > BLOCK_8X8 && last >= 0) {
|
||||
c = &pc_tree->current;
|
||||
p = &(pc_tree->split[last]->current);
|
||||
copy_palette_info(c, p);
|
||||
} else {
|
||||
c = &pc_tree->current;
|
||||
c->palette_buf_size = previous_size;
|
||||
memcpy(c->palette_colors_buf, previous_colors,
|
||||
previous_size * sizeof(previous_colors[0]));
|
||||
memcpy(c->palette_count_buf, previous_count,
|
||||
previous_size * sizeof(previous_count[0]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
// skip rectangular partition test when larger block size
|
||||
@@ -3145,6 +3248,9 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
|
||||
// PARTITION_HORZ
|
||||
if (partition_horz_allowed && do_rect) {
|
||||
#if CONFIG_PALETTE
|
||||
int last;
|
||||
#endif
|
||||
subsize = get_subsize(bsize, PARTITION_HORZ);
|
||||
if (cpi->sf.adaptive_motion_search)
|
||||
load_pred_mv(x, ctx);
|
||||
@@ -3152,6 +3258,17 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
partition_none_allowed)
|
||||
pc_tree->horizontal[0].pred_interp_filter =
|
||||
ctx->mic.mbmi.interp_filter;
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
c = &pc_tree->horizontal[0];
|
||||
c->palette_buf_size = previous_size;
|
||||
memcpy(c->palette_colors_buf, previous_colors,
|
||||
previous_size * sizeof(previous_colors[0]));
|
||||
memcpy(c->palette_count_buf, previous_count,
|
||||
previous_size * sizeof(previous_count[0]));
|
||||
last = 0;
|
||||
#endif
|
||||
|
||||
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rdc,
|
||||
#if CONFIG_SUPERTX
|
||||
&sum_rate_nocoef,
|
||||
@@ -3174,6 +3291,12 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
partition_none_allowed)
|
||||
pc_tree->horizontal[1].pred_interp_filter =
|
||||
ctx->mic.mbmi.interp_filter;
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
copy_palette_info(&pc_tree->horizontal[1], &pc_tree->horizontal[0]);
|
||||
last = 1;
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
rd_pick_sb_modes(cpi, tile, mi_row + mi_step, mi_col, &this_rdc,
|
||||
&this_rate_nocoef,
|
||||
@@ -3259,12 +3382,29 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
assert(best_rate_nocoef >= 0);
|
||||
#endif
|
||||
pc_tree->partitioning = PARTITION_HORZ;
|
||||
#if CONFIG_PALETTE
|
||||
if (bsize > BLOCK_8X8) {
|
||||
c = &pc_tree->current;
|
||||
p = &pc_tree->horizontal[last];
|
||||
copy_palette_info(c, p);
|
||||
} else {
|
||||
c = &pc_tree->current;
|
||||
c->palette_buf_size = previous_size;
|
||||
memcpy(c->palette_colors_buf, previous_colors,
|
||||
previous_size * sizeof(previous_colors[0]));
|
||||
memcpy(c->palette_count_buf, previous_count,
|
||||
previous_size * sizeof(previous_count[0]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
||||
}
|
||||
// PARTITION_VERT
|
||||
if (partition_vert_allowed && do_rect) {
|
||||
#if CONFIG_PALETTE
|
||||
int last;
|
||||
#endif
|
||||
subsize = get_subsize(bsize, PARTITION_VERT);
|
||||
|
||||
if (cpi->sf.adaptive_motion_search)
|
||||
@@ -3273,6 +3413,17 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
partition_none_allowed)
|
||||
pc_tree->vertical[0].pred_interp_filter =
|
||||
ctx->mic.mbmi.interp_filter;
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
c = &pc_tree->vertical[0];
|
||||
c->palette_buf_size = previous_size;
|
||||
memcpy(c->palette_colors_buf, previous_colors,
|
||||
previous_size * sizeof(previous_colors[0]));
|
||||
memcpy(c->palette_count_buf, previous_count,
|
||||
previous_size * sizeof(previous_count[0]));
|
||||
last = 0;
|
||||
#endif
|
||||
|
||||
rd_pick_sb_modes(cpi, tile, mi_row, mi_col, &sum_rdc,
|
||||
#if CONFIG_SUPERTX
|
||||
&sum_rate_nocoef,
|
||||
@@ -3294,6 +3445,12 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
partition_none_allowed)
|
||||
pc_tree->vertical[1].pred_interp_filter =
|
||||
ctx->mic.mbmi.interp_filter;
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
copy_palette_info(&pc_tree->vertical[1], &pc_tree->vertical[0]);
|
||||
last = 1;
|
||||
#endif
|
||||
|
||||
#if CONFIG_SUPERTX
|
||||
rd_pick_sb_modes(cpi, tile, mi_row, mi_col + mi_step, &this_rdc,
|
||||
&this_rate_nocoef, subsize, &pc_tree->vertical[1],
|
||||
@@ -3377,6 +3534,20 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
|
||||
assert(best_rate_nocoef >= 0);
|
||||
#endif
|
||||
pc_tree->partitioning = PARTITION_VERT;
|
||||
#if CONFIG_PALETTE
|
||||
if (bsize > BLOCK_8X8) {
|
||||
c = &pc_tree->current;
|
||||
p = &pc_tree->vertical[last];
|
||||
copy_palette_info(c, p);
|
||||
} else {
|
||||
c = &pc_tree->current;
|
||||
c->palette_buf_size = previous_size;
|
||||
memcpy(c->palette_colors_buf, previous_colors,
|
||||
previous_size * sizeof(previous_colors[0]));
|
||||
memcpy(c->palette_count_buf, previous_count,
|
||||
previous_size * sizeof(previous_count[0]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
|
||||
@@ -4439,6 +4610,16 @@ static void encode_frame_internal(VP9_COMP *cpi) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
if (frame_is_intra_only(cm)) {
|
||||
cm->current_palette_size = 0;
|
||||
memset(cm->current_palette_count, 0,
|
||||
PALETTE_BUF_SIZE * sizeof(cm->current_palette_count[0]));
|
||||
cm->palette_counter = 0;
|
||||
cm->block_counter = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
encode_tiles(cpi);
|
||||
|
||||
vpx_usec_timer_mark(&emr_timer);
|
||||
@@ -4782,6 +4963,18 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled,
|
||||
#endif
|
||||
mi);
|
||||
vp9_tokenize_sb(cpi, t, !output_enabled, MAX(bsize, BLOCK_8X8));
|
||||
#if CONFIG_PALETTE
|
||||
if (mbmi->palette_enabled && output_enabled) {
|
||||
palette_color_insertion(cm->current_palette_colors,
|
||||
&cm ->current_palette_size,
|
||||
cm->current_palette_count, mbmi);
|
||||
}
|
||||
if (frame_is_intra_only(cm) && output_enabled && bsize >= BLOCK_8X8) {
|
||||
cm->block_counter++;
|
||||
if (mbmi->palette_enabled)
|
||||
cm->palette_counter++;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
int ref;
|
||||
const int is_compound = has_second_ref(mbmi);
|
||||
|
||||
@@ -2602,6 +2602,11 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
||||
if (loop_count == 0)
|
||||
setup_frame(cpi);
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
if (loop_count == 0 && frame_is_intra_only(cm))
|
||||
cm->allow_palette_mode = 1;
|
||||
#endif
|
||||
|
||||
// Variance adaptive and in frame q adjustment experiments are mutually
|
||||
// exclusive.
|
||||
if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
|
||||
@@ -2773,6 +2778,14 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
||||
rc->projected_frame_size < rc->max_frame_bandwidth)
|
||||
loop = 0;
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
if (frame_is_intra_only(cm) && cm->allow_palette_mode &&
|
||||
cm->palette_counter * 100 < cm->block_counter) {
|
||||
cm->allow_palette_mode = 0;
|
||||
loop = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (loop) {
|
||||
loop_count++;
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#include "vp9/common/vp9_entropymode.h"
|
||||
#include "vp9/common/vp9_idct.h"
|
||||
#include "vp9/common/vp9_mvref_common.h"
|
||||
#if CONFIG_PALETTE
|
||||
#include "vp9/common/vp9_palette.h"
|
||||
#endif
|
||||
#include "vp9/common/vp9_pred_common.h"
|
||||
#include "vp9/common/vp9_quant_common.h"
|
||||
#include "vp9/common/vp9_reconinter.h"
|
||||
@@ -869,10 +872,18 @@ static void super_block_yrd(VP9_COMP *cpi, MACROBLOCK *x, int *rate,
|
||||
assert(bs == xd->mi[0].src_mi->mbmi.sb_type);
|
||||
|
||||
#if CONFIG_TX_SKIP
|
||||
if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
|
||||
if (cpi->sf.tx_size_search_method == USE_LARGESTALL
|
||||
#if CONFIG_PALETTE
|
||||
|| x->e_mbd.mi[0].src_mi->mbmi.palette_enabled
|
||||
#endif // CONFIG_PALETTE
|
||||
) {
|
||||
#else
|
||||
if (cpi->sf.tx_size_search_method == USE_LARGESTALL || xd->lossless) {
|
||||
#endif
|
||||
if (cpi->sf.tx_size_search_method == USE_LARGESTALL || xd->lossless
|
||||
#if CONFIG_PALETTE
|
||||
|| xd->mi[0].src_mi->mbmi.palette_enabled
|
||||
#endif // CONFIG_PALETTE
|
||||
) {
|
||||
#endif // CONFIG_TX_SKIP
|
||||
vpx_memset(txfm_cache, 0, TX_MODES * sizeof(int64_t));
|
||||
choose_largest_tx_size(cpi, x, rate, distortion, skip, ret_sse, ref_best_rd,
|
||||
bs);
|
||||
@@ -1086,7 +1097,10 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
|
||||
#if CONFIG_TX_SKIP
|
||||
xd->mi[0].src_mi->mbmi.tx_skip[0] = 0;
|
||||
xd->mi[0].src_mi->mbmi.tx_skip[1] = 0;
|
||||
#endif
|
||||
#endif // CONFIG_TX_SKIP
|
||||
#if CONFIG_PALETTE
|
||||
xd->mi[0].src_mi->mbmi.palette_enabled = 0;
|
||||
#endif // CONFIG_PALETTE
|
||||
for (idy = 0; idy < num_4x4_blocks_high; ++idy) {
|
||||
for (idx = 0; idx < num_4x4_blocks_wide; ++idx) {
|
||||
const int block = ib + idy * 2 + idx;
|
||||
@@ -1283,6 +1297,19 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
int q_idx = vp9_get_qindex(&cpi->common.seg, mic->mbmi.segment_id,
|
||||
cpi->common.base_qindex);
|
||||
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA;
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
int palette_selected = 0, best_n = 0, best_l = 0, colors;
|
||||
int best_m1 = 0, best_m2 = 0, palette_delta_bitdepth = 0;
|
||||
int rows = 4 * num_4x4_blocks_high_lookup[bsize];
|
||||
int cols = 4 * num_4x4_blocks_wide_lookup[bsize];
|
||||
int src_stride = x->plane[0].src.stride;
|
||||
uint8_t *src = x->plane[0].src.buf;
|
||||
uint16_t best_runs[PALETTE_MAX_RUNS];
|
||||
uint8_t best_palette[PALETTE_MAX_SIZE], best_map[4096];
|
||||
uint8_t best_index[PALETTE_MAX_SIZE], best_literal[PALETTE_MAX_SIZE];
|
||||
int8_t palette_color_delta[PALETTE_MAX_SIZE];
|
||||
PALETTE_SCAN_ORDER best_ps = H_SCAN;
|
||||
#endif
|
||||
bmode_costs = cpi->y_mode_costs[A][L];
|
||||
|
||||
@@ -1310,6 +1337,10 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
mic->mbmi.tx_skip[0] = 0;
|
||||
#endif
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
mic->mbmi.palette_enabled = 0;
|
||||
#endif
|
||||
|
||||
super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
|
||||
&s, NULL, bsize, local_tx_cache, best_rd);
|
||||
|
||||
@@ -1325,6 +1356,10 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
if (is_filter_allowed(mode) && is_filter_enabled(mic->mbmi.tx_size))
|
||||
this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
|
||||
[mic->mbmi.tx_size][mode], fbit);
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
if (this_rate != INT_MAX && cpi->common.allow_palette_mode)
|
||||
this_rate += vp9_cost_bit(128, 0);
|
||||
#endif
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
|
||||
|
||||
@@ -1404,6 +1439,257 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
mic->mbmi.palette_enabled = 0;
|
||||
mic->mbmi.palette_size = 0;
|
||||
mic->mbmi.current_palette_size = cpi->common.current_palette_size;
|
||||
colors = count_colors(src, src_stride, rows, cols);
|
||||
if (colors > 1 && colors <= 64 && cpi->common.allow_palette_mode) {
|
||||
int n, r, c, i, j, temp, max_itr = 50, k;
|
||||
int indices[4096];
|
||||
int l, m1, m2, d = get_bit_depth(rows * cols);
|
||||
int bits, best_bits = 0, total_bits, best_total_bits;
|
||||
int palette_size_cost[PALETTE_SIZES];
|
||||
int palette_run_length_cost[PALETTE_RUN_LENGTHS];
|
||||
double data[4096];
|
||||
double centroids[PALETTE_MAX_SIZE];
|
||||
double lb = src[0], ub = src[0], val;
|
||||
int64_t local_tx_cache[TX_MODES];
|
||||
PALETTE_SCAN_ORDER ps;
|
||||
uint8_t map[4096];
|
||||
#if CONFIG_TX_SKIP
|
||||
int this_rate_tokenonly_s, s_s;
|
||||
int64_t this_distortion_s;
|
||||
#endif
|
||||
|
||||
memset(data, 0, sizeof(data[0] * 4096));
|
||||
memset(indices, 0, sizeof(indices[0] * 4096));
|
||||
mic->mbmi.palette_enabled = 1;
|
||||
vp9_cost_tokens(palette_size_cost,
|
||||
cpi->common.fc.palette_size_prob[bsize - BLOCK_8X8],
|
||||
vp9_palette_size_tree);
|
||||
vp9_cost_tokens(palette_run_length_cost,
|
||||
cpi->common.fc.palette_run_length_prob[bsize - BLOCK_8X8],
|
||||
vp9_palette_run_length_tree);
|
||||
#if CONFIG_FILTERINTRA
|
||||
mic->mbmi.filterbit = 0;
|
||||
#endif
|
||||
for (r = 0; r < rows; r++) {
|
||||
for (c = 0; c < cols; c++) {
|
||||
val = src[r * src_stride + c];
|
||||
data[r * cols + c] = val;
|
||||
if (val < lb)
|
||||
lb = val;
|
||||
else if (val > ub)
|
||||
ub = val;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = colors > PALETTE_MAX_SIZE ? PALETTE_MAX_SIZE : colors;
|
||||
n >= 2; n--) {
|
||||
for (i = 0; i < n; i++)
|
||||
centroids[i] = lb + (2 * i + 1) * (ub - lb) / n / 2;
|
||||
r = k_means(data, centroids, indices, rows * cols, n, 1, max_itr);
|
||||
insertion_sort(centroids, n);
|
||||
i = 1;
|
||||
k = n;
|
||||
while (i < k) {
|
||||
if (centroids[i] == centroids[i - 1]) {
|
||||
j = i;
|
||||
while (j < k - 1) {
|
||||
centroids[j] = centroids[j + 1];
|
||||
j++;
|
||||
}
|
||||
k--;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
mic->mbmi.palette_size = k;
|
||||
for (i = 0; i < k; i++)
|
||||
mic->mbmi.palette_colors[i] = clip_pixel(round(centroids[i]));
|
||||
|
||||
best_total_bits = INT_MAX;
|
||||
for (bits = 0; bits < 1 << PALETTE_DELTA_BIT; bits++) {
|
||||
m1 = 0;
|
||||
m2 = 0;
|
||||
for (j = 0; j < k; j++) {
|
||||
temp = palette_color_lookup(cpi->common.current_palette_colors,
|
||||
cpi->common.current_palette_size,
|
||||
mic->mbmi.palette_colors[j], bits);
|
||||
if (temp >= 0) {
|
||||
mic->mbmi.palette_indexed_colors[m1] = temp;
|
||||
mic->mbmi.palette_color_delta[m1] =
|
||||
mic->mbmi.palette_colors[j] -
|
||||
cpi->common.current_palette_colors[temp];
|
||||
m1++;
|
||||
} else {
|
||||
mic->mbmi.palette_literal_colors[m2] =
|
||||
mic->mbmi.palette_colors[j];
|
||||
m2++;
|
||||
}
|
||||
}
|
||||
total_bits = m1 * get_bit_depth(cpi->common.current_palette_size) +
|
||||
m1 * (bits == 0 ? 0 : bits + 1) + m2 * 8;
|
||||
if (total_bits <= best_total_bits) {
|
||||
best_total_bits = total_bits;
|
||||
best_bits = bits;
|
||||
}
|
||||
}
|
||||
|
||||
m1 = 0;
|
||||
m2 = 0;
|
||||
for (i = 0; i < k; i++) {
|
||||
temp = palette_color_lookup(cpi->common.current_palette_colors,
|
||||
cpi->common.current_palette_size,
|
||||
mic->mbmi.palette_colors[i], best_bits);
|
||||
if (temp >= 0) {
|
||||
mic->mbmi.palette_indexed_colors[m1] = temp;
|
||||
mic->mbmi.palette_color_delta[m1] =
|
||||
mic->mbmi.palette_colors[i] -
|
||||
cpi->common.current_palette_colors[temp];
|
||||
m1++;
|
||||
} else {
|
||||
mic->mbmi.palette_literal_colors[m2] =
|
||||
mic->mbmi.palette_colors[i];
|
||||
m2++;
|
||||
}
|
||||
}
|
||||
if (m1 == PALETTE_MAX_SIZE)
|
||||
continue;
|
||||
mic->mbmi.palette_indexed_size = m1;
|
||||
mic->mbmi.palette_literal_size = m2;
|
||||
mic->mbmi.palette_delta_bitdepth = best_bits;
|
||||
|
||||
calc_indices(data, centroids, indices, rows * cols, k, 1);
|
||||
for (r = 0; r < rows; r++) {
|
||||
for (c = 0; c < cols; c++) {
|
||||
xd->plane[0].color_index_map[r * cols + c] = indices[r * cols + c];
|
||||
}
|
||||
}
|
||||
|
||||
for (ps = H_SCAN; ps < PALETTE_SCAN_ORDERS; ps++) {
|
||||
int scan_order[4096];
|
||||
mic->mbmi.palette_scan_order = ps;
|
||||
|
||||
switch (ps) {
|
||||
case H_SCAN:
|
||||
memcpy(map, xd->plane[0].color_index_map, rows * cols);
|
||||
break;
|
||||
case V_SCAN:
|
||||
transpose_block(xd->plane[0].color_index_map,
|
||||
map, rows, cols);
|
||||
break;
|
||||
case SPIN_SCAN:
|
||||
spin_scan_order(scan_order, rows, cols);
|
||||
for (i = 0; i < rows * cols; i++)
|
||||
map[i] = xd->plane[0].color_index_map[scan_order[i]];
|
||||
break;
|
||||
case ZZ_SCAN:
|
||||
zz_scan_order(scan_order, rows, cols);
|
||||
for (i = 0; i < rows * cols; i++)
|
||||
map[i] = xd->plane[0].color_index_map[scan_order[i]];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
l = run_lengh_encoding(map, rows * cols, mic->mbmi.palette_runs,
|
||||
palette_max_run(bsize));
|
||||
if (!l) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#if CONFIG_TX_SKIP
|
||||
mic->mbmi.tx_skip[0] = 0;
|
||||
#endif
|
||||
super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
|
||||
&s, NULL, bsize, local_tx_cache, best_rd);
|
||||
#if CONFIG_TX_SKIP
|
||||
if (try_tx_skip) {
|
||||
if (this_rate_tokenonly != INT_MAX)
|
||||
this_rate_tokenonly +=
|
||||
vp9_cost_bit(cpi->common.fc.y_tx_skip_prob[0], 0);
|
||||
|
||||
mic->mbmi.tx_skip[0] = 1;
|
||||
super_block_yrd(cpi, x, &this_rate_tokenonly_s, &this_distortion_s,
|
||||
&s_s, NULL, bsize, local_tx_cache, best_rd);
|
||||
if (this_rate_tokenonly_s != INT_MAX)
|
||||
this_rate_tokenonly_s +=
|
||||
vp9_cost_bit(cpi->common.fc.y_tx_skip_prob[0], 1);
|
||||
|
||||
if ((this_rate_tokenonly_s != INT_MAX &&
|
||||
this_rate_tokenonly == INT_MAX) ||
|
||||
(RDCOST(x->rdmult, x->rddiv, this_rate_tokenonly, this_distortion)
|
||||
> RDCOST(x->rdmult, x->rddiv, this_rate_tokenonly_s,
|
||||
this_distortion_s))) {
|
||||
mic->mbmi.tx_skip[0] = 1;
|
||||
} else {
|
||||
mic->mbmi.tx_skip[0] = 0;
|
||||
}
|
||||
} else {
|
||||
mic->mbmi.tx_skip[0] = 0;
|
||||
}
|
||||
|
||||
super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
|
||||
&s, NULL, bsize, local_tx_cache, best_rd);
|
||||
if (this_rate_tokenonly != INT_MAX)
|
||||
this_rate_tokenonly += vp9_cost_bit(cpi->common.fc.y_tx_skip_prob[0],
|
||||
mic->mbmi.tx_skip[0]);
|
||||
#endif
|
||||
if (this_rate_tokenonly == INT_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this_rate = this_rate_tokenonly +
|
||||
(1 + vp9_encode_uniform_cost(MIN(k + 1, 8), m1) + PALETTE_DELTA_BIT
|
||||
+ get_bit_depth(palette_max_run(bsize)) + 2 +
|
||||
get_bit_depth(mic->mbmi.current_palette_size) * m1 +
|
||||
mic->mbmi.palette_delta_bitdepth * m1 +
|
||||
8 * m2 + get_bit_depth(k) * (l >> 1)) * vp9_cost_bit(128, 0) +
|
||||
palette_size_cost[k - 2];
|
||||
for (i = 0; i < l; i += 2) {
|
||||
int bits = get_bit_depth(mic->mbmi.palette_runs[i + 1]);
|
||||
this_rate += palette_run_length_cost[bits > 6 ? 6 : bits - 1];
|
||||
this_rate += (bits > 6 ? d : bits) * vp9_cost_bit(128, 0);
|
||||
}
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
|
||||
if (this_rd < best_rd) {
|
||||
mode_selected = DC_PRED;
|
||||
best_rd = this_rd;
|
||||
best_tx = mic->mbmi.tx_size;
|
||||
*rate = this_rate;
|
||||
*rate_tokenonly = this_rate_tokenonly;
|
||||
*distortion = this_distortion;
|
||||
*skippable = s;
|
||||
best_n = k;
|
||||
best_l = l;
|
||||
palette_selected = 1;
|
||||
best_ps = ps;
|
||||
best_m1 = mic->mbmi.palette_indexed_size;
|
||||
best_m2 = mic->mbmi.palette_literal_size;
|
||||
palette_delta_bitdepth = mic->mbmi.palette_delta_bitdepth;
|
||||
memcpy(best_palette, mic->mbmi.palette_colors,
|
||||
k * sizeof(best_palette[0]));
|
||||
memcpy(best_runs, mic->mbmi.palette_runs, l * sizeof(best_runs[0]));
|
||||
memcpy(best_map, xd->plane[0].color_index_map,
|
||||
rows * cols * sizeof(best_map[0]));
|
||||
memcpy(best_index, mic->mbmi.palette_indexed_colors,
|
||||
best_m1 * sizeof(best_index[0]));
|
||||
memcpy(palette_color_delta, mic->mbmi.palette_color_delta,
|
||||
best_m1 * sizeof(palette_color_delta[0]));
|
||||
memcpy(best_literal, mic->mbmi.palette_literal_colors,
|
||||
best_m2 * sizeof(best_literal[0]));
|
||||
#if CONFIG_TX_SKIP
|
||||
tx_skipped = mic->mbmi.tx_skip[0];
|
||||
#endif // CONFIG_TX_SKIP
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mic->mbmi.mode = mode_selected;
|
||||
#if CONFIG_FILTERINTRA
|
||||
if (is_filter_enabled(best_tx))
|
||||
@@ -1415,6 +1701,32 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
#if CONFIG_TX_SKIP
|
||||
mic->mbmi.tx_skip[0] = tx_skipped;
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
mic->mbmi.palette_enabled = palette_selected;
|
||||
if (palette_selected) {
|
||||
mic->mbmi.palette_size = best_n;
|
||||
mic->mbmi.palette_run_length = best_l;
|
||||
mic->mbmi.palette_scan_order = best_ps;
|
||||
mic->mbmi.palette_indexed_size = best_m1;
|
||||
mic->mbmi.palette_literal_size = best_m2;
|
||||
mic->mbmi.palette_delta_bitdepth = palette_delta_bitdepth;
|
||||
memcpy(mic->mbmi.palette_colors, best_palette,
|
||||
best_n * sizeof(best_palette[0]));
|
||||
memcpy(mic->mbmi.palette_runs, best_runs, best_l * sizeof(best_runs[0]));
|
||||
memcpy(xd->plane[0].color_index_map, best_map,
|
||||
4 * num_4x4_blocks_high_lookup[bsize] *
|
||||
4 * num_4x4_blocks_wide_lookup[bsize] * sizeof(best_map[0]));
|
||||
memcpy(mic->mbmi.palette_indexed_colors, best_index,
|
||||
best_m1 * sizeof(best_index[0]));
|
||||
memcpy(mic->mbmi.palette_color_delta, palette_color_delta,
|
||||
best_m1 * sizeof(palette_color_delta[0]));
|
||||
memcpy(mic->mbmi.palette_literal_colors, best_literal,
|
||||
best_m2 * sizeof(best_literal[0]));
|
||||
#if CONFIG_FILTERINTRA
|
||||
mic->mbmi.filterbit = 0;
|
||||
#endif // CONFIG_FILTERINTRA
|
||||
}
|
||||
#endif
|
||||
|
||||
return best_rd;
|
||||
}
|
||||
@@ -4128,6 +4440,14 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
rd_cost->rate = INT_MAX;
|
||||
return;
|
||||
}
|
||||
#if CONFIG_PALETTE
|
||||
if (xd->mi[0].src_mi->mbmi.palette_enabled) {
|
||||
palette_color_insertion(ctx->palette_colors_buf,
|
||||
&ctx->palette_buf_size,
|
||||
ctx->palette_count_buf,
|
||||
&(xd->mi[0].src_mi->mbmi));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
y_skip = 0;
|
||||
if (rd_pick_intra_sub_8x8_y_mode(cpi, x, &rate_y, &rate_y_tokenonly,
|
||||
@@ -4255,7 +4575,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
int tx_skipped_uv[TX_SIZES];
|
||||
int q_idx = vp9_get_qindex(seg, segment_id, cm->base_qindex);
|
||||
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA;
|
||||
#endif
|
||||
#endif // CONFIG_TX_SKIP
|
||||
#if CONFIG_COPY_MODE
|
||||
COPY_MODE copy_mode;
|
||||
int inter_ref_count;
|
||||
@@ -4644,10 +4964,13 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
#if CONFIG_TX_SKIP
|
||||
mbmi->tx_skip[0] = 0;
|
||||
mbmi->tx_skip[1] = 0;
|
||||
#endif
|
||||
#endif // CONFIG_TX_SKIP
|
||||
#if CONFIG_COPY_MODE
|
||||
mbmi->copy_mode = NOREF;
|
||||
#endif
|
||||
#endif // CONFIG_COPY_MODE
|
||||
#if CONFIG_PALETTE
|
||||
mbmi->palette_enabled = 0;
|
||||
#endif // CONFIG_PALETTE
|
||||
// Evaluate all sub-pel filters irrespective of whether we can use
|
||||
// them for this frame.
|
||||
mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
|
||||
|
||||
@@ -89,6 +89,29 @@ static INLINE void vp9_write_literal(vp9_writer *w, int data, int bits) {
|
||||
vp9_write_bit(w, 1 & (data >> bit));
|
||||
}
|
||||
|
||||
static INLINE void vp9_encode_uniform(vp9_writer *w, int n, int v) {
|
||||
int l = get_unsigned_bits(n);
|
||||
int m = (1 << l) - n;
|
||||
if (l == 0)
|
||||
return;
|
||||
if (v < m) {
|
||||
vp9_write_literal(w, v, l - 1);
|
||||
} else {
|
||||
vp9_write_literal(w, m + ((v - m) >> 1), l - 1);
|
||||
vp9_write_literal(w, (v - m) & 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE int vp9_encode_uniform_cost(int n, int v) {
|
||||
int l = get_unsigned_bits(n), m = (1 << l) - n;
|
||||
if (l == 0)
|
||||
return 0;
|
||||
if (v < m)
|
||||
return l - 1;
|
||||
else
|
||||
return l;
|
||||
}
|
||||
|
||||
#define vp9_write_prob(w, v) vp9_write_literal((w), (v), 8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -35,6 +35,8 @@ VP9_COMMON_SRCS-yes += common/vp9_idct.h
|
||||
VP9_COMMON_SRCS-yes += common/vp9_loopfilter.h
|
||||
VP9_COMMON_SRCS-yes += common/vp9_mv.h
|
||||
VP9_COMMON_SRCS-yes += common/vp9_onyxc_int.h
|
||||
VP9_COMMON_SRCS-$(CONFIG_EXPERIMENTAL) += common/vp9_palette.h
|
||||
VP9_COMMON_SRCS-$(CONFIG_EXPERIMENTAL) += common/vp9_palette.c
|
||||
VP9_COMMON_SRCS-yes += common/vp9_pred_common.h
|
||||
VP9_COMMON_SRCS-yes += common/vp9_pred_common.c
|
||||
VP9_COMMON_SRCS-yes += common/vp9_prob.h
|
||||
|
||||
Reference in New Issue
Block a user