int_8x8fdct
newintramodes
adaptive_entropy
+ pred_filter
"
CONFIG_LIST="
external_build
// 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
#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
/*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)
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);
}
}
/*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);
}
}
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;
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)
{
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 ((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 filter
#if CONFIG_SIXTEENTH_SUBPEL_UV
- x->subpixel_predict_avg16x16(ptr, pre_stride, (mv_col & 7)<<1, (mv_row & 7)<<1, dst_y, dst_ystride);
+ x->subpixel_predict_avg16x16(pTemp, len, (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);
+ 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 */
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)
{
#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);
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 ))) )
#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);
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))
{
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;
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);
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
&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)
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;
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;
#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_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_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;
+ sf->thresh_mult[THR_NEARMV ] = 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_NEARESTA ] = 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_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_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;
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
}
+#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,
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.
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);
#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
MBGRAPH_MB_STATS *mb_stats;
} MBGRAPH_FRAME_STATS;
+#if CONFIG_PRED_FILTER
+typedef enum
+{
+ THR_ZEROMV,
+ THR_ZEROMV_FILT,
+ THR_DC,
+
+ THR_NEARESTMV,
+ THR_NEARESTMV_FILT,
+ THR_NEARMV,
+ THR_NEARMV_FILT,
+
+ THR_ZEROG,
+ THR_ZEROG_FILT,
+ THR_NEARESTG,
+ THR_NEARESTG_FILT,
+
+ THR_ZEROA,
+ THR_ZEROA_FILT,
+ THR_NEARESTA,
+ THR_NEARESTA_FILT,
+
+ THR_NEARG,
+ THR_NEARG_FILT,
+ THR_NEARA,
+ THR_NEARA_FILT,
+
+ 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 = 0,
- THR_DC = 1,
+ THR_ZEROMV,
+ THR_DC,
- THR_NEARESTMV = 2,
- THR_NEARMV = 3,
+ THR_NEARESTMV,
+ THR_NEARMV,
- THR_ZEROG = 4,
- THR_NEARESTG = 5,
+ THR_ZEROG,
+ THR_NEARESTG,
- THR_ZEROA = 6,
- THR_NEARESTA = 7,
+ THR_ZEROA,
+ THR_NEARESTA,
- THR_NEARG = 8,
- THR_NEARA = 9,
+ THR_NEARG,
+ THR_NEARA,
- THR_V_PRED = 10,
- THR_H_PRED = 11,
+ THR_V_PRED,
+ THR_H_PRED,
#if CONFIG_NEWINTRAMODES
THR_D45_PRED,
THR_D135_PRED,
THR_COMP_SPLITLG,
THR_COMP_SPLITLA,
- THR_COMP_SPLITGA,
+ THR_COMP_SPLITGA
}
THR_MODES;
+#endif
typedef enum
{
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);
#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
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,
-
- NEARESTMV,
- NEARMV,
-
- ZEROMV,
- NEARESTMV,
-
- ZEROMV,
- NEARESTMV,
-
- NEARMV,
- NEARMV,
-
- V_PRED,
- H_PRED,
+ {ZEROMV, LAST_FRAME, 0, 0},
+ {ZEROMV, LAST_FRAME, 0, 1},
+ {DC_PRED, INTRA_FRAME, 0, 0},
+
+ {NEARESTMV, LAST_FRAME, 0, 0},
+ {NEARESTMV, LAST_FRAME, 0, 1},
+ {NEARMV, LAST_FRAME, 0, 0},
+ {NEARMV, LAST_FRAME, 0, 1},
+
+ {ZEROMV, GOLDEN_FRAME, 0, 0},
+ {ZEROMV, GOLDEN_FRAME, 0, 1},
+ {NEARESTMV, GOLDEN_FRAME, 0, 0},
+ {NEARESTMV, GOLDEN_FRAME, 0, 1},
+
+ {ZEROMV, ALTREF_FRAME, 0, 0},
+ {ZEROMV, ALTREF_FRAME, 0, 1},
+ {NEARESTMV, ALTREF_FRAME, 0, 0},
+ {NEARESTMV, ALTREF_FRAME, 0, 1},
+
+ {NEARMV, GOLDEN_FRAME, 0, 0},
+ {NEARMV, GOLDEN_FRAME, 0, 1},
+ {NEARMV, ALTREF_FRAME, 0, 0},
+ {NEARMV, ALTREF_FRAME, 0, 1},
+
+ {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},
- /* compound prediction modes */
- LAST_FRAME,
- LAST_FRAME,
- LAST_FRAME,
-
- ALTREF_FRAME,
- ALTREF_FRAME,
- ALTREF_FRAME,
-
- GOLDEN_FRAME,
- GOLDEN_FRAME,
- GOLDEN_FRAME,
-
- LAST_FRAME,
- ALTREF_FRAME,
- GOLDEN_FRAME,
-
- LAST_FRAME,
- ALTREF_FRAME,
- GOLDEN_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,
+ {B_PRED, INTRA_FRAME, 0},
+ {I8X8_PRED, INTRA_FRAME, 0},
/* compound prediction modes */
- GOLDEN_FRAME,
- GOLDEN_FRAME,
- GOLDEN_FRAME,
+ {ZEROMV, LAST_FRAME, GOLDEN_FRAME},
+ {NEARESTMV, LAST_FRAME, GOLDEN_FRAME},
+ {NEARMV, LAST_FRAME, GOLDEN_FRAME},
- LAST_FRAME,
- LAST_FRAME,
- LAST_FRAME,
+ {ZEROMV, ALTREF_FRAME, LAST_FRAME},
+ {NEARESTMV, ALTREF_FRAME, LAST_FRAME},
+ {NEARMV, ALTREF_FRAME, LAST_FRAME},
- ALTREF_FRAME,
- ALTREF_FRAME,
- ALTREF_FRAME,
+ {ZEROMV, GOLDEN_FRAME, ALTREF_FRAME},
+ {NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME},
+ {NEARMV, GOLDEN_FRAME, ALTREF_FRAME},
- GOLDEN_FRAME,
- LAST_FRAME,
- ALTREF_FRAME,
+ {NEWMV, LAST_FRAME, GOLDEN_FRAME},
+ {NEWMV, ALTREF_FRAME, LAST_FRAME },
+ {NEWMV, GOLDEN_FRAME, ALTREF_FRAME},
- GOLDEN_FRAME,
- LAST_FRAME,
- ALTREF_FRAME,
+ {SPLITMV, LAST_FRAME, GOLDEN_FRAME},
+ {SPLITMV, ALTREF_FRAME, LAST_FRAME },
+ {SPLITMV, GOLDEN_FRAME, ALTREF_FRAME}
};
+#endif
static void fill_token_costs(
unsigned int (*c)[COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS],
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;
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];
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..
// 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;
}
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 =
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)
{
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)))
{
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;