You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

259 lines
11 KiB

/*
* 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
*/
#ifndef AVCODEC_VULKAN_ENCODE_H
#define AVCODEC_VULKAN_ENCODE_H
#include "codec_id.h"
#include "internal.h"
#include "encode.h"
#include "hwconfig.h"
#include "vulkan_video.h"
#include "hw_base_encode.h"
typedef struct FFVulkanEncodeDescriptor {
enum AVCodecID codec_id;
FFVulkanExtensions encode_extension;
VkVideoCodecOperationFlagBitsKHR encode_op;
VkExtensionProperties ext_props;
} FFVulkanEncodeDescriptor;
typedef struct FFVulkanEncodePicture {
FFHWBaseEncodePicture base;
VkVideoPictureResourceInfoKHR dpb_res;
VkVideoReferenceSlotInfoKHR dpb_slot;
struct {
VkImageView view;
VkImageAspectFlags aspect;
} in;
struct {
VkImageView view;
VkImageAspectFlags aspect;
} dpb;
void *codec_layer;
void *codec_rc_layer;
FFVkExecContext *exec;
AVBufferRef *pkt_buf;
int slices_offset;
} FFVulkanEncodePicture;
/**
* Callback for writing stream-level headers.
*/
typedef int (*vkenc_cb_write_stream_headers)(AVCodecContext *avctx,
uint8_t *data, size_t *data_len);
/**
* Callback for initializing codec-specific picture headers.
*/
typedef int (*vkenc_cb_init_pic_headers)(AVCodecContext *avctx,
FFVulkanEncodePicture *pic);
/**
* Callback for writing alignment data.
* Align is the value to align offset to.
*/
typedef int (*vkenc_cb_write_filler)(AVCodecContext *avctx, uint32_t filler,
uint8_t *data, size_t *data_len);
/**
* Callback for writing any extra units requested. data_len must be set
* to the available size, and its value will be overwritten by the #bytes written
* to the output buffer.
*/
typedef int (*vkenc_cb_write_extra_headers)(AVCodecContext *avctx,
FFVulkanEncodePicture *pic,
uint8_t *data, size_t *data_len);
typedef struct FFVulkanCodec {
/**
* Codec feature flags.
*/
int flags;
/* Codec output packet without timestamp delay, which means the
* output packet has same PTS and DTS. For AV1. */
#define VK_ENC_FLAG_NO_DELAY 1 << 6
/**
* Size of the codec-specific picture struct.
*/
size_t picture_priv_data_size;
/**
* Size of the filler header.
*/
size_t filler_header_size;
/**
* Initialize codec-specific structs in a Vulkan profile.
*/
int (*init_profile)(AVCodecContext *avctx, VkVideoProfileInfoKHR *profile,
void *pnext);
/**
* Initialize codec-specific rate control structures for a picture.
*/
int (*init_pic_rc)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
VkVideoEncodeRateControlInfoKHR *rc_info,
VkVideoEncodeRateControlLayerInfoKHR *rc_layer);
/**
* Initialize codec-specific picture parameters.
*/
int (*init_pic_params)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
VkVideoEncodeInfoKHR *encode_info);
/**
* Callback for writing stream headers.
*/
int (*write_sequence_headers)(AVCodecContext *avctx,
FFHWBaseEncodePicture *base_pic,
uint8_t *data, size_t *data_len);
/**
* Callback for writing alignment data.
*/
int (*write_filler)(AVCodecContext *avctx, uint32_t filler,
uint8_t *data, size_t *data_len);
/**
* Callback for writing any extra units requested. data_len must be set
* to the available size, and its value will be overwritten by the #bytes written
* to the output buffer.
*/
int (*write_extra_headers)(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
uint8_t *data, size_t *data_len);
} FFVulkanCodec;
typedef struct FFVkEncodeCommonOptions {
int qp;
int quality;
int profile;
int level;
int tier;
int async_depth;
VkVideoEncodeUsageFlagBitsKHR usage;
VkVideoEncodeContentFlagBitsKHR content;
VkVideoEncodeTuningModeKHR tune;
VkVideoEncodeRateControlModeFlagBitsKHR rc_mode;
#define FF_VK_RC_MODE_AUTO 0xFFFFFFFF
} FFVkEncodeCommonOptions;
typedef struct FFVulkanEncodeContext {
FFVulkanContext s;
FFVkVideoCommon common;
FFHWBaseEncodeContext base;
const FFVulkanCodec *codec;
int explicit_qp;
int session_reset;
/* Session parameters object, initialized by each codec independently
* and set here. */
VkVideoSessionParametersKHR session_params;
AVBufferPool *buf_pool;
VkFormat pic_format;
FFVkEncodeCommonOptions opts;
VkVideoProfileInfoKHR profile;
VkVideoProfileListInfoKHR profile_list;
VkVideoCapabilitiesKHR caps;
VkVideoEncodeQualityLevelPropertiesKHR quality_props;
VkVideoEncodeCapabilitiesKHR enc_caps;
VkVideoEncodeUsageInfoKHR usage_info;
FFVkQueueFamilyCtx qf_enc;
FFVkExecPool enc_pool;
FFHWBaseEncodePicture *slots[32];
} FFVulkanEncodeContext;
#define VULKAN_ENCODE_COMMON_OPTIONS \
{ "qp", "Use an explicit constant quantizer for the whole stream", OFFSET(common.opts.qp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, FLAGS }, \
{ "quality", "Set encode quality (trades off against speed, higher is faster)", OFFSET(common.opts.quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, \
{ "rc_mode", "Select rate control type", OFFSET(common.opts.rc_mode), AV_OPT_TYPE_INT, { .i64 = FF_VK_RC_MODE_AUTO }, 0, FF_VK_RC_MODE_AUTO, FLAGS, "rc_mode" }, \
{ "auto", "Choose mode automatically based on parameters", 0, AV_OPT_TYPE_CONST, { .i64 = FF_VK_RC_MODE_AUTO }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
{ "driver", "Driver-specific rate control", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
{ "cqp", "Constant quantizer mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
{ "cbr", "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
{ "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "rc_mode" }, \
{ "tune", "Select tuning type", OFFSET(common.opts.tune), AV_OPT_TYPE_INT, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "tune" }, \
{ "default", "Default tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_DEFAULT_KHR }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
{ "hq", "High quality tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_HIGH_QUALITY_KHR }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
{ "ll", "Low-latency tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_LOW_LATENCY_KHR }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
{ "ull", "Ultra low-latency tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_ULTRA_LOW_LATENCY_KHR }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
{ "lossless", "Lossless mode tuning", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_TUNING_MODE_LOSSLESS_KHR }, INT_MIN, INT_MAX, FLAGS, "tune" }, \
{ "usage", "Select usage type", OFFSET(common.opts.usage), AV_OPT_TYPE_FLAGS, { .i64 = VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "usage" }, \
{ "default", "Default optimizations", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_DEFAULT_KHR }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
{ "transcode", "Optimize for transcoding", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_TRANSCODING_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
{ "stream", "Optimize for streaming", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_STREAMING_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
{ "record", "Optimize for offline recording", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_RECORDING_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
{ "conference", "Optimize for teleconferencing", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_USAGE_CONFERENCING_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "usage" }, \
{ "content", "Select content type", OFFSET(common.opts.content), AV_OPT_TYPE_FLAGS, { .i64 = VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR }, 0, INT_MAX, FLAGS, "content" }, \
{ "default", "Default content", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_DEFAULT_KHR }, INT_MIN, INT_MAX, FLAGS, "content" }, \
{ "camera", "Camera footage", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_CAMERA_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "content" }, \
{ "desktop", "Screen recording", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_DESKTOP_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "content" }, \
{ "rendered", "Game or 3D content", 0, AV_OPT_TYPE_CONST, { .i64 = VK_VIDEO_ENCODE_CONTENT_RENDERED_BIT_KHR }, INT_MIN, INT_MAX, FLAGS, "content" }
/**
* Initialize encoder.
*/
av_cold int ff_vulkan_encode_init(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
const FFVulkanEncodeDescriptor *vk_desc,
const FFVulkanCodec *codec,
void *codec_caps, void *quality_pnext);
/**
* Write out the extradata in case its needed.
*/
av_cold int ff_vulkan_write_global_header(AVCodecContext *avctx,
FFVulkanEncodeContext *ctx);
/**
* Encode.
*/
int ff_vulkan_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt);
/**
* Uninitialize encoder.
*/
void ff_vulkan_encode_uninit(FFVulkanEncodeContext *ctx);
/**
* Create session parameters.
*/
int ff_vulkan_encode_create_session_params(AVCodecContext *avctx, FFVulkanEncodeContext *ctx,
void *codec_params_pnext);
/**
* Paperwork.
*/
extern const AVCodecHWConfigInternal *const ff_vulkan_encode_hw_configs[];
#endif /* AVCODEC_VULKAN_ENCODE_H */