Added Prediction Filter to Mode Selection

Added the ability to optionally filter the prediction data
when inter modes are selected (excludes SPLITMV, for now).

The mode selection loop considers both the filtered and
non-filtered prediction data when choosing mode. The filter
can be turned on/off at the frame-level, or signaled for
each MB.

Change-Id: I1b783c71d95a361ab36c761b07e8a6b06bc36822
This commit is contained in:
Adrian Grange 2012-06-25 16:23:58 -07:00
parent f3dff40255
commit bbc926dca2
14 changed files with 1024 additions and 183 deletions

1
configure vendored
View File

@ -231,6 +231,7 @@ EXPERIMENT_LIST="
int_8x8fdct
newintramodes
adaptive_entropy
pred_filter
"
CONFIG_LIST="
external_build

View File

@ -214,6 +214,11 @@ typedef struct
// a valid predictor
unsigned char mb_in_image;
#if CONFIG_PRED_FILTER
// Flag to turn prediction signal filter on(1)/off(0 ) at the MB level
unsigned int pred_filter_enabled;
#endif
} MB_MODE_INFO;
typedef struct

View File

@ -287,6 +287,15 @@ typedef struct VP8Common
#if CONFIG_POSTPROC
struct postproc_state postproc_state;
#endif
#if CONFIG_PRED_FILTER
/* Prediction filter variables */
int pred_filter_mode; // 0=disabled at the frame level (no MB filtered)
// 1=enabled at the frame level (all MB filtered)
// 2=specified per MB (1=filtered, 0=non-filtered)
vp8_prob prob_pred_filter_off;
#endif
} VP8_COMMON;
#endif

View File

