From 6a9c85944427e3c4355bce67d7f677ec69527bff Mon Sep 17 00:00:00 2001 From: Alexander Strange Date: Thu, 2 Jun 2011 10:15:58 -0700 Subject: H264/MPEG frame-level multi-threading. Signed-off-by: Ronald S. Bultje --- libavcodec/h264_direct.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'libavcodec/h264_direct.c') diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index 3c7f57aa0c..a7e6853b5c 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -31,6 +31,7 @@ #include "mpegvideo.h" #include "h264.h" #include "rectangle.h" +#include "thread.h" //#undef NDEBUG #include @@ -126,7 +127,7 @@ void ff_h264_direct_ref_list_init(H264Context * const h){ h->col_parity= (FFABS(col_poc[0] - cur_poc) >= FFABS(col_poc[1] - cur_poc)); ref1sidx=sidx= h->col_parity; }else if(!(s->picture_structure & h->ref_list[1][0].reference) && !h->ref_list[1][0].mbaff){ // FL -> FL & differ parity - h->col_fieldoff= s->mb_stride*(2*(h->ref_list[1][0].reference) - 3); + h->col_fieldoff= 2*(h->ref_list[1][0].reference) - 3; } if(cur->pict_type != AV_PICTURE_TYPE_B || h->direct_spatial_mv_pred) @@ -140,11 +141,27 @@ void ff_h264_direct_ref_list_init(H264Context * const h){ } } +static void await_reference_mb_row(H264Context * const h, Picture *ref, int mb_y) +{ + int ref_field = ref->reference - 1; + int ref_field_picture = ref->field_picture; + int ref_height = 16*h->s.mb_height >> ref_field_picture; + + if(!HAVE_PTHREADS || !(h->s.avctx->active_thread_type&FF_THREAD_FRAME)) + return; + + //FIXME it can be safe to access mb stuff + //even if pixels aren't deblocked yet + + ff_thread_await_progress((AVFrame*)ref, FFMIN(16*mb_y >> ref_field_picture, ref_height-1), + ref_field_picture && ref_field); +} + static void pred_spatial_direct_motion(H264Context * const h, int *mb_type){ MpegEncContext * const s = &h->s; int b8_stride = 2; int b4_stride = h->b_stride; - int mb_xy = h->mb_xy; + int mb_xy = h->mb_xy, mb_y = s->mb_y; int mb_type_col[2]; const int16_t (*l1mv0)[2], (*l1mv1)[2]; const int8_t *l1ref0, *l1ref1; @@ -157,6 +174,8 @@ static void pred_spatial_direct_motion(H264Context * const h, int *mb_type){ assert(h->ref_list[1][0].reference&3); + await_reference_mb_row(h, &h->ref_list[1][0], s->mb_y + !!IS_INTERLACED(*mb_type)); + #define MB_TYPE_16x16_OR_INTRA (MB_TYPE_16x16|MB_TYPE_INTRA4x4|MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM) @@ -217,14 +236,17 @@ static void pred_spatial_direct_motion(H264Context * const h, int *mb_type){ if(IS_INTERLACED(h->ref_list[1][0].mb_type[mb_xy])){ // AFL/AFR/FR/FL -> AFL/FL if(!IS_INTERLACED(*mb_type)){ // AFR/FR -> AFL/FL + mb_y = (s->mb_y&~1) + h->col_parity; mb_xy= s->mb_x + ((s->mb_y&~1) + h->col_parity)*s->mb_stride; b8_stride = 0; }else{ - mb_xy += h->col_fieldoff; // non zero for FL -> FL & differ parity + mb_y += h->col_fieldoff; + mb_xy += s->mb_stride*h->col_fieldoff; // non zero for FL -> FL & differ parity } goto single_col; }else{ // AFL/AFR/FR/FL -> AFR/FR if(IS_INTERLACED(*mb_type)){ // AFL /FL -> AFR/FR + mb_y = s->mb_y&~1; mb_xy= s->mb_x + (s->mb_y&~1)*s->mb_stride; mb_type_col[0] = h->ref_list[1][0].mb_type[mb_xy]; mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy + s->mb_stride]; @@ -260,6 +282,8 @@ single_col: } } + await_reference_mb_row(h, &h->ref_list[1][0], mb_y); + l1mv0 = &h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]]; l1mv1 = &h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]]; l1ref0 = &h->ref_list[1][0].ref_index [0][4*mb_xy]; @@ -384,7 +408,7 @@ static void pred_temp_direct_motion(H264Context * const h, int *mb_type){ MpegEncContext * const s = &h->s; int b8_stride = 2; int b4_stride = h->b_stride; - int mb_xy = h->mb_xy; + int mb_xy = h->mb_xy, mb_y = s->mb_y; int mb_type_col[2]; const int16_t (*l1mv0)[2], (*l1mv1)[2]; const int8_t *l1ref0, *l1ref1; @@ -394,16 +418,21 @@ static void pred_temp_direct_motion(H264Context * const h, int *mb_type){ assert(h->ref_list[1][0].reference&3); + await_reference_mb_row(h, &h->ref_list[1][0], s->mb_y + !!IS_INTERLACED(*mb_type)); + if(IS_INTERLACED(h->ref_list[1][0].mb_type[mb_xy])){ // AFL/AFR/FR/FL -> AFL/FL if(!IS_INTERLACED(*mb_type)){ // AFR/FR -> AFL/FL + mb_y = (s->mb_y&~1) + h->col_parity; mb_xy= s->mb_x + ((s->mb_y&~1) + h->col_parity)*s->mb_stride; b8_stride = 0; }else{ - mb_xy += h->col_fieldoff; // non zero for FL -> FL & differ parity + mb_y += h->col_fieldoff; + mb_xy += s->mb_stride*h->col_fieldoff; // non zero for FL -> FL & differ parity } goto single_col; }else{ // AFL/AFR/FR/FL -> AFR/FR if(IS_INTERLACED(*mb_type)){ // AFL /FL -> AFR/FR + mb_y = s->mb_y&~1; mb_xy= s->mb_x + (s->mb_y&~1)*s->mb_stride; mb_type_col[0] = h->ref_list[1][0].mb_type[mb_xy]; mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy + s->mb_stride]; @@ -440,6 +469,8 @@ single_col: } } + await_reference_mb_row(h, &h->ref_list[1][0], mb_y); + l1mv0 = &h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]]; l1mv1 = &h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]]; l1ref0 = &h->ref_list[1][0].ref_index [0][4*mb_xy]; -- cgit v1.2.3