[FFmpeg-devel] [PATCH 2/3 v1.1] avcodec/vaapi: add fields for VAAPI VC-1 interlaced decoding

Mark Thompson sw at jkqxz.net
Tue Feb 27 01:54:29 EET 2018


On 25/02/18 19:12, Jerome Borsboom wrote:
> avcodec/vaapi: add fields for VAAPI VC-1 interlaced decoding
> 
> Pass necessary bitstream elements to the VAAPI VC-1 decoder in order
> to start doing interlaced decoding in hardware.
> 
> Signed-off-by: Jerome Borsboom <jerome.borsboom at carpalis.nl>
> ---
>  libavcodec/vaapi_vc1.c | 167 ++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 138 insertions(+), 29 deletions(-)
> 
> diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c
> index 525376790e..a137979dd4 100644
> --- a/libavcodec/vaapi_vc1.c
> +++ b/libavcodec/vaapi_vc1.c
> @@ -44,7 +44,8 @@ static inline int vc1_has_MVTYPEMB_bitplane(const VC1Context *v)
>  {
>      if (v->mv_type_is_raw)
>          return 0;
> -    return v->s.pict_type == AV_PICTURE_TYPE_P &&
> +    return v->fcm == PROGRESSIVE &&
> +           (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
>             (v->mv_mode == MV_PMODE_MIXED_MV ||
>              (v->mv_mode == MV_PMODE_INTENSITY_COMP &&
>               v->mv_mode2 == MV_PMODE_MIXED_MV));
> @@ -55,8 +56,9 @@ static inline int vc1_has_SKIPMB_bitplane(const VC1Context *v)
>  {
>      if (v->skip_is_raw)
>          return 0;
> -    return v->s.pict_type == AV_PICTURE_TYPE_P ||
> -           (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type);
> +    return (v->fcm == PROGRESSIVE || v->fcm == ILACE_FRAME) &&
> +           ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) ||
> +            (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type));
>  }
>  
>  /** Check whether the DIRECTMB bitplane is present */
> @@ -64,7 +66,8 @@ static inline int vc1_has_DIRECTMB_bitplane(const VC1Context *v)
>  {
>      if (v->dmb_is_raw)
>          return 0;
> -    return v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type;
> +    return (v->fcm == PROGRESSIVE || v->fcm == ILACE_FRAME) &&
> +           (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type);
>  }
>  
>  /** Check whether the ACPRED bitplane is present */
> @@ -89,6 +92,25 @@ static inline int vc1_has_OVERFLAGS_bitplane(const VC1Context *v)
>             v->condover == CONDOVER_SELECT;
>  }
>  
> +/** Check whether the FIELDTX bitplane is present */
> +static inline int vc1_has_FIELDTX_bitplane(const VC1Context *v)
> +{
> +    if (v->fieldtx_is_raw)
> +        return 0;
> +    return v->fcm == ILACE_FRAME &&
> +           (v->s.pict_type == AV_PICTURE_TYPE_I ||
> +            (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type));
> +}
> +
> +/** Check whether the FORWARDMB bitplane is present */
> +static inline int vc1_has_FORWARDMB_bitplane(const VC1Context *v)
> +{
> +    if (v->fmb_is_raw)
> +        return 0;
> +    return v->fcm == ILACE_FIELD &&
> +           (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type);
> +}
> +
>  /** Reconstruct bitstream PTYPE (7.1.1.4, index into Table-35) */
>  static int vc1_get_PTYPE(const VC1Context *v)
>  {
> @@ -101,10 +123,22 @@ static int vc1_get_PTYPE(const VC1Context *v)
>      return 0;
>  }
>  
> +/** Reconstruct bitstream FPTYPE (9.1.1.42, index into Table-105) */
> +static int vc1_get_FPTYPE(const VC1Context *v)
> +{
> +    const MpegEncContext *s = &v->s;
> +    switch (s->pict_type) {
> +    case AV_PICTURE_TYPE_I: return 0;
> +    case AV_PICTURE_TYPE_P: return 3;
> +    case AV_PICTURE_TYPE_B: return v->bi_type ? 7 : 4;
> +    }
> +    return 0;
> +}
> +
>  /** Reconstruct bitstream MVMODE (7.1.1.32) */
>  static inline VAMvModeVC1 vc1_get_MVMODE(const VC1Context *v)
>  {
> -    if (v->s.pict_type == AV_PICTURE_TYPE_P ||
> +    if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) ||
>          (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type))
>          return get_VAMvModeVC1(v->mv_mode);
>      return 0;
> @@ -113,11 +147,81 @@ static inline VAMvModeVC1 vc1_get_MVMODE(const VC1Context *v)
>  /** Reconstruct bitstream MVMODE2 (7.1.1.33) */
>  static inline VAMvModeVC1 vc1_get_MVMODE2(const VC1Context *v)
>  {
> -    if (v->s.pict_type == AV_PICTURE_TYPE_P && v->mv_mode == MV_PMODE_INTENSITY_COMP)
> +    if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
> +        v->mv_mode == MV_PMODE_INTENSITY_COMP)
>          return get_VAMvModeVC1(v->mv_mode2);
>      return 0;
>  }
>  
> +#if VA_CHECK_VERSION(1, 1, 0)