@ -335,18 +335,153 @@ static void build_inter_predictors2b(MACROBLOCKD *x, BLOCKD *d, int pitch)
/*encoder only*/
void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x)
#if CONFIG_PRED_FILTER
// Select the thresholded or non-thresholded filter
#define USE_THRESH_FILTER 0
#define PRED_FILT_LEN 5
static const int filt_shift = 4;
static const int pred_filter[PRED_FILT_LEN] = {1, 2, 10, 2, 1};
// Alternative filter {1, 1, 4, 1, 1}
#if !USE_THRESH_FILTER
void filter_mb(unsigned char *src, int src_stride,
unsigned char *dst, int dst_stride,
int width, int height)
{
int i, j, k;
unsigned int Temp[32*32];
unsigned int *pTmp = Temp;
unsigned char *pSrc = src - (1 + src_stride) * (PRED_FILT_LEN/2);
// Horizontal
for (i=0; i<height+PRED_FILT_LEN-1; i++)
{
for (j=0; j<width; j++)
{
int sum=0;
for (k=0; k<PRED_FILT_LEN; k++)
sum += pSrc[j+k] * pred_filter[k];
pTmp[j] = sum;
}
pSrc += src_stride;
pTmp += width;
}
// Vertical
pTmp = Temp;
for (i=0; i<width; i++)
{
unsigned char *pDst = dst + i;
for (j=0; j<height; j++)
{
int sum=0;
for (k=0; k<PRED_FILT_LEN; k++)
sum += pTmp[(j+k)*width] * pred_filter[k];
// Round
sum = (sum + ((1 << (filt_shift<<1))>>1)) >> (filt_shift << 1);
pDst[j*dst_stride] = (sum < 0 ? 0 : sum > 255 ? 255 : sum);
}
++pTmp;
}
}
#else
// Based on vp8_post_proc_down_and_across_c (postproc.c)
void filter_mb(unsigned char *src, int src_stride,
unsigned char *dst, int dst_stride,
int width, int height)
{
unsigned char *pSrc, *pDst;
int row;
int col;
int i;
int v;
unsigned char d[8];
/* TODO flimit should be linked to the quantizer value */
int flimit = 7;
for (row = 0; row < height; row++)
{
/* post_proc_down for one row */
pSrc = src;
pDst = dst;
for (col = 0; col < width; col++)
{
int kernel = (1 << (filt_shift-1));
int v = pSrc[col];
for (i = -2; i <= 2; i++)
{
if (abs(v - pSrc[col+i*src_stride]) > flimit)
goto down_skip_convolve;
kernel += pred_filter[2+i] * pSrc[col+i*src_stride];
}
v = (kernel >> filt_shift);
down_skip_convolve:
pDst[col] = v;
}
/* now post_proc_across */
pSrc = dst;
pDst = dst;
for (i = 0; i < 8; i++)
d[i] = pSrc[i];
for (col = 0; col < width; col++)
{
int kernel = (1 << (filt_shift-1));
v = pSrc[col];
d[col&7] = v;
for (i = -2; i <= 2; i++)
{
if (abs(v - pSrc[col+i]) > flimit)
goto across_skip_convolve;
kernel += pred_filter[2+i] * pSrc[col+i];
}
d[col&7] = (kernel >> filt_shift);
across_skip_convolve:
if (col >= 2)
pDst[col-2] = d[(col-2)&7];
}
/* handle the last two pixels */
pDst[col-2] = d[(col-2)&7];
pDst[col-1] = d[(col-1)&7];
/* next row */
src += src_stride;
dst += dst_stride;
}
}
#endif // !USE_THRESH_FILTER
#endif // CONFIG_PRED_FILTER
void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *xd)
{
unsigned char *uptr, *vptr;
unsigned char *upred_ptr = &x->predictor[256];
unsigned char *vpred_ptr = &x->predictor[320];
unsigned char *upred_ptr = &xd->predictor[256];
unsigned char *vpred_ptr = &xd->predictor[320];
int omv_row = x->mode_info_context->mbmi.mv.as_mv.row;
int omv_col = x->mode_info_context->mbmi.mv.as_mv.col;
int omv_row = xd->mode_info_context->mbmi.mv.as_mv.row;
int omv_col = xd->mode_info_context->mbmi.mv.as_mv.col;
int mv_row = omv_row;
int mv_col = omv_col;
int offset;
int pre_stride = x->block[16].pre_stride;
int pre_stride = xd->block[16].pre_stride;
/* calc uv motion vectors */
if (mv_row < 0)
@ -362,30 +497,84 @@ void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x)
mv_row /= 2;
mv_col /= 2;
mv_row &= x->fullpixel_mask;
mv_col &= x->fullpixel_mask;
mv_row &= xd->fullpixel_mask;
mv_col &= xd->fullpixel_mask;
offset = (mv_row >> 3) * pre_stride + (mv_col >> 3);
uptr = x->pre.u_buffer + offset;
vptr = x->pre.v_buffer + offset;
uptr = xd->pre.u_buffer + offset;
vptr = xd->pre.v_buffer + offset;
#if CONFIG_PRED_FILTER
if (xd->mode_info_context->mbmi.pred_filter_enabled)
{
int i;
#if CONFIG_ENHANCED_INTERP
int Interp_Extend = 4; // 8-tap filter needs 3+4 pels extension
#else
int Interp_Extend = 3; // 6-tap filter needs 2+3 pels extension
#endif
int len = 7 + (Interp_Extend << 1);
unsigned char Temp[32*32]; // Input data required by sub-pel filter
unsigned char *pTemp = Temp + (Interp_Extend-1)*(len+1);
unsigned char *pSrc = uptr;
unsigned char *pDst = upred_ptr;
// U & V
for (i=0; i<2 ; i++)
{
#if CONFIG_SIXTEENTH_SUBPEL_UV
if ((omv_row | omv_col) & 15)
{
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(pSrc-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel interpolation
xd->subpixel_predict8x8(pTemp, len, omv_col & 15,
omv_row & 15, pDst, 8);
}
#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
if ((mv_row | mv_col) & 7)
{
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(pSrc-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel interpolation
xd->subpixel_predict8x8(pTemp, len, mv_col & 7,
mv_row & 7, pDst, 8);
}
#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
else
{
// Apply prediction filter as we copy from source to destination
filter_mb(pSrc, pre_stride, pDst, 8, 8, 8);
}
// V
pSrc = vptr;
pDst = vpred_ptr;
}
}
else
#endif
#if CONFIG_SIXTEENTH_SUBPEL_UV
if ((omv_row | omv_col) & 15)
{
x->subpixel_predict8x8(uptr, pre_stride, omv_col & 15, omv_row & 15, upred_ptr, 8);
x->subpixel_predict8x8(vptr, pre_stride, omv_col & 15, omv_row & 15, vpred_ptr, 8);
xd->subpixel_predict8x8(uptr, pre_stride, omv_col & 15, omv_row & 15, upred_ptr, 8);
xd->subpixel_predict8x8(vptr, pre_stride, omv_col & 15, omv_row & 15, vpred_ptr, 8);
}
#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
if ((mv_row | mv_col) & 7)
{
x->subpixel_predict8x8(uptr, pre_stride, mv_col & 7, mv_row & 7, upred_ptr, 8);
x->subpixel_predict8x8(vptr, pre_stride, mv_col & 7, mv_row & 7, vpred_ptr, 8);
xd->subpixel_predict8x8(uptr, pre_stride, mv_col & 7, mv_row & 7, upred_ptr, 8);
xd->subpixel_predict8x8(vptr, pre_stride, mv_col & 7, mv_row & 7, vpred_ptr, 8);
}
#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
else
{
RECON_INVOKE(&x->rtcd->recon, copy8x8)(uptr, pre_stride, upred_ptr, 8);
RECON_INVOKE(&x->rtcd->recon, copy8x8)(vptr, pre_stride, vpred_ptr, 8);
RECON_INVOKE(&xd->rtcd->recon, copy8x8)(uptr, pre_stride, upred_ptr, 8);
RECON_INVOKE(&xd->rtcd->recon, copy8x8)(vptr, pre_stride, vpred_ptr, 8);
}
}
@ -494,29 +683,68 @@ void vp8_build_inter4x4_predictors_mbuv(MACROBLOCKD *x)
/*encoder only*/
void vp8_build_inter16x16_predictors_mby(MACROBLOCKD *x)
void vp8_build_inter16x16_predictors_mby(MACROBLOCKD *xd)
{
unsigned char *ptr_base;
unsigned char *ptr;
unsigned char *pred_ptr = x->predictor;
int mv_row = x->mode_info_context->mbmi.mv.as_mv.row;
int mv_col = x->mode_info_context->mbmi.mv.as_mv.col;
int pre_stride = x->block[0].pre_stride;
unsigned char *pred_ptr = xd->predictor;
int mv_row = xd->mode_info_context->mbmi.mv.as_mv.row;
int mv_col = xd->mode_info_context->mbmi.mv.as_mv.col;
int pre_stride = xd->block[0].pre_stride;
ptr_base = x->pre.y_buffer;
ptr_base = xd->pre.y_buffer;
ptr = ptr_base + (mv_row >> 3) * pre_stride + (mv_col >> 3);
#if CONFIG_PRED_FILTER
if (xd->mode_info_context->mbmi.pred_filter_enabled)
{
// Produce predictor from the filtered source
if ((mv_row | mv_col) & 7)
{
// Sub-pel filter needs extended input
#if CONFIG_ENHANCED_INTERP
int Interp_Extend = 4; // 8-tap filter needs 3+4 pels extension
#else
int Interp_Extend = 3; // 6-tap filter needs 2+3 pels extension
#endif
int len = 15 + (Interp_Extend << 1);
unsigned char Temp[32*32]; // Data required by sub-pel filter
unsigned char *pTemp = Temp + (Interp_Extend-1)*(len+1);
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(ptr-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel interpolation
#if CONFIG_SIXTEENTH_SUBPEL_UV
xd->subpixel_predict16x16(pTemp, len, (mv_col & 7)<<1,
(mv_row & 7)<<1, pred_ptr, 16);
#else
xd->subpixel_predict16x16(pTemp, len, mv_col & 7,
mv_row & 7, pred_ptr, 16);
#endif
}
else
{
// Apply spatial filter to create the prediction directly
filter_mb(ptr, pre_stride, pred_ptr, 16, 16, 16);
}
}
else
#endif
if ((mv_row | mv_col) & 7)
{
#if CONFIG_SIXTEENTH_SUBPEL_UV
x->subpixel_predict16x16(ptr, pre_stride, (mv_col & 7)<<1, (mv_row & 7)<<1, pred_ptr, 16);
xd->subpixel_predict16x16(ptr, pre_stride, (mv_col & 7)<<1,
(mv_row & 7)<<1, pred_ptr, 16);
#else
x->subpixel_predict16x16(ptr, pre_stride, mv_col & 7, mv_row & 7, pred_ptr, 16);
xd->subpixel_predict16x16(ptr, pre_stride, mv_col & 7,
mv_row & 7, pred_ptr, 16);
#endif
}
else
{
RECON_INVOKE(&x->rtcd->recon, copy16x16)(ptr, pre_stride, pred_ptr, 16);
RECON_INVOKE(&xd->rtcd->recon, copy16x16)(ptr, pre_stride, pred_ptr, 16);
}
}
@ -582,19 +810,64 @@ void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
clamp_mv_to_umv_border(&_16x16mv.as_mv, x);
}
ptr = ptr_base + ( _16x16mv.as_mv.row >> 3) * pre_stride + (_16x16mv.as_mv.col >> 3);
ptr = ptr_base + (_16x16mv.as_mv.row >> 3) * pre_stride +
(_16x16mv.as_mv.col >> 3);
#if CONFIG_PRED_FILTER
if (x->mode_info_context->mbmi.pred_filter_enabled)
{
if ( _16x16mv.as_int & 0x00070007)
{
// Sub-pel filter needs extended input
#if CONFIG_ENHANCED_INTERP
int Interp_Extend = 4; // 8-tap filter needs 3+4 pels extension
#else
int Interp_Extend = 3; // 6-tap filter needs 2+3 pels extension
#endif
int len = 15 + (Interp_Extend << 1);
unsigned char Temp[32*32]; // Data required by the sub-pel filter
unsigned char *pTemp = Temp + (Interp_Extend-1)*(len+1);
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(ptr-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel filter
#if CONFIG_SIXTEENTH_SUBPEL_UV
x->subpixel_predict16x16(pTemp, len,
(_16x16mv.as_mv.col & 7)<<1,
(_16x16mv.as_mv.row & 7)<<1,
dst_y, dst_ystride);
#else
x->subpixel_predict16x16(pTemp, len,
_16x16mv.as_mv.col & 7,
_16x16mv.as_mv.row & 7,
dst_y, dst_ystride);
#endif
}
else
{
// Apply spatial filter to create the prediction directly
filter_mb(ptr, pre_stride, dst_y, dst_ystride, 16, 16);
}
}
else
#endif
if ( _16x16mv.as_int & 0x00070007)
{
#if CONFIG_SIXTEENTH_SUBPEL_UV
x->subpixel_predict16x16(ptr, pre_stride, (_16x16mv.as_mv.col & 7)<<1, (_16x16mv.as_mv.row & 7)<<1, dst_y, dst_ystride);
x->subpixel_predict16x16(ptr, pre_stride, (_16x16mv.as_mv.col & 7)<<1,
(_16x16mv.as_mv.row & 7)<<1,
dst_y, dst_ystride);
#else
x->subpixel_predict16x16(ptr, pre_stride, _16x16mv.as_mv.col & 7, _16x16mv.as_mv.row & 7, dst_y, dst_ystride);
x->subpixel_predict16x16(ptr, pre_stride, _16x16mv.as_mv.col & 7,
_16x16mv.as_mv.row & 7, dst_y, dst_ystride);
#endif
}
else
{
RECON_INVOKE(&x->rtcd->recon, copy16x16)(ptr, pre_stride, dst_y, dst_ystride);
RECON_INVOKE(&x->rtcd->recon, copy16x16)(ptr, pre_stride, dst_y,
dst_ystride);
}
_o16x16mv = _16x16mv;
@ -620,6 +893,63 @@ void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x,
uptr = x->pre.u_buffer + offset;
vptr = x->pre.v_buffer + offset;
#if CONFIG_PRED_FILTER
if (x->mode_info_context->mbmi.pred_filter_enabled)
{
int i;
unsigned char *pSrc = uptr;
unsigned char *pDst = dst_u;
#if CONFIG_ENHANCED_INTERP
int Interp_Extend = 4; // 8-tap filter needs 3+4 pels extension
#else
int Interp_Extend = 3; // 6-tap filter needs 2+3 pels extension
#endif
int len = 7 + (Interp_Extend << 1);
unsigned char Temp[32*32]; // Data required by the sub-pel filter
unsigned char *pTemp = Temp + (Interp_Extend-1)*(len+1);
// U & V
for (i=0; i<2; i++)
{
#if CONFIG_SIXTEENTH_SUBPEL_UV
if ( _o16x16mv.as_int & 0x000f000f)
{
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(pSrc-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel filter
x->subpixel_predict8x8(pTemp, len,
_o16x16mv.as_mv.col & 15,
_o16x16mv.as_mv.row & 15,
pDst, dst_uvstride);
}
#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
if ( _16x16mv.as_int & 0x00070007)
{
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(pSrc-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel filter
x->subpixel_predict8x8(pTemp, len,
_16x16mv.as_mv.col & 7,
_16x16mv.as_mv.row & 7,
pDst, dst_uvstride);
}
#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
else
{
filter_mb(pSrc, pre_stride, pDst, dst_uvstride, 8, 8);
}
// V
pSrc = vptr;
pDst = dst_v;
}
}
else
#endif
#if CONFIG_SIXTEENTH_SUBPEL_UV
if ( _o16x16mv.as_int & 0x000f000f)
{
@ -687,17 +1017,60 @@ void vp8_build_2nd_inter16x16_predictors_mb(MACROBLOCKD *x,
ptr = ptr_base + (mv_row >> 3) * pre_stride + (mv_col >> 3);
if ((mv_row | mv_col) & 7)
#if CONFIG_PRED_FILTER
if (x->mode_info_context->mbmi.pred_filter_enabled)
{
#if CONFIG_SIXTEENTH_SUBPEL_UV
x->subpixel_predict_avg16x16(ptr, pre_stride, (mv_col & 7)<<1, (mv_row & 7)<<1, dst_y, dst_ystride);
if ((mv_row | mv_col) & 7)
{
// Sub-pel filter needs extended input
#if CONFIG_ENHANCED_INTERP
int Interp_Extend = 4; // 8-tap filter needs 3+4 pels extension
#else
x->subpixel_predict_avg16x16(ptr, pre_stride, mv_col & 7, mv_row & 7, dst_y, dst_ystride);
int Interp_Extend = 3; // 6-tap filter needs 2+3 pels extension
#endif
int len = 15 + (Interp_Extend << 1);
unsigned char Temp[32*32]; // Data required by sub-pel filter
unsigned char *pTemp = Temp + (Interp_Extend-1)*(len+1);
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(ptr-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel filter
#if CONFIG_SIXTEENTH_SUBPEL_UV
x->subpixel_predict_avg16x16(pTemp, len, (mv_col & 7)<<1,
(mv_row & 7)<<1, dst_y, dst_ystride);
#else
x->subpixel_predict_avg16x16(pTemp, len, mv_col & 7,
mv_row & 7, dst_y, dst_ystride);
#endif
}
else
{
// TODO Needs to AVERAGE with the dst_y
// For now, do not apply the prediction filter in these cases!
RECON_INVOKE(&x->rtcd->recon, avg16x16)(ptr, pre_stride, dst_y,
dst_ystride);
}
}
else
#endif // CONFIG_PRED_FILTER
{
RECON_INVOKE(&x->rtcd->recon, avg16x16)(ptr, pre_stride, dst_y, dst_ystride);
if ((mv_row | mv_col) & 7)
{
#if CONFIG_SIXTEENTH_SUBPEL_UV
x->subpixel_predict_avg16x16(ptr, pre_stride, (mv_col & 7)<<1,
(mv_row & 7)<<1, dst_y, dst_ystride);
#else
x->subpixel_predict_avg16x16(ptr, pre_stride, mv_col & 7,
mv_row & 7, dst_y, dst_ystride);
#endif
}
else
{
RECON_INVOKE(&x->rtcd->recon, avg16x16)(ptr, pre_stride, dst_y,
dst_ystride);
}
}
/* calc uv motion vectors */
@ -714,6 +1087,62 @@ void vp8_build_2nd_inter16x16_predictors_mb(MACROBLOCKD *x,
uptr = x->second_pre.u_buffer + offset;
vptr = x->second_pre.v_buffer + offset;
#if CONFIG_PRED_FILTER
if (x->mode_info_context->mbmi.pred_filter_enabled)
{
int i;
#if CONFIG_ENHANCED_INTERP
int Interp_Extend = 4; // 8-tap filter needs 3+4 pels extension
#else
int Interp_Extend = 3; // 6-tap filter needs 2+3 pels extension
#endif
int len = 7 + (Interp_Extend << 1);
unsigned char Temp[32*32]; // Data required by sub-pel filter
unsigned char *pTemp = Temp + (Interp_Extend-1)*(len+1);
unsigned char *pSrc = uptr;
unsigned char *pDst = dst_u;
// U & V
for (i=0; i<2; i++)
{
#if CONFIG_SIXTEENTH_SUBPEL_UV
if ((omv_row | omv_col) & 15)
{
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(pSrc-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel filter
x->subpixel_predict_avg8x8(pTemp, len, omv_col & 15,
omv_row & 15, pDst, dst_uvstride);
}
#else /* CONFIG_SIXTEENTH_SUBPEL_UV */
if ((mv_row | mv_col) & 7)
{
// Copy extended MB into Temp array, applying the spatial filter
filter_mb(pSrc-(Interp_Extend-1)*(pre_stride+1), pre_stride,
Temp, len, len, len);
// Sub-pel filter
x->subpixel_predict_avg8x8(pTemp, len, mv_col & 7, mv_row & 7,
pDst, dst_uvstride);
}
#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */
else
{
// TODO Needs to AVERAGE with the dst_[u|v]
// For now, do not apply the prediction filter here!
RECON_INVOKE(&x->rtcd->recon, avg8x8)(pSrc, pre_stride, pDst,
dst_uvstride);
}
// V
pSrc = vptr;
pDst = dst_v;
}
}
else
#endif // CONFIG_PRED_FILTER
#if CONFIG_SIXTEENTH_SUBPEL_UV
if ((omv_row | omv_col) & 15)
{

View File

@ -527,8 +527,14 @@ static void mb_mode_mv_init(VP8D_COMP *pbi)
#endif
}
if(pbi->common.frame_type != KEY_FRAME)
if(cm->frame_type != KEY_FRAME)
{
#if CONFIG_PRED_FILTER
cm->pred_filter_mode = (vp8_prob)vp8_read_literal(bc, 2);
if (cm->pred_filter_mode == 2)
cm->prob_pred_filter_off = (vp8_prob)vp8_read_literal(bc, 8);
#endif
// Decode the baseline probabilities for decoding reference frame
cm->prob_intra_coded = (vp8_prob)vp8_read_literal(bc, 8);
cm->prob_last_coded = (vp8_prob)vp8_read_literal(bc, 8);
@ -728,6 +734,18 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
vp8_accum_mv_refs(&pbi->common, mbmi->mode, rct);
}
#if CONFIG_PRED_FILTER
if (mbmi->mode >= NEARESTMV && mbmi->mode < SPLITMV)
{
// Is the prediction filter enabled
if (cm->pred_filter_mode == 2)
mbmi->pred_filter_enabled =
vp8_read(bc, cm->prob_pred_filter_off);
else
mbmi->pred_filter_enabled = cm->pred_filter_mode;
}
#endif
if ( cm->comp_pred_mode == COMP_PREDICTION_ONLY ||
(cm->comp_pred_mode == HYBRID_PREDICTION &&
vp8_read(bc, get_pred_prob( cm, xd, PRED_COMP ))) )

View File

@ -815,6 +815,18 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
#endif
}
#if CONFIG_PRED_FILTER
// Write the prediction filter mode used for this frame
vp8_write_literal(w, pc->pred_filter_mode, 2);
// Write prediction filter on/off probability if signaling at MB level
if (pc->pred_filter_mode == 2)
vp8_write_literal(w, pc->prob_pred_filter_off, 8);
//printf("pred_filter_mode:%d prob_pred_filter_off:%d\n",
// pc->pred_filter_mode, pc->prob_pred_filter_off);
#endif
vp8_write_literal(w, pc->prob_intra_coded, 8);
vp8_write_literal(w, pc->prob_last_coded, 8);
vp8_write_literal(w, pc->prob_gf_coded, 8);
@ -1032,6 +1044,18 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
vp8_accum_mv_refs(&cpi->common, mode, ct);
}
#if CONFIG_PRED_FILTER
// Is the prediction filter enabled
if (mode >= NEARESTMV && mode < SPLITMV)
{
if (cpi->common.pred_filter_mode == 2 )
vp8_write(w, mi->pred_filter_enabled,
pc->prob_pred_filter_off);
else
assert (mi->pred_filter_enabled ==
cpi->common.pred_filter_mode);
}
#endif
if (mi->second_ref_frame &&
(mode == NEWMV || mode == SPLITMV))
{

View File

@ -1201,6 +1201,19 @@ static void encode_frame_internal(VP8_COMP *cpi)
cpi->skip_false_count = 0;
#endif
#if CONFIG_PRED_FILTER
if (cm->current_video_frame == 0)
{
// Initially assume that we'll signal the prediction filter
// state at the frame level and that it is off.
cpi->common.pred_filter_mode = 0;
cpi->common.prob_pred_filter_off = 128;
}
cpi->pred_filter_on_count = 0;
cpi->pred_filter_off_count = 0;
#endif
#if 0
// Experimental code
cpi->frame_distortion = 0;

View File

@ -1223,6 +1223,11 @@ void vp8_encode_inter16x16y(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
BLOCK *b = &x->block[0];
#if CONFIG_PRED_FILTER
// Disable the prediction filter for firstpass
x->e_mbd.mode_info_context->mbmi.pred_filter_enabled = 0;
#endif
vp8_build_inter16x16_predictors_mby(&x->e_mbd);
ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, *(b->base_src), x->e_mbd.predictor, b->src_stride);

View File

@ -83,6 +83,17 @@ typedef struct
prototype_submbuv(*submbuv);
} vp8_encodemb_rtcd_vtable_t;
typedef struct
{
MB_PREDICTION_MODE mode;
MV_REFERENCE_FRAME ref_frame;
MV_REFERENCE_FRAME second_ref_frame;
#if CONFIG_PRED_FILTER
int pred_filter_flag;
#endif
} MODE_DEFINITION;
#if CONFIG_RUNTIME_CPU_DETECT
#define ENCODEMB_INVOKE(ctx,fn) (ctx)->fn
#else

View File

@ -104,6 +104,11 @@ static unsigned int do_16x16_motion_iteration
&distortion, &sse);
}
#if CONFIG_PRED_FILTER
// Disable the prediction filter
xd->mode_info_context->mbmi.pred_filter_enabled = 0;
#endif
vp8_set_mbmode_and_mvs(x, NEWMV, dst_mv);
vp8_build_inter16x16_predictors_mby(xd);
//VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)

View File

@ -741,6 +741,41 @@ void vp8_set_speed_features(VP8_COMP *cpi)
switch (Mode)
{
case 0: // best quality mode
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_ZEROMV_FILT ] = 0;
sf->thresh_mult[THR_ZEROG ] = 0;
sf->thresh_mult[THR_ZEROG_FILT ] = 0;
sf->thresh_mult[THR_ZEROA ] = 0;
sf->thresh_mult[THR_ZEROA_FILT ] = 0;
sf->thresh_mult[THR_NEARESTMV ] = 0;
sf->thresh_mult[THR_NEARESTMV_FILT] = 0;
sf->thresh_mult[THR_NEARESTG ] = 0;
sf->thresh_mult[THR_NEARESTG_FILT ] = 0;
sf->thresh_mult[THR_NEARESTA ] = 0;
sf->thresh_mult[THR_NEARESTA_FILT ] = 0;
sf->thresh_mult[THR_NEARMV ] = 0;
sf->thresh_mult[THR_NEARMV_FILT ] = 0;
sf->thresh_mult[THR_NEARG ] = 0;
sf->thresh_mult[THR_NEARG_FILT ] = 0;
sf->thresh_mult[THR_NEARA ] = 0;
sf->thresh_mult[THR_NEARA_FILT ] = 0;
sf->thresh_mult[THR_DC ] = 0;
sf->thresh_mult[THR_V_PRED ] = 1000;
sf->thresh_mult[THR_H_PRED ] = 1000;
sf->thresh_mult[THR_B_PRED ] = 2000;
sf->thresh_mult[THR_I8X8_PRED] = 2000;
sf->thresh_mult[THR_TM ] = 1000;
sf->thresh_mult[THR_NEWMV ] = 1000;
sf->thresh_mult[THR_NEWG ] = 1000;
sf->thresh_mult[THR_NEWA ] = 1000;
sf->thresh_mult[THR_NEWMV_FILT ] = 1000;
sf->thresh_mult[THR_NEWG_FILT ] = 1000;
sf->thresh_mult[THR_NEWA_FILT ] = 1000;
#else
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_ZEROG ] = 0;
sf->thresh_mult[THR_ZEROA ] = 0;
@ -770,7 +805,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_NEWMV ] = 1000;
sf->thresh_mult[THR_NEWG ] = 1000;
sf->thresh_mult[THR_NEWA ] = 1000;
#endif
sf->thresh_mult[THR_SPLITMV ] = 2500;
sf->thresh_mult[THR_SPLITG ] = 5000;
sf->thresh_mult[THR_SPLITA ] = 5000;
@ -800,6 +835,68 @@ void vp8_set_speed_features(VP8_COMP *cpi)
#endif
break;
case 1:
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEARESTMV] = 0;
sf->thresh_mult[THR_NEARESTMV_FILT] = 0;
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_ZEROMV_FILT ] = 0;
sf->thresh_mult[THR_DC ] = 0;
sf->thresh_mult[THR_NEARMV ] = 0;
sf->thresh_mult[THR_NEARMV_FILT ] = 0;
sf->thresh_mult[THR_V_PRED ] = 1000;
sf->thresh_mult[THR_H_PRED ] = 1000;
#if CONFIG_NEWINTRAMODES
sf->thresh_mult[THR_D45_PRED ] = 1000;
sf->thresh_mult[THR_D135_PRED] = 1000;
sf->thresh_mult[THR_D117_PRED] = 1000;
sf->thresh_mult[THR_D153_PRED] = 1000;
sf->thresh_mult[THR_D27_PRED ] = 1000;
sf->thresh_mult[THR_D63_PRED ] = 1000;
#endif
sf->thresh_mult[THR_B_PRED ] = 2500;
sf->thresh_mult[THR_I8X8_PRED] = 2500;
sf->thresh_mult[THR_TM ] = 1000;
sf->thresh_mult[THR_NEARESTG ] = 1000;
sf->thresh_mult[THR_NEARESTG_FILT ] = 1000;
sf->thresh_mult[THR_NEARESTA ] = 1000;
sf->thresh_mult[THR_NEARESTA_FILT ] = 1000;
sf->thresh_mult[THR_ZEROG ] = 1000;
sf->thresh_mult[THR_ZEROA ] = 1000;
sf->thresh_mult[THR_NEARG ] = 1000;
sf->thresh_mult[THR_NEARA ] = 1000;
sf->thresh_mult[THR_ZEROG_FILT ] = 1000;
sf->thresh_mult[THR_ZEROA_FILT ] = 1000;
sf->thresh_mult[THR_NEARG_FILT ] = 1000;
sf->thresh_mult[THR_NEARA_FILT ] = 1000;
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_ZEROG ] = 0;
sf->thresh_mult[THR_ZEROA ] = 0;
sf->thresh_mult[THR_NEARESTMV] = 0;
sf->thresh_mult[THR_NEARESTG ] = 0;
sf->thresh_mult[THR_NEARESTA ] = 0;
sf->thresh_mult[THR_NEARMV ] = 0;
sf->thresh_mult[THR_NEARG ] = 0;
sf->thresh_mult[THR_NEARA ] = 0;
sf->thresh_mult[THR_ZEROMV_FILT ] = 0;
sf->thresh_mult[THR_ZEROG_FILT ] = 0;
sf->thresh_mult[THR_ZEROA_FILT ] = 0;
sf->thresh_mult[THR_NEARESTMV_FILT] = 0;
sf->thresh_mult[THR_NEARESTG_FILT ] = 0;
sf->thresh_mult[THR_NEARESTA_FILT ] = 0;
sf->thresh_mult[THR_NEARMV_FILT ] = 0;
sf->thresh_mult[THR_NEARG_FILT ] = 0;
sf->thresh_mult[THR_NEARA_FILT ] = 0;
sf->thresh_mult[THR_NEWMV ] = 1000;
sf->thresh_mult[THR_NEWG ] = 1000;
sf->thresh_mult[THR_NEWA ] = 1000;
sf->thresh_mult[THR_NEWMV_FILT ] = 1000;
sf->thresh_mult[THR_NEWG_FILT ] = 1000;
sf->thresh_mult[THR_NEWA_FILT ] = 1000;
#else
sf->thresh_mult[THR_NEARESTMV] = 0;
sf->thresh_mult[THR_ZEROMV ] = 0;
sf->thresh_mult[THR_DC ] = 0;
@ -839,7 +936,7 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_NEWMV ] = 1000;
sf->thresh_mult[THR_NEWG ] = 1000;
sf->thresh_mult[THR_NEWA ] = 1000;
#endif
sf->thresh_mult[THR_SPLITMV ] = 1700;
sf->thresh_mult[THR_SPLITG ] = 4500;
sf->thresh_mult[THR_SPLITA ] = 4500;
@ -906,6 +1003,9 @@ void vp8_set_speed_features(VP8_COMP *cpi)
if (cpi->ref_frame_flags & VP8_LAST_FLAG)
{
sf->thresh_mult[THR_NEWMV ] = 2000;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEWMV_FILT ] = 2000;
#endif
sf->thresh_mult[THR_SPLITMV ] = 10000;
sf->thresh_mult[THR_COMP_SPLITLG ] = 20000;
}
@ -916,6 +1016,12 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_ZEROG ] = 1500;
sf->thresh_mult[THR_NEARG ] = 1500;
sf->thresh_mult[THR_NEWG ] = 2000;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEARESTG_FILT ] = 1500;
sf->thresh_mult[THR_ZEROG_FILT ] = 1500;
sf->thresh_mult[THR_NEARG_FILT ] = 1500;
sf->thresh_mult[THR_NEWG_FILT ] = 2000;
#endif
sf->thresh_mult[THR_SPLITG ] = 20000;
sf->thresh_mult[THR_COMP_SPLITGA ] = 20000;
}
@ -926,6 +1032,12 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_ZEROA ] = 1500;
sf->thresh_mult[THR_NEARA ] = 1500;
sf->thresh_mult[THR_NEWA ] = 2000;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEARESTA_FILT ] = 1500;
sf->thresh_mult[THR_ZEROA_FILT ] = 1500;
sf->thresh_mult[THR_NEARA_FILT ] = 1500;
sf->thresh_mult[THR_NEWA_FILT ] = 2000;
#endif
sf->thresh_mult[THR_SPLITA ] = 20000;
sf->thresh_mult[THR_COMP_SPLITLA ] = 10000;
}
@ -972,6 +1084,9 @@ void vp8_set_speed_features(VP8_COMP *cpi)
if (cpi->ref_frame_flags & VP8_LAST_FLAG)
{
sf->thresh_mult[THR_NEWMV ] = 2000;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEWMV_FILT ] = 2000;
#endif
sf->thresh_mult[THR_SPLITMV ] = 25000;
sf->thresh_mult[THR_COMP_SPLITLG ] = 50000;
}
@ -982,6 +1097,12 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_ZEROG ] = 2000;
sf->thresh_mult[THR_NEARG ] = 2000;
sf->thresh_mult[THR_NEWG ] = 2500;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEARESTG_FILT ] = 2000;
sf->thresh_mult[THR_ZEROG_FILT ] = 2000;
sf->thresh_mult[THR_NEARG_FILT ] = 2000;
sf->thresh_mult[THR_NEWG_FILT ] = 2500;
#endif
sf->thresh_mult[THR_SPLITG ] = 50000;
sf->thresh_mult[THR_COMP_SPLITGA ] = 50000;
}
@ -992,6 +1113,12 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_ZEROA ] = 2000;
sf->thresh_mult[THR_NEARA ] = 2000;
sf->thresh_mult[THR_NEWA ] = 2500;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEARESTA_FILT ] = 2000;
sf->thresh_mult[THR_ZEROA_FILT ] = 2000;
sf->thresh_mult[THR_NEARA_FILT ] = 2000;
sf->thresh_mult[THR_NEWA_FILT ] = 2500;
#endif
sf->thresh_mult[THR_SPLITA ] = 50000;
sf->thresh_mult[THR_COMP_SPLITLA ] = 25000;
}
@ -1029,6 +1156,12 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_NEARESTMV] = INT_MAX;
sf->thresh_mult[THR_ZEROMV ] = INT_MAX;
sf->thresh_mult[THR_NEARMV ] = INT_MAX;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEWMV_FILT ] = INT_MAX;
sf->thresh_mult[THR_NEARESTMV_FILT] = INT_MAX;
sf->thresh_mult[THR_ZEROMV_FILT ] = INT_MAX;
sf->thresh_mult[THR_NEARMV_FILT ] = INT_MAX;
#endif
sf->thresh_mult[THR_SPLITMV ] = INT_MAX;
}
@ -1038,6 +1171,12 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_ZEROG ] = INT_MAX;
sf->thresh_mult[THR_NEARG ] = INT_MAX;
sf->thresh_mult[THR_NEWG ] = INT_MAX;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEARESTG_FILT ] = INT_MAX;
sf->thresh_mult[THR_ZEROG_FILT ] = INT_MAX;
sf->thresh_mult[THR_NEARG_FILT ] = INT_MAX;
sf->thresh_mult[THR_NEWG_FILT ] = INT_MAX;
#endif
sf->thresh_mult[THR_SPLITG ] = INT_MAX;
}
@ -1047,6 +1186,12 @@ void vp8_set_speed_features(VP8_COMP *cpi)
sf->thresh_mult[THR_ZEROA ] = INT_MAX;
sf->thresh_mult[THR_NEARA ] = INT_MAX;
sf->thresh_mult[THR_NEWA ] = INT_MAX;
#if CONFIG_PRED_FILTER
sf->thresh_mult[THR_NEARESTA_FILT ] = INT_MAX;
sf->thresh_mult[THR_ZEROA_FILT ] = INT_MAX;
sf->thresh_mult[THR_NEARA_FILT ] = INT_MAX;
sf->thresh_mult[THR_NEWA_FILT ] = INT_MAX;
#endif
sf->thresh_mult[THR_SPLITA ] = INT_MAX;
}
@ -2866,6 +3011,55 @@ void loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm)
}
#if CONFIG_PRED_FILTER
void select_pred_filter_mode(VP8_COMP *cpi)
{
VP8_COMMON *cm = &cpi->common;
int prob_pred_filter_off = cm->prob_pred_filter_off;
// Force filter on/off if probability is extreme
if (prob_pred_filter_off >= 255 * 0.95)
cm->pred_filter_mode = 0; // Off at the frame level
else if (prob_pred_filter_off <= 255 * 0.05)
cm->pred_filter_mode = 1; // On at the frame level
else
cm->pred_filter_mode = 2; // Selectable at the MB level
}
void update_pred_filt_prob(VP8_COMP *cpi)
{
VP8_COMMON *cm = &cpi->common;
int prob_pred_filter_off;
// Based on the selection in the previous frame determine what mode
// to use for the current frame and work out the signaling probability
if ( cpi->pred_filter_on_count + cpi->pred_filter_off_count )
{
prob_pred_filter_off = cpi->pred_filter_off_count * 256 /
( cpi->pred_filter_on_count + cpi->pred_filter_off_count);
if (prob_pred_filter_off < 1)
prob_pred_filter_off = 1;
if (prob_pred_filter_off > 255)
prob_pred_filter_off = 255;
cm->prob_pred_filter_off = prob_pred_filter_off;
}
else
cm->prob_pred_filter_off = 128;
/*
{
FILE *fp = fopen("filt_use.txt", "a");
fprintf (fp, "%d %d prob=%d\n", cpi->pred_filter_off_count,
cpi->pred_filter_on_count, cm->prob_pred_filter_off);
fclose(fp);
}
*/
}
#endif
static void encode_frame_to_data_rate
(
VP8_COMP *cpi,
@ -3358,6 +3552,13 @@ static void encode_frame_to_data_rate
vp8_clear_system_state(); //__asm emms;
#if CONFIG_PRED_FILTER
// Update prediction filter on/off probability based on
// selection made for the current frame
if (cm->frame_type != KEY_FRAME)
update_pred_filt_prob( cpi );
#endif
// Dummy pack of the bitstream using up to date stats to get an
// accurate estimate of output frame size to determine if we need
// to recode.
@ -3691,6 +3892,13 @@ static void encode_frame_to_data_rate
cpi->dummy_packing = 0;
vp8_pack_bitstream(cpi, dest, size);
#if CONFIG_PRED_FILTER
// Select the prediction filtering mode to use for the
// next frame based on the current frame selections
if(cm->frame_type != KEY_FRAME)
select_pred_filter_mode (cpi);
#endif
update_reference_frames(cm);
#if CONFIG_ADAPTIVE_ENTROPY
vp8_copy(cpi->common.fc.coef_counts, cpi->coef_counts);

View File

@ -43,11 +43,19 @@
#define AF_THRESH2 100
#define ARF_DECAY_THRESH 12
#if CONFIG_PRED_FILTER
#if CONFIG_NEWINTRAMODES
#define MAX_MODES 54
#else
#define MAX_MODES 48
#endif
#else // CONFIG_PRED_FILTER
#if CONFIG_NEWINTRAMODES
#define MAX_MODES 42
#else
#define MAX_MODES 36
#endif
#endif // CONFIG_PRED_FILTER
#define MIN_THRESHMULT 32
#define MAX_THRESHMULT 512
@ -164,25 +172,100 @@ typedef struct
MBGRAPH_MB_STATS *mb_stats;
} MBGRAPH_FRAME_STATS;
#if CONFIG_PRED_FILTER
typedef enum
{
THR_ZEROMV = 0,
THR_DC = 1,
THR_ZEROMV,
THR_ZEROMV_FILT,
THR_DC,
THR_NEARESTMV = 2,
THR_NEARMV = 3,
THR_NEARESTMV,
THR_NEARESTMV_FILT,
THR_NEARMV,
THR_NEARMV_FILT,
THR_ZEROG = 4,
THR_NEARESTG = 5,
THR_ZEROG,
THR_ZEROG_FILT,
THR_NEARESTG,
THR_NEARESTG_FILT,
THR_ZEROA = 6,
THR_NEARESTA = 7,
THR_ZEROA,
THR_ZEROA_FILT,
THR_NEARESTA,
THR_NEARESTA_FILT,
THR_NEARG = 8,
THR_NEARA = 9,
THR_NEARG,
THR_NEARG_FILT,
THR_NEARA,
THR_NEARA_FILT,
THR_V_PRED = 10,
THR_H_PRED = 11,
THR_V_PRED,
THR_H_PRED,
#if CONFIG_NEWINTRAMODES
THR_D45_PRED,
THR_D135_PRED,
THR_D117_PRED,
THR_D153_PRED,
THR_D27_PRED,
THR_D63_PRED,
#endif
THR_TM,
THR_NEWMV,
THR_NEWMV_FILT,
THR_NEWG,
THR_NEWG_FILT,
THR_NEWA,
THR_NEWA_FILT,
THR_SPLITMV,
THR_SPLITG,
THR_SPLITA,
THR_B_PRED,
THR_I8X8_PRED,
THR_COMP_ZEROLG,
THR_COMP_NEARESTLG,
THR_COMP_NEARLG,
THR_COMP_ZEROLA,
THR_COMP_NEARESTLA,
THR_COMP_NEARLA,
THR_COMP_ZEROGA,
THR_COMP_NEARESTGA,
THR_COMP_NEARGA,
THR_COMP_NEWLG,
THR_COMP_NEWLA,
THR_COMP_NEWGA,
THR_COMP_SPLITLG,
THR_COMP_SPLITLA,
THR_COMP_SPLITGA,
}
THR_MODES;
#else
typedef enum
{
THR_ZEROMV,
THR_DC,
THR_NEARESTMV,
THR_NEARMV,
THR_ZEROG,
THR_NEARESTG,
THR_ZEROA,
THR_NEARESTA,
THR_NEARG,
THR_NEARA,
THR_V_PRED,
THR_H_PRED,
#if CONFIG_NEWINTRAMODES
THR_D45_PRED,
THR_D135_PRED,
@ -222,9 +305,10 @@ typedef enum
THR_COMP_SPLITLG,
THR_COMP_SPLITLA,
THR_COMP_SPLITGA,
THR_COMP_SPLITGA
}
THR_MODES;
#endif
typedef enum
{
@ -679,6 +763,11 @@ typedef struct VP8_COMP
int dummy_packing; /* flag to indicate if packing is dummy */
#if CONFIG_PRED_FILTER
int pred_filter_on_count;
int pred_filter_off_count;
#endif
} VP8_COMP;
void control_data_rate(VP8_COMP *cpi);

