5259744145
Allows for swtiching/setting interpolation filters at the MB level. A frame level flag indicates whether to use a specifc filter for the entire frame or to signal the interpolation filter for each MB. When switchable filters are used, the encoder chooses between 8-tap and 8-tap sharp filters. The code currently has options to explore other variations as well, which will be cleaned up subsequently. One issue with the framework is that encoding is slow. I tried to do some tricks to speed things up but it is still slow. Decoding speed should not be affected since the number of filter taps remain unchanged. With the current version, we are up 0.5% on derf on average but some videos city/mobile improve by close to 4 and 2% respectively. If we did a full-search by turning the SEARCH_BEST_FILTER flag on, the results are somewhat better. The framework can be combined with filtered prediction, and I seek feedback regarding that. Rebased. Change-Id: I8f632cb2c111e76284140a2bd480945d6d42b77a
413 lines
13 KiB
C
413 lines
13 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
|
|
}
|
|
|
|
// #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
|
|
}
|