Module: Mesa
Branch: main
Commit: 8daa329634e049b377c61eb3ada9f291584c971b
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=8daa329634e049b377c61eb3ada9f291584c971b

Author: Benjamin Cheng <[email protected]>
Date:   Wed Aug  9 00:19:27 2023 -0400

vulkan/video: add helper to derive H264 scaling lists

The H264 spec defines a complicated way of layering PPS scaling lists
on top of SPS scaling lists. The details can be found in 7.4.2.1
(seq_scaling_matrix_present_flag semantics) and 7.4.2.2
(pic_scaling_matrix_present_flag semantics).

Both ANV and RADV need to derive the final scaling lists sent to HW
using this logic in order to handle H264 scaling lists correctly.

Reviewed-by: Hyunjun Ko <[email protected]>
Reviewed-by: Dave Airlie <[email protected]>
Reviewed-by: Lynne <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24572>

---

 src/vulkan/runtime/vk_video.c | 171 ++++++++++++++++++++++++++++++++++++++++++
 src/vulkan/runtime/vk_video.h |   4 +
 2 files changed, 175 insertions(+)

diff --git a/src/vulkan/runtime/vk_video.c b/src/vulkan/runtime/vk_video.c
index 6920d9de59b..0e90f18ae90 100644
--- a/src/vulkan/runtime/vk_video.c
+++ b/src/vulkan/runtime/vk_video.c
@@ -333,6 +333,177 @@ vk_video_session_parameters_update(struct 
vk_video_session_parameters *params,
    return result;
 }
 