View File

@ -27,9 +27,7 @@
#define MIN_BPB_FACTOR 0.005
#define MAX_BPB_FACTOR 50
extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
extern const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES];
extern const MODE_DEFINITION vp8_mode_order[MAX_MODES];
#ifdef MODE_STATS

View File

@ -81,161 +81,145 @@ static const int auto_speed_thresh[17] =
105
};
const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES] =
#if CONFIG_PRED_FILTER
const MODE_DEFINITION vp8_mode_order[MAX_MODES] =
{
ZEROMV,
DC_PRED,
{ZEROMV, LAST_FRAME, 0, 0},
{ZEROMV, LAST_FRAME, 0, 1},
{DC_PRED, INTRA_FRAME, 0, 0},
NEARESTMV,
NEARMV,
{NEARESTMV, LAST_FRAME, 0, 0},
{NEARESTMV, LAST_FRAME, 0, 1},
{NEARMV, LAST_FRAME, 0, 0},
{NEARMV, LAST_FRAME, 0, 1},
ZEROMV,
NEARESTMV,
{ZEROMV, GOLDEN_FRAME, 0, 0},
{ZEROMV, GOLDEN_FRAME, 0, 1},
{NEARESTMV, GOLDEN_FRAME, 0, 0},
{NEARESTMV, GOLDEN_FRAME, 0, 1},
ZEROMV,
NEARESTMV,
{ZEROMV, ALTREF_FRAME, 0, 0},
{ZEROMV, ALTREF_FRAME, 0, 1},
{NEARESTMV, ALTREF_FRAME, 0, 0},
{NEARESTMV, ALTREF_FRAME, 0, 1},
NEARMV,
NEARMV,
{NEARMV, GOLDEN_FRAME, 0, 0},
{NEARMV, GOLDEN_FRAME, 0, 1},
{NEARMV, ALTREF_FRAME, 0, 0},
{NEARMV, ALTREF_FRAME, 0, 1},
V_PRED,
H_PRED,
{V_PRED, INTRA_FRAME, 0, 0},
{H_PRED, INTRA_FRAME, 0, 0},
#if CONFIG_NEWINTRAMODES
D45_PRED,
D135_PRED,
D117_PRED,
D153_PRED,
D27_PRED,
D63_PRED,
{D45_PRED, INTRA_FRAME, 0, 0},
{D135_PRED, INTRA_FRAME, 0, 0},
{D117_PRED, INTRA_FRAME, 0, 0},
{D153_PRED, INTRA_FRAME, 0, 0},
{D27_PRED, INTRA_FRAME, 0, 0},
{D63_PRED, INTRA_FRAME, 0, 0},
#endif
TM_PRED,
NEWMV,
NEWMV,
NEWMV,
{TM_PRED, INTRA_FRAME, 0, 0},
SPLITMV,
SPLITMV,
SPLITMV,
{NEWMV, LAST_FRAME, 0, 0},
{NEWMV, LAST_FRAME, 0, 1},
{NEWMV, GOLDEN_FRAME, 0, 0},
{NEWMV, GOLDEN_FRAME, 0, 1},
{NEWMV, ALTREF_FRAME, 0, 0},
{NEWMV, ALTREF_FRAME, 0, 1},
B_PRED,
I8X8_PRED,
{SPLITMV, LAST_FRAME, 0, 0},
{SPLITMV, GOLDEN_FRAME, 0, 0},
{SPLITMV, ALTREF_FRAME, 0, 0},
{B_PRED, INTRA_FRAME, 0, 0},
{I8X8_PRED, INTRA_FRAME, 0, 0},
/* compound prediction modes */
ZEROMV,
NEARESTMV,
NEARMV,
{ZEROMV, LAST_FRAME, GOLDEN_FRAME, 0},
{NEARESTMV, LAST_FRAME, GOLDEN_FRAME, 0},
{NEARMV, LAST_FRAME, GOLDEN_FRAME, 0},
ZEROMV,
NEARESTMV,
NEARMV,
{ZEROMV, ALTREF_FRAME, LAST_FRAME, 0},
{NEARESTMV, ALTREF_FRAME, LAST_FRAME, 0},
{NEARMV, ALTREF_FRAME, LAST_FRAME, 0},
ZEROMV,
NEARESTMV,
NEARMV,
{ZEROMV, GOLDEN_FRAME, ALTREF_FRAME, 0},
{NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME, 0},
{NEARMV, GOLDEN_FRAME, ALTREF_FRAME, 0},
NEWMV,
NEWMV,
NEWMV,
{NEWMV, LAST_FRAME, GOLDEN_FRAME, 0},
{NEWMV, ALTREF_FRAME, LAST_FRAME, 0},
{NEWMV, GOLDEN_FRAME, ALTREF_FRAME, 0},
SPLITMV,
SPLITMV,
SPLITMV,
{SPLITMV, LAST_FRAME, GOLDEN_FRAME, 0},
{SPLITMV, ALTREF_FRAME, LAST_FRAME, 0},
{SPLITMV, GOLDEN_FRAME, ALTREF_FRAME, 0}
};
const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES] =
#else
const MODE_DEFINITION vp8_mode_order[MAX_MODES] =
{
LAST_FRAME,
INTRA_FRAME,
{ZEROMV, LAST_FRAME, 0},
{DC_PRED, INTRA_FRAME, 0},
LAST_FRAME,
LAST_FRAME,
{NEARESTMV, LAST_FRAME, 0},
{NEARMV, LAST_FRAME, 0},
GOLDEN_FRAME,
GOLDEN_FRAME,
{ZEROMV, GOLDEN_FRAME, 0},
{NEARESTMV, GOLDEN_FRAME, 0},
ALTREF_FRAME,
ALTREF_FRAME,
{ZEROMV, ALTREF_FRAME, 0},
{NEARESTMV, ALTREF_FRAME, 0},
GOLDEN_FRAME,
ALTREF_FRAME,
{NEARMV, GOLDEN_FRAME, 0},
{NEARMV, ALTREF_FRAME, 0},
INTRA_FRAME,
INTRA_FRAME,
{V_PRED, INTRA_FRAME, 0},
{H_PRED, INTRA_FRAME, 0},
#if CONFIG_NEWINTRAMODES
INTRA_FRAME,
INTRA_FRAME,
INTRA_FRAME,
INTRA_FRAME,
INTRA_FRAME,
INTRA_FRAME,
{D45_PRED, INTRA_FRAME, 0},
{D135_PRED, INTRA_FRAME, 0},
{D117_PRED, INTRA_FRAME, 0},
{D153_PRED, INTRA_FRAME, 0},
{D27_PRED, INTRA_FRAME, 0},
{D63_PRED, INTRA_FRAME, 0},
#endif
INTRA_FRAME,
LAST_FRAME,
GOLDEN_FRAME,
ALTREF_FRAME,
{TM_PRED, INTRA_FRAME, 0},
LAST_FRAME,
GOLDEN_FRAME,
ALTREF_FRAME,
{NEWMV, LAST_FRAME, 0},
{NEWMV, GOLDEN_FRAME, 0},
{NEWMV, ALTREF_FRAME, 0},
INTRA_FRAME,
INTRA_FRAME,
{SPLITMV, LAST_FRAME, 0},
{SPLITMV, GOLDEN_FRAME, 0},
{SPLITMV, ALTREF_FRAME, 0},
{B_PRED, INTRA_FRAME, 0},
{I8X8_PRED, INTRA_FRAME, 0},
/* compound prediction modes */
LAST_FRAME,
LAST_FRAME,
LAST_FRAME,
{ZEROMV, LAST_FRAME, GOLDEN_FRAME},
{NEARESTMV, LAST_FRAME, GOLDEN_FRAME},
{NEARMV, LAST_FRAME, GOLDEN_FRAME},
ALTREF_FRAME,
ALTREF_FRAME,
ALTREF_FRAME,
{ZEROMV, ALTREF_FRAME, LAST_FRAME},
{NEARESTMV, ALTREF_FRAME, LAST_FRAME},
{NEARMV, ALTREF_FRAME, LAST_FRAME},
GOLDEN_FRAME,
GOLDEN_FRAME,
GOLDEN_FRAME,
{ZEROMV, GOLDEN_FRAME, ALTREF_FRAME},
{NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME},
{NEARMV, GOLDEN_FRAME, ALTREF_FRAME},
LAST_FRAME,
ALTREF_FRAME,
GOLDEN_FRAME,
{NEWMV, LAST_FRAME, GOLDEN_FRAME},
{NEWMV, ALTREF_FRAME, LAST_FRAME },
{NEWMV, GOLDEN_FRAME, ALTREF_FRAME},
LAST_FRAME,
ALTREF_FRAME,
GOLDEN_FRAME,
{SPLITMV, LAST_FRAME, GOLDEN_FRAME},
{SPLITMV, ALTREF_FRAME, LAST_FRAME },
{SPLITMV, GOLDEN_FRAME, ALTREF_FRAME}
};
const MV_REFERENCE_FRAME vp8_second_ref_frame_order[MAX_MODES] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#if CONFIG_NEWINTRAMODES
0, 0,
0, 0,
0, 0,
#endif
0, 0, 0, 0, 0, 0, 0, 0, 0,
/* compound prediction modes */
GOLDEN_FRAME,
GOLDEN_FRAME,
GOLDEN_FRAME,
LAST_FRAME,
LAST_FRAME,
LAST_FRAME,
ALTREF_FRAME,
ALTREF_FRAME,
ALTREF_FRAME,
GOLDEN_FRAME,
LAST_FRAME,
ALTREF_FRAME,
GOLDEN_FRAME,
LAST_FRAME,
ALTREF_FRAME,
};
static void fill_token_costs(
unsigned int (*c)[COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS],
@ -2827,6 +2811,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
int best_comp_rd = INT_MAX;
int best_single_rd = INT_MAX;
int best_hybrid_rd = INT_MAX;
int best_overall_rd = INT_MAX;
int rate2, distortion2;
int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly;
int uv_intra_skippable = 0;
@ -2835,6 +2820,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
int rate_y, UNINITIALIZED_IS_SAFE(rate_uv);
int distortion_uv;
int best_yrd = INT_MAX;
int best_filter_state;
//int all_rds[MAX_MODES]; // Experimental debug code.
//int all_rates[MAX_MODES];
@ -2978,16 +2964,21 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
rate_y = 0;
rate_uv =0;
this_mode = vp8_mode_order[mode_index];
x->e_mbd.mode_info_context->mbmi.mode = this_mode;
this_mode = vp8_mode_order[mode_index].mode;
xd->mode_info_context->mbmi.mode = this_mode;
xd->mode_info_context->mbmi.uv_mode = DC_PRED;
xd->mode_info_context->mbmi.ref_frame =
vp8_mode_order[mode_index].ref_frame;
xd->mode_info_context->mbmi.second_ref_frame =
vp8_mode_order[mode_index].second_ref_frame;
#if CONFIG_PRED_FILTER
xd->mode_info_context->mbmi.pred_filter_enabled = 0;
#endif
#if CONFIG_COMP_INTRA_PRED
x->e_mbd.mode_info_context->mbmi.second_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
x->e_mbd.mode_info_context->mbmi.second_uv_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
xd->mode_info_context->mbmi.second_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
xd->mode_info_context->mbmi.second_uv_mode = (MB_PREDICTION_MODE) (DC_PRED - 1);
#endif
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
x->e_mbd.mode_info_context->mbmi.ref_frame = vp8_ref_frame_order[mode_index];
x->e_mbd.mode_info_context->mbmi.second_ref_frame = vp8_second_ref_frame_order[mode_index];
// If the segment reference frame feature is enabled....
// then do nothing if the current ref frame is not allowed..
@ -3053,18 +3044,18 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
// Increase zbin size to suppress noise
if (cpi->zbin_mode_boost_enabled)
{
if ( vp8_ref_frame_order[mode_index] == INTRA_FRAME )
if ( vp8_mode_order[mode_index].ref_frame == INTRA_FRAME )
cpi->zbin_mode_boost = 0;
else
{
if (vp8_mode_order[mode_index] == ZEROMV)
if (vp8_mode_order[mode_index].mode == ZEROMV)
{
if (vp8_ref_frame_order[mode_index] != LAST_FRAME)
if (vp8_mode_order[mode_index].ref_frame != LAST_FRAME)
cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
else
cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
}
else if (vp8_mode_order[mode_index] == SPLITMV)
else if (vp8_mode_order[mode_index].mode == SPLITMV)
cpi->zbin_mode_boost = 0;
else
cpi->zbin_mode_boost = MV_ZBIN_BOOST;
@ -3389,6 +3380,15 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
}
vp8_set_mbmode_and_mvs(x, this_mode, &mode_mv[this_mode]);
#if CONFIG_PRED_FILTER
// Filtered prediction:
xd->mode_info_context->mbmi.pred_filter_enabled =
vp8_mode_order[mode_index].pred_filter_flag;
rate2 += vp8_cost_bit( cpi->common.prob_pred_filter_off,
xd->mode_info_context->mbmi.pred_filter_enabled);
#endif
vp8_build_inter16x16_predictors_mby(&x->e_mbd);
compmode_cost =
@ -3741,6 +3741,21 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
best_hybrid_rd = this_rd;
}
#if CONFIG_PRED_FILTER
// Keep track of the best mode irrespective of prediction filter state
if (this_rd < best_overall_rd)
{
best_overall_rd = this_rd;
best_filter_state = xd->mode_info_context->mbmi.pred_filter_enabled;
}
// Ignore modes where the prediction filter state doesn't
// match the state signaled at the frame level
if ((cm->pred_filter_mode == 2) ||
(cm->pred_filter_mode ==
xd->mode_info_context->mbmi.pred_filter_enabled))
{
#endif
// Did this mode help.. i.e. is it the new best mode
if (this_rd < best_rd || x->skip)
{
@ -3833,12 +3848,23 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
best_hybrid_rd = hybrid_rd;
}
}
#if CONFIG_PRED_FILTER
}
#endif
if (x->skip)
break;
}
#if CONFIG_PRED_FILTER
// Update counts for prediction filter usage
if (best_filter_state != 0)
++cpi->pred_filter_on_count;
else
++cpi->pred_filter_off_count;
#endif
// Reduce the activation RD thresholds for the best choice mode
if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2)))
{
@ -3848,7 +3874,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
cpi->rd_threshes[best_mode_index] = (cpi->rd_baseline_thresh[best_mode_index] >> 7) * cpi->rd_thresh_mult[best_mode_index];
// If we chose a split mode then reset the new MV thresholds as well
/*if ( vp8_mode_order[best_mode_index] == SPLITMV )
/*if ( vp8_mode_order[best_mode_index].mode == SPLITMV )
{
best_adjustment = 4; //(cpi->rd_thresh_mult[THR_NEWMV] >> 4);
cpi->rd_thresh_mult[THR_NEWMV] = (cpi->rd_thresh_mult[THR_NEWMV] >= (MIN_THRESHMULT+best_adjustment)) ? cpi->rd_thresh_mult[THR_NEWMV]-best_adjustment: MIN_THRESHMULT;