IMO it would be preferable not to guard this function with the libva version check - it doesn't depend on anything about libva (it's only the use of it that does), so it would be better if it's always built and the compiler can eliminate it later.

(Mark them with av_unused to avoid the warning.)

> +static inline int vc1_get_INTCOMPFIELD(const VC1Context *v)
> +{
> +    if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
> +        v->fcm == ILACE_FIELD &&
> +        v->mv_mode == MV_PMODE_INTENSITY_COMP)
> +        switch (v->intcompfield) {
> +        case 1: return 1;
> +        case 2: return 2;
> +        case 3: return 0;
> +        }
> +    return 0;
> +}
> +#endif
> +
> +static inline int vc1_get_LUMSCALE(const VC1Context *v)
> +{
> +    if (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) {
> +        if ((v->fcm == PROGRESSIVE && v->mv_mode == MV_PMODE_INTENSITY_COMP) ||
> +            (v->fcm == ILACE_FRAME && v->intcomp))
> +            return v->lumscale;
> +        else if (v->fcm == ILACE_FIELD && v->mv_mode == MV_PMODE_INTENSITY_COMP)
> +            switch (v->intcompfield) {
> +            case 1: return v->lumscale;
> +            case 2: return v->lumscale2;
> +            case 3: return v->lumscale;
> +        }
> +    }
> +    return 0;
> +}
> +
> +static inline int vc1_get_LUMSHIFT(const VC1Context *v)
> +{
> +    if (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) {
> +        if ((v->fcm == PROGRESSIVE && v->mv_mode == MV_PMODE_INTENSITY_COMP) ||
> +            (v->fcm == ILACE_FRAME && v->intcomp))
> +            return v->lumshift;
> +        else if (v->fcm == ILACE_FIELD && v->mv_mode == MV_PMODE_INTENSITY_COMP)
> +            switch (v->intcompfield) {
> +            case 1: return v->lumshift;
> +            case 2: return v->lumshift2;
> +            case 3: return v->lumshift;
> +        }
> +    }
> +    return 0;
> +}
> +
> +#if VA_CHECK_VERSION(1, 1, 0)

And these two.

