gallium: Parse packed HEVC SPS encode header for crop parameters
authorThong Thai <thong.thai@amd.com>
Thu, 12 Mar 2020 14:06:52 +0000 (10:06 -0400)
committerMarge Bot <eric+marge@anholt.net>
Mon, 21 Sep 2020 18:45:35 +0000 (18:45 +0000)
The crop / conformance window parameters are set by ffmpeg but they only
seem to be made available in packed headers. This commit copies the H265
header parsing code from st/omx (planning in the future to move this
code to a common place to be shared by the different state trackers) in
order to grab the crop parameters

Signed-off-by: Thong Thai <thong.thai@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4184>

src/gallium/frontends/va/config.c
src/gallium/frontends/va/picture.c
src/gallium/frontends/va/picture_hevc_enc.c
src/gallium/frontends/va/va_private.h
src/gallium/include/pipe/p_video_state.h

index 294cbcc..f9f5519 100644 (file)
@@ -157,7 +157,9 @@ vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint en
             value = VA_RC_CQP | VA_RC_CBR | VA_RC_VBR;
             break;
          case VAConfigAttribEncPackedHeaders:
-            value = 0;
+            value = VA_ENC_PACKED_HEADER_NONE;
+            if (u_reduce_video_profile(ProfileToPipe(profile)) == PIPE_VIDEO_FORMAT_HEVC)
+               value |= VA_ENC_PACKED_HEADER_SEQUENCE;
             break;
          case VAConfigAttribEncMaxRefFrames:
             value = 1;
index d529a2b..bd687c8 100644 (file)
@@ -466,6 +466,48 @@ handleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaB
    return status;
 }
 
+static VAStatus
+handleVAEncPackedHeaderParameterBufferType(vlVaContext *context, vlVaBuffer *buf)
+{
+   VAStatus status = VA_STATUS_SUCCESS;
+
+   switch (u_reduce_video_profile(context->templat.profile)) {
+   case PIPE_VIDEO_FORMAT_HEVC:
+      break;
+
+   default:
+      return VA_STATUS_ERROR_UNIMPLEMENTED;
+   }
+
+   VAEncPackedHeaderParameterBuffer *param = (VAEncPackedHeaderParameterBuffer *)buf->data;
+   if (param->type == VAEncPackedHeaderSequence)
+      context->packed_header_type = param->type;
+   else
+      status = VA_STATUS_ERROR_UNIMPLEMENTED;
+
+   return status;
+}
+
+static VAStatus
+handleVAEncPackedHeaderDataBufferType(vlVaContext *context, vlVaBuffer *buf)
+{
+   VAStatus status = VA_STATUS_SUCCESS;
+
+   if (context->packed_header_type != VAEncPackedHeaderSequence)
+      return VA_STATUS_ERROR_UNIMPLEMENTED;
+
+   switch (u_reduce_video_profile(context->templat.profile)) {
+   case PIPE_VIDEO_FORMAT_HEVC:
+      status = vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(context, buf);
+      break;
+
+   default:
+      break;
+   }
+
+   return status;
+}
+
 VAStatus
 vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers)
 {
@@ -536,6 +578,13 @@ vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buff
          vlVaHandleHuffmanTableBufferType(context, buf);
          break;
 
+      case VAEncPackedHeaderParameterBufferType:
+         handleVAEncPackedHeaderParameterBufferType(context, buf);
+         break;
+      case VAEncPackedHeaderDataBufferType:
+         handleVAEncPackedHeaderDataBufferType(context, buf);
+         break;
+
       default:
          break;
       }
index 5105977..96420b3 100644 (file)
 #include "util/u_video.h"
 #include "va_private.h"
 
+#include "vl/vl_vlc.h"
+#include "vl/vl_rbsp.h"
+
+enum HEVCNALUnitType {
+    HEVC_NAL_VPS        = 32,
+    HEVC_NAL_SPS        = 33,
+    HEVC_NAL_PPS        = 34,
+};
+
 VAStatus
 vlVaHandleVAEncPictureParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
 {
@@ -188,6 +197,128 @@ vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscPar
    return VA_STATUS_SUCCESS;
 }
 
