You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-04 22:03:09 +02:00
vulkan_decode: support software-defined decoders
This commit is contained in:
@ -24,6 +24,9 @@
|
|||||||
#include "libavutil/mem.h"
|
#include "libavutil/mem.h"
|
||||||
#include "libavutil/vulkan_loader.h"
|
#include "libavutil/vulkan_loader.h"
|
||||||
|
|
||||||
|
#define DECODER_IS_SDR(codec_id) \
|
||||||
|
((codec_id) == AV_CODEC_ID_FFV1)
|
||||||
|
|
||||||
#if CONFIG_H264_VULKAN_HWACCEL
|
#if CONFIG_H264_VULKAN_HWACCEL
|
||||||
extern const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc;
|
extern const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc;
|
||||||
#endif
|
#endif
|
||||||
@ -63,7 +66,9 @@ static const VkVideoProfileInfoKHR *get_video_profile(FFVulkanDecodeShared *ctx,
|
|||||||
codec_id == AV_CODEC_ID_H264 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR :
|
codec_id == AV_CODEC_ID_H264 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR :
|
||||||
codec_id == AV_CODEC_ID_HEVC ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR :
|
codec_id == AV_CODEC_ID_HEVC ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR :
|
||||||
codec_id == AV_CODEC_ID_AV1 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR :
|
codec_id == AV_CODEC_ID_AV1 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR :
|
||||||
0;
|
VK_STRUCTURE_TYPE_MAX_ENUM;
|
||||||
|
if (profile_struct_type == VK_STRUCTURE_TYPE_MAX_ENUM)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
profile_list = ff_vk_find_struct(ctx->s.hwfc->create_pnext,
|
profile_list = ff_vk_find_struct(ctx->s.hwfc->create_pnext,
|
||||||
VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
|
VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
|
||||||
@ -119,21 +124,11 @@ static AVFrame *vk_get_dpb_pool(FFVulkanDecodeShared *ctx)
|
|||||||
return avf;
|
return avf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
|
static void init_frame(FFVulkanDecodeContext *dec, FFVulkanDecodePicture *vkpic)
|
||||||
FFVulkanDecodePicture *vkpic, int is_current,
|
|
||||||
int alloc_dpb)
|
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
FFVulkanDecodeShared *ctx = dec->shared_ctx;
|
FFVulkanDecodeShared *ctx = dec->shared_ctx;
|
||||||
FFVulkanFunctions *vk = &ctx->s.vkfn;
|
FFVulkanFunctions *vk = &ctx->s.vkfn;
|
||||||
|
|
||||||
vkpic->slices_size = 0;
|
|
||||||
|
|
||||||
/* If the decoder made a blank frame to make up for a missing ref, or the
|
|
||||||
* frame is the current frame so it's missing one, create a re-representation */
|
|
||||||
if (vkpic->img_view_ref)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
vkpic->dpb_frame = NULL;
|
vkpic->dpb_frame = NULL;
|
||||||
vkpic->img_view_ref = VK_NULL_HANDLE;
|
vkpic->img_view_ref = VK_NULL_HANDLE;
|
||||||
vkpic->img_view_out = VK_NULL_HANDLE;
|
vkpic->img_view_out = VK_NULL_HANDLE;
|
||||||
@ -141,6 +136,23 @@ int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
|
|||||||
|
|
||||||
vkpic->destroy_image_view = vk->DestroyImageView;
|
vkpic->destroy_image_view = vk->DestroyImageView;
|
||||||
vkpic->wait_semaphores = vk->WaitSemaphores;
|
vkpic->wait_semaphores = vk->WaitSemaphores;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
|
||||||
|
FFVulkanDecodePicture *vkpic, int is_current,
|
||||||
|
int alloc_dpb)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
FFVulkanDecodeShared *ctx = dec->shared_ctx;
|
||||||
|
|
||||||
|
vkpic->slices_size = 0;
|
||||||
|
|
||||||
|
/* If the decoder made a blank frame to make up for a missing ref, or the
|
||||||
|
* frame is the current frame so it's missing one, create a re-representation */
|
||||||
|
if (vkpic->img_view_ref)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
init_frame(dec, vkpic);
|
||||||
|
|
||||||
if (ctx->common.layered_dpb && alloc_dpb) {
|
if (ctx->common.layered_dpb && alloc_dpb) {
|
||||||
vkpic->img_view_ref = ctx->common.layered_view;
|
vkpic->img_view_ref = ctx->common.layered_view;
|
||||||
@ -183,6 +195,53 @@ int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_vk_decode_prepare_frame_sdr(FFVulkanDecodeContext *dec, AVFrame *pic,
|
||||||
|
FFVulkanDecodePicture *vkpic, int is_current,
|
||||||
|
enum FFVkShaderRepFormat rep_fmt, int alloc_dpb)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
FFVulkanDecodeShared *ctx = dec->shared_ctx;
|
||||||
|
|
||||||
|
vkpic->slices_size = 0;
|
||||||
|
|
||||||
|
if (vkpic->img_view_ref)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
init_frame(dec, vkpic);
|
||||||
|
|
||||||
|
if (ctx->common.layered_dpb && alloc_dpb) {
|
||||||
|
vkpic->img_view_ref = ctx->common.layered_view;
|
||||||
|
vkpic->img_aspect_ref = ctx->common.layered_aspect;
|
||||||
|
} else if (alloc_dpb) {
|
||||||
|
vkpic->dpb_frame = vk_get_dpb_pool(ctx);
|
||||||
|
if (!vkpic->dpb_frame)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
err = ff_vk_create_imageview(&ctx->s,
|
||||||
|
&vkpic->img_view_ref, &vkpic->img_aspect_ref,
|
||||||
|
vkpic->dpb_frame, 0, rep_fmt);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
vkpic->img_view_dest = vkpic->img_view_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!alloc_dpb || is_current) {
|
||||||
|
err = ff_vk_create_imageview(&ctx->s,
|
||||||
|
&vkpic->img_view_out, &vkpic->img_aspect,
|
||||||
|
pic, 0, rep_fmt);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!alloc_dpb) {
|
||||||
|
vkpic->img_view_ref = vkpic->img_view_out;
|
||||||
|
vkpic->img_aspect_ref = vkpic->img_aspect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp,
|
int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp,
|
||||||
const uint8_t *data, size_t size, int add_startcode,
|
const uint8_t *data, size_t size, int add_startcode,
|
||||||
uint32_t *nb_slices, const uint32_t **offsets)
|
uint32_t *nb_slices, const uint32_t **offsets)
|
||||||
@ -223,9 +282,14 @@ int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp,
|
|||||||
buf_size = 2 << av_log2(buf_size);
|
buf_size = 2 << av_log2(buf_size);
|
||||||
|
|
||||||
err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_ref,
|
err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_ref,
|
||||||
|
DECODER_IS_SDR(avctx->codec_id) ?
|
||||||
|
(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
|
||||||
|
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) :
|
||||||
VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
|
VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
|
||||||
ctx->s.hwfc->create_pnext, buf_size,
|
ctx->s.hwfc->create_pnext, buf_size,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||||
|
(DECODER_IS_SDR(avctx->codec_id) ?
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0x0));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -276,6 +340,10 @@ void ff_vk_decode_flush(AVCodecContext *avctx)
|
|||||||
VkCommandBuffer cmd_buf;
|
VkCommandBuffer cmd_buf;
|
||||||
FFVkExecContext *exec;
|
FFVkExecContext *exec;
|
||||||
|
|
||||||
|
/* Non-video queues do not need to be reset */
|
||||||
|
if (!(get_codecdesc(avctx->codec_id)->decode_op))
|
||||||
|
return;
|
||||||
|
|
||||||
exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
|
exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
|
||||||
ff_vk_exec_start(&ctx->s, exec);
|
ff_vk_exec_start(&ctx->s, exec);
|
||||||
cmd_buf = exec->buf;
|
cmd_buf = exec->buf;
|
||||||
@ -544,6 +612,9 @@ static void free_common(AVRefStructOpaque unused, void *obj)
|
|||||||
|
|
||||||
ff_vk_video_common_uninit(s, &ctx->common);
|
ff_vk_video_common_uninit(s, &ctx->common);
|
||||||
|
|
||||||
|
if (ctx->sd_ctx_free)
|
||||||
|
ctx->sd_ctx_free(ctx);
|
||||||
|
|
||||||
ff_vk_uninit(s);
|
ff_vk_uninit(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,6 +622,7 @@ static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_re
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
|
FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
|
||||||
|
const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
|
||||||
AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;
|
AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;
|
||||||
AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
|
AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
|
||||||
AVVulkanDeviceContext *hwctx = device->hwctx;
|
AVVulkanDeviceContext *hwctx = device->hwctx;
|
||||||
@ -569,12 +641,14 @@ static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_re
|
|||||||
ctx->s.extensions = ff_vk_extensions_to_mask(hwctx->enabled_dev_extensions,
|
ctx->s.extensions = ff_vk_extensions_to_mask(hwctx->enabled_dev_extensions,
|
||||||
hwctx->nb_enabled_dev_extensions);
|
hwctx->nb_enabled_dev_extensions);
|
||||||
|
|
||||||
|
if (vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
|
||||||
if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) {
|
if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
|
av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
|
||||||
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
|
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
|
||||||
av_refstruct_unref(&dec->shared_ctx);
|
av_refstruct_unref(&dec->shared_ctx);
|
||||||
return AVERROR(ENOSYS);
|
return AVERROR(ENOSYS);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1);
|
err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
@ -927,20 +1001,20 @@ static void free_profile_data(AVHWFramesContext *hwfc)
|
|||||||
|
|
||||||
int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
|
int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
|
||||||
{
|
{
|
||||||
VkFormat vkfmt;
|
VkFormat vkfmt = VK_FORMAT_UNDEFINED;
|
||||||
int err, dedicated_dpb;
|
int err, dedicated_dpb;
|
||||||
AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
|
AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
|
||||||
AVVulkanFramesContext *hwfc = frames_ctx->hwctx;
|
AVVulkanFramesContext *hwfc = frames_ctx->hwctx;
|
||||||
FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
|
FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
|
||||||
FFVulkanDecodeProfileData *prof;
|
FFVulkanDecodeProfileData *prof = NULL;
|
||||||
FFVulkanDecodeShared *ctx;
|
|
||||||
|
|
||||||
frames_ctx->sw_format = AV_PIX_FMT_NONE;
|
|
||||||
|
|
||||||
err = vulkan_decode_bootstrap(avctx, hw_frames_ctx);
|
err = vulkan_decode_bootstrap(avctx, hw_frames_ctx);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
frames_ctx->sw_format = avctx->sw_pix_fmt;
|
||||||
|
|
||||||
|
if (!DECODER_IS_SDR(avctx->codec_id)) {
|
||||||
prof = av_mallocz(sizeof(FFVulkanDecodeProfileData));
|
prof = av_mallocz(sizeof(FFVulkanDecodeProfileData));
|
||||||
if (!prof)
|
if (!prof)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
@ -956,17 +1030,22 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
|
|||||||
frames_ctx->user_opaque = prof;
|
frames_ctx->user_opaque = prof;
|
||||||
frames_ctx->free = free_profile_data;
|
frames_ctx->free = free_profile_data;
|
||||||
|
|
||||||
|
hwfc->create_pnext = &prof->profile_list;
|
||||||
|
}
|
||||||
|
|
||||||
frames_ctx->width = avctx->coded_width;
|
frames_ctx->width = avctx->coded_width;
|
||||||
frames_ctx->height = avctx->coded_height;
|
frames_ctx->height = avctx->coded_height;
|
||||||
frames_ctx->format = AV_PIX_FMT_VULKAN;
|
frames_ctx->format = AV_PIX_FMT_VULKAN;
|
||||||
|
|
||||||
hwfc->format[0] = vkfmt;
|
hwfc->format[0] = vkfmt;
|
||||||
hwfc->create_pnext = &prof->profile_list;
|
|
||||||
hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
|
hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
hwfc->usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
hwfc->usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||||
VK_IMAGE_USAGE_SAMPLED_BIT |
|
VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
|
|
||||||
|
|
||||||
|
if (prof) {
|
||||||
|
FFVulkanDecodeShared *ctx;
|
||||||
|
|
||||||
|
hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
|
||||||
if (!dec->dedicated_dpb)
|
if (!dec->dedicated_dpb)
|
||||||
hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
|
hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
|
||||||
|
|
||||||
@ -974,6 +1053,9 @@ int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
|
|||||||
if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
|
if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
|
||||||
FF_VK_EXT_VIDEO_MAINTENANCE_1))
|
FF_VK_EXT_VIDEO_MAINTENANCE_1))
|
||||||
hwfc->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
|
hwfc->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
|
||||||
|
} else if (DECODER_IS_SDR(avctx->codec_id)) {
|
||||||
|
hwfc->usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1075,8 +1157,10 @@ int ff_vk_decode_init(AVCodecContext *avctx)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
vk_desc = get_codecdesc(avctx->codec_id);
|
||||||
|
|
||||||
profile = get_video_profile(ctx, avctx->codec_id);
|
profile = get_video_profile(ctx, avctx->codec_id);
|
||||||
if (!profile) {
|
if ((vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) && !profile) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!");
|
av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!");
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
@ -1109,9 +1193,11 @@ int ff_vk_decode_init(AVCodecContext *avctx)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
if (profile) {
|
||||||
err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
|
err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* If doing an out-of-place decoding, create a DPB pool */
|
/* If doing an out-of-place decoding, create a DPB pool */
|
||||||
if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) {
|
if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) {
|
||||||
@ -1163,6 +1249,7 @@ int ff_vk_decode_init(AVCodecContext *avctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
session_params_create.videoSession = ctx->common.session;
|
session_params_create.videoSession = ctx->common.session;
|
||||||
|
if (profile) {
|
||||||
ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
|
ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
|
||||||
s->hwctx->alloc, &ctx->empty_session_params);
|
s->hwctx->alloc, &ctx->empty_session_params);
|
||||||
if (ret != VK_SUCCESS) {
|
if (ret != VK_SUCCESS) {
|
||||||
@ -1170,6 +1257,11 @@ int ff_vk_decode_init(AVCodecContext *avctx)
|
|||||||
ff_vk_ret2str(ret));
|
ff_vk_ret2str(ret));
|
||||||
return AVERROR_EXTERNAL;
|
return AVERROR_EXTERNAL;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* For SDR decoders, this alignment value will be 0. Since this will make
|
||||||
|
* add_slice() malfunction, set it to a sane default value. */
|
||||||
|
ctx->caps.minBitstreamBufferSizeAlignment = AV_INPUT_BUFFER_PADDING_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
driver_props = &dec->shared_ctx->s.driver_props;
|
driver_props = &dec->shared_ctx->s.driver_props;
|
||||||
if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
|
if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
|
||||||
|
@ -56,6 +56,10 @@ typedef struct FFVulkanDecodeShared {
|
|||||||
VkVideoDecodeCapabilitiesKHR dec_caps;
|
VkVideoDecodeCapabilitiesKHR dec_caps;
|
||||||
|
|
||||||
VkVideoSessionParametersKHR empty_session_params;
|
VkVideoSessionParametersKHR empty_session_params;
|
||||||
|
|
||||||
|
/* Software-defined decoder context */
|
||||||
|
void *sd_ctx;
|
||||||
|
void (*sd_ctx_free)(struct FFVulkanDecodeShared *ctx);
|
||||||
} FFVulkanDecodeShared;
|
} FFVulkanDecodeShared;
|
||||||
|
|
||||||
typedef struct FFVulkanDecodeContext {
|
typedef struct FFVulkanDecodeContext {
|
||||||
@ -141,6 +145,13 @@ int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic,
|
|||||||
FFVulkanDecodePicture *vkpic, int is_current,
|
FFVulkanDecodePicture *vkpic, int is_current,
|
||||||
int alloc_dpb);
|
int alloc_dpb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Software-defined decoder version of ff_vk_decode_prepare_frame.
|
||||||
|
*/
|
||||||
|
int ff_vk_decode_prepare_frame_sdr(FFVulkanDecodeContext *dec, AVFrame *pic,
|
||||||
|
FFVulkanDecodePicture *vkpic, int is_current,
|
||||||
|
enum FFVkShaderRepFormat rep_fmt, int alloc_dpb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add slice data to frame.
|
* Add slice data to frame.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user