Split filter_mb_dir() out of filter_mb().

1% overall decoding speed up for cathedral-beta2-400extra-crop-avc.mp4
no speed change for Aladin.mpg
Benchmarks done on Pentium dual

Originally committed as revision 16182 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
Michael Niedermayer 16 years ago
parent 6c414bb6d4
commit ad9ca7e720
  1. 248
      libavcodec/h264.c

@ -6241,126 +6241,9 @@ static void filter_mb_fast( H264Context *h, int mb_x, int mb_y, uint8_t *img_y,
} }
} }
static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) {
MpegEncContext * const s = &h->s;
const int mb_xy= mb_x + mb_y*s->mb_stride;
const int mb_type = s->current_picture.mb_type[mb_xy];
const int mvy_limit = IS_INTERLACED(mb_type) ? 2 : 4;
int first_vertical_edge_done = 0;
int dir;
//for sufficiently low qp, filtering wouldn't do anything static void av_always_inline filter_mb_dir(H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize, int mb_xy, int mb_type, int mvy_limit, int first_vertical_edge_done, int dir) {
//this is a conservative estimate: could also check beta_offset and more accurate chroma_qp MpegEncContext * const s = &h->s;
if(!FRAME_MBAFF){
int qp_thresh = 15 - h->slice_alpha_c0_offset - FFMAX3(0, h->pps.chroma_qp_index_offset[0], h->pps.chroma_qp_index_offset[1]);
int qp = s->current_picture.qscale_table[mb_xy];
if(qp <= qp_thresh
&& (mb_x == 0 || ((qp + s->current_picture.qscale_table[mb_xy-1] + 1)>>1) <= qp_thresh)
&& (mb_y == 0 || ((qp + s->current_picture.qscale_table[h->top_mb_xy] + 1)>>1) <= qp_thresh)){
return;
}
}
// CAVLC 8x8dct requires NNZ values for residual decoding that differ from what the loop filter needs
if(!h->pps.cabac && h->pps.transform_8x8_mode){
int top_type, left_type[2];
top_type = s->current_picture.mb_type[h->top_mb_xy] ;
left_type[0] = s->current_picture.mb_type[h->left_mb_xy[0]];
left_type[1] = s->current_picture.mb_type[h->left_mb_xy[1]];
if(IS_8x8DCT(top_type)){
h->non_zero_count_cache[4+8*0]=
h->non_zero_count_cache[5+8*0]= h->cbp_table[h->top_mb_xy] & 4;
h->non_zero_count_cache[6+8*0]=
h->non_zero_count_cache[7+8*0]= h->cbp_table[h->top_mb_xy] & 8;
}
if(IS_8x8DCT(left_type[0])){
h->non_zero_count_cache[3+8*1]=
h->non_zero_count_cache[3+8*2]= h->cbp_table[h->left_mb_xy[0]]&2; //FIXME check MBAFF
}
if(IS_8x8DCT(left_type[1])){
h->non_zero_count_cache[3+8*3]=
h->non_zero_count_cache[3+8*4]= h->cbp_table[h->left_mb_xy[1]]&8; //FIXME check MBAFF
}
if(IS_8x8DCT(mb_type)){
h->non_zero_count_cache[scan8[0 ]]= h->non_zero_count_cache[scan8[1 ]]=
h->non_zero_count_cache[scan8[2 ]]= h->non_zero_count_cache[scan8[3 ]]= h->cbp_table[mb_xy] & 1;
h->non_zero_count_cache[scan8[0+ 4]]= h->non_zero_count_cache[scan8[1+ 4]]=
h->non_zero_count_cache[scan8[2+ 4]]= h->non_zero_count_cache[scan8[3+ 4]]= h->cbp_table[mb_xy] & 2;
h->non_zero_count_cache[scan8[0+ 8]]= h->non_zero_count_cache[scan8[1+ 8]]=
h->non_zero_count_cache[scan8[2+ 8]]= h->non_zero_count_cache[scan8[3+ 8]]= h->cbp_table[mb_xy] & 4;
h->non_zero_count_cache[scan8[0+12]]= h->non_zero_count_cache[scan8[1+12]]=
h->non_zero_count_cache[scan8[2+12]]= h->non_zero_count_cache[scan8[3+12]]= h->cbp_table[mb_xy] & 8;
}
}
if (FRAME_MBAFF
// left mb is in picture
&& h->slice_table[mb_xy-1] != 0xFFFF
// and current and left pair do not have the same interlaced type
&& (IS_INTERLACED(mb_type) != IS_INTERLACED(s->current_picture.mb_type[mb_xy-1]))
// and left mb is in the same slice if deblocking_filter == 2
&& (h->deblocking_filter!=2 || h->slice_table[mb_xy-1] == h->slice_table[mb_xy])) {
/* First vertical edge is different in MBAFF frames
* There are 8 different bS to compute and 2 different Qp
*/
const int pair_xy = mb_x + (mb_y&~1)*s->mb_stride;
const int left_mb_xy[2] = { pair_xy-1, pair_xy-1+s->mb_stride };
int16_t bS[8];
int qp[2];
int bqp[2];
int rqp[2];
int mb_qp, mbn0_qp, mbn1_qp;
int i;
first_vertical_edge_done = 1;
if( IS_INTRA(mb_type) )
bS[0] = bS[1] = bS[2] = bS[3] = bS[4] = bS[5] = bS[6] = bS[7] = 4;
else {
for( i = 0; i < 8; i++ ) {
int mbn_xy = MB_FIELD ? left_mb_xy[i>>2] : left_mb_xy[i&1];
if( IS_INTRA( s->current_picture.mb_type[mbn_xy] ) )
bS[i] = 4;
else if( h->non_zero_count_cache[12+8*(i>>1)] != 0 ||
((!h->pps.cabac && IS_8x8DCT(s->current_picture.mb_type[mbn_xy])) ?
(h->cbp_table[mbn_xy] & ((MB_FIELD ? (i&2) : (mb_y&1)) ? 8 : 2))
:
h->non_zero_count[mbn_xy][MB_FIELD ? i&3 : (i>>2)+(mb_y&1)*2]))
bS[i] = 2;
else
bS[i] = 1;
}
}
mb_qp = s->current_picture.qscale_table[mb_xy];
mbn0_qp = s->current_picture.qscale_table[left_mb_xy[0]];
mbn1_qp = s->current_picture.qscale_table[left_mb_xy[1]];
qp[0] = ( mb_qp + mbn0_qp + 1 ) >> 1;
bqp[0] = ( get_chroma_qp( h, 0, mb_qp ) +
get_chroma_qp( h, 0, mbn0_qp ) + 1 ) >> 1;
rqp[0] = ( get_chroma_qp( h, 1, mb_qp ) +
get_chroma_qp( h, 1, mbn0_qp ) + 1 ) >> 1;
qp[1] = ( mb_qp + mbn1_qp + 1 ) >> 1;
bqp[1] = ( get_chroma_qp( h, 0, mb_qp ) +
get_chroma_qp( h, 0, mbn1_qp ) + 1 ) >> 1;
rqp[1] = ( get_chroma_qp( h, 1, mb_qp ) +
get_chroma_qp( h, 1, mbn1_qp ) + 1 ) >> 1;
/* Filter edge */
tprintf(s->avctx, "filter mb:%d/%d MBAFF, QPy:%d/%d, QPb:%d/%d QPr:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], bqp[0], bqp[1], rqp[0], rqp[1], linesize, uvlinesize);
{ int i; for (i = 0; i < 8; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); }
filter_mb_mbaff_edgev ( h, &img_y [0], linesize, bS, qp );
filter_mb_mbaff_edgecv( h, &img_cb[0], uvlinesize, bS, bqp );
filter_mb_mbaff_edgecv( h, &img_cr[0], uvlinesize, bS, rqp );
}
/* dir : 0 -> vertical edge, 1 -> horizontal edge */
for( dir = 0; dir < 2; dir++ )
{
int edge; int edge;
const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy; const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy;
const int mbm_type = s->current_picture.mb_type[mbm_xy]; const int mbm_type = s->current_picture.mb_type[mbm_xy];
@ -6378,7 +6261,6 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8
if (first_vertical_edge_done) { if (first_vertical_edge_done) {
start = 1; start = 1;
first_vertical_edge_done = 0;
} }
if (h->deblocking_filter==2 && h->slice_table[mbm_xy] != h->slice_table[mb_xy]) if (h->deblocking_filter==2 && h->slice_table[mbm_xy] != h->slice_table[mb_xy])
@ -6561,7 +6443,133 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8
} }
} }
} }
}
static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) {
MpegEncContext * const s = &h->s;
const int mb_xy= mb_x + mb_y*s->mb_stride;
const int mb_type = s->current_picture.mb_type[mb_xy];
const int mvy_limit = IS_INTERLACED(mb_type) ? 2 : 4;
int first_vertical_edge_done = 0;
int dir;
//for sufficiently low qp, filtering wouldn't do anything
//this is a conservative estimate: could also check beta_offset and more accurate chroma_qp
if(!FRAME_MBAFF){
int qp_thresh = 15 - h->slice_alpha_c0_offset - FFMAX3(0, h->pps.chroma_qp_index_offset[0], h->pps.chroma_qp_index_offset[1]);
int qp = s->current_picture.qscale_table[mb_xy];
if(qp <= qp_thresh
&& (mb_x == 0 || ((qp + s->current_picture.qscale_table[mb_xy-1] + 1)>>1) <= qp_thresh)
&& (mb_y == 0 || ((qp + s->current_picture.qscale_table[h->top_mb_xy] + 1)>>1) <= qp_thresh)){
return;
}
}
// CAVLC 8x8dct requires NNZ values for residual decoding that differ from what the loop filter needs
if(!h->pps.cabac && h->pps.transform_8x8_mode){
int top_type, left_type[2];
top_type = s->current_picture.mb_type[h->top_mb_xy] ;
left_type[0] = s->current_picture.mb_type[h->left_mb_xy[0]];
left_type[1] = s->current_picture.mb_type[h->left_mb_xy[1]];
if(IS_8x8DCT(top_type)){
h->non_zero_count_cache[4+8*0]=
h->non_zero_count_cache[5+8*0]= h->cbp_table[h->top_mb_xy] & 4;
h->non_zero_count_cache[6+8*0]=
h->non_zero_count_cache[7+8*0]= h->cbp_table[h->top_mb_xy] & 8;
}
if(IS_8x8DCT(left_type[0])){
h->non_zero_count_cache[3+8*1]=
h->non_zero_count_cache[3+8*2]= h->cbp_table[h->left_mb_xy[0]]&2; //FIXME check MBAFF
}
if(IS_8x8DCT(left_type[1])){
h->non_zero_count_cache[3+8*3]=
h->non_zero_count_cache[3+8*4]= h->cbp_table[h->left_mb_xy[1]]&8; //FIXME check MBAFF
}
if(IS_8x8DCT(mb_type)){
h->non_zero_count_cache[scan8[0 ]]= h->non_zero_count_cache[scan8[1 ]]=
h->non_zero_count_cache[scan8[2 ]]= h->non_zero_count_cache[scan8[3 ]]= h->cbp_table[mb_xy] & 1;
h->non_zero_count_cache[scan8[0+ 4]]= h->non_zero_count_cache[scan8[1+ 4]]=
h->non_zero_count_cache[scan8[2+ 4]]= h->non_zero_count_cache[scan8[3+ 4]]= h->cbp_table[mb_xy] & 2;
h->non_zero_count_cache[scan8[0+ 8]]= h->non_zero_count_cache[scan8[1+ 8]]=
h->non_zero_count_cache[scan8[2+ 8]]= h->non_zero_count_cache[scan8[3+ 8]]= h->cbp_table[mb_xy] & 4;
h->non_zero_count_cache[scan8[0+12]]= h->non_zero_count_cache[scan8[1+12]]=
h->non_zero_count_cache[scan8[2+12]]= h->non_zero_count_cache[scan8[3+12]]= h->cbp_table[mb_xy] & 8;
} }
}
if (FRAME_MBAFF
// left mb is in picture
&& h->slice_table[mb_xy-1] != 0xFFFF
// and current and left pair do not have the same interlaced type
&& (IS_INTERLACED(mb_type) != IS_INTERLACED(s->current_picture.mb_type[mb_xy-1]))
// and left mb is in the same slice if deblocking_filter == 2
&& (h->deblocking_filter!=2 || h->slice_table[mb_xy-1] == h->slice_table[mb_xy])) {
/* First vertical edge is different in MBAFF frames
* There are 8 different bS to compute and 2 different Qp
*/
const int pair_xy = mb_x + (mb_y&~1)*s->mb_stride;
const int left_mb_xy[2] = { pair_xy-1, pair_xy-1+s->mb_stride };
int16_t bS[8];
int qp[2];
int bqp[2];
int rqp[2];
int mb_qp, mbn0_qp, mbn1_qp;
int i;
first_vertical_edge_done = 1;
if( IS_INTRA(mb_type) )
bS[0] = bS[1] = bS[2] = bS[3] = bS[4] = bS[5] = bS[6] = bS[7] = 4;
else {
for( i = 0; i < 8; i++ ) {
int mbn_xy = MB_FIELD ? left_mb_xy[i>>2] : left_mb_xy[i&1];
if( IS_INTRA( s->current_picture.mb_type[mbn_xy] ) )
bS[i] = 4;
else if( h->non_zero_count_cache[12+8*(i>>1)] != 0 ||
((!h->pps.cabac && IS_8x8DCT(s->current_picture.mb_type[mbn_xy])) ?
(h->cbp_table[mbn_xy] & ((MB_FIELD ? (i&2) : (mb_y&1)) ? 8 : 2))
:
h->non_zero_count[mbn_xy][MB_FIELD ? i&3 : (i>>2)+(mb_y&1)*2]))
bS[i] = 2;
else
bS[i] = 1;
}
}
mb_qp = s->current_picture.qscale_table[mb_xy];
mbn0_qp = s->current_picture.qscale_table[left_mb_xy[0]];
mbn1_qp = s->current_picture.qscale_table[left_mb_xy[1]];
qp[0] = ( mb_qp + mbn0_qp + 1 ) >> 1;
bqp[0] = ( get_chroma_qp( h, 0, mb_qp ) +
get_chroma_qp( h, 0, mbn0_qp ) + 1 ) >> 1;
rqp[0] = ( get_chroma_qp( h, 1, mb_qp ) +
get_chroma_qp( h, 1, mbn0_qp ) + 1 ) >> 1;
qp[1] = ( mb_qp + mbn1_qp + 1 ) >> 1;
bqp[1] = ( get_chroma_qp( h, 0, mb_qp ) +
get_chroma_qp( h, 0, mbn1_qp ) + 1 ) >> 1;
rqp[1] = ( get_chroma_qp( h, 1, mb_qp ) +
get_chroma_qp( h, 1, mbn1_qp ) + 1 ) >> 1;
/* Filter edge */
tprintf(s->avctx, "filter mb:%d/%d MBAFF, QPy:%d/%d, QPb:%d/%d QPr:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], bqp[0], bqp[1], rqp[0], rqp[1], linesize, uvlinesize);
{ int i; for (i = 0; i < 8; i++) tprintf(s->avctx, " bS[%d]:%d", i, bS[i]); tprintf(s->avctx, "\n"); }
filter_mb_mbaff_edgev ( h, &img_y [0], linesize, bS, qp );
filter_mb_mbaff_edgecv( h, &img_cb[0], uvlinesize, bS, bqp );
filter_mb_mbaff_edgecv( h, &img_cr[0], uvlinesize, bS, rqp );
}
#ifdef CONFIG_SMALL
for( dir = 0; dir < 2; dir++ )
filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, dir ? 0 : first_vertical_edge_done, dir);
#else
filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, first_vertical_edge_done, 0);
filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, 0, 1);
#endif
} }
static int decode_slice(struct AVCodecContext *avctx, void *arg){ static int decode_slice(struct AVCodecContext *avctx, void *arg){

Loading…
Cancel
Save