+const uint8_t h264_scaling_list_default_4x4_intra[] =
+{
+   /* Table 7-3 - Default_4x4_Intra */
+   6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42
+};
+
+const uint8_t h264_scaling_list_default_4x4_inter[] =
+{
+   /* Table 7-3 - Default_4x4_Inter */
+   10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34
+};
+
+const uint8_t h264_scaling_list_default_8x8_intra[] =
+{
+   /* Table 7-4 - Default_8x8_Intra */
+   6,  10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
+   23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
+   27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
+   31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42,
+};
+
+const uint8_t h264_scaling_list_default_8x8_inter[] =
+{
+   /* Table 7-4 - Default_8x8_Inter */
+   9 , 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
+   21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
+   24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
+   27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35,
+};
+
+void
+vk_video_derive_h264_scaling_list(const StdVideoH264SequenceParameterSet *sps,
+                                  const StdVideoH264PictureParameterSet *pps,
+                                  StdVideoH264ScalingLists *list)
+{
+   StdVideoH264ScalingLists temp;
+
+   /* derive SPS scaling list first, because PPS may depend on it in fall-back
+    * rule B */
+   if (sps->flags.seq_scaling_matrix_present_flag)
+   {
+      for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
+      {
+         if (sps->pScalingLists->scaling_list_present_mask & (1 << i))
+            memcpy(temp.ScalingList4x4[i],
+                   pps->pScalingLists->ScalingList4x4[i],
+                   STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+         else /* fall-back rule A */
+         {
+            if (i == 0)
+               memcpy(temp.ScalingList4x4[i],
+                      h264_scaling_list_default_4x4_intra,
+                      STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+            else if (i == 3)
+               memcpy(temp.ScalingList4x4[i],
+                      h264_scaling_list_default_4x4_inter,
+                      STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+            else
+               memcpy(temp.ScalingList4x4[i],
+                      temp.ScalingList4x4[i - 1],
+                      STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+         }
+      }
+
+      for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; j++)
+      {
+         int i = j + STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS;
+         if (sps->pScalingLists->scaling_list_present_mask & (1 << i))
+            memcpy(temp.ScalingList8x8[j], 
pps->pScalingLists->ScalingList8x8[j],
+                   STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+         else /* fall-back rule A */
+         {
+            if (i == 6)
+               memcpy(temp.ScalingList8x8[j],
+                      h264_scaling_list_default_8x8_intra,
+                      STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+            else if (i == 7)
+               memcpy(temp.ScalingList8x8[j],
+                      h264_scaling_list_default_8x8_inter,
+                      STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+            else
+               memcpy(temp.ScalingList8x8[j], temp.ScalingList8x8[j - 2],
+                      STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+         }
+      }
+   }
+   else
+   {
+      memset(temp.ScalingList4x4, 0x10,
+             STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS *
+             STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+      memset(temp.ScalingList8x8, 0x10,
+             STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS *
+             STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+   }
+
+   if (pps->flags.pic_scaling_matrix_present_flag)
+   {
+      for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
+      {
+         if (pps->pScalingLists->scaling_list_present_mask & (1 << i))
+            memcpy(list->ScalingList4x4[i], 
pps->pScalingLists->ScalingList4x4[i],
+                   STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+         else if (sps->flags.seq_scaling_matrix_present_flag) /* fall-back 
rule B */
+         {
+            if (i == 0 || i == 3)
+               memcpy(list->ScalingList4x4[i], temp.ScalingList4x4[i],
+                      STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+            else
+               memcpy(list->ScalingList4x4[i], list->ScalingList4x4[i - 1],
+                      STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+         }
+         else /* fall-back rule A */
+         {
+            if (i == 0)
+               memcpy(list->ScalingList4x4[i],
+                      h264_scaling_list_default_4x4_intra,
+                      STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+            else if (i == 3)
+               memcpy(list->ScalingList4x4[i],
+                      h264_scaling_list_default_4x4_inter,
+                      STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+            else
+               memcpy(list->ScalingList4x4[i],
+                      list->ScalingList4x4[i - 1],
+                      STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+         }
+      }
+
+      for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; j++)
+      {
+         int i = j + STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS;
+         if (pps->pScalingLists->scaling_list_present_mask & (1 << i))
+            memcpy(list->ScalingList8x8[j], 
pps->pScalingLists->ScalingList8x8[j],
+                   STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+         else if (sps->flags.seq_scaling_matrix_present_flag) /* fall-back 
rule B */
+         {
+            if (i == 6 || i == 7)
+               memcpy(list->ScalingList8x8[j], temp.ScalingList8x8[j],
+                      STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+            else
+               memcpy(list->ScalingList8x8[j], list->ScalingList8x8[j - 2],
+                      STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+         }
+         else /* fall-back rule A */
+         {
+            if (i == 6)
+               memcpy(list->ScalingList8x8[j],
+                      h264_scaling_list_default_8x8_intra,
+                      STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+            else if (i == 7)
+               memcpy(list->ScalingList8x8[j],
+                      h264_scaling_list_default_8x8_inter,
+                      STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+            else
+               memcpy(list->ScalingList8x8[j], list->ScalingList8x8[j - 2],
+                      STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+         }
+      }
+   }
+   else
+   {
+      memcpy(list->ScalingList4x4, temp.ScalingList4x4,
+            STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS *
+            STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS);
+      memcpy(list->ScalingList8x8, temp.ScalingList8x8,
+            STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS *
+            STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS);
+   }
+}
+
 const StdVideoH264SequenceParameterSet *
 vk_video_find_h264_dec_std_sps(const struct vk_video_session_parameters 
*params,
                                uint32_t id)
diff --git a/src/vulkan/runtime/vk_video.h b/src/vulkan/runtime/vk_video.h
index 29fb905c92f..442c54b34f3 100644
--- a/src/vulkan/runtime/vk_video.h
+++ b/src/vulkan/runtime/vk_video.h
@@ -93,6 +93,10 @@ VkResult vk_video_session_parameters_update(struct 
vk_video_session_parameters *
 void vk_video_session_parameters_finish(struct vk_device *device,
                                         struct vk_video_session_parameters 
*params);
 
+void vk_video_derive_h264_scaling_list(const StdVideoH264SequenceParameterSet 
*sps,
+                                       const StdVideoH264PictureParameterSet 
*pps,
+                                       StdVideoH264ScalingLists *list);
+
 const StdVideoH264SequenceParameterSet *
 vk_video_find_h264_dec_std_sps(const struct vk_video_session_parameters 
*params,
                                uint32_t id);

Reply via email to