From: Lynne <dev@lynne.ee> To: ffmpeg-devel@ffmpeg.org Cc: Lynne <dev@lynne.ee> Subject: [FFmpeg-devel] [PATCH 5/6] vulkan_h264: make all temporary structs temporary Date: Mon, 31 Mar 2025 04:37:41 +0200 Message-ID: <20250331023753.285499-5-dev@lynne.ee> (raw) In-Reply-To: <20250331023753.285499-1-dev@lynne.ee> This commit moves all temporary structs used for decoding out of the common picture header and onto stack. --- libavcodec/vulkan_decode.c | 1 + libavcodec/vulkan_decode.h | 3 + libavcodec/vulkan_h264.c | 322 +++++++++++++++++++------------------ 3 files changed, 168 insertions(+), 158 deletions(-) diff --git a/libavcodec/vulkan_decode.c b/libavcodec/vulkan_decode.c index 893f8fca3d..5505fbda28 100644 --- a/libavcodec/vulkan_decode.c +++ b/libavcodec/vulkan_decode.c @@ -253,6 +253,7 @@ int ff_vk_decode_start_frame(AVCodecContext *avctx, FFVulkanDecodePicture *vp, vp->nb_slices = 0; vp->slices_size = 0; + vp->intra_pic_flag = 1; /* Host map the input slices data if supported */ if (complete && ctx->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) { diff --git a/libavcodec/vulkan_decode.h b/libavcodec/vulkan_decode.h index 103be09943..5b14d962f2 100644 --- a/libavcodec/vulkan_decode.h +++ b/libavcodec/vulkan_decode.h @@ -105,6 +105,9 @@ typedef struct FFVulkanDecodePicture { /* Vulkan functions needed for destruction, as no other context is guaranteed to exist */ PFN_vkWaitSemaphores wait_semaphores; PFN_vkDestroyImageView destroy_image_view; + + /* Codec specific */ + int intra_pic_flag; /* Only used by H264 */ } FFVulkanDecodePicture; /** diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c index 71a9c06801..e697583ba9 100644 --- a/libavcodec/vulkan_h264.c +++ b/libavcodec/vulkan_h264.c @@ -32,99 +32,8 @@ const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc = { }, }; -typedef struct H264VulkanDecodePicture { - FFVulkanDecodePicture vp; - - /* Current picture */ - StdVideoDecodeH264ReferenceInfo h264_ref; - VkVideoDecodeH264DpbSlotInfoKHR vkh264_ref; - - /* Picture refs */ - H264Picture *ref_src [H264_MAX_PICTURE_COUNT]; - StdVideoDecodeH264ReferenceInfo h264_refs [H264_MAX_PICTURE_COUNT]; - VkVideoDecodeH264DpbSlotInfoKHR vkh264_refs[H264_MAX_PICTURE_COUNT]; - - /* Current picture (contd.) */ - StdVideoDecodeH264PictureInfo h264pic; - VkVideoDecodeH264PictureInfoKHR h264_pic_info; - - /* Current picture */ - VkVideoPictureResourceInfoKHR ref; - VkVideoReferenceSlotInfoKHR ref_slot; - - /* Picture refs. H264 has the maximum number of refs (36) of any supported codec. */ - VkVideoPictureResourceInfoKHR refs [36]; - VkVideoReferenceSlotInfoKHR ref_slots[36]; - - /* Main decoding struct */ - VkVideoDecodeInfoKHR decode_info; -} H264VulkanDecodePicture; - const static int h264_scaling_list8_order[] = { 0, 3, 1, 4, 2, 5 }; -static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src, - VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */ - VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */ - VkVideoDecodeH264DpbSlotInfoKHR *vkh264_ref, /* Goes in ^ */ - StdVideoDecodeH264ReferenceInfo *h264_ref, /* Goes in ^ */ - H264Picture *pic, int is_current, - int is_field, int picture_structure, - int dpb_slot_index) -{ - FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; - FFVulkanDecodeShared *ctx = dec->shared_ctx; - H264VulkanDecodePicture *hp = pic->hwaccel_picture_private; - FFVulkanDecodePicture *vkpic = &hp->vp; - - int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current, - dec->dedicated_dpb); - if (err < 0) - return err; - - *h264_ref = (StdVideoDecodeH264ReferenceInfo) { - .FrameNum = pic->long_ref ? pic->pic_id : pic->frame_num, - .PicOrderCnt = { pic->field_poc[0], pic->field_poc[1] }, - .flags = (StdVideoDecodeH264ReferenceInfoFlags) { - .top_field_flag = is_field ? !!(picture_structure & PICT_TOP_FIELD) : 0, - .bottom_field_flag = is_field ? !!(picture_structure & PICT_BOTTOM_FIELD) : 0, - .used_for_long_term_reference = pic->reference && pic->long_ref, - /* - * flags.is_non_existing is used to indicate whether the picture is marked as - * “non-existing” as defined in section 8.2.5.2 of the ITU-T H.264 Specification; - * 8.2.5.2 Decoding process for gaps in frame_num - * corresponds to the code in h264_slice.c:h264_field_start, - * which sets the invalid_gap flag when decoding. - */ - .is_non_existing = pic->invalid_gap, - }, - }; - - *vkh264_ref = (VkVideoDecodeH264DpbSlotInfoKHR) { - .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR, - .pStdReferenceInfo = h264_ref, - }; - - *ref = (VkVideoPictureResourceInfoKHR) { - .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, - .codedOffset = (VkOffset2D){ 0, 0 }, - .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height }, - .baseArrayLayer = ctx->common.layered_dpb ? dpb_slot_index : 0, - .imageViewBinding = vkpic->view.ref[0], - }; - - *ref_slot = (VkVideoReferenceSlotInfoKHR) { - .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR, - .pNext = vkh264_ref, - .slotIndex = dpb_slot_index, - .pPictureResource = ref, - }; - - if (ref_src) - *ref_src = pic; - - return 0; -} - static StdVideoH264LevelIdc convert_to_vk_level_idc(int level_idc) { switch (level_idc) { @@ -369,18 +278,124 @@ static int vk_h264_create_params(AVCodecContext *avctx, AVBufferRef **buf) return 0; } +static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src, + VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */ + VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */ + VkVideoDecodeH264DpbSlotInfoKHR *vkh264_ref, /* Goes in ^ */ + StdVideoDecodeH264ReferenceInfo *h264_ref, /* Goes in ^ */ + H264Picture *pic, int is_current, + int is_field, int picture_structure, + int dpb_slot_index) +{ + FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; + FFVulkanDecodeShared *ctx = dec->shared_ctx; + FFVulkanDecodePicture *vkpic = pic->hwaccel_picture_private; + + int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current, + dec->dedicated_dpb); + if (err < 0) + return err; + + *h264_ref = (StdVideoDecodeH264ReferenceInfo) { + .FrameNum = pic->long_ref ? pic->pic_id : pic->frame_num, + .PicOrderCnt = { pic->field_poc[0], pic->field_poc[1] }, + .flags = (StdVideoDecodeH264ReferenceInfoFlags) { + .top_field_flag = is_field ? !!(picture_structure & PICT_TOP_FIELD) : 0, + .bottom_field_flag = is_field ? !!(picture_structure & PICT_BOTTOM_FIELD) : 0, + .used_for_long_term_reference = pic->reference && pic->long_ref, + /* + * flags.is_non_existing is used to indicate whether the picture is marked as + * “non-existing” as defined in section 8.2.5.2 of the ITU-T H.264 Specification; + * 8.2.5.2 Decoding process for gaps in frame_num + * corresponds to the code in h264_slice.c:h264_field_start, + * which sets the invalid_gap flag when decoding. + */ + .is_non_existing = pic->invalid_gap, + }, + }; + + *vkh264_ref = (VkVideoDecodeH264DpbSlotInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR, + .pStdReferenceInfo = h264_ref, + }; + + *ref = (VkVideoPictureResourceInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR, + .codedOffset = (VkOffset2D){ 0, 0 }, + .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height }, + .baseArrayLayer = ctx->common.layered_dpb ? dpb_slot_index : 0, + .imageViewBinding = vkpic->view.ref[0], + }; + + *ref_slot = (VkVideoReferenceSlotInfoKHR) { + .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR, + .pNext = vkh264_ref, + .slotIndex = dpb_slot_index, + .pPictureResource = ref, + }; + + if (ref_src) + *ref_src = pic; + + return 0; +} + static int vk_h264_start_frame(AVCodecContext *avctx, av_unused const AVBufferRef *buffer_ref, av_unused const uint8_t *buffer, av_unused uint32_t size) +{ + const H264Context *h = avctx->priv_data; + H264Picture *pic = h->cur_pic_ptr; + FFVulkanDecodePicture *vp = pic->hwaccel_picture_private; + + return ff_vk_decode_start_frame(avctx, vp, buffer_ref, 0); +} + +typedef struct H264VulkanDecodeParams { + /* Current picture */ + StdVideoDecodeH264ReferenceInfo h264_ref; + VkVideoDecodeH264DpbSlotInfoKHR vkh264_ref; + + /* Picture refs */ + H264Picture *ref_src [H264_MAX_PICTURE_COUNT]; + StdVideoDecodeH264ReferenceInfo h264_refs [H264_MAX_PICTURE_COUNT]; + VkVideoDecodeH264DpbSlotInfoKHR vkh264_refs[H264_MAX_PICTURE_COUNT]; + + /* Current picture (contd.) */ + StdVideoDecodeH264PictureInfo h264pic; + VkVideoDecodeH264PictureInfoKHR h264_pic_info; + + /* Current picture */ + VkVideoPictureResourceInfoKHR ref; + VkVideoReferenceSlotInfoKHR ref_slot; + + /* Picture refs. H264 has the maximum number of refs (36) of any supported codec. */ + VkVideoPictureResourceInfoKHR refs [36]; + VkVideoReferenceSlotInfoKHR ref_slots[36]; + + /* Maintenance 2 */ +#ifdef VK_KHR_video_maintenance2 + StdVideoH264ScalingLists vksps_scaling; + StdVideoH264HrdParameters vksps_vui_header; + StdVideoH264SequenceParameterSetVui vksps_vui; + StdVideoH264SequenceParameterSet vksps; + StdVideoH264ScalingLists vkpps_scaling; + StdVideoH264PictureParameterSet vkpps; + VkVideoDecodeH264InlineSessionParametersInfoKHR h264_params; +#endif + + /* Main decoding struct */ + VkVideoDecodeInfoKHR decode_info; +} H264VulkanDecodeParams; + +static int vk_h264_fill_params(AVCodecContext *avctx, FFVulkanDecodePicture *vp, + H264VulkanDecodeParams *hp) { int err; int dpb_slot_index = 0; H264Context *h = avctx->priv_data; - H264Picture *pic = h->cur_pic_ptr; - H264VulkanDecodePicture *hp = pic->hwaccel_picture_private; - FFVulkanDecodePicture *vp = &hp->vp; /* Fill in main slot */ dpb_slot_index = 0; @@ -445,13 +460,13 @@ static int vk_h264_start_frame(AVCodecContext *avctx, hp->h264pic = (StdVideoDecodeH264PictureInfo) { .seq_parameter_set_id = pic->pps->sps_id, .pic_parameter_set_id = pic->pps->pps_id, - .frame_num = 0, /* Set later */ - .idr_pic_id = 0, /* Set later */ + .frame_num = h->slice_ctx[0].frame_num, + .idr_pic_id = h->slice_ctx[0].idr_pic_id, .PicOrderCnt[0] = pic->field_poc[0], .PicOrderCnt[1] = pic->field_poc[1], .flags = (StdVideoDecodeH264PictureInfoFlags) { + .is_intra = vp->intra_pic_flag, .field_pic_flag = FIELD_PICTURE(h), - .is_intra = 1, /* Set later */ .IdrPicFlag = h->picture_idr, .bottom_field_flag = h->picture_structure != PICT_FRAME && h->picture_structure & PICT_BOTTOM_FIELD, @@ -463,6 +478,8 @@ static int vk_h264_start_frame(AVCodecContext *avctx, hp->h264_pic_info = (VkVideoDecodeH264PictureInfoKHR) { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR, .pStdPictureInfo = &hp->h264pic, + .pSliceOffsets = vp->slice_offsets, + .sliceCount = vp->nb_slices, }; hp->decode_info = (VkVideoDecodeInfoKHR) { @@ -484,100 +501,89 @@ static int vk_h264_start_frame(AVCodecContext *avctx, return 0; } -static int vk_h264_decode_slice(AVCodecContext *avctx, - const uint8_t *data, - uint32_t size) -{ - const H264Context *h = avctx->priv_data; - const H264SliceContext *sl = &h->slice_ctx[0]; - H264VulkanDecodePicture *hp = h->cur_pic_ptr->hwaccel_picture_private; - FFVulkanDecodePicture *vp = &hp->vp; - - int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1); - if (err < 0) - return err; - - hp->h264pic.frame_num = sl->frame_num; - hp->h264pic.idr_pic_id = sl->idr_pic_id; - - /* Frame is only intra of all slices are marked as intra */ - if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI) - hp->h264pic.flags.is_intra = 0; - - return 0; -} - static int vk_h264_end_frame(AVCodecContext *avctx) { + int err; const H264Context *h = avctx->priv_data; FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; FFVulkanDecodeShared *ctx = dec->shared_ctx; H264Picture *pic = h->cur_pic_ptr; - H264VulkanDecodePicture *hp = pic->hwaccel_picture_private; - FFVulkanDecodePicture *vp = &hp->vp; + FFVulkanDecodePicture *vp = pic->hwaccel_picture_private; FFVulkanDecodePicture *rvp[H264_MAX_PICTURE_COUNT] = { 0 }; AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 }; -#ifdef VK_KHR_video_maintenance2 - StdVideoH264ScalingLists vksps_scaling; - StdVideoH264HrdParameters vksps_vui_header; - StdVideoH264SequenceParameterSetVui vksps_vui; - StdVideoH264SequenceParameterSet vksps; - StdVideoH264ScalingLists vkpps_scaling; - StdVideoH264PictureParameterSet vkpps; - VkVideoDecodeH264InlineSessionParametersInfoKHR h264_params; + H264VulkanDecodeParams hp = { 0 }; + + if (!vp->nb_slices) + return 0; + + err = vk_h264_fill_params(avctx, vp, &hp); + if (err < 0) + return err; +#ifdef VK_KHR_video_maintenance2 if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2) { - set_sps(h->ps.sps, &vksps_scaling, - &vksps_vui_header, &vksps_vui, &vksps); - set_pps(h->ps.pps, h->ps.sps, &vkpps_scaling, &vkpps); - h264_params = (VkVideoDecodeH264InlineSessionParametersInfoKHR) { + set_sps(h->ps.sps, &hp.vksps_scaling, + &hp.vksps_vui_header, &hp.vksps_vui, &hp.vksps); + set_pps(h->ps.pps, h->ps.sps, &hp.vkpps_scaling, &hp.vkpps); + hp.h264_params = (VkVideoDecodeH264InlineSessionParametersInfoKHR) { .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR, - .pStdSPS = &vksps, - .pStdPPS = &vkpps, + .pStdSPS = &hp.vksps, + .pStdPPS = &hp.vkpps, }; - hp->h264_pic_info.pNext = &h264_params; - } + hp.h264_pic_info.pNext = &hp.h264_params; + } else #endif - hp->h264_pic_info.pSliceOffsets = vp->slice_offsets; - hp->h264_pic_info.sliceCount = vp->nb_slices; - if (!hp->h264_pic_info.sliceCount) - return 0; - - if (!dec->session_params && - !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) { + if (!dec->session_params) { int err = vk_h264_create_params(avctx, &dec->session_params); if (err < 0) return err; - hp->h264pic.seq_parameter_set_id = pic->pps->sps_id; - hp->h264pic.pic_parameter_set_id = pic->pps->pps_id; + hp.h264pic.seq_parameter_set_id = pic->pps->sps_id; + hp.h264pic.pic_parameter_set_id = pic->pps->pps_id; } - for (int i = 0; i < hp->decode_info.referenceSlotCount; i++) { - H264Picture *rp = hp->ref_src[i]; - H264VulkanDecodePicture *rhp = rp->hwaccel_picture_private; - - rvp[i] = &rhp->vp; - rav[i] = hp->ref_src[i]->f; + for (int i = 0; i < hp.decode_info.referenceSlotCount; i++) { + H264Picture *rp = hp.ref_src[i]; + rvp[i] = rp->hwaccel_picture_private; + rav[i] = hp.ref_src[i]->f; } av_log(avctx, AV_LOG_VERBOSE, "Decoding frame, %"SIZE_SPECIFIER" bytes, %i slices\n", - vp->slices_size, hp->h264_pic_info.sliceCount); + vp->slices_size, hp.h264_pic_info.sliceCount); - return ff_vk_decode_frame(avctx, &hp->decode_info, + return ff_vk_decode_frame(avctx, &hp.decode_info, pic->f, vp, rav, rvp); } +static int vk_h264_decode_slice(AVCodecContext *avctx, + const uint8_t *data, + uint32_t size) +{ + const H264Context *h = avctx->priv_data; + const H264SliceContext *sl = &h->slice_ctx[0]; + FFVulkanDecodePicture *vp = h->cur_pic_ptr->hwaccel_picture_private; + + int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1); + if (err < 0) + return err; + + /* Frame is only intra of all slices are marked as intra */ + if (sl->slice_type != AV_PICTURE_TYPE_I && sl->slice_type != AV_PICTURE_TYPE_SI) + vp->intra_pic_flag = 0; + + return 0; +} + static void vk_h264_free_frame_priv(AVRefStructOpaque _hwctx, void *data) { AVHWDeviceContext *hwctx = _hwctx.nc; - H264VulkanDecodePicture *hp = data; + FFVulkanDecodePicture *vp = data; /* Free frame resources, this also destroys the session parameters. */ - ff_vk_decode_free_frame(hwctx, &hp->vp); + ff_vk_decode_free_frame(hwctx, vp); } const FFHWAccel ff_h264_vulkan_hwaccel = { @@ -589,7 +595,7 @@ const FFHWAccel ff_h264_vulkan_hwaccel = { .decode_slice = &vk_h264_decode_slice, .end_frame = &vk_h264_end_frame, .free_frame_priv = &vk_h264_free_frame_priv, - .frame_priv_data_size = sizeof(H264VulkanDecodePicture), + .frame_priv_data_size = sizeof(FFVulkanDecodePicture), .init = &ff_vk_decode_init, .update_thread_context = &ff_vk_update_thread_context, .decode_params = &ff_vk_params_invalidate, -- 2.49.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2025-03-31 2:38 UTC|newest] Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top 2025-03-31 2:37 [FFmpeg-devel] [PATCH 1/6] vulkan_decode: generalize handling of slice offsets/nb Lynne 2025-03-31 2:37 ` [FFmpeg-devel] [PATCH 2/6] vulkan_decode: only create sequence params in end_frame Lynne 2025-03-31 2:37 ` [FFmpeg-devel] [PATCH 3/6] vulkan_decode: move temporary Vulkan structs into each codec Lynne 2025-03-31 2:37 ` [FFmpeg-devel] [PATCH 4/6] vulkan_decode: add a generic start_frame function Lynne 2025-03-31 2:37 ` Lynne [this message] 2025-03-31 2:37 ` [FFmpeg-devel] [PATCH 6/6] vulkan_hevc: make all temporary structs temporary Lynne
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20250331023753.285499-5-dev@lynne.ee \ --to=dev@lynne.ee \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git