> +static inline int vc1_get_LUMSCALE2(const VC1Context *v)
> +{
> +    if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
> +        v->fcm == ILACE_FIELD &&
> +        v->mv_mode == MV_PMODE_INTENSITY_COMP &&
> +        v->intcompfield == 3)
> +        return v->lumscale2;
> +    return 0;
> +}
> +
> +static inline int vc1_get_LUMSHIFT2(const VC1Context *v)
> +{
> +    if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
> +        v->fcm == ILACE_FIELD &&
> +        v->mv_mode == MV_PMODE_INTENSITY_COMP &&
> +        v->intcompfield == 3)
> +        return v->lumshift2;
> +    return 0;
> +}
> +#endif
> +
>  /** Reconstruct bitstream TTFRM (7.1.1.41, Table-53) */
>  static inline int vc1_get_TTFRM(const VC1Context *v)
>  {
> @@ -189,27 +293,32 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t
>              .chroma                        = v->range_mapuv,
>          },
>          .b_picture_fraction                = v->bfraction_lut_index,
> -        .cbp_table                         = v->cbpcy_vlc ? v->cbpcy_vlc - ff_vc1_cbpcy_p_vlc : 0,
> -        .mb_mode_table                     = 0, /* XXX: interlaced frame */
> +        .cbp_table                         = (v->fcm == PROGRESSIVE ? v->cbptab : v->icbptab),
> +        .mb_mode_table                     = v->mbmodetab,
>          .range_reduction_frame             = v->rangeredfrm,
>          .rounding_control                  = v->rnd,
>          .post_processing                   = v->postproc,
>          .picture_resolution_index          = v->respic,
> -        .luma_scale                        = v->lumscale,
> -        .luma_shift                        = v->lumshift,
>          .picture_fields.bits = {
> -            .picture_type                  = vc1_get_PTYPE(v),
> +            .picture_type                  = (v->fcm == ILACE_FIELD ? vc1_get_FPTYPE(v) : vc1_get_PTYPE(v)),
>              .frame_coding_mode             = v->fcm,
>              .top_field_first               = v->tff,
> -            .is_first_field                = v->fcm == 0, /* XXX: interlaced frame */
> -            .intensity_compensation        = v->mv_mode == MV_PMODE_INTENSITY_COMP,
> +            .is_first_field                = !v->second_field,
> +            .intensity_compensation        = v->intcomp,
>          },
> +        .luma_scale                        = vc1_get_LUMSCALE(v),
> +        .luma_shift                        = vc1_get_LUMSHIFT(v),
> +#if VA_CHECK_VERSION(1, 1, 0)
> +        .luma_scale2                       = vc1_get_LUMSCALE2(v),
> +        .luma_shift2                       = vc1_get_LUMSHIFT2(v),
> +        .intensity_compensation_field      = vc1_get_INTCOMPFIELD(v),
> +#endif
>          .raw_coding.flags = {
>              .mv_type_mb                    = v->mv_type_is_raw,
>              .direct_mb                     = v->dmb_is_raw,
>              .skip_mb                       = v->skip_is_raw,
> -            .field_tx                      = 0, /* XXX: interlaced frame */
> -            .forward_mb                    = 0, /* XXX: interlaced frame */
> +            .field_tx                      = v->fieldtx_is_raw,
> +            .forward_mb                    = v->fmb_is_raw,
>              .ac_pred                       = v->acpred_is_raw,
>              .overflags                     = v->overflg_is_raw,
>          },
> @@ -217,28 +326,28 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t
>              .bp_mv_type_mb                 = vc1_has_MVTYPEMB_bitplane(v),
>              .bp_direct_mb                  = vc1_has_DIRECTMB_bitplane(v),
>              .bp_skip_mb                    = vc1_has_SKIPMB_bitplane(v),
> -            .bp_field_tx                   = 0, /* XXX: interlaced frame */
> -            .bp_forward_mb                 = 0, /* XXX: interlaced frame */
> +            .bp_field_tx                   = vc1_has_FIELDTX_bitplane(v),
> +            .bp_forward_mb                 = vc1_has_FORWARDMB_bitplane(v),
>              .bp_ac_pred                    = vc1_has_ACPRED_bitplane(v),
>              .bp_overflags                  = vc1_has_OVERFLAGS_bitplane(v),
>          },
>          .reference_fields.bits = {
>              .reference_distance_flag       = v->refdist_flag,
> -            .reference_distance            = 0, /* XXX: interlaced frame */
> -            .num_reference_pictures        = 0, /* XXX: interlaced frame */
> -            .reference_field_pic_indicator = 0, /* XXX: interlaced frame */
> +            .reference_distance            = v->refdist,
> +            .num_reference_pictures        = v->numref,
> +            .reference_field_pic_indicator = v->reffield,
>          },
>          .mv_fields.bits = {
>              .mv_mode                       = vc1_get_MVMODE(v),
>              .mv_mode2                      = vc1_get_MVMODE2(v),
> -            .mv_table                      = s->mv_table_index,
> -            .two_mv_block_pattern_table    = 0, /* XXX: interlaced frame */
> -            .four_mv_switch                = 0, /* XXX: interlaced frame */
> -            .four_mv_block_pattern_table   = 0, /* XXX: interlaced frame */
> +            .mv_table                      = (v->fcm == PROGRESSIVE ? s->mv_table_index : v->imvtab),
> +            .two_mv_block_pattern_table    = v->twomvbptab,
> +            .four_mv_switch                = v->fourmvswitch,
> +            .four_mv_block_pattern_table   = v->fourmvbptab,
>              .extended_mv_flag              = v->extended_mv,
>              .extended_mv_range             = v->mvrange,
>              .extended_dmv_flag             = v->extended_dmv,
> -            .extended_dmv_range            = 0, /* XXX: interlaced frame */
> +            .extended_dmv_range            = v->dmvrange,
>          },
>          .pic_quantizer_fields.bits = {
>              .dquant                        = v->dquant,
> @@ -298,14 +407,14 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t
>              break;
>          case AV_PICTURE_TYPE_B:
>              if (!v->bi_type) {
> -                ff_bp[0] = pic_param.bitplane_present.flags.bp_direct_mb ? v->direct_mb_plane : NULL;
> -                ff_bp[1] = pic_param.bitplane_present.flags.bp_skip_mb   ? s->mbskip_table    : NULL;
> -                ff_bp[2] = NULL; /* XXX: interlaced frame (FORWARD plane) */
> +                ff_bp[0] = pic_param.bitplane_present.flags.bp_direct_mb  ? v->direct_mb_plane  : NULL;
> +                ff_bp[1] = pic_param.bitplane_present.flags.bp_skip_mb    ? s->mbskip_table     : NULL;
> +                ff_bp[2] = pic_param.bitplane_present.flags.bp_forward_mb ? v->forward_mb_plane : NULL;
>                  break;
>              }
>              /* fall-through (BI-type) */
>          case AV_PICTURE_TYPE_I:
> -            ff_bp[0] = NULL; /* XXX: interlaced frame (FIELDTX plane) */
> +            ff_bp[0] = pic_param.bitplane_present.flags.bp_field_tx   ? v->fieldtx_plane      : NULL;
>              ff_bp[1] = pic_param.bitplane_present.flags.bp_ac_pred    ? v->acpred_plane       : NULL;
>              ff_bp[2] = pic_param.bitplane_present.flags.bp_overflags  ? v->over_flags_plane   : NULL;
>              break;
> 

Is this expected to pass the two fate tests for VC-1 interlaced, fate-vc1_sa10143 and fate-vc1_ilaced_twomv?  (It doesn't on my system, all output frames are different.)  If not, could you explain why not?

Thanks,

- Mark


More information about the ffmpeg-devel mailing list