48#define APV_DEFAULT_QMAT 16
49#define APV_MAX_NUM_COMP 4
170 16, 16, 16, 16, 17, 18, 21, 24,
171 16, 16, 16, 16, 17, 19, 22, 25,
172 16, 16, 17, 18, 20, 22, 25, 29,
173 16, 16, 18, 21, 24, 27, 31, 36,
174 17, 17, 20, 24, 30, 35, 41, 47,
175 18, 19, 22, 27, 35, 44, 54, 65,
176 21, 22, 25, 31, 41, 54, 70, 88,
177 24, 25, 29, 36, 47, 65, 88, 115,
243 (uint32_t []) { 8, 4, 1 }, 0);
246 VK_SHADER_STAGE_COMPUTE_BIT);
250 .name =
"coeffs_buf",
251 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
252 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
256 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
257 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
285 (uint32_t []) { wg, 1, 1 }, 0);
288 VK_SHADER_STAGE_COMPUTE_BIT);
292 .name =
"coeffs_buf",
293 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
294 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
298 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
299 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
321 (uint32_t []) { 256, 1, 1 }, 0);
324 VK_SHADER_STAGE_COMPUTE_BIT);
329 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
330 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
374 int qp = (
c == 0 ||
c == 3) ? ev->
qp_y : ev->
qp_c;
376 int qp_shift = qp / 6;
387 for (
int i = 0;
i < 64;
i++)
402 VkBufferMemoryBarrier2 buf_bar[4];
419 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
421 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
429 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
430 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
432 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
440 VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
441 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
442 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
444 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
450 VK_BUFFER_USAGE_TRANSFER_DST_BIT |
451 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
452 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
454 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
455 VK_MEMORY_PROPERTY_HOST_CACHED_BIT));
459 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
461 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
462 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
463 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
472 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
473 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
478 img_bar, &nb_img_bar,
479 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
480 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
481 VK_ACCESS_SHADER_READ_BIT,
482 VK_IMAGE_LAYOUT_GENERAL,
483 VK_QUEUE_FAMILY_IGNORED);
485 vk->CmdPipelineBarrier2(exec->
buf, &(VkDependencyInfo) {
486 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
487 .pImageMemoryBarriers = img_bar,
488 .imageMemoryBarrierCount = nb_img_bar,
496 coeffs_buf, 0, coeffs_buf->
size,
497 VK_FORMAT_UNDEFINED);
501 VK_IMAGE_LAYOUT_GENERAL,
506 VK_SHADER_STAGE_COMPUTE_BIT,
509 vk->CmdDispatch(exec->
buf,
515 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT,
NONE,
516 COMPUTE_SHADER_BIT, SHADER_READ_BIT,
NONE,
517 0, coeffs_buf->
size);
519 vk->CmdPipelineBarrier2(exec->
buf, &(VkDependencyInfo) {
520 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
521 .pBufferMemoryBarriers = buf_bar,
522 .bufferMemoryBarrierCount = nb_buf_bar,
535 uint32_t z_comps = (p == 0) ? 1 : ev->
num_comp - 1;
541 .bytestream = bytestream_buf->
address,
545 .comp_base = (uint32_t)p,
555 coeffs_buf, 0, coeffs_buf->
size,
556 VK_FORMAT_UNDEFINED);
558 sizes_buf, 0, sizes_buf->
size,
559 VK_FORMAT_UNDEFINED);
563 VK_SHADER_STAGE_COMPUTE_BIT,
572 if (!ev->headers_only) {
574 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT,
NONE,
575 COMPUTE_SHADER_BIT, SHADER_READ_BIT,
NONE,
576 0, bytestream_buf->size);
578 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT,
NONE,
579 COMPUTE_SHADER_BIT, SHADER_READ_BIT,
NONE,
581 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
582 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
583 .pBufferMemoryBarriers = buf_bar,
584 .bufferMemoryBarrierCount = nb_buf_bar,
589 .sparse = bytestream_buf->address,
590 .compacted = gathered_buf->address,
591 .slot_size = (uint32_t)ev->slot_size,
596 sizes_buf, 0, sizes_buf->size,
597 VK_FORMAT_UNDEFINED);
600 VK_SHADER_STAGE_COMPUTE_BIT,
603 vk->CmdDispatch(exec->buf, ev->tile_count * ev->num_comp, 1, 1);
609 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT,
NONE,
610 TRANSFER_BIT, TRANSFER_READ_BIT,
NONE,
611 0, gathered_buf->size);
612 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
613 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
614 .pBufferMemoryBarriers = buf_bar,
615 .bufferMemoryBarrierCount = nb_buf_bar,
619 vk->CmdCopyBuffer(exec->buf, gathered_buf->buf, compacted_buf->buf,
620 1, &(VkBufferCopy) { .size = ev->bytestream_size });
651 static uint8_t headers_only_tile;
656 if (!(compacted_buf->
flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
657 VkMappedMemoryRange
r = {
658 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
659 .memory = compacted_buf->
mem,
661 .size = VK_WHOLE_SIZE,
665 if (!(sizes_buf->
flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
666 VkMappedMemoryRange
r = {
667 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
668 .memory = sizes_buf->
mem,
670 .size = VK_WHOLE_SIZE,
707 for (
int y = 0; y < 8; y++)
708 for (
int x = 0; x < 8; x++)
719 uint32_t comp_off = 0;
722 uint32_t total_tile_data = 0;
724 tile->tile_header.tile_header_size =
726 tile->tile_header.tile_index = t;
733 tile->tile_data[
c] = &headers_only_tile;
739 tile->tile_header.tile_data_size[
c] = sz;
740 tile->tile_header.tile_qp[
c] =
742 total_tile_data += sz;
744 tile->tile_header.reserved_zero_8bits = 0;
745 tile->tile_dummy_byte_size = 0;
749 tile->tile_header.tile_header_size + total_tile_data;
753 ff_cbs_fragment_reset(&ev->
au);
766 err = ff_cbs_write_packet(ev->
cbc,
pkt, &ev->
au);
782 pkt->size,
pkt->size / (1024.0 * 1024.0));
871 ff_cbs_fragment_free(&ev->
au);
872 ff_cbs_close(&ev->
cbc);
936 "Tile size %dx%d MBs is below the spec minimum of %dx%d: "
937 "NON-CONFORMANT bitstream, most decoders will reject it.\n",
972 "Tile-component has too many transform blocks (%d > 1024).\n",
983 if (ev->
qp_y < 0 || ev->
qp_y > max_qp || ev->
qp_c < 0 || ev->
qp_c > max_qp) {
985 "QP out of range [0, %d]: qp_y=%d, qp_c=%d.\n",
1003 "APV Vulkan encoder: %dx%d, %d tiles (%dx%d MBs each), "
1004 "qp_y=%d qp_c=%d, coeffs=%zu KiB, bytestream=%zu KiB\n",
1009 ev->
headers_only = !!getenv(
"APV_VULKAN_HEADERS_ONLY");
1010 ev->
skip_entropy = !!getenv(
"APV_VULKAN_SKIP_ENTROPY");
1015 "APV_VULKAN_HEADERS_ONLY set: tiles will not be downloaded "
1016 "or assembled; output packets contain headers only.\n");
1019 "APV_VULKAN_SKIP_ENTROPY set: entropy dispatch skipped "
1020 "(DCT-only benchmark mode).\n");
1077#define OFFSET(x) offsetof(VulkanEncodeAPVContext, x)
1078#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1080 {
"qp",
"Quantization parameter (luma)",
OFFSET(qp_y),
1082 {
"qp_chroma",
"Chroma quantization parameter (0 = same as luma qp)",
OFFSET(qp_c),
1084 {
"qmatrix",
"Quantization matrix",
OFFSET(qmatrix),
1086 {
"flat",
"Uniform matrix, all 16 (APV spec default)", 0,
1088 {
"hevc",
"HEVC default intra scaling list (mild perceptual shaping)", 0,
1094 {
"tile_width",
"Tile width in macroblocks (0 = adaptive, auto-sized per frame)",
OFFSET(tile_w_mbs_opt),
1096 {
"tile_height",
"Tile height in macroblocks (0 = adaptive, auto-sized per frame)",
OFFSET(tile_h_mbs_opt),
1098 {
"async_depth",
"Internal parallelization depth",
OFFSET(async_depth),
1109 .class_name =
"apv_vulkan",
1121 .p.name =
"apv_vulkan",
1139 .p.wrapper_name =
"vulkan",
static double fact(double i)
const FFCodec ff_apv_vulkan_encoder
const unsigned int ff_apv_encode_dct_comp_spv_len
static int build_packet(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt)
const unsigned char ff_apv_encode_tiles_comp_spv_data[]
static int vulkan_encode_apv_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
static const uint8_t apv_qmat_hevc_intra[64]
static av_cold int vulkan_encode_apv_init(AVCodecContext *avctx)
static const AVCodecHWConfigInternal *const vulkan_encode_apv_hw_configs[]
const unsigned char ff_apv_encode_dct_comp_spv_data[]
static const uint8_t apv_level_scale[6]
static int init_dct_shader(AVCodecContext *avctx)
static int init_entropy_shader(AVCodecContext *avctx, int blocks_per_mb, FFVulkanShader *shd)
static const AVClass vulkan_encode_apv_class
static av_cold int vulkan_encode_apv_close(AVCodecContext *avctx)
static void build_dct_push_const(AVCodecContext *avctx)
static const AVOption vulkan_encode_apv_options[]
static const FFCodecDefault vulkan_encode_apv_defaults[]
static int profile_idc_from_pix_fmt(enum AVPixelFormat sw_fmt)
static int chroma_format_from_pix_fmt(enum AVPixelFormat sw_fmt)
static int submit_frame(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame)
static int init_compact_shader(AVCodecContext *avctx)
const unsigned char ff_seg_gather_comp_spv_data[]
const unsigned int ff_seg_gather_comp_spv_len
static int apv_qmatrix_value(int qmatrix, int i)
const unsigned int ff_apv_encode_tiles_comp_spv_len
Libavcodec external API header.
static int FUNC tile(CodedBitstreamContext *ctx, RWContext *rw, APVRawTile *current, int tile_idx, uint32_t tile_size)
#define i(width, name, range_min, range_max)
#define FF_CODEC_CAP_EOF_FLUSH
The encoder has AV_CODEC_CAP_DELAY set, but does not actually have delay - it only wants to be flushe...
#define CODEC_PIXFMTS(...)
#define FF_CODEC_RECEIVE_PACKET_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
int(* init)(AVBSFContext *ctx)
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
#define AV_NUM_DATA_POINTERS
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
#define AV_CODEC_CAP_ENCODER_FLUSH
This encoder can be flushed using avcodec_flush_buffers().
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
#define AV_CODEC_CAP_HARDWARE
Codec is backed by a hardware implementation.
#define AV_CODEC_FLAG_COPY_OPAQUE
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#define AVERROR_EOF
End of file.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
#define LIBAVUTIL_VERSION_INT
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
static const int sizes[][2]
static const int level_scale[2][6]
@ APV_MIN_TILE_WIDTH_IN_MBS
@ APV_MIN_TILE_HEIGHT_IN_MBS
common internal api header.
void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, AVFrame *f, VkImageView *views, int set, int binding, VkImageLayout layout, VkSampler sampler)
Update a descriptor in a buffer with an image array.
int ff_vk_shader_load(FFVulkanShader *shd, VkPipelineStageFlags stage, VkSpecializationInfo *spec, uint32_t wg_size[3], uint32_t required_subgroup_size)
Initialize a shader object.
void ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, const FFVulkanDescriptorSetBinding *desc, int nb, int singular)
Add descriptor to a shader.
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf, FFVkExecPool *pool, int nb_contexts, int nb_queries, VkQueryType query_type, int query_64bit, const void *query_create_pnext)
Allocates/frees an execution pool.
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
int ff_vk_init(FFVulkanContext *s, void *log_parent, AVBufferRef *device_ref, AVBufferRef *frames_ref)
Initializes the AVClass, in case this context is not used as the main user's context.
void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, VkPipelineStageFlags2 src_stage, VkPipelineStageFlags2 dst_stage, VkAccessFlagBits2 new_access, VkImageLayout new_layout, uint32_t new_qf)
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, VkImageView views[AV_NUM_DATA_POINTERS], AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
Create an imageview and add it as a dependency to an execution.
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, const FFVulkanShader *shd)
Bind a shader.
void ff_vk_exec_move_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind, int elem, FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len, VkFormat fmt)
Update a descriptor in a buffer with a buffer.
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Execution dependency management.
int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool, FFVkBuffer **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props)
Initialize a pool and create AVBufferRefs containing FFVkBuffer.
void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd, const char *spirv, size_t spirv_len, const char *entrypoint)
Link a shader into an executable.
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, VkShaderStageFlagBits stage, int offset, size_t size, void *src)
Update push constant in a shader.
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_GRAY12
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
#define AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUV444P10
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
uint8_t chroma_format_idc
uint8_t capture_time_distance
APVRawFrameHeader frame_header
APVRawTile tile[APV_MAX_TILE_COUNT]
APVRawPBUHeader pbu_header
uint32_t tile_size[APV_MAX_TILE_COUNT]
uint8_t q_matrix[APV_MAX_NUM_COMP][APV_TR_SIZE][APV_TR_SIZE]
uint32_t tile_width_in_mbs
uint32_t tile_height_in_mbs
uint8_t tile_size_present_in_fh_flag
A reference to a data buffer.
uint8_t * data
The data buffer.
Describe the class of an AVClass context structure.
main external API structure.
int width
picture width / height.
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
int flags
AV_CODEC_FLAG_*.
This structure describes decoded (raw) audio or video data.
This struct describes a set or pool of "hardware" frames (i.e.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
This structure stores compressed data.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
AVRefStructPool is an API for a thread-safe pool of objects managed via the RefStruct API.
VkDevice act_dev
Active device.
Context structure for coded bitstream operations.
Coded bitstream fragment structure, combining one or more units.
VkDeviceAddress compacted
float qf[APV_MAX_NUM_COMP]
VkDeviceAddress bytestream
VkMemoryPropertyFlagBits flags
FFVkExecContext * contexts
AVVulkanDeviceContext * hwctx
CodedBitstreamContext * cbc
AVRefStructPool * coeffs_pool
AVRefStructPool * gathered_pool
CodedBitstreamFragment au
AVVulkanDeviceQueueFamily * qf
FFVulkanShader shd_compact
AVRefStructPool * sizes_pool
FFVulkanShader shd_entropy[2]
AVRefStructPool * compacted_pool
enum AVPixelFormat sw_format
VulkanEncodeAPVFrameData * exec_ctx_info
AVRefStructPool * bytestream_pool
AVBufferRef * frame_opaque_ref
FFVkBuffer * bytestream_ref
FFVkBuffer * compacted_ref
#define ff_vk_buf_barrier(dst, vkb, s_stage, s_access, s_access2, d_stage, d_access, d_access2, offs, bsz)
#define SPEC_LIST_ADD(name, idx, val_bits, val)
#define SPEC_LIST_CREATE(name, max_length, max_size)