aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorLynne <dev@lynne.ee>2022-12-14 08:27:18 +0100
committerLynne <dev@lynne.ee>2023-05-29 00:41:58 +0200
commit36c16a06b2e31a39c236d724c2fd5d457f02493a (patch)
treec42f986aae9d3c3b8ed7c6054ba2c34f4f3da17a /libavcodec
parenta9fbe8b47269e86a38f73d705426c6e853cdd887 (diff)
downloadffmpeg-36c16a06b2e31a39c236d724c2fd5d457f02493a.tar.gz
hevcdec: add Vulkan hwaccel
Thanks to Dave Airlie for figuring out a lot of the parameters.
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/Makefile1
-rw-r--r--libavcodec/hevcdec.c25
-rw-r--r--libavcodec/hwaccels.h1
-rw-r--r--libavcodec/vulkan_hevc.c948
4 files changed, 974 insertions, 1 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 62b24630bf..d421844903 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1005,6 +1005,7 @@ OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o
OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.o
OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o
OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o h265_profile_level.o
+OBJS-$(CONFIG_HEVC_VULKAN_HWACCEL) += vulkan_decode.o vulkan_hevc.o
OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o
OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o
OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 8764e0bd83..eee77ec4db 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -405,7 +405,8 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
CONFIG_HEVC_NVDEC_HWACCEL + \
CONFIG_HEVC_VAAPI_HWACCEL + \
CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \
- CONFIG_HEVC_VDPAU_HWACCEL)
+ CONFIG_HEVC_VDPAU_HWACCEL + \
+ CONFIG_HEVC_VULKAN_HWACCEL)
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts;
switch (sps->pix_fmt) {
@@ -430,6 +431,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+ *fmt++ = AV_PIX_FMT_VULKAN;
+#endif
break;
case AV_PIX_FMT_YUV420P10:
#if CONFIG_HEVC_DXVA2_HWACCEL
@@ -445,6 +449,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+ *fmt++ = AV_PIX_FMT_VULKAN;
+#endif
#if CONFIG_HEVC_VDPAU_HWACCEL
*fmt++ = AV_PIX_FMT_VDPAU;
#endif
@@ -465,6 +472,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+ *fmt++ = AV_PIX_FMT_VULKAN;
+#endif
break;
case AV_PIX_FMT_YUV422P:
case AV_PIX_FMT_YUV422P10LE:
@@ -474,11 +484,15 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+ *fmt++ = AV_PIX_FMT_VULKAN;
+#endif
break;
case AV_PIX_FMT_YUV444P10:
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
#endif
+ /* NOTE: fallthrough */
case AV_PIX_FMT_YUV420P12:
case AV_PIX_FMT_YUV444P12:
#if CONFIG_HEVC_VAAPI_HWACCEL
@@ -487,6 +501,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#if CONFIG_HEVC_VDPAU_HWACCEL
*fmt++ = AV_PIX_FMT_VDPAU;
#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+ *fmt++ = AV_PIX_FMT_VULKAN;
+#endif
#if CONFIG_HEVC_NVDEC_HWACCEL
*fmt++ = AV_PIX_FMT_CUDA;
#endif
@@ -495,6 +512,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#if CONFIG_HEVC_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+ *fmt++ = AV_PIX_FMT_VULKAN;
+#endif
break;
}
@@ -3770,6 +3790,9 @@ const FFCodec ff_hevc_decoder = {
#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL
HWACCEL_VIDEOTOOLBOX(hevc),
#endif
+#if CONFIG_HEVC_VULKAN_HWACCEL
+ HWACCEL_VULKAN(hevc),
+#endif
NULL
},
};
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index 23d0843c76..a7c74d07cb 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -44,6 +44,7 @@ extern const AVHWAccel ff_hevc_nvdec_hwaccel;
extern const AVHWAccel ff_hevc_vaapi_hwaccel;
extern const AVHWAccel ff_hevc_vdpau_hwaccel;
extern const AVHWAccel ff_hevc_videotoolbox_hwaccel;
+extern const AVHWAccel ff_hevc_vulkan_hwaccel;
extern const AVHWAccel ff_mjpeg_nvdec_hwaccel;
extern const AVHWAccel ff_mjpeg_vaapi_hwaccel;
extern const AVHWAccel ff_mpeg1_nvdec_hwaccel;
diff --git a/libavcodec/vulkan_hevc.c b/libavcodec/vulkan_hevc.c
new file mode 100644
index 0000000000..592b2526e8
--- /dev/null
+++ b/libavcodec/vulkan_hevc.c
@@ -0,0 +1,948 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hevcdec.h"
+#include "hevc_ps.h"
+
+#include "vulkan_decode.h"
+
+const VkExtensionProperties ff_vk_dec_hevc_ext = {
+ .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME,
+ .specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION,
+};
+
+typedef struct HEVCHeaderSPS {
+ StdVideoH265ScalingLists scaling;
+ StdVideoH265HrdParameters vui_header;
+ StdVideoH265SequenceParameterSetVui vui;
+ StdVideoH265ProfileTierLevel ptl;
+ StdVideoH265DecPicBufMgr dpbm;
+ StdVideoH265PredictorPaletteEntries pal;
+ StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS];
+ StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS];
+ StdVideoH265ShortTermRefPicSet str[HEVC_MAX_SHORT_TERM_REF_PIC_SETS];
+ StdVideoH265LongTermRefPicsSps ltr;
+} HEVCHeaderSPS;
+
+typedef struct HEVCHeaderPPS {
+ StdVideoH265ScalingLists scaling;
+ StdVideoH265PredictorPaletteEntries pal;
+} HEVCHeaderPPS;
+
+typedef struct HEVCHeaderVPSSet {
+ StdVideoH265SubLayerHrdParameters nal_hdr[HEVC_MAX_SUB_LAYERS];
+ StdVideoH265SubLayerHrdParameters vcl_hdr[HEVC_MAX_SUB_LAYERS];
+} HEVCHeaderVPSSet;
+
+typedef struct HEVCHeaderVPS {
+ StdVideoH265ProfileTierLevel ptl;
+ StdVideoH265DecPicBufMgr dpbm;
+ StdVideoH265HrdParameters hdr[HEVC_MAX_LAYER_SETS];
+ HEVCHeaderVPSSet *sls;
+} HEVCHeaderVPS;
+
+typedef struct HEVCHeaderSet {
+ StdVideoH265SequenceParameterSet sps[HEVC_MAX_SPS_COUNT];
+ HEVCHeaderSPS hsps[HEVC_MAX_SPS_COUNT];
+
+ StdVideoH265PictureParameterSet pps[HEVC_MAX_PPS_COUNT];
+ HEVCHeaderPPS hpps[HEVC_MAX_PPS_COUNT];
+
+ StdVideoH265VideoParameterSet vps[HEVC_MAX_PPS_COUNT];
+ HEVCHeaderVPS *hvps;
+} HEVCHeaderSet;
+
+static int get_data_set_buf(FFVulkanDecodeContext *s, AVBufferRef **data_buf,
+ int nb_vps, AVBufferRef * const vps_list[HEVC_MAX_VPS_COUNT])
+{
+ uint8_t *data_ptr;
+ HEVCHeaderSet *hdr;
+
+ size_t base_size = sizeof(StdVideoH265SequenceParameterSet)*HEVC_MAX_SPS_COUNT +
+ sizeof(HEVCHeaderSPS)*HEVC_MAX_SPS_COUNT +
+ sizeof(StdVideoH265PictureParameterSet)*HEVC_MAX_PPS_COUNT +
+ sizeof(HEVCHeaderPPS)*HEVC_MAX_PPS_COUNT +
+ sizeof(StdVideoH265VideoParameterSet)*HEVC_MAX_VPS_COUNT +
+ sizeof(HEVCHeaderVPS *);
+
+ size_t vps_size = sizeof(StdVideoH265ProfileTierLevel) +
+ sizeof(StdVideoH265DecPicBufMgr) +
+ sizeof(StdVideoH265HrdParameters)*HEVC_MAX_LAYER_SETS +
+ sizeof(HEVCHeaderVPSSet *);
+
+ size_t buf_size = base_size + vps_size*nb_vps;
+
+ for (int i = 0; i < nb_vps; i++) {
+ const HEVCVPS *vps = (const HEVCVPS *)vps_list[i]->data;
+ buf_size += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters;
+ }
+
+ if (buf_size > s->tmp_pool_ele_size) {
+ av_buffer_pool_uninit(&s->tmp_pool);
+ s->tmp_pool_ele_size = 0;
+ s->tmp_pool = av_buffer_pool_init(buf_size, NULL);
+ if (!s->tmp_pool)
+ return AVERROR(ENOMEM);
+ s->tmp_pool_ele_size = buf_size;
+ }
+
+ *data_buf = av_buffer_pool_get(s->tmp_pool);
+ if (!(*data_buf))
+ return AVERROR(ENOMEM);
+
+ /* Setup pointers */
+ data_ptr = (*data_buf)->data;
+ hdr = (HEVCHeaderSet *)data_ptr;
+ hdr->hvps = (HEVCHeaderVPS *)(data_ptr + base_size);
+ data_ptr += base_size + vps_size*nb_vps;
+ for (int i = 0; i < nb_vps; i++) {
+ const HEVCVPS *vps = (const HEVCVPS *)vps_list[i]->data;
+ hdr->hvps[i].sls = (HEVCHeaderVPSSet *)data_ptr;
+ data_ptr += sizeof(HEVCHeaderVPSSet)*vps->vps_num_hrd_parameters;
+ }
+
+ return 0;
+}
+
+typedef struct HEVCVulkanDecodePicture {
+ FFVulkanDecodePicture vp;
+
+ /* Current picture */
+ StdVideoDecodeH265ReferenceInfo h265_ref;
+ VkVideoDecodeH265DpbSlotInfoKHR vkh265_ref;
+
+ /* Picture refs */
+ HEVCFrame *ref_src [HEVC_MAX_REFS];
+ StdVideoDecodeH265ReferenceInfo h265_refs [HEVC_MAX_REFS];
+ VkVideoDecodeH265DpbSlotInfoKHR vkh265_refs[HEVC_MAX_REFS];
+
+ /* Current picture (contd.) */
+ StdVideoDecodeH265PictureInfo h265pic;
+ VkVideoDecodeH265PictureInfoKHR h265_pic_info;
+} HEVCVulkanDecodePicture;
+
+static int vk_hevc_fill_pict(AVCodecContext *avctx, HEVCFrame **ref_src,
+ VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */
+ VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */
+ VkVideoDecodeH265DpbSlotInfoKHR *vkh265_ref, /* Goes in ^ */
+ StdVideoDecodeH265ReferenceInfo *h265_ref, /* Goes in ^ */
+ HEVCFrame *pic, int is_current, int pic_id)
+{
+ FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+ HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
+ FFVulkanDecodePicture *vkpic = &hp->vp;
+
+ int err = ff_vk_decode_prepare_frame(dec, pic->frame, vkpic, is_current,
+ dec->dedicated_dpb);
+ if (err < 0)
+ return err;
+
+ *h265_ref = (StdVideoDecodeH265ReferenceInfo) {
+ .flags = (StdVideoDecodeH265ReferenceInfoFlags) {
+ .used_for_long_term_reference = pic->flags & HEVC_FRAME_FLAG_LONG_REF,
+ .unused_for_reference = 0,
+ },
+ .PicOrderCntVal = pic->poc,
+ };
+
+ *vkh265_ref = (VkVideoDecodeH265DpbSlotInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR,
+ .pStdReferenceInfo = h265_ref,
+ };
+
+ *ref = (VkVideoPictureResourceInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+ .codedOffset = (VkOffset2D){ 0, 0 },
+ .codedExtent = (VkExtent2D){ pic->frame->width, pic->frame->height },
+ .baseArrayLayer = dec->layered_dpb ? pic_id : 0,
+ .imageViewBinding = vkpic->img_view_ref,
+ };
+
+ *ref_slot = (VkVideoReferenceSlotInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
+ .pNext = vkh265_ref,
+ .slotIndex = pic_id,
+ .pPictureResource = ref,
+ };
+
+ if (ref_src)
+ *ref_src = pic;
+
+ return 0;
+}
+
+static StdVideoH265LevelIdc convert_to_vk_level_idc(int level_idc)
+{
+ switch (level_idc) {
+ case 10: return STD_VIDEO_H265_LEVEL_IDC_1_0;
+ case 20: return STD_VIDEO_H265_LEVEL_IDC_2_0;
+ case 21: return STD_VIDEO_H265_LEVEL_IDC_2_1;
+ case 30: return STD_VIDEO_H265_LEVEL_IDC_3_0;
+ case 31: return STD_VIDEO_H265_LEVEL_IDC_3_1;
+ case 40: return STD_VIDEO_H265_LEVEL_IDC_4_0;
+ case 41: return STD_VIDEO_H265_LEVEL_IDC_4_1;
+ case 50: return STD_VIDEO_H265_LEVEL_IDC_5_0;
+ case 51: return STD_VIDEO_H265_LEVEL_IDC_5_1;
+ case 60: return STD_VIDEO_H265_LEVEL_IDC_6_0;
+ case 61: return STD_VIDEO_H265_LEVEL_IDC_6_1;
+ default:
+ case 62: return STD_VIDEO_H265_LEVEL_IDC_6_2;
+ }
+}
+
+static void set_sps(const HEVCSPS *sps, int sps_idx,
+ StdVideoH265ScalingLists *vksps_scaling,
+ StdVideoH265HrdParameters *vksps_vui_header,
+ StdVideoH265SequenceParameterSetVui *vksps_vui,
+ StdVideoH265SequenceParameterSet *vksps,
+ StdVideoH265SubLayerHrdParameters *slhdrnal,
+ StdVideoH265SubLayerHrdParameters *slhdrvcl,
+ StdVideoH265ProfileTierLevel *ptl,
+ StdVideoH265DecPicBufMgr *dpbm,
+ StdVideoH265PredictorPaletteEntries *pal,
+ StdVideoH265ShortTermRefPicSet *str,
+ StdVideoH265LongTermRefPicsSps *ltr)
+{
+ for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++)
+ memcpy(vksps_scaling->ScalingList4x4[i], sps->scaling_list.sl[0][i],
+ STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList4x4));
+
+ for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++)
+ memcpy(vksps_scaling->ScalingList8x8[i], sps->scaling_list.sl[1][i],
+ STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList8x8));
+
+ for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++)
+ memcpy(vksps_scaling->ScalingList16x16[i], sps->scaling_list.sl[2][i],
+ STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList16x16));
+
+ for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++)
+ memcpy(vksps_scaling->ScalingList32x32[i], sps->scaling_list.sl[3][i],
+ STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vksps_scaling->ScalingList32x32));
+
+ memcpy(vksps_scaling->ScalingListDCCoef16x16, sps->scaling_list.sl_dc[0],
+ STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(*vksps_scaling->ScalingListDCCoef16x16));
+
+ memcpy(vksps_scaling->ScalingListDCCoef32x32, sps->scaling_list.sl_dc[1],
+ STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(*vksps_scaling->ScalingListDCCoef32x32));
+
+ *vksps_vui_header = (StdVideoH265HrdParameters) {
+ .flags = (StdVideoH265HrdFlags) {
+ .nal_hrd_parameters_present_flag = sps->hdr.flags.nal_hrd_parameters_present_flag,
+ .vcl_hrd_parameters_present_flag = sps->hdr.flags.vcl_hrd_parameters_present_flag,
+ .sub_pic_hrd_params_present_flag = sps->hdr.flags.sub_pic_hrd_params_present_flag,
+ .sub_pic_cpb_params_in_pic_timing_sei_flag = sps->hdr.flags.sub_pic_cpb_params_in_pic_timing_sei_flag,
+ .fixed_pic_rate_general_flag = sps->hdr.flags.fixed_pic_rate_general_flag,
+ .fixed_pic_rate_within_cvs_flag = sps->hdr.flags.fixed_pic_rate_within_cvs_flag,
+ .low_delay_hrd_flag = sps->hdr.flags.low_delay_hrd_flag,
+ },
+ .tick_divisor_minus2 = sps->hdr.tick_divisor_minus2,
+ .du_cpb_removal_delay_increment_length_minus1 = sps->hdr.du_cpb_removal_delay_increment_length_minus1,
+ .dpb_output_delay_du_length_minus1 = sps->hdr.dpb_output_delay_du_length_minus1,
+ .bit_rate_scale = sps->hdr.bit_rate_scale,
+ .cpb_size_scale = sps->hdr.cpb_size_scale,
+ .cpb_size_du_scale = sps->hdr.cpb_size_du_scale,
+ .initial_cpb_removal_delay_length_minus1 = sps->hdr.initial_cpb_removal_delay_length_minus1,
+ .au_cpb_removal_delay_length_minus1 = sps->hdr.au_cpb_removal_delay_length_minus1,
+ .dpb_output_delay_length_minus1 = sps->hdr.dpb_output_delay_length_minus1,
+ /* Reserved - 3*16 bits */
+ .pSubLayerHrdParametersNal = slhdrnal,
+ .pSubLayerHrdParametersVcl = slhdrvcl,
+ };
+
+ memcpy(vksps_vui_header->cpb_cnt_minus1, sps->hdr.cpb_cnt_minus1,
+ STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->cpb_cnt_minus1));
+ memcpy(vksps_vui_header->elemental_duration_in_tc_minus1, sps->hdr.elemental_duration_in_tc_minus1,
+ STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*vksps_vui_header->elemental_duration_in_tc_minus1));
+
+ memcpy(slhdrnal, sps->hdr.nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrnal));
+ memcpy(slhdrvcl, sps->hdr.vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*slhdrvcl));
+
+ *vksps_vui = (StdVideoH265SequenceParameterSetVui) {
+ .flags = (StdVideoH265SpsVuiFlags) {
+ .aspect_ratio_info_present_flag = sps->vui.common.aspect_ratio_info_present_flag,
+ .overscan_info_present_flag = sps->vui.common.overscan_info_present_flag,
+ .overscan_appropriate_flag = sps->vui.common.overscan_appropriate_flag,
+ .video_signal_type_present_flag = sps->vui.common.video_signal_type_present_flag,
+ .video_full_range_flag = sps->vui.common.video_full_range_flag,
+ .colour_description_present_flag = sps->vui.common.colour_description_present_flag,
+ .chroma_loc_info_present_flag = sps->vui.common.chroma_loc_info_present_flag,
+ .neutral_chroma_indication_flag = sps->vui.neutra_chroma_indication_flag,
+ .field_seq_flag = sps->vui.field_seq_flag,
+ .frame_field_info_present_flag = sps->vui.frame_field_info_present_flag,
+ .default_display_window_flag = sps->vui.default_display_window_flag,
+ .vui_timing_info_present_flag = sps->vui.vui_timing_info_present_flag,
+ .vui_poc_proportional_to_timing_flag = sps->vui.vui_poc_proportional_to_timing_flag,
+ .vui_hrd_parameters_present_flag = sps->vui.vui_hrd_parameters_present_flag,
+ .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag,
+ .tiles_fixed_structure_flag = sps->vui.tiles_fixed_structure_flag,
+ .motion_vectors_over_pic_boundaries_flag = sps->vui.motion_vectors_over_pic_boundaries_flag,
+ .restricted_ref_pic_lists_flag = sps->vui.restricted_ref_pic_lists_flag,
+ },
+ .aspect_ratio_idc = sps->vui.common.aspect_ratio_idc,
+ .sar_width = sps->vui.common.sar.num,
+ .sar_height = sps->vui.common.sar.den,
+ .video_format = sps->vui.common.video_format,
+ .colour_primaries = sps->vui.common.colour_primaries,
+ .transfer_characteristics = sps->vui.common.transfer_characteristics,
+ .matrix_coeffs = sps->vui.common.matrix_coeffs,
+ .chroma_sample_loc_type_top_field = sps->vui.common.chroma_sample_loc_type_top_field,
+ .chroma_sample_loc_type_bottom_field = sps->vui.common.chroma_sample_loc_type_bottom_field,
+ /* Reserved */
+ /* Reserved */
+ .def_disp_win_left_offset = sps->vui.def_disp_win.left_offset,
+ .def_disp_win_right_offset = sps->vui.def_disp_win.right_offset,
+ .def_disp_win_top_offset = sps->vui.def_disp_win.top_offset,
+ .def_disp_win_bottom_offset = sps->vui.def_disp_win.bottom_offset,
+ .vui_num_units_in_tick = sps->vui.vui_num_units_in_tick,
+ .vui_time_scale = sps->vui.vui_time_scale,
+ .vui_num_ticks_poc_diff_one_minus1 = sps->vui.vui_num_ticks_poc_diff_one_minus1,
+ .min_spatial_segmentation_idc = sps->vui.min_spatial_segmentation_idc,
+ .max_bytes_per_pic_denom = sps->vui.max_bytes_per_pic_denom,
+ .max_bits_per_min_cu_denom = sps->vui.max_bits_per_min_cu_denom,
+ .log2_max_mv_length_horizontal = sps->vui.log2_max_mv_length_horizontal,
+ .log2_max_mv_length_vertical = sps->vui.log2_max_mv_length_vertical,
+ .pHrdParameters = vksps_vui_header,
+ };
+
+ *ptl = (StdVideoH265ProfileTierLevel) {
+ .flags = (StdVideoH265ProfileTierLevelFlags) {
+ .general_tier_flag = sps->ptl.general_ptl.tier_flag,
+ .general_progressive_source_flag = sps->ptl.general_ptl.progressive_source_flag,
+ .general_interlaced_source_flag = sps->ptl.general_ptl.interlaced_source_flag,
+ .general_non_packed_constraint_flag = sps->ptl.general_ptl.non_packed_constraint_flag,
+ .general_frame_only_constraint_flag = sps->ptl.general_ptl.frame_only_constraint_flag,
+ },
+ .general_profile_idc = sps->ptl.general_ptl.profile_idc,
+ .general_level_idc = convert_to_vk_level_idc(sps->ptl.general_ptl.level_idc),
+ };
+
+ for (int i = 0; i < sps->max_sub_layers; i++) {
+ dpbm->max_latency_increase_plus1[i] = sps->temporal_layer[i].max_latency_increase + 1;
+ dpbm->max_dec_pic_buffering_minus1[i] = sps->temporal_layer[i].max_dec_pic_buffering - 1;
+ dpbm->max_num_reorder_pics[i] = sps->temporal_layer[i].num_reorder_pics;
+ }
+
+ for (int i = 0; i < (sps->chroma_format_idc ? 3 : 1); i++)
+ for (int j = 0; j < sps->sps_num_palette_predictor_initializers; j++)
+ pal->PredictorPaletteEntries[i][j] = sps->sps_palette_predictor_initializer[i][j];
+
+ for (int i = 0; i < sps->nb_st_rps; i++) {
+ str[i] = (StdVideoH265ShortTermRefPicSet) {
+ .flags = (StdVideoH265ShortTermRefPicSetFlags) {
+ .inter_ref_pic_set_prediction_flag = sps->st_rps[i].rps_predict,
+ .delta_rps_sign = sps->st_rps[i].delta_rps_sign,
+ },
+ .delta_idx_minus1 = sps->st_rps[i].delta_idx - 1,
+ .use_delta_flag = sps->st_rps[i].use_delta_flag,
+ .abs_delta_rps_minus1 = sps->st_rps[i].abs_delta_rps - 1,
+ .used_by_curr_pic_flag = 0x0,
+ .used_by_curr_pic_s0_flag = 0x0,
+ .used_by_curr_pic_s1_flag = 0x0,
+ /* Reserved */
+ /* Reserved */
+ /* Reserved */
+ .num_negative_pics = sps->st_rps[i].num_negative_pics,
+ .num_positive_pics = sps->st_rps[i].num_delta_pocs - sps->st_rps[i].num_negative_pics,
+ };
+
+ /* NOTE: This is the predicted, and *reordered* version.
+ * Probably incorrect, but the spec doesn't say which version to use. */
+ for (int j = 0; j < sps->st_rps[i].num_delta_pocs; j++)
+ str[i].used_by_curr_pic_flag |= sps->st_rps[i].used[j] << j;
+
+ for (int j = 0; j < str[i].num_negative_pics; j++) {
+ str[i].delta_poc_s0_minus1[j] = sps->st_rps[i].delta_poc_s0[j] - 1;
+ str[i].used_by_curr_pic_s0_flag |= sps->st_rps[i].used[j] << j;
+ }
+
+ for (int j = 0; j < str[i].num_positive_pics; j++) {
+ str[i].delta_poc_s1_minus1[j] = sps->st_rps[i].delta_poc_s1[j] - 1;
+ str[i].used_by_curr_pic_s0_flag |= sps->st_rps[i].used[str[i].num_negative_pics + j] << j;
+ }
+ }
+
+ *ltr = (StdVideoH265LongTermRefPicsSps) {
+ .used_by_curr_pic_lt_sps_flag = 0x0,
+ };
+
+ for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) {
+ ltr->used_by_curr_pic_lt_sps_flag |= sps->used_by_curr_pic_lt_sps_flag[i] << i;
+ ltr->lt_ref_pic_poc_lsb_sps[i] = sps->lt_ref_pic_poc_lsb_sps[i];
+ }
+
+ *vksps = (StdVideoH265SequenceParameterSet) {
+ .flags = (StdVideoH265SpsFlags) {
+ .sps_temporal_id_nesting_flag = sps->temporal_id_nesting_flag,
+ .separate_colour_plane_flag = sps->separate_colour_plane_flag,
+ .conformance_window_flag = sps->conformance_window_flag,
+ .sps_sub_layer_ordering_info_present_flag = sps->sublayer_ordering_info_flag,
+ .scaling_list_enabled_flag = sps->scaling_list_enable_flag,
+ .sps_scaling_list_data_present_flag = sps->scaling_list_enable_flag,
+ .amp_enabled_flag = sps->amp_enabled_flag,
+ .sample_adaptive_offset_enabled_flag = sps->sao_enabled,
+ .pcm_enabled_flag = sps->pcm_enabled_flag,
+ .pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag,
+ .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
+ .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag,
+ .strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag,
+ .vui_parameters_present_flag = sps->vui_present,
+ .sps_extension_present_flag = sps->sps_extension_present_flag,
+ .sps_range_extension_flag = sps->sps_range_extension_flag,
+ .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,
+ .sps_scc_extension_flag = sps->sps_scc_extension_flag,
+ .sps_curr_pic_ref_enabled_flag = sps->sps_curr_pic_ref_enabled_flag,
+ .palette_mode_enabled_flag = sps->palette_mode_enabled_flag,
+ .sps_palette_predictor_initializers_present_flag = sps->sps_palette_predictor_initializers_present_flag,
+ .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disabled_flag,
+ },
+ .chroma_format_idc = sps->chroma_format_idc,
+ .pic_width_in_luma_samples = sps->width,
+ .pic_height_in_luma_samples = sps->height,
+ .sps_video_parameter_set_id = sps->vps_id,
+ .sps_max_sub_layers_minus1 = sps->max_sub_layers - 1,
+ .sps_seq_parameter_set_id = sps_idx,
+ .bit_depth_luma_minus8 = sps->bit_depth - 8,
+ .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
+ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4,
+ .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3,
+ .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size,
+ .log2_min_luma_transform_block_size_minus2 = sps->log2_min_tb_size - 2,
+ .log2_diff_max_min_luma_transform_block_size = sps->log2_diff_max_min_transform_block_size,
+ .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
+ .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
+ .num_short_term_ref_pic_sets = sps->nb_st_rps,
+ .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
+ .pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1,
+ .pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1,
+ .log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3,
+ .log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size,
+ /* Reserved */
+ /* Reserved */
+ .palette_max_size = sps->palette_max_size,
+ .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size,
+ .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc,
+ .sps_num_palette_predictor_initializers_minus1 = sps->sps_num_palette_predictor_initializers - 1,
+ .conf_win_left_offset = sps->pic_conf_win.left_offset,
+ .conf_win_right_offset = sps->pic_conf_win.right_offset,
+ .conf_win_top_offset = sps->pic_conf_win.top_offset,
+ .conf_win_bottom_offset = sps->pic_conf_win.bottom_offset,
+ .pProfileTierLevel = ptl,
+ .pDecPicBufMgr = dpbm,
+ .pScalingLists = vksps_scaling,
+ .pShortTermRefPicSet = str,
+ .pLongTermRefPicsSps = ltr,
+ .pSequenceParameterSetVui = vksps_vui,
+ .pPredictorPaletteEntries = pal,
+ };
+}
+
+static void set_pps(const HEVCPPS *pps, const HEVCSPS *sps,
+ StdVideoH265ScalingLists *vkpps_scaling,
+ StdVideoH265PictureParameterSet *vkpps,
+ StdVideoH265PredictorPaletteEntries *pal)
+{
+ for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++)
+ memcpy(vkpps_scaling->ScalingList4x4[i], pps->scaling_list.sl[0][i],
+ STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList4x4));
+
+ for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS; i++)
+ memcpy(vkpps_scaling->ScalingList8x8[i], pps->scaling_list.sl[1][i],
+ STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList8x8));
+
+ for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS; i++)
+ memcpy(vkpps_scaling->ScalingList16x16[i], pps->scaling_list.sl[2][i],
+ STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList16x16));
+
+ for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS; i++)
+ memcpy(vkpps_scaling->ScalingList32x32[i], pps->scaling_list.sl[3][i],
+ STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(**vkpps_scaling->ScalingList32x32));
+
+ memcpy(vkpps_scaling->ScalingListDCCoef16x16, pps->scaling_list.sl_dc[0],
+ STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS * sizeof(*vkpps_scaling->ScalingListDCCoef16x16));
+
+ memcpy(vkpps_scaling->ScalingListDCCoef32x32, pps->scaling_list.sl_dc[1],
+ STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS * sizeof(*vkpps_scaling->ScalingListDCCoef32x32));
+
+ *vkpps = (StdVideoH265PictureParameterSet) {
+ .flags = (StdVideoH265PpsFlags) {
+ .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
+ .output_flag_present_flag = pps->output_flag_present_flag,
+ .sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag,
+ .cabac_init_present_flag = pps->cabac_init_present_flag,
+ .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
+ .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
+ .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
+ .pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag,
+ .weighted_pred_flag = pps->weighted_pred_flag,
+ .weighted_bipred_flag = pps->weighted_bipred_flag,
+ .transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag,
+ .tiles_enabled_flag = pps->tiles_enabled_flag,
+ .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
+ .uniform_spacing_flag = pps->uniform_spacing_flag,
+ .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
+ .pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag,
+ .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag,
+ .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
+ .pps_deblocking_filter_disabled_flag = pps->disable_dbf,
+ .pps_scaling_list_data_present_flag = pps->scaling_list_data_present_flag,
+ .lists_modification_present_flag = pps->lists_modification_present_flag,
+ .slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag,
+ .pps_extension_present_flag = pps->pps_extension_present_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,
+ .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag,
+ .residual_adaptive_colour_transform_enabled_flag = pps->residual_adaptive_colour_transform_enabled_flag,
+ .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag,
+ .pps_palette_predictor_initializers_present_flag = pps->pps_palette_predictor_initializers_present_flag,
+ .monochrome_palette_flag = pps->monochrome_palette_flag,
+ .pps_range_extension_flag = pps->pps_range_extensions_flag,
+ },
+ .pps_pic_parameter_set_id = pps->pps_id,
+ .pps_seq_parameter_set_id = pps->sps_id,
+ .sps_video_parameter_set_id = sps->vps_id,
+ .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
+ .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1,
+ .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1,
+ .init_qp_minus26 = pps->pic_init_qp_minus26,
+ .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
+ .pps_cb_qp_offset = pps->cb_qp_offset,
+ .pps_cr_qp_offset = pps->cr_qp_offset,
+ .pps_beta_offset_div2 = pps->beta_offset >> 1,
+ .pps_tc_offset_div2 = pps->tc_offset >> 1,
+ .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2,
+ .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2,
+ .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,
+ .pps_act_y_qp_offset_plus5 = pps->pps_act_y_qp_offset + 5,
+ .pps_act_cb_qp_offset_plus5 = pps->pps_act_cb_qp_offset + 5,
+ .pps_act_cr_qp_offset_plus3 = pps->pps_act_cr_qp_offset + 3,
+ .pps_num_palette_predictor_initializers = pps->pps_num_palette_predictor_initializers,
+ .luma_bit_depth_entry_minus8 = pps->luma_bit_depth_entry - 8,
+ .chroma_bit_depth_entry_minus8 = pps->chroma_bit_depth_entry - 8,
+ .num_tile_columns_minus1 = pps->num_tile_columns - 1,
+ .num_tile_rows_minus1 = pps->num_tile_rows - 1,
+ .pScalingLists = vkpps_scaling,
+ .pPredictorPaletteEntries = pal,
+ };
+
+ for (int i = 0; i < (pps->monochrome_palette_flag ? 1 : 3); i++) {
+ for (int j = 0; j < pps->pps_num_palette_predictor_initializers; j++)
+ pal->PredictorPaletteEntries[i][j] = pps->pps_palette_predictor_initializer[i][j];
+ }
+
+ for (int i = 0; i < pps->num_tile_columns - 1; i++)
+ vkpps->column_width_minus1[i] = pps->column_width[i] - 1;
+
+ for (int i = 0; i < pps->num_tile_rows - 1; i++)
+ vkpps->row_height_minus1[i] = pps->row_height[i] - 1;
+
+ for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
+ vkpps->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i];
+ vkpps->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i];
+ }
+}
+
+static void set_vps(const HEVCVPS *vps,
+ StdVideoH265VideoParameterSet *vkvps,
+ StdVideoH265ProfileTierLevel *ptl,
+ StdVideoH265DecPicBufMgr *dpbm,
+ StdVideoH265HrdParameters *sls_hdr,
+ HEVCHeaderVPSSet sls[])
+{
+ for (int i = 0; i < vps->vps_num_hrd_parameters; i++) {
+ const HEVCHdrParams *src = &vps->hdr[i];
+
+ sls_hdr[i] = (StdVideoH265HrdParameters) {
+ .flags = (StdVideoH265HrdFlags) {
+ .nal_hrd_parameters_present_flag = src->flags.nal_hrd_parameters_present_flag,
+ .vcl_hrd_parameters_present_flag = src->flags.vcl_hrd_parameters_present_flag,
+ .sub_pic_hrd_params_present_flag = src->flags.sub_pic_hrd_params_present_flag,
+ .sub_pic_cpb_params_in_pic_timing_sei_flag = src->flags.sub_pic_cpb_params_in_pic_timing_sei_flag,
+ .fixed_pic_rate_general_flag = src->flags.fixed_pic_rate_general_flag,
+ .fixed_pic_rate_within_cvs_flag = src->flags.fixed_pic_rate_within_cvs_flag,
+ .low_delay_hrd_flag = src->flags.low_delay_hrd_flag,
+ },
+ .tick_divisor_minus2 = src->tick_divisor_minus2,
+ .du_cpb_removal_delay_increment_length_minus1 = src->du_cpb_removal_delay_increment_length_minus1,
+ .dpb_output_delay_du_length_minus1 = src->dpb_output_delay_du_length_minus1,
+ .bit_rate_scale = src->bit_rate_scale,
+ .cpb_size_scale = src->cpb_size_scale,
+ .cpb_size_du_scale = src->cpb_size_du_scale,
+ .initial_cpb_removal_delay_length_minus1 = src->initial_cpb_removal_delay_length_minus1,
+ .au_cpb_removal_delay_length_minus1 = src->au_cpb_removal_delay_length_minus1,
+ .dpb_output_delay_length_minus1 = src->dpb_output_delay_length_minus1,
+ /* Reserved - 3*16 bits */
+ .pSubLayerHrdParametersNal = sls[i].nal_hdr,
+ .pSubLayerHrdParametersVcl = sls[i].vcl_hdr,
+ };
+
+ memcpy(sls_hdr[i].cpb_cnt_minus1, src->cpb_cnt_minus1,
+ STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].cpb_cnt_minus1));
+ memcpy(sls_hdr[i].elemental_duration_in_tc_minus1, src->elemental_duration_in_tc_minus1,
+ STD_VIDEO_H265_SUBLAYERS_LIST_SIZE*sizeof(*sls_hdr[i].elemental_duration_in_tc_minus1));
+
+ memcpy(sls[i].nal_hdr, src->nal_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].nal_hdr));
+ memcpy(sls[i].vcl_hdr, src->vcl_params, HEVC_MAX_SUB_LAYERS*sizeof(*sls[i].vcl_hdr));
+ }
+
+ *ptl = (StdVideoH265ProfileTierLevel) {
+ .flags = (StdVideoH265ProfileTierLevelFlags) {
+ .general_tier_flag = vps->ptl.general_ptl.tier_flag,
+ .general_progressive_source_flag = vps->ptl.general_ptl.progressive_source_flag,
+ .general_interlaced_source_flag = vps->ptl.general_ptl.interlaced_source_flag,
+ .general_non_packed_constraint_flag = vps->ptl.general_ptl.non_packed_constraint_flag,
+ .general_frame_only_constraint_flag = vps->ptl.general_ptl.frame_only_constraint_flag,
+ },
+ .general_profile_idc = vps->ptl.general_ptl.profile_idc,
+ .general_level_idc = convert_to_vk_level_idc(vps->ptl.general_ptl.level_idc),
+ };
+
+ for (int i = 0; i < vps->vps_max_sub_layers; i++) {
+ dpbm->max_latency_increase_plus1[i] = vps->vps_max_latency_increase[i] + 1;
+ dpbm->max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering[i] - 1;
+ dpbm->max_num_reorder_pics[i] = vps->vps_num_reorder_pics[i];
+ }
+
+ *vkvps = (StdVideoH265VideoParameterSet) {
+ .flags = (StdVideoH265VpsFlags) {
+ .vps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag,
+ .vps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag,
+ .vps_timing_info_present_flag = vps->vps_timing_info_present_flag,
+ .vps_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag,
+ },
+ .vps_video_parameter_set_id = vps->vps_id,
+ .vps_max_sub_layers_minus1 = vps->vps_max_sub_layers - 1,
+ /* Reserved */
+ /* Reserved */
+ .vps_num_units_in_tick = vps->vps_num_units_in_tick,
+ .vps_time_scale = vps->vps_time_scale,
+ .vps_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one - 1,
+ /* Reserved */
+ .pDecPicBufMgr = dpbm,
+ .pHrdParameters = sls_hdr,
+ .pProfileTierLevel = ptl,
+ };
+}
+
+static int vk_hevc_create_params(AVCodecContext *avctx, AVBufferRef **buf)
+{
+ int err;
+ VkResult ret;
+ const HEVCContext *h = avctx->priv_data;
+ FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+ FFVulkanDecodeShared *ctx = (FFVulkanDecodeShared *)dec->shared_ref->data;
+ FFVulkanFunctions *vk = &ctx->s.vkfn;
+
+ VkVideoDecodeH265SessionParametersAddInfoKHR h265_params_info = {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR,
+ .stdSPSCount = 0,
+ .stdPPSCount = 0,
+ .stdVPSCount = 0,
+ };
+ VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
+ .pParametersAddInfo = &h265_params_info,
+ };
+ VkVideoSessionParametersCreateInfoKHR session_params_create = {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
+ .pNext = &h265_params,
+ .videoSession = ctx->common.session,
+ .videoSessionParametersTemplate = NULL,
+ };
+
+ int nb_vps = 0;
+ AVBufferRef *data_set;
+ HEVCHeaderSet *hdr;
+
+ AVBufferRef *tmp;
+ VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par));
+ if (!par)
+ return AVERROR(ENOMEM);
+
+ for (int i = 0; h->ps.vps_list[i]; i++)
+ nb_vps++;
+
+ err = get_data_set_buf(dec, &data_set, nb_vps, h->ps.vps_list);
+ if (err < 0)
+ return err;
+
+ hdr = (HEVCHeaderSet *)data_set->data;
+
+ h265_params_info.pStdSPSs = hdr->sps;
+ h265_params_info.pStdPPSs = hdr->pps;
+ h265_params_info.pStdVPSs = hdr->vps;
+
+ /* SPS list */
+ for (int i = 0; h->ps.sps_list[i]; i++) {
+ const HEVCSPS *sps_l = (const HEVCSPS *)h->ps.sps_list[i]->data;
+ set_sps(sps_l, i, &hdr->hsps[i].scaling, &hdr->hsps[i].vui_header,
+ &hdr->hsps[i].vui, &hdr->sps[i], hdr->hsps[i].nal_hdr,
+ hdr->hsps[i].vcl_hdr, &hdr->hsps[i].ptl, &hdr->hsps[i].dpbm,
+ &hdr->hsps[i].pal, hdr->hsps[i].str, &hdr->hsps[i].ltr);
+ h265_params_info.stdSPSCount++;
+ }
+
+ /* PPS list */
+ for (int i = 0; h->ps.pps_list[i]; i++) {
+ const HEVCPPS *pps_l = (const HEVCPPS *)h->ps.pps_list[i]->data;
+ const HEVCSPS *sps_l = (const HEVCSPS *)h->ps.sps_list[pps_l->sps_id]->data;
+ set_pps(pps_l, sps_l, &hdr->hpps[i].scaling, &hdr->pps[i], &hdr->hpps[i].pal);
+ h265_params_info.stdPPSCount++;
+ }
+
+ /* VPS list */
+ for (int i = 0; i < nb_vps; i++) {
+ const HEVCVPS *vps_l = (const HEVCVPS *)h->ps.vps_list[i]->data;
+ set_vps(vps_l, &hdr->vps[i], &hdr->hvps[i].ptl, &hdr->hvps[i].dpbm,
+ hdr->hvps[i].hdr, hdr->hvps[i].sls);
+ h265_params_info.stdVPSCount++;
+ }
+
+ h265_params.maxStdSPSCount = h265_params_info.stdSPSCount;
+ h265_params.maxStdPPSCount = h265_params_info.stdPPSCount;
+ h265_params.maxStdVPSCount = h265_params_info.stdVPSCount;
+
+ /* Create session parameters */
+ ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, &session_params_create,
+ ctx->s.hwctx->alloc, par);
+ av_buffer_unref(&data_set);
+ if (ret != VK_SUCCESS) {
+ av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
+ ff_vk_ret2str(ret));
+ return AVERROR_EXTERNAL;
+ }
+
+ tmp = av_buffer_create((uint8_t *)par, sizeof(*par), ff_vk_decode_free_params,
+ ctx, 0);
+ if (!tmp) {
+ ff_vk_decode_free_params(ctx, (uint8_t *)par);
+ return AVERROR(ENOMEM);
+ }
+
+ av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS %i VPS\n",
+ h265_params_info.stdSPSCount, h265_params_info.stdPPSCount,
+ h265_params_info.stdVPSCount);
+
+ *buf = tmp;
+
+ return 0;
+}
+
+static int vk_hevc_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ int err;
+ HEVCContext *h = avctx->priv_data;
+ HEVCFrame *pic = h->ref;
+ FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
+ HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
+ FFVulkanDecodePicture *vp = &hp->vp;
+ const HEVCSPS *sps = h->ps.sps;
+ const HEVCPPS *pps = h->ps.pps;
+ int nb_refs = 0;
+
+ if (!dec->session_params || dec->params_changed) {
+ av_buffer_unref(&dec->session_params);
+ err = vk_hevc_create_params(avctx, &dec->session_params);
+ if (err < 0)
+ return err;
+ dec->params_changed = 0;
+ }
+
+ hp->h265pic = (StdVideoDecodeH265PictureInfo) {
+ .flags = (StdVideoDecodeH265PictureInfoFlags) {
+ .IrapPicFlag = IS_IRAP(h),
+ .IdrPicFlag = IS_IDR(h),
+ .IsReference = h->nal_unit_type < 16 ? h->nal_unit_type & 1 : 1,
+ .short_term_ref_pic_set_sps_flag = h->sh.short_term_ref_pic_set_sps_flag,
+ },
+ .sps_video_parameter_set_id = sps->vps_id,
+ .pps_seq_parameter_set_id = pps->sps_id,
+ .pps_pic_parameter_set_id = pps->pps_id,
+ .NumDeltaPocsOfRefRpsIdx = h->sh.short_term_rps ? h->sh.short_term_rps->rps_idx_num_delta_pocs : 0,
+ .PicOrderCntVal = h->poc,
+ .NumBitsForSTRefPicSetInSlice = !h->sh.short_term_ref_pic_set_sps_flag ?
+ h->sh.bits_used_for_short_term_rps : 0,
+ };
+
+ /* Fill in references */
+ for (int i = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
+ const HEVCFrame *ref = &h->DPB[i];
+ int idx = nb_refs;
+
+ if (!(ref->flags & (HEVC_FRAME_FLAG_SHORT_REF | HEVC_FRAME_FLAG_LONG_REF)))
+ continue;
+
+ if (ref == pic) {
+ err = vk_hevc_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
+ &hp->vkh265_ref, &hp->h265_ref, pic, 1, i);
+ if (err < 0)
+ return err;
+
+ continue;
+ }
+
+ err = vk_hevc_fill_pict(avctx, &hp->ref_src[idx], &vp->ref_slots[idx],
+ &vp->refs[idx], &hp->vkh265_refs[idx],
+ &hp->h265_refs[idx], (HEVCFrame *)ref, 0, i);
+ if (err < 0)
+ return err;
+
+ nb_refs++;
+ }
+
+ memset(hp->h265pic.RefPicSetStCurrBefore, 0xff, 8);
+ for (int i = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {
+ HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i];
+ for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) {
+ const HEVCFrame *ref = &h->DPB[j];
+ if (ref == frame) {
+ hp->h265pic.RefPicSetStCurrBefore[i] = j;
+ break;
+ }
+ }
+ }
+ memset(hp->h265pic.RefPicSetStCurrAfter, 0xff, 8);
+ for (int i = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {
+ HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i];
+ for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) {
+ const HEVCFrame *ref = &h->DPB[j];
+ if (ref == frame) {
+ hp->h265pic.RefPicSetStCurrAfter[i] = j;
+ break;
+ }
+ }
+ }
+ memset(hp->h265pic.RefPicSetLtCurr, 0xff, 8);
+ for (int i = 0; i < h->rps[LT_CURR].nb_refs; i++) {
+ HEVCFrame *frame = h->rps[LT_CURR].ref[i];
+ for (int j = 0; j < FF_ARRAY_ELEMS(h->DPB); j++) {
+ const HEVCFrame *ref = &h->DPB[j];
+ if (ref == frame) {
+ hp->h265pic.RefPicSetLtCurr[i] = j;
+ break;
+ }
+ }
+ }
+
+ hp->h265_pic_info = (VkVideoDecodeH265PictureInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR,
+ .pStdPictureInfo = &hp->h265pic,
+ .sliceSegmentCount = 0,
+ .pSliceSegmentOffsets = vp->slice_off,
+ };
+
+ vp->decode_info = (VkVideoDecodeInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
+ .pNext = &hp->h265_pic_info,
+ .flags = 0x0,
+ .pSetupReferenceSlot = &vp->ref_slot,
+ .referenceSlotCount = nb_refs,
+ .pReferenceSlots = vp->ref_slots,
+ .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
+ .codedOffset = (VkOffset2D){ 0, 0 },
+ .codedExtent = (VkExtent2D){ pic->frame->width, pic->frame->height },
+ .baseArrayLayer = 0,
+ .imageViewBinding = vp->img_view_out,
+ },
+ };
+
+ return 0;
+}
+
+static int vk_hevc_decode_slice(AVCodecContext *avctx,
+ const uint8_t *data,
+ uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ HEVCVulkanDecodePicture *hp = h->ref->hwaccel_picture_private;
+ FFVulkanDecodePicture *vp = &hp->vp;
+
+ int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1,
+ &hp->h265_pic_info.sliceSegmentCount,
+ &hp->h265_pic_info.pSliceSegmentOffsets);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int vk_hevc_end_frame(AVCodecContext *avctx)
+{
+ const HEVCContext *h = avctx->priv_data;
+ HEVCFrame *pic = h->ref;
+ HEVCVulkanDecodePicture *hp = pic->hwaccel_picture_private;
+ FFVulkanDecodePicture *vp = &hp->vp;
+ FFVulkanDecodePicture *rvp[HEVC_MAX_REFS] = { 0 };
+ AVFrame *rav[HEVC_MAX_REFS] = { 0 };
+
+ for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
+ HEVCVulkanDecodePicture *rfhp = hp->ref_src[i]->hwaccel_picture_private;
+ rav[i] = hp->ref_src[i]->frame;
+ rvp[i] = &rfhp->vp;
+ }
+
+ av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %lu bytes, %i slices\n",
+ vp->slices_size, hp->h265_pic_info.sliceSegmentCount);
+
+ return ff_vk_decode_frame(avctx, pic->frame, vp, rav, rvp);
+}
+
+static void vk_hevc_free_frame_priv(void *_hwctx, uint8_t *data)
+{
+ AVHWDeviceContext *hwctx = _hwctx;
+ HEVCVulkanDecodePicture *hp = (HEVCVulkanDecodePicture *)data;
+
+ /* Free frame resources */
+ ff_vk_decode_free_frame(hwctx, &hp->vp);
+
+ /* Free frame context */
+ av_free(hp);
+}
+
+const AVHWAccel ff_hevc_vulkan_hwaccel = {
+ .name = "hevc_vulkan",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_HEVC,
+ .pix_fmt = AV_PIX_FMT_VULKAN,
+ .start_frame = &vk_hevc_start_frame,
+ .decode_slice = &vk_hevc_decode_slice,
+ .end_frame = &vk_hevc_end_frame,
+ .free_frame_priv = &vk_hevc_free_frame_priv,
+ .frame_priv_data_size = sizeof(HEVCVulkanDecodePicture),
+ .init = &ff_vk_decode_init,
+ .update_thread_context = &ff_vk_update_thread_context,
+ .decode_params = &ff_vk_params_changed,
+ .flush = &ff_vk_decode_flush,
+ .uninit = &ff_vk_decode_uninit,
+ .frame_params = &ff_vk_frame_params,
+ .priv_data_size = sizeof(FFVulkanDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE | HWACCEL_CAP_THREAD_SAFE,
+};