1fe85a35e0
This patch incorporates adaptive entropy coding of coefficient tokens, and mode/mv information based on distributions encountered in a frame. Specifically, there is an initial forward update to the probabilities in the bitstream as before for coding the symbols in the frame, however at the end of decoding each frame, the forward update to the probabilities is reverted and instead the probabilities are updated towards the actual distributions encountered within the frame. The amount of update is weighted by the number of hits within each context. Results on derf/hd/std-hd are all up by 1.6%. On derf, the most of the gains come from coefficients, however for the hd and std-hd sets, the most of the gains come from the mode/mv information updates. Change-Id: I708c0e11fdacafee04940fe7ae159ba6844005fd
440 lines
14 KiB
C
440 lines
14 KiB
C
/*
|
|
* Copyright (c) 2010 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 "onyxc_int.h"
|
|
#include "entropymv.h"
|
|
|
|
#if CONFIG_HIGH_PRECISION_MV
|
|
const MV_CONTEXT_HP vp8_mv_update_probs_hp[2] =
|
|
{
|
|
{{
|
|
237,
|
|
246,
|
|
253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
|
|
254, 254, 254, 254, 254, 250, 250, 252, 254, 254, 254
|
|
}},
|
|
{{
|
|
231,
|
|
243,
|
|
245, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
|
|
254, 254, 254, 254, 254, 251, 251, 254, 254, 254, 254
|
|
}}
|
|
};
|
|
const MV_CONTEXT_HP vp8_default_mv_context_hp[2] =
|
|
{
|
|
{{
|
|
/* row */
|
|
162, /* is short */
|
|
128, /* sign */
|
|
220, 204, 180, 192, 192, 119, 192, 192, 180, 140, 192, 192, 224, 224, 224, /* short tree */
|
|
128, 129, 132, 75, 145, 178, 206, 239, 254, 254, 254 /* long bits */
|
|
}},
|
|
{{
|
|
/* same for column */
|
|
164, /* is short */
|
|
128,
|
|
220, 204, 180, 192, 192, 119, 192, 192, 180, 140, 192, 192, 224, 224, 224, /* short tree */
|
|
128, 130, 130, 74, 148, 180, 203, 236, 254, 254, 254 /* long bits */
|
|
}}
|
|
};
|
|
#endif /* CONFIG_HIGH_PRECISION_MV */
|
|
|
|
const MV_CONTEXT vp8_mv_update_probs[2] =
|
|
{
|
|
{{
|
|
237,
|
|
246,
|
|
253, 253, 254, 254, 254, 254, 254,
|
|
254, 254, 254, 254, 254, 250, 250, 252, 254, 254
|
|
}},
|
|
{{
|
|
231,
|
|
243,
|
|
245, 253, 254, 254, 254, 254, 254,
|
|
254, 254, 254, 254, 254, 251, 251, 254, 254, 254
|
|
}}
|
|
};
|
|
const MV_CONTEXT vp8_default_mv_context[2] =
|
|
{
|
|
{{
|
|
/* row */
|
|
162, /* is short */
|
|
128, /* sign */
|
|
225, 146, 172, 147, 214, 39, 156, /* short tree */
|
|
128, 129, 132, 75, 145, 178, 206, 239, 254, 254 /* long bits */
|
|
}},
|
|
{{
|
|
/* same for column */
|
|
164, /* is short */
|
|
128,
|
|
204, 170, 119, 235, 140, 230, 228,
|
|
128, 130, 130, 74, 148, 180, 203, 236, 254, 254 /* long bits */
|
|
}}
|
|
};
|
|
|
|
#if CONFIG_HIGH_PRECISION_MV
|
|
const vp8_tree_index vp8_small_mvtree_hp [30] =
|
|
{
|
|
2, 16,
|
|
4, 10,
|
|
6, 8,
|
|
-0, -1,
|
|
-2, -3,
|
|
12, 14,
|
|
-4, -5,
|
|
-6, -7,
|
|
18, 24,
|
|
20, 22,
|
|
-8, -9,
|
|
-10, -11,
|
|
26, 28,
|
|
-12, -13,
|
|
-14, -15
|
|
};
|
|
struct vp8_token_struct vp8_small_mvencodings_hp [16];
|
|
#endif /* CONFIG_HIGH_PRECISION_MV */
|
|
|
|
const vp8_tree_index vp8_small_mvtree [14] =
|
|
{
|
|
2, 8,
|
|
4, 6,
|
|
-0, -1,
|
|
-2, -3,
|
|
10, 12,
|
|
-4, -5,
|
|
-6, -7
|
|
};
|
|
struct vp8_token_struct vp8_small_mvencodings [8];
|
|
|
|
|
|
__inline static void calc_prob(vp8_prob *p, const unsigned int ct[2], int pbits)
|
|
{
|
|
const unsigned int tot = ct[0] + ct[1];
|
|
if (tot)
|
|
{
|
|
const vp8_prob x = ((ct[0] * 255) / tot) & -(1<<(8-pbits));
|
|
*p = x ? x : 1;
|
|
}
|
|
}
|
|
|
|
static void compute_component_probs(
|
|
const unsigned int events [MVvals],
|
|
vp8_prob Pnew [MVPcount],
|
|
unsigned int is_short_ct[2],
|
|
unsigned int sign_ct[2],
|
|
unsigned int bit_ct [mvlong_width] [2],
|
|
unsigned int short_ct [mvnum_short],
|
|
unsigned int short_bct [mvnum_short-1] [2]
|
|
)
|
|
{
|
|
is_short_ct[0] = is_short_ct[1] = 0;
|
|
sign_ct[0] = sign_ct[1] = 0;
|
|
vpx_memset(bit_ct, 0, sizeof(unsigned int)*mvlong_width*2);
|
|
vpx_memset(short_ct, 0, sizeof(unsigned int)*mvnum_short);
|
|
vpx_memset(short_bct, 0, sizeof(unsigned int)*(mvnum_short-1)*2);
|
|
|
|
{
|
|
const int c = events [mv_max];
|
|
is_short_ct [0] += c; // Short vector
|
|
short_ct [0] += c; // Magnitude distribution
|
|
}
|
|
{
|
|
int j = 1;
|
|
do
|
|
{
|
|
const int c1 = events [mv_max + j]; //positive
|
|
const int c2 = events [mv_max - j]; //negative
|
|
const int c = c1 + c2;
|
|
int a = j;
|
|
|
|
sign_ct [0] += c1;
|
|
sign_ct [1] += c2;
|
|
|
|
if (a < mvnum_short)
|
|
{
|
|
is_short_ct [0] += c; // Short vector
|
|
short_ct [a] += c; // Magnitude distribution
|
|
}
|
|
else
|
|
{
|
|
int k = mvlong_width - 1;
|
|
is_short_ct [1] += c; // Long vector
|
|
|
|
do
|
|
bit_ct [k] [(a >> k) & 1] += c;
|
|
|
|
while (--k >= 0);
|
|
}
|
|
}
|
|
while (++j <= mv_max);
|
|
}
|
|
calc_prob(Pnew + mvpis_short, is_short_ct, 8);
|
|
|
|
calc_prob(Pnew + MVPsign, sign_ct, 8);
|
|
|
|
{
|
|
vp8_prob p [mvnum_short - 1]; /* actually only need branch ct */
|
|
int j = 0;
|
|
|
|
vp8_tree_probs_from_distribution(
|
|
mvnum_short, vp8_small_mvencodings, vp8_small_mvtree,
|
|
p, short_bct, short_ct,
|
|
256, 1
|
|
);
|
|
|
|
do
|
|
calc_prob(Pnew + MVPshort + j, short_bct[j], 8);
|
|
while (++j < mvnum_short - 1);
|
|
}
|
|
|
|
{
|
|
int j = 0;
|
|
do
|
|
calc_prob(Pnew + MVPbits + j, bit_ct[j], 8);
|
|
while (++j < mvlong_width);
|
|
}
|
|
}
|
|
|
|
#if CONFIG_HIGH_PRECISION_MV
|
|
static void compute_component_probs_hp(
|
|
const unsigned int events [MVvals_hp],
|
|
vp8_prob Pnew [MVPcount_hp],
|
|
unsigned int is_short_ct[2],
|
|
unsigned int sign_ct[2],
|
|
unsigned int bit_ct [mvlong_width_hp] [2],
|
|
unsigned int short_ct [mvnum_short_hp],
|
|
unsigned int short_bct [mvnum_short_hp-1] [2]
|
|
)
|
|
{
|
|
is_short_ct[0] = is_short_ct[1] = 0;
|
|
sign_ct[0] = sign_ct[1] = 0;
|
|
vpx_memset(bit_ct, 0, sizeof(unsigned int)*mvlong_width_hp*2);
|
|
vpx_memset(short_ct, 0, sizeof(unsigned int)*mvnum_short_hp);
|
|
vpx_memset(short_bct, 0, sizeof(unsigned int)*(mvnum_short_hp-1)*2);
|
|
|
|
{
|
|
const int c = events [mv_max_hp];
|
|
is_short_ct [0] += c; // Short vector
|
|
short_ct [0] += c; // Magnitude distribution
|
|
}
|
|
{
|
|
int j = 1;
|
|
do
|
|
{
|
|
const int c1 = events [mv_max_hp + j]; //positive
|
|
const int c2 = events [mv_max_hp - j]; //negative
|
|
const int c = c1 + c2;
|
|
int a = j;
|
|
|
|
sign_ct [0] += c1;
|
|
sign_ct [1] += c2;
|
|
|
|
if (a < mvnum_short_hp)
|
|
{
|
|
is_short_ct [0] += c; // Short vector
|
|
short_ct [a] += c; // Magnitude distribution
|
|
}
|
|
else
|
|
{
|
|
int k = mvlong_width_hp - 1;
|
|
is_short_ct [1] += c; // Long vector
|
|
|
|
do
|
|
bit_ct [k] [(a >> k) & 1] += c;
|
|
|
|
while (--k >= 0);
|
|
}
|
|
}
|
|
while (++j <= mv_max_hp);
|
|
}
|
|
calc_prob(Pnew + mvpis_short_hp, is_short_ct, 8);
|
|
|
|
calc_prob(Pnew + MVPsign_hp, sign_ct, 8);
|
|
|
|
{
|
|
vp8_prob p [mvnum_short_hp - 1]; /* actually only need branch ct */
|
|
int j = 0;
|
|
|
|
vp8_tree_probs_from_distribution(
|
|
mvnum_short_hp, vp8_small_mvencodings_hp, vp8_small_mvtree_hp,
|
|
p, short_bct, short_ct,
|
|
256, 1
|
|
);
|
|
|
|
do
|
|
calc_prob(Pnew + MVPshort_hp + j, short_bct[j], 8);
|
|
while (++j < mvnum_short_hp - 1);
|
|
}
|
|
|
|
{
|
|
int j = 0;
|
|
do
|
|
calc_prob(Pnew + MVPbits_hp + j, bit_ct[j], 8);
|
|
while (++j < mvlong_width_hp);
|
|
}
|
|
}
|
|
#endif /* CONFIG_HIGH_PRECISION_MV */
|
|
|
|
void vp8_entropy_mv_init()
|
|
{
|
|
vp8_tokens_from_tree(vp8_small_mvencodings, vp8_small_mvtree);
|
|
#if CONFIG_HIGH_PRECISION_MV
|
|
vp8_tokens_from_tree(vp8_small_mvencodings_hp, vp8_small_mvtree_hp);
|
|
#endif
|
|
}
|
|
|
|
#if CONFIG_ADAPTIVE_ENTROPY
|
|
//#define MV_COUNT_TESTING
|
|
#define MV_COUNT_SAT 16
|
|
#define MV_MAX_UPDATE_FACTOR 128
|
|
void vp8_adapt_mv_probs(VP8_COMMON *cm)
|
|
{
|
|
int i, t, count, factor;
|
|
#ifdef MV_COUNT_TESTING
|
|
printf("static const unsigned int\nMVcount[2][MVvals]={\n");
|
|
for (i = 0; i < 2; ++i)
|
|
{
|
|
printf(" { ");
|
|
for (t = 0; t < MVvals; t++)
|
|
{
|
|
printf("%d, ", cm->fc.MVcount[i][t]);
|
|
if (t%16 == 15 && t!=MVvals-1) printf("\n ");
|
|
}
|
|
printf("},\n");
|
|
}
|
|
printf("};\n");
|
|
#if CONFIG_HIGH_PRECISION_MV
|
|
printf("static const unsigned int\nMVcount_hp[2][MVvals_hp]={\n");
|
|
for (i = 0; i < 2; ++i)
|
|
{
|
|
printf(" { ");
|
|
for (t = 0; t < MVvals_hp; t++)
|
|
{
|
|
printf("%d, ", cm->fc.MVcount_hp[i][t]);
|
|
if (t%16 == 15 && t!=MVvals_hp-1) printf("\n ");
|
|
}
|
|
printf("},\n");
|
|
}
|
|
printf("};\n");
|
|
#endif
|
|
#endif /* MV_COUNT_TESTING */
|
|
|
|
for (i = 0; i < 2; ++i)
|
|
{
|
|
int prob;
|
|
unsigned int is_short_ct[2];
|
|
unsigned int sign_ct[2];
|
|
unsigned int bit_ct [mvlong_width] [2];
|
|
unsigned int short_ct [mvnum_short];
|
|
unsigned int short_bct [mvnum_short-1] [2];
|
|
vp8_prob Pnew [MVPcount];
|
|
compute_component_probs(cm->fc.MVcount[i], Pnew,
|
|
is_short_ct, sign_ct,
|
|
bit_ct, short_ct, short_bct);
|
|
count = is_short_ct[0] + is_short_ct[1];
|
|
count = count > MV_COUNT_SAT ? MV_COUNT_SAT : count;
|
|
factor = (MV_MAX_UPDATE_FACTOR * count / MV_COUNT_SAT);
|
|
prob = ((int)cm->fc.pre_mvc[i].prob[mvpis_short] * (256-factor) +
|
|
(int)Pnew[mvpis_short] * factor + 128) >> 8;
|
|
if (prob <= 0) cm->fc.mvc[i].prob[mvpis_short] = 1;
|
|
else if (prob > 255) cm->fc.mvc[i].prob[mvpis_short] = 255;
|
|
else cm->fc.mvc[i].prob[mvpis_short] = prob;
|
|
|
|
count = sign_ct[0] + sign_ct[1];
|
|
count = count > MV_COUNT_SAT ? MV_COUNT_SAT : count;
|
|
factor = (MV_MAX_UPDATE_FACTOR * count / MV_COUNT_SAT);
|
|
prob = ((int)cm->fc.pre_mvc[i].prob[MVPsign] * (256-factor) +
|
|
(int)Pnew[MVPsign] * factor + 128) >> 8;
|
|
if (prob <= 0) cm->fc.mvc[i].prob[MVPsign] = 1;
|
|
else if (prob > 255) cm->fc.mvc[i].prob[MVPsign] = 255;
|
|
else cm->fc.mvc[i].prob[MVPsign] = prob;
|
|
|
|
for (t = 0; t < mvnum_short - 1; ++t)
|
|
{
|
|
count = short_bct[t][0] + short_bct[t][1];
|
|
count = count > MV_COUNT_SAT ? MV_COUNT_SAT : count;
|
|
factor = (MV_MAX_UPDATE_FACTOR * count / MV_COUNT_SAT);
|
|
prob = ((int)cm->fc.pre_mvc[i].prob[MVPshort+t] * (256-factor) +
|
|
(int)Pnew[MVPshort+t] * factor + 128) >> 8;
|
|
if (prob <= 0) cm->fc.mvc[i].prob[MVPshort+t] = 1;
|
|
else if (prob > 255) cm->fc.mvc[i].prob[MVPshort+t] = 255;
|
|
else cm->fc.mvc[i].prob[MVPshort+t] = prob;
|
|
}
|
|
for (t = 0; t < mvlong_width; ++t)
|
|
{
|
|
count = bit_ct[t][0] + bit_ct[t][1];
|
|
count = count > MV_COUNT_SAT ? MV_COUNT_SAT : count;
|
|
factor = (MV_MAX_UPDATE_FACTOR * count / MV_COUNT_SAT);
|
|
prob = ((int)cm->fc.pre_mvc[i].prob[MVPbits+t] * (256-factor) +
|
|
(int)Pnew[MVPbits+t] * factor + 128) >> 8;
|
|
if (prob <= 0) cm->fc.mvc[i].prob[MVPbits+t] = 1;
|
|
else if (prob > 255) cm->fc.mvc[i].prob[MVPbits+t] = 255;
|
|
else cm->fc.mvc[i].prob[MVPbits+t] = prob;
|
|
}
|
|
}
|
|
#if CONFIG_HIGH_PRECISION_MV
|
|
for (i = 0; i < 2; ++i)
|
|
{
|
|
int prob;
|
|
unsigned int is_short_ct[2];
|
|
unsigned int sign_ct[2];
|
|
unsigned int bit_ct [mvlong_width_hp] [2];
|
|
unsigned int short_ct [mvnum_short_hp];
|
|
unsigned int short_bct [mvnum_short_hp-1] [2];
|
|
vp8_prob Pnew [MVPcount_hp];
|
|
compute_component_probs_hp(cm->fc.MVcount_hp[i], Pnew,
|
|
is_short_ct, sign_ct,
|
|
bit_ct, short_ct, short_bct);
|
|
count = is_short_ct[0] + is_short_ct[1];
|
|
count = count > MV_COUNT_SAT ? MV_COUNT_SAT : count;
|
|
factor = (MV_MAX_UPDATE_FACTOR * count / MV_COUNT_SAT);
|
|
prob = ((int)cm->fc.pre_mvc_hp[i].prob[mvpis_short_hp] * (256-factor) +
|
|
(int)Pnew[mvpis_short_hp] * factor + 128) >> 8;
|
|
if (prob <= 0) cm->fc.mvc_hp[i].prob[mvpis_short_hp] = 1;
|
|
else if (prob > 255) cm->fc.mvc_hp[i].prob[mvpis_short_hp] = 255;
|
|
else cm->fc.mvc_hp[i].prob[mvpis_short_hp] = prob;
|
|
|
|
count = sign_ct[0] + sign_ct[1];
|
|
count = count > MV_COUNT_SAT ? MV_COUNT_SAT : count;
|
|
factor = (MV_MAX_UPDATE_FACTOR * count / MV_COUNT_SAT);
|
|
prob = ((int)cm->fc.pre_mvc_hp[i].prob[MVPsign_hp] * (256-factor) +
|
|
(int)Pnew[MVPsign_hp] * factor + 128) >> 8;
|
|
if (prob <= 0) cm->fc.mvc_hp[i].prob[MVPsign_hp] = 1;
|
|
else if (prob > 255) cm->fc.mvc_hp[i].prob[MVPsign_hp] = 255;
|
|
else cm->fc.mvc_hp[i].prob[MVPsign_hp] = prob;
|
|
|
|
for (t = 0; t < mvnum_short_hp - 1; ++t)
|
|
{
|
|
count = short_bct[t][0] + short_bct[t][1];
|
|
count = count > MV_COUNT_SAT ? MV_COUNT_SAT : count;
|
|
factor = (MV_MAX_UPDATE_FACTOR * count / MV_COUNT_SAT);
|
|
prob = ((int)cm->fc.pre_mvc_hp[i].prob[MVPshort_hp+t] * (256-factor) +
|
|
(int)Pnew[MVPshort_hp+t] * factor + 128) >> 8;
|
|
if (prob <= 0) cm->fc.mvc_hp[i].prob[MVPshort_hp+t] = 1;
|
|
else if (prob > 255) cm->fc.mvc_hp[i].prob[MVPshort_hp+t] = 255;
|
|
else cm->fc.mvc_hp[i].prob[MVPshort_hp+t] = prob;
|
|
}
|
|
for (t = 0; t < mvlong_width_hp; ++t)
|
|
{
|
|
count = bit_ct[t][0] + bit_ct[t][1];
|
|
count = count > MV_COUNT_SAT ? MV_COUNT_SAT : count;
|
|
factor = (MV_MAX_UPDATE_FACTOR * count / MV_COUNT_SAT);
|
|
prob = ((int)cm->fc.pre_mvc_hp[i].prob[MVPbits_hp+t] * (256-factor) +
|
|
(int)Pnew[MVPbits_hp+t] * factor + 128) >> 8;
|
|
if (prob <= 0) cm->fc.mvc_hp[i].prob[MVPbits_hp+t] = 1;
|
|
else if (prob > 255) cm->fc.mvc_hp[i].prob[MVPbits_hp+t] = 255;
|
|
else cm->fc.mvc_hp[i].prob[MVPbits_hp+t] = prob;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
#endif /* CONFIG_ADAPTIVE_ENTROPY */
|