diff mbox

[FFmpeg-devel,4/8] lavc/vaapi_hevc: Add HEVC Rext parameter for VAPicture and VASlice

Message ID 1577636978-12870-1-git-send-email-linjie.fu@intel.com
State New
Headers show

Commit Message

Fu, Linjie Dec. 29, 2019, 4:29 p.m. UTC
Add VAPictureParameterBufferHEVCRext and VASliceParameterBufferHEVCRext.

Pass Range Extension flags to support the decode for HEVC REXT.

Signed-off-by: Linjie Fu <linjie.fu@intel.com>
---
 libavcodec/vaapi_hevc.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 76 insertions(+), 3 deletions(-)

Comments

Mark Thompson Jan. 8, 2020, 10:18 p.m. UTC | #1
On 29/12/2019 16:29, Linjie Fu wrote:
> Add VAPictureParameterBufferHEVCRext and VASliceParameterBufferHEVCRext.
> 
> Pass Range Extension flags to support the decode for HEVC REXT.
> 
> Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> ---
>  libavcodec/vaapi_hevc.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 76 insertions(+), 3 deletions(-)
> 
> diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c
> index c69d63d..ab48b73 100644
> --- a/libavcodec/vaapi_hevc.c
> +++ b/libavcodec/vaapi_hevc.c
> @@ -30,7 +30,13 @@
>  
>  typedef struct VAAPIDecodePictureHEVC {
>      VAPictureParameterBufferHEVC pic_param;
> +#if VA_CHECK_VERSION(1, 2, 0)
> +    VAPictureParameterBufferHEVCRext pic_rext_param;
> +#endif
>      VASliceParameterBufferHEVC last_slice_param;
> +#if VA_CHECK_VERSION(1, 2, 0)
> +    VASliceParameterBufferHEVCRext slice_rext_param;
> +#endif

I would feel happier if this wasn't playing games with concatenated structures and sizing.  Can you have a single VAPictureParameterBufferHEVCExtension here, and then use either just the first element of it for Main / Main 10, or the whole thing for extension profiles?

>      const uint8_t *last_buffer;
>      size_t         last_size;
>  
> @@ -119,6 +125,11 @@ static int vaapi_hevc_start_frame(AVCodecContext          *avctx,
>      const ScalingList *scaling_list = NULL;
>      int err, i;
>  
> +    int pic_param_size = sizeof(pic->pic_param);
> +#if VA_CHECK_VERSION(1, 2, 0)
> +    pic_param_size += sizeof(pic->pic_rext_param);

But only if in an extension profile?  (Or replace with sizeof the extension structure.)

> +#endif
> +
>      pic->pic.output_surface = ff_vaapi_get_surface_id(h->ref->frame);
>  
>      pic->pic_param = (VAPictureParameterBufferHEVC) {
> @@ -208,9 +219,38 @@ static int vaapi_hevc_start_frame(AVCodecContext          *avctx,
>          pic->pic_param.st_rps_bits = 0;
>      }
>  
> +#if VA_CHECK_VERSION(1, 2, 0)
> +    if (sps->sps_range_extension_flag) {
> +        pic->pic_rext_param = (VAPictureParameterBufferHEVCRext) {
> +            .range_extension_pic_fields.bits  = {
> +                .transform_skip_rotation_enabled_flag       = sps->transform_skip_rotation_enabled_flag,
> +                .transform_skip_context_enabled_flag        = sps->transform_skip_context_enabled_flag,
> +                .implicit_rdpcm_enabled_flag                = sps->implicit_rdpcm_enabled_flag,
> +                .explicit_rdpcm_enabled_flag                = sps->explicit_rdpcm_enabled_flag,
> +                .extended_precision_processing_flag         = sps->extended_precision_processing_flag,
> +                .intra_smoothing_disabled_flag              = sps->intra_smoothing_disabled_flag,
> +                .high_precision_offsets_enabled_flag        = sps->high_precision_offsets_enabled_flag,
> +                .persistent_rice_adaptation_enabled_flag    = sps->persistent_rice_adaptation_enabled_flag,
> +                .cabac_bypass_alignment_enabled_flag        = sps->cabac_bypass_alignment_enabled_flag,
> +                .cross_component_prediction_enabled_flag    = pps->cross_component_prediction_enabled_flag,
> +                .chroma_qp_offset_list_enabled_flag         = pps->chroma_qp_offset_list_enabled_flag,
> +            },
> +            .diff_cu_chroma_qp_offset_depth                 = pps->diff_cu_chroma_qp_offset_depth,
> +            .chroma_qp_offset_list_len_minus1               = pps->chroma_qp_offset_list_len_minus1,
> +            .log2_sao_offset_scale_luma                     = pps->log2_sao_offset_scale_luma,
> +            .log2_sao_offset_scale_chroma                   = pps->log2_sao_offset_scale_chroma,
> +            .log2_max_transform_skip_block_size_minus2      = pps->log2_max_transform_skip_block_size - 2,
> +        };
> +
> +        for (i = 0; i < 6; i++)
> +            pic->pic_rext_param.cb_qp_offset_list[i]        = pps->cb_qp_offset_list[i];
> +        for (i = 0; i < 6; i++)
> +            pic->pic_rext_param.cr_qp_offset_list[i]        = pps->cr_qp_offset_list[i];
> +    }

Do inferred values do the right thing if pps_range_extension_flag is not set?  What if sps_r_e_f is not set but pps_r_e_f is?

> +#endif
>      err = ff_vaapi_decode_make_param_buffer(avctx, &pic->pic,
>                                              VAPictureParameterBufferType,
> -                                            &pic->pic_param, sizeof(pic->pic_param));
> +                                            &pic->pic_param, pic_param_size);
>      if (err < 0)
>          goto fail;
>  
> @@ -255,12 +295,19 @@ static int vaapi_hevc_end_frame(AVCodecContext *avctx)
>  {
>      const HEVCContext        *h = avctx->priv_data;
>      VAAPIDecodePictureHEVC *pic = h->ref->hwaccel_picture_private;
> +    const HEVCSPS          *sps = h->ps.sps;
>      int ret;
>  
> +    int slice_param_size = sizeof(pic->last_slice_param);
> +#if VA_CHECK_VERSION(1, 2, 0)
> +    if (sps->sps_range_extension_flag)
> +        slice_param_size += sizeof(pic->slice_rext_param);
> +#endif
> +
>      if (pic->last_size) {
>          pic->last_slice_param.LongSliceFlags.fields.LastSliceOfPic = 1;
>          ret = ff_vaapi_decode_make_slice_buffer(avctx, &pic->pic,
> -                                                &pic->last_slice_param, sizeof(pic->last_slice_param),
> +                                                &pic->last_slice_param, slice_param_size,
>                                                  pic->last_buffer, pic->last_size);
>          if (ret < 0)
>              goto fail;
> @@ -351,6 +398,7 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx,
>                                     uint32_t        size)
>  {
>      const HEVCContext        *h = avctx->priv_data;
> +    const HEVCSPS          *sps = h->ps.sps;
>      const SliceHeader       *sh = &h->sh;
>      VAAPIDecodePictureHEVC *pic = h->ref->hwaccel_picture_private;
>  
> @@ -358,10 +406,15 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx,
>                    2 : (sh->slice_type == HEVC_SLICE_I ? 0 : 1);
>  
>      int err, i, list_idx;
> +    int slice_param_size = sizeof(pic->last_slice_param);
> +#if VA_CHECK_VERSION(1, 2, 0)
> +    if (sps->sps_range_extension_flag)
> +        slice_param_size += sizeof(pic->slice_rext_param);
> +#endif
>  
>      if (!sh->first_slice_in_pic_flag) {
>          err = ff_vaapi_decode_make_slice_buffer(avctx, &pic->pic,
> -                                                &pic->last_slice_param, sizeof(pic->last_slice_param),
> +                                                &pic->last_slice_param, slice_param_size,
>                                                  pic->last_buffer, pic->last_size);
>          pic->last_buffer = NULL;
>          pic->last_size   = 0;
> @@ -415,6 +468,26 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx,
>  
>      fill_pred_weight_table(h, sh, &pic->last_slice_param);
>  
> +#if VA_CHECK_VERSION(1, 2, 0)
> +    if (sps->sps_range_extension_flag) {
> +        // pass the slice parameter for REXT
> +        pic->slice_rext_param = (VASliceParameterBufferHEVCRext) {
> +            .slice_ext_flags.bits = {
> +                .cu_chroma_qp_offset_enabled_flag = sh->cu_chroma_qp_offset_enabled_flag,
> +            },

It doesn't look like the presence of this value depends on sps_range_extension_flag?

> +        };
> +
> +        memcpy(pic->slice_rext_param.luma_offset_l0, pic->last_slice_param.luma_offset_l0,
> +                                                sizeof(pic->last_slice_param.luma_offset_l0));
> +        memcpy(pic->slice_rext_param.luma_offset_l1, pic->last_slice_param.luma_offset_l1,
> +                                                sizeof(pic->last_slice_param.luma_offset_l1));
> +        memcpy(pic->slice_rext_param.ChromaOffsetL0, pic->last_slice_param.ChromaOffsetL0,
> +                                                sizeof(pic->last_slice_param.ChromaOffsetL0));
> +        memcpy(pic->slice_rext_param.ChromaOffsetL1, pic->last_slice_param.ChromaOffsetL1,
> +                                                sizeof(pic->last_slice_param.ChromaOffsetL1));
> +    }
> +#endif
> +
>      pic->last_buffer = buffer;
>      pic->last_size   = size;
>  
> 

Thanks,

- Mark
Fu, Linjie Jan. 14, 2020, 8:43 a.m. UTC | #2
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Mark Thompson
> Sent: Thursday, January 9, 2020 06:19
> To: ffmpeg-devel@ffmpeg.org
> Subject: Re: [FFmpeg-devel] [PATCH 4/8] lavc/vaapi_hevc: Add HEVC Rext
> parameter for VAPicture and VASlice
> 
> On 29/12/2019 16:29, Linjie Fu wrote:
> > Add VAPictureParameterBufferHEVCRext and
> VASliceParameterBufferHEVCRext.
> >
> > Pass Range Extension flags to support the decode for HEVC REXT.
> >
> > Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> > ---
> >  libavcodec/vaapi_hevc.c | 79
> +++++++++++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 76 insertions(+), 3 deletions(-)
> >
> > diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c
> > index c69d63d..ab48b73 100644
> > --- a/libavcodec/vaapi_hevc.c
> > +++ b/libavcodec/vaapi_hevc.c
> > @@ -30,7 +30,13 @@
> >
> >  typedef struct VAAPIDecodePictureHEVC {
> >      VAPictureParameterBufferHEVC pic_param;
> > +#if VA_CHECK_VERSION(1, 2, 0)
> > +    VAPictureParameterBufferHEVCRext pic_rext_param;
> > +#endif
> >      VASliceParameterBufferHEVC last_slice_param;
> > +#if VA_CHECK_VERSION(1, 2, 0)
> > +    VASliceParameterBufferHEVCRext slice_rext_param;
> > +#endif
> 
> I would feel happier if this wasn't playing games with concatenated
> structures and sizing.  Can you have a single
> VAPictureParameterBufferHEVCExtension here, and then use either just the
> first element of it for Main / Main 10, or the whole thing for extension
> profiles?

Will update.

> >      const uint8_t *last_buffer;
> >      size_t         last_size;
> >
> > @@ -119,6 +125,11 @@ static int
> vaapi_hevc_start_frame(AVCodecContext          *avctx,
> >      const ScalingList *scaling_list = NULL;
> >      int err, i;
> >
> > +    int pic_param_size = sizeof(pic->pic_param);
> > +#if VA_CHECK_VERSION(1, 2, 0)
> > +    pic_param_size += sizeof(pic->pic_rext_param);
> 
> But only if in an extension profile?  (Or replace with sizeof the extension
> structure.)

Will update to use sizeof the extension structure for rext.

> > +#endif
> > +
> 
> Do inferred values do the right thing if pps_range_extension_flag is not set?
...
> It doesn't look like the presence of this value depends on
> sps_range_extension_flag?
> 

Will check the profile and only pass above parameters to driver/hardware while decoding
HEVC range extension clips.

Thanks for the review.
diff mbox

Patch

diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c
index c69d63d..ab48b73 100644
--- a/libavcodec/vaapi_hevc.c
+++ b/libavcodec/vaapi_hevc.c
@@ -30,7 +30,13 @@ 
 
 typedef struct VAAPIDecodePictureHEVC {
     VAPictureParameterBufferHEVC pic_param;
+#if VA_CHECK_VERSION(1, 2, 0)
+    VAPictureParameterBufferHEVCRext pic_rext_param;
+#endif
     VASliceParameterBufferHEVC last_slice_param;
+#if VA_CHECK_VERSION(1, 2, 0)
+    VASliceParameterBufferHEVCRext slice_rext_param;
+#endif
     const uint8_t *last_buffer;
     size_t         last_size;
 
@@ -119,6 +125,11 @@  static int vaapi_hevc_start_frame(AVCodecContext          *avctx,
     const ScalingList *scaling_list = NULL;
     int err, i;
 
+    int pic_param_size = sizeof(pic->pic_param);
+#if VA_CHECK_VERSION(1, 2, 0)
+    pic_param_size += sizeof(pic->pic_rext_param);
+#endif
+
     pic->pic.output_surface = ff_vaapi_get_surface_id(h->ref->frame);
 
     pic->pic_param = (VAPictureParameterBufferHEVC) {
@@ -208,9 +219,38 @@  static int vaapi_hevc_start_frame(AVCodecContext          *avctx,
         pic->pic_param.st_rps_bits = 0;
     }
 
+#if VA_CHECK_VERSION(1, 2, 0)
+    if (sps->sps_range_extension_flag) {
+        pic->pic_rext_param = (VAPictureParameterBufferHEVCRext) {
+            .range_extension_pic_fields.bits  = {
+                .transform_skip_rotation_enabled_flag       = sps->transform_skip_rotation_enabled_flag,
+                .transform_skip_context_enabled_flag        = sps->transform_skip_context_enabled_flag,
+                .implicit_rdpcm_enabled_flag                = sps->implicit_rdpcm_enabled_flag,
+                .explicit_rdpcm_enabled_flag                = sps->explicit_rdpcm_enabled_flag,
+                .extended_precision_processing_flag         = sps->extended_precision_processing_flag,
+                .intra_smoothing_disabled_flag              = sps->intra_smoothing_disabled_flag,
+                .high_precision_offsets_enabled_flag        = sps->high_precision_offsets_enabled_flag,
+                .persistent_rice_adaptation_enabled_flag    = sps->persistent_rice_adaptation_enabled_flag,
+                .cabac_bypass_alignment_enabled_flag        = sps->cabac_bypass_alignment_enabled_flag,
+                .cross_component_prediction_enabled_flag    = pps->cross_component_prediction_enabled_flag,
+                .chroma_qp_offset_list_enabled_flag         = pps->chroma_qp_offset_list_enabled_flag,
+            },
+            .diff_cu_chroma_qp_offset_depth                 = pps->diff_cu_chroma_qp_offset_depth,
+            .chroma_qp_offset_list_len_minus1               = pps->chroma_qp_offset_list_len_minus1,
+            .log2_sao_offset_scale_luma                     = pps->log2_sao_offset_scale_luma,
+            .log2_sao_offset_scale_chroma                   = pps->log2_sao_offset_scale_chroma,
+            .log2_max_transform_skip_block_size_minus2      = pps->log2_max_transform_skip_block_size - 2,
+        };
+
+        for (i = 0; i < 6; i++)
+            pic->pic_rext_param.cb_qp_offset_list[i]        = pps->cb_qp_offset_list[i];
+        for (i = 0; i < 6; i++)
+            pic->pic_rext_param.cr_qp_offset_list[i]        = pps->cr_qp_offset_list[i];
+    }
+#endif
     err = ff_vaapi_decode_make_param_buffer(avctx, &pic->pic,
                                             VAPictureParameterBufferType,
-                                            &pic->pic_param, sizeof(pic->pic_param));
+                                            &pic->pic_param, pic_param_size);
     if (err < 0)
         goto fail;
 
@@ -255,12 +295,19 @@  static int vaapi_hevc_end_frame(AVCodecContext *avctx)
 {
     const HEVCContext        *h = avctx->priv_data;
     VAAPIDecodePictureHEVC *pic = h->ref->hwaccel_picture_private;
+    const HEVCSPS          *sps = h->ps.sps;
     int ret;
 
+    int slice_param_size = sizeof(pic->last_slice_param);
+#if VA_CHECK_VERSION(1, 2, 0)
+    if (sps->sps_range_extension_flag)
+        slice_param_size += sizeof(pic->slice_rext_param);
+#endif
+
     if (pic->last_size) {
         pic->last_slice_param.LongSliceFlags.fields.LastSliceOfPic = 1;
         ret = ff_vaapi_decode_make_slice_buffer(avctx, &pic->pic,
-                                                &pic->last_slice_param, sizeof(pic->last_slice_param),
+                                                &pic->last_slice_param, slice_param_size,
                                                 pic->last_buffer, pic->last_size);
         if (ret < 0)
             goto fail;
@@ -351,6 +398,7 @@  static int vaapi_hevc_decode_slice(AVCodecContext *avctx,
                                    uint32_t        size)
 {
     const HEVCContext        *h = avctx->priv_data;
+    const HEVCSPS          *sps = h->ps.sps;
     const SliceHeader       *sh = &h->sh;
     VAAPIDecodePictureHEVC *pic = h->ref->hwaccel_picture_private;
 
@@ -358,10 +406,15 @@  static int vaapi_hevc_decode_slice(AVCodecContext *avctx,
                   2 : (sh->slice_type == HEVC_SLICE_I ? 0 : 1);
 
     int err, i, list_idx;
+    int slice_param_size = sizeof(pic->last_slice_param);
+#if VA_CHECK_VERSION(1, 2, 0)
+    if (sps->sps_range_extension_flag)
+        slice_param_size += sizeof(pic->slice_rext_param);
+#endif
 
     if (!sh->first_slice_in_pic_flag) {
         err = ff_vaapi_decode_make_slice_buffer(avctx, &pic->pic,
-                                                &pic->last_slice_param, sizeof(pic->last_slice_param),
+                                                &pic->last_slice_param, slice_param_size,
                                                 pic->last_buffer, pic->last_size);
         pic->last_buffer = NULL;
         pic->last_size   = 0;
@@ -415,6 +468,26 @@  static int vaapi_hevc_decode_slice(AVCodecContext *avctx,
 
     fill_pred_weight_table(h, sh, &pic->last_slice_param);
 
+#if VA_CHECK_VERSION(1, 2, 0)
+    if (sps->sps_range_extension_flag) {
+        // pass the slice parameter for REXT
+        pic->slice_rext_param = (VASliceParameterBufferHEVCRext) {
+            .slice_ext_flags.bits = {
+                .cu_chroma_qp_offset_enabled_flag = sh->cu_chroma_qp_offset_enabled_flag,
+            },
+        };
+
+        memcpy(pic->slice_rext_param.luma_offset_l0, pic->last_slice_param.luma_offset_l0,
+                                                sizeof(pic->last_slice_param.luma_offset_l0));
+        memcpy(pic->slice_rext_param.luma_offset_l1, pic->last_slice_param.luma_offset_l1,
+                                                sizeof(pic->last_slice_param.luma_offset_l1));
+        memcpy(pic->slice_rext_param.ChromaOffsetL0, pic->last_slice_param.ChromaOffsetL0,
+                                                sizeof(pic->last_slice_param.ChromaOffsetL0));
+        memcpy(pic->slice_rext_param.ChromaOffsetL1, pic->last_slice_param.ChromaOffsetL1,
+                                                sizeof(pic->last_slice_param.ChromaOffsetL1));
+    }
+#endif
+
     pic->last_buffer = buffer;
     pic->last_size   = size;