+static void profile_tier(struct vl_rbsp *rbsp)
+{
+   vl_rbsp_u(rbsp, 2); /* general_profile_space */
+   vl_rbsp_u(rbsp, 1); /* general_tier_flag */
+   vl_rbsp_u(rbsp, 5); /* general_profile_idc */
+
+   /* general_profile_compatibility_flag */
+   for(int i = 0; i < 32; ++i)
+      vl_rbsp_u(rbsp, 1);
+
+   vl_rbsp_u(rbsp, 1); /* general_progressive_source_flag */
+   vl_rbsp_u(rbsp, 1); /* general_interlaced_source_flag */
+   vl_rbsp_u(rbsp, 1); /* general_non_packed_constraint_flag */
+   vl_rbsp_u(rbsp, 1); /* general_frame_only_constraint_flag */
+
+   /* general_reserved_zero_44bits */
+   vl_rbsp_u(rbsp, 16);
+   vl_rbsp_u(rbsp, 16);
+   vl_rbsp_u(rbsp, 12);
+}
+
+static unsigned profile_tier_level(struct vl_rbsp *rbsp,
+                                   int max_sublayers_minus1)
+{
+   bool sub_layer_profile_present_flag[6];
+   bool sub_layer_level_present_flag[6];
+   unsigned level_idc;
+   int i;
+
+   profile_tier(rbsp);
+   level_idc = vl_rbsp_u(rbsp, 8);  /* general_level_idc */
+
+   for (i = 0; i < max_sublayers_minus1; ++i) {
+      sub_layer_profile_present_flag[i] = vl_rbsp_u(rbsp, 1);
+      sub_layer_level_present_flag[i] = vl_rbsp_u(rbsp, 1);
+   }
+
+   if (max_sublayers_minus1 > 0)
+      for (i = max_sublayers_minus1; i < 8; ++i)
+         vl_rbsp_u(rbsp, 2);        /* reserved_zero_2bits */
+
+   for (i = 0; i < max_sublayers_minus1; ++i) {
+      if (sub_layer_profile_present_flag[i])
+         profile_tier(rbsp);
+
+      if (sub_layer_level_present_flag[i])
+         vl_rbsp_u(rbsp, 8);        /* sub_layer_level_idc */
+   }
+
+   return level_idc;
+}
+
+static void parseEncSpsParamsH265(vlVaContext *context, struct vl_rbsp *rbsp)
+{
+   int sps_max_sub_layers_minus1;
+
+   vl_rbsp_u(rbsp, 4);     /* sps_video_parameter_set_id */
+   sps_max_sub_layers_minus1 = vl_rbsp_u(rbsp, 3);
+   vl_rbsp_u(rbsp, 1);     /* sps_temporal_id_nesting_flag */
+
+   /* level_idc */
+   profile_tier_level(rbsp, sps_max_sub_layers_minus1);
+
+   vl_rbsp_ue(rbsp);       /* id */
+   context->desc.h265enc.seq.chroma_format_idc = vl_rbsp_ue(rbsp);
+   if (context->desc.h265enc.seq.chroma_format_idc == 3)
+      vl_rbsp_u(rbsp, 1);  /* separate_colour_plane_flag */
+
+   context->desc.h265enc.seq.pic_width_in_luma_samples = vl_rbsp_ue(rbsp);
+   context->desc.h265enc.seq.pic_height_in_luma_samples = vl_rbsp_ue(rbsp);
+
+   /* conformance_window_flag - used for cropping */
+   context->desc.h265enc.seq.conformance_window_flag = vl_rbsp_u(rbsp, 1);
+   if (context->desc.h265enc.seq.conformance_window_flag) {
+      context->desc.h265enc.seq.conf_win_left_offset = vl_rbsp_ue(rbsp);
+      context->desc.h265enc.seq.conf_win_right_offset = vl_rbsp_ue(rbsp);
+      context->desc.h265enc.seq.conf_win_top_offset = vl_rbsp_ue(rbsp);
+      context->desc.h265enc.seq.conf_win_bottom_offset = vl_rbsp_ue(rbsp);
+   }
+}
+
+VAStatus
+vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(vlVaContext *context, vlVaBuffer *buf)
+{
+   struct vl_vlc vlc = {0};
+   vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size);
+
+   while (vl_vlc_bits_left(&vlc) > 0) {
+      /* search the first 64 bytes for a startcode */
+      for (int i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= 24; ++i) {
+         if (vl_vlc_peekbits(&vlc, 24) == 0x000001)
+            break;
+         vl_vlc_eatbits(&vlc, 8);
+         vl_vlc_fillbits(&vlc);
+      }
+      vl_vlc_eatbits(&vlc, 24); /* eat the startcode */
+
+      if (vl_vlc_valid_bits(&vlc) < 15)
+         vl_vlc_fillbits(&vlc);
+
+      vl_vlc_eatbits(&vlc, 1);
+      unsigned nal_unit_type = vl_vlc_get_uimsbf(&vlc, 6);
+      vl_vlc_eatbits(&vlc, 6);
+      vl_vlc_eatbits(&vlc, 3);
+
+      struct vl_rbsp rbsp;
+      vl_rbsp_init(&rbsp, &vlc, ~0);
+
+      switch(nal_unit_type) {
+      case HEVC_NAL_SPS:
+         parseEncSpsParamsH265(context, &rbsp);
+         break;
+      case HEVC_NAL_VPS:
+      case HEVC_NAL_PPS:
+      default:
+         break;
+      }
+   }
+
+   return VA_STATUS_SUCCESS;
+}
+
 void getEncParamPresetH265(vlVaContext *context)
 {
    //rate control
index b80eea5..0e7393f 100644 (file)
@@ -308,6 +308,7 @@ typedef struct {
    int gop_coeff;
    bool needs_begin_frame;
    void *blit_cs;
+   int packed_header_type;
 } vlVaContext;
 
 typedef struct {
@@ -459,5 +460,5 @@ VAStatus vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContex
 VAStatus vlVaHandleVAEncSequenceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf);
 VAStatus vlVaHandleVAEncMiscParameterTypeRateControlHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf);
 VAStatus vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf);
-
+VAStatus vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(vlVaContext *context, vlVaBuffer *buf);
 #endif //VA_PRIVATE_H
index 2ace947..58dc69d 100644 (file)
@@ -457,6 +457,11 @@ struct pipe_h265_enc_seq_param
    uint8_t  log2_diff_max_min_transform_block_size;
    uint8_t  max_transform_hierarchy_depth_inter;
    uint8_t  max_transform_hierarchy_depth_intra;
+   uint8_t conformance_window_flag;
+   uint16_t conf_win_left_offset;
+   uint16_t conf_win_right_offset;
+   uint16_t conf_win_top_offset;
+   uint16_t conf_win_bottom_offset;
 };
 
 struct pipe_h265_enc_pic_param