Commit c6f1bf43 authored by Deb Mukherjee's avatar Deb Mukherjee

Differential encoding of probability updates

Adds differential encoding of prob updates using a subexponential
code centered around the previous probability value.
Also searches for the most cost-effective update, and breaks
up the coefficient updates into smaller groups.

Small gain on Derf: 0.2%

Change-Id: Ie0071e3dc113e3d0d7ab95b6442bb07a89970030
parent 2210767c
......@@ -224,6 +224,7 @@ EXPERIMENT_LIST="
sixteenth_subpel_uv
comp_intra_pred
newentropy
newupdate
superblocks
"
CONFIG_LIST="
......
......@@ -173,6 +173,10 @@ vp8_extra_bit_struct vp8_extra_bits[12] =
{ 0, 0, 0, 0}
};
#if CONFIG_NEWUPDATE
const vp8_prob updprobs[4] = {128, 136, 120, 112};
#endif
#include "default_coef_probs.h"
#include "defaultcoefcounts.h"
......
......@@ -82,7 +82,11 @@ extern DECLARE_ALIGNED(64, const unsigned char, vp8_coef_bands_8x8[64]);
distinct bands). */
/*# define DC_TOKEN_CONTEXTS 3*/ /* 00, 0!0, !0!0 */
# define PREV_COEF_CONTEXTS 3
#define PREV_COEF_CONTEXTS 3
#if CONFIG_NEWUPDATE
#define SUBEXP_PARAM 1 /* Subexponential code parameter */
#define COEFUPDATETYPE 2 /* coef update type to use (1/2/3) */
#endif
extern DECLARE_ALIGNED(16, const unsigned char, vp8_prev_token_class[MAX_ENTROPY_TOKENS]);
......
......@@ -50,3 +50,67 @@ void vp8dx_bool_decoder_fill(BOOL_DECODER *br)
br->value = value;
br->count = count;
}
#if CONFIG_NEWUPDATE
static int get_unsigned_bits(unsigned num_values)
{
int cat=0;
if ((num_values--)<=1) return 0;
while (num_values>0)
{
cat++;
num_values>>=1;
}
return cat;
}
int inv_recenter_nonneg(int v, int m)
{
if (v>(m<<1)) return v;
else if ((v&1)==0) return (v>>1)+m;
else return m-((v+1)>>1);
}
int vp8_decode_uniform(BOOL_DECODER *br, int n)
{
int v;
int l=get_unsigned_bits(n);
int m=(1<<l)-n;
if (!l) return 0;
v = vp8_decode_value(br, l-1);
if (v < m)
return v;
else
return (v<<1)-m+vp8_decode_value(br, 1);
}
int vp8_decode_term_subexp(BOOL_DECODER *br, int k, int num_syms)
{
int i=0, mk=0, word;
while (1)
{
int b = (i?k+i-1:k);
int a = (1<<b);
if (num_syms<=mk+3*a)
{
word = vp8_decode_uniform(br, num_syms-mk) + mk;
break;
}
else
{
if (vp8_decode_value(br, 1))
{
i++;
mk += a;
}
else
{
word = vp8_decode_value(br, b) + mk;
break;
}
}
}
return word;
}
#endif
......@@ -42,6 +42,12 @@ int vp8dx_start_decode(BOOL_DECODER *br,
void vp8dx_bool_decoder_fill(BOOL_DECODER *br);
#if CONFIG_NEWUPDATE
int vp8_decode_uniform(BOOL_DECODER *br, int n);
int vp8_decode_term_subexp(BOOL_DECODER *br, int k, int num_syms);
int inv_recenter_nonneg(int v, int m);
#endif
/*The refill loop is used in several places, so define it in a macro to make
sure they're all consistent.
An inline function would be cleaner, but has a significant penalty, because
......@@ -151,4 +157,5 @@ static int vp8dx_bool_error(BOOL_DECODER *br)
/* No error. */
return 0;
}
#endif
......@@ -34,6 +34,7 @@
#include "dboolhuff.h"
#include "vp8/common/seg_common.h"
#include "vp8/common/entropy.h"
#include <assert.h>
#include <stdio.h>
......@@ -43,6 +44,23 @@
int dec_debug = 0;
#endif
#if CONFIG_NEWUPDATE
static int inv_remap_prob(int v, int m)
{
const int n = 256;
int i;
//if (v <= n - 2 - s) v += s; else v = n - 2 - v;
//v = ((v&240)>>4) | ((v&15)<<4);
v = (v%15)*17 + (v/15);
if ((m<<1)<=n) {
i = inv_recenter_nonneg(v+1, m);
} else {
i = n-1-inv_recenter_nonneg(v+1, n-1-m);
}
return i;
}
#endif
void vp8cx_init_de_quantizer(VP8D_COMP *pbi)
{
int i;
......@@ -769,6 +787,170 @@ static void init_frame(VP8D_COMP *pbi)
}
#if CONFIG_NEWUPDATE
static void read_coef_probs3(VP8D_COMP *pbi)
{
const vp8_prob grpupd = 216;
int i, j, k, l;
vp8_reader *const bc = & pbi->bc;
VP8_COMMON *const pc = & pbi->common;
for (i = 0; i < BLOCK_TYPES; i++)
for (l = 0; l < ENTROPY_NODES; l++)
{
if(vp8_read(bc, grpupd))
{
//printf("Decoding %d\n", l);
for (j = !i; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
{
vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
int u = vp8_read(bc, vp8_coef_update_probs [i][j][k][l]);
if (u)
{
int delp = vp8_decode_term_subexp(bc, SUBEXP_PARAM, 255);
*p = (vp8_prob)inv_remap_prob(delp, *p);
}
}
}
}
if(pbi->common.txfm_mode == ALLOW_8X8)
{
for (i = 0; i < BLOCK_TYPES; i++)
for (l = 0; l < ENTROPY_NODES; l++)
{
if(vp8_read(bc, grpupd))
{
for (j = !i; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
{
vp8_prob *const p = pc->fc.coef_probs_8x8 [i][j][k] + l;
int u = vp8_read(bc, vp8_coef_update_probs_8x8 [i][j][k][l]);
if (u)
{
int delp = vp8_decode_term_subexp(bc, SUBEXP_PARAM, 255);
*p = (vp8_prob)inv_remap_prob(delp, *p);
}
}
}
}
}
}
static void read_coef_probs2(VP8D_COMP *pbi)
{
const vp8_prob grpupd = 192;
int i, j, k, l;
vp8_reader *const bc = & pbi->bc;
VP8_COMMON *const pc = & pbi->common;
for (l = 0; l < ENTROPY_NODES; l++)
{
if(vp8_read(bc, grpupd))
{
//printf("Decoding %d\n", l);
for (i = 0; i < BLOCK_TYPES; i++)
for (j = !i; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
{
vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
int u = vp8_read(bc, vp8_coef_update_probs [i][j][k][l]);
if (u)
{
int delp = vp8_decode_term_subexp(bc, SUBEXP_PARAM, 255);
*p = (vp8_prob)inv_remap_prob(delp, *p);
}
}
}
}
if(pbi->common.txfm_mode == ALLOW_8X8)
{
for (l = 0; l < ENTROPY_NODES; l++)
{
if(vp8_read(bc, grpupd))
{
for (i = 0; i < BLOCK_TYPES; i++)
for (j = !i; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
{
vp8_prob *const p = pc->fc.coef_probs_8x8 [i][j][k] + l;
int u = vp8_read(bc, vp8_coef_update_probs_8x8 [i][j][k][l]);
if (u)
{
int delp = vp8_decode_term_subexp(bc, SUBEXP_PARAM, 255);
*p = (vp8_prob)inv_remap_prob(delp, *p);
}
}
}
}
}
}
#endif
static void read_coef_probs(VP8D_COMP *pbi)
{
int i, j, k, l;
vp8_reader *const bc = & pbi->bc;
VP8_COMMON *const pc = & pbi->common;
{
if(vp8_read_bit(bc))
{
/* read coef probability tree */
for (i = 0; i < BLOCK_TYPES; i++)
#if CONFIG_NEWUPDATE
for (j = !i; j < COEF_BANDS; j++)
#else
for (j = 0; j < COEF_BANDS; j++)
#endif
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
for (l = 0; l < ENTROPY_NODES; l++)
{
vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
if (vp8_read(bc, vp8_coef_update_probs [i][j][k][l]))
{
#if CONFIG_NEWUPDATE
int delp = vp8_decode_term_subexp(bc, SUBEXP_PARAM, 255);
//printf("delp = %d/%d", *p, delp);
*p = (vp8_prob)inv_remap_prob(delp, *p);
//printf("/%d\n", *p);
#else
*p = (vp8_prob)vp8_read_literal(bc, 8);
#endif
}
}
}
}
if(pbi->common.txfm_mode == ALLOW_8X8 && vp8_read_bit(bc))
{
// read coef probability tree
for (i = 0; i < BLOCK_TYPES; i++)
#if CONFIG_NEWUPDATE
for (j = !i; j < COEF_BANDS; j++)
#else
for (j = 0; j < COEF_BANDS; j++)
#endif
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
for (l = 0; l < ENTROPY_NODES; l++)
{
vp8_prob *const p = pc->fc.coef_probs_8x8 [i][j][k] + l;
if (vp8_read(bc, vp8_coef_update_probs_8x8 [i][j][k][l]))
{
#if CONFIG_NEWUPDATE
int delp = vp8_decode_term_subexp(bc, SUBEXP_PARAM, 255);
*p = (vp8_prob)inv_remap_prob(delp, *p);
#else
*p = (vp8_prob)vp8_read_literal(bc, 8);
#endif
}
}
}
}
int vp8_decode_frame(VP8D_COMP *pbi)
{
vp8_reader *const bc = & pbi->bc;
......@@ -1198,44 +1380,13 @@ int vp8_decode_frame(VP8D_COMP *pbi)
fclose(z);
}
{
if(vp8_read_bit(bc))
{
/* read coef probability tree */
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
for (l = 0; l < ENTROPY_NODES; l++)
{
vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
if (vp8_read(bc, vp8_coef_update_probs [i][j][k][l]))
{
*p = (vp8_prob)vp8_read_literal(bc, 8);
}
}
}
}
if(pbi->common.txfm_mode == ALLOW_8X8 && vp8_read_bit(bc))
{
// read coef probability tree
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
for (l = 0; l < MAX_ENTROPY_TOKENS - 1; l++)
{
vp8_prob *const p = pc->fc.coef_probs_8x8 [i][j][k] + l;
if (vp8_read(bc, vp8_coef_update_probs_8x8 [i][j][k][l]))
{
*p = (vp8_prob)vp8_read_literal(bc, 8);
}
}
}
#if COEFUPDATETYPE == 2
read_coef_probs2(pbi);
#elif COEFUPDATETYPE == 3
read_coef_probs3(pbi);
#else
read_coef_probs(pbi);
#endif
vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->lst_fb_idx], sizeof(YV12_BUFFER_CONFIG));
......
This diff is collapsed.
......@@ -68,3 +68,99 @@ void vp8_encode_value(BOOL_CODER *br, int data, int bits)
vp8_encode_bool(br, (1 & (data >> bit)), 0x80);
}
#if CONFIG_NEWUPDATE
int recenter_nonneg(int v, int m)
{
if (v > (m<<1)) return v;
else if (v >= m) return ((v-m)<<1);
else return ((m-v)<<1)-1;
}
static int get_unsigned_bits(unsigned num_values)
{
int cat=0;
if ((num_values--)<=1) return 0;
while (num_values>0)
{
cat++;
num_values>>=1;
}
return cat;
}
void vp8_encode_uniform(BOOL_CODER *br, int v, int n)
{
int l = get_unsigned_bits(n);
if (l == 0) return;
int m = (1<<l)-n;
if (v<m)
vp8_encode_value(br, v, l-1);
else
{
vp8_encode_value(br, m+((v-m)>>1), l-1);
vp8_encode_value(br, (v-m)&1, 1);
}
}
int vp8_count_uniform(int v, int n)
{
int l = get_unsigned_bits(n);
if (l == 0) return 0;
int m = (1<<l)-n;
if (v<m)
return l-1;
else
return l;
}
void vp8_encode_term_subexp(BOOL_CODER *br, int word, int k, int num_syms)
{
int i = 0;
int mk = 0;
while (1) {
int b = (i?k+i-1:k);
int a = (1<<b);
if (num_syms<=mk+3*a) {
vp8_encode_uniform(br, word-mk, num_syms-mk);
break;
} else {
int t = (word>=mk+a);
vp8_encode_value(br, t, 1);
if (t) {
i=i+1;
mk+=a;
} else {
vp8_encode_value(br, word-mk, b);
break;
}
}
}
}
int vp8_count_term_subexp(int word, int k, int num_syms)
{
int count = 0;
int i = 0;
int mk = 0;
while (1) {
int b = (i?k+i-1:k);
int a = (1<<b);
if (num_syms<=mk+3*a) {
count += vp8_count_uniform(num_syms-mk, word-mk);
break;
} else {
int t = (word>=mk+a);
count++;
if (t) {
i=i+1;
mk+=a;
} else {
count += b;
break;
}
}
}
return count;
}
#endif
......@@ -41,6 +41,13 @@ extern void vp8_encode_value(BOOL_CODER *br, int data, int bits);
extern void vp8_stop_encode(BOOL_CODER *bc);
extern const unsigned int vp8_prob_cost[256];
#if CONFIG_NEWENTROPY
extern void vp8_encode_uniform(BOOL_CODER *bc, int v, int n);
extern void vp8_encode_term_subexp(BOOL_CODER *bc, int v, int k, int n);
extern int vp8_count_uniform(int v, int n);
extern int vp8_count_term_subexp(int v, int k, int n);
extern int recenter_nonneg(int v, int m);
#endif
DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
......
......@@ -50,6 +50,14 @@ static __inline unsigned int vp8_cost_branch(const unsigned int ct[2], vp8_prob
+ (ct[1] * vp8_cost_one(p))) >> 8;
}
static __inline unsigned int vp8_cost_branch256(const unsigned int ct[2], vp8_prob p)
{
/* Imitate existing calculation */
return ((ct[0] * vp8_cost_zero(p))
+ (ct[1] * vp8_cost_one(p)));
}
/* Small functions to write explicit values and tokens, as well as
estimate their lengths. */
......
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