46#define APV_DEFAULT_QMAT 16
47#define APV_MAX_NUM_COMP 4
161 16, 16, 16, 16, 17, 18, 21, 24,
162 16, 16, 16, 16, 17, 19, 22, 25,
163 16, 16, 17, 18, 20, 22, 25, 29,
164 16, 16, 18, 21, 24, 27, 31, 36,
165 17, 17, 20, 24, 30, 35, 41, 47,
166 18, 19, 22, 27, 35, 44, 54, 65,
167 21, 22, 25, 31, 41, 54, 70, 88,
168 24, 25, 29, 36, 47, 65, 88, 115,
234 (uint32_t []) { 8, 4, 1 }, 0);
237 VK_SHADER_STAGE_COMPUTE_BIT);
241 .name =
"coeffs_buf",
242 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
243 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
247 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
248 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
281 (uint32_t []) { wg, 1, 1 }, 0);
284 VK_SHADER_STAGE_COMPUTE_BIT);
288 .name =
"coeffs_buf",
289 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
290 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
294 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
295 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
339 int qp = (
c == 0 ||
c == 3) ? ev->
qp_y : ev->
qp_c;
341 int qp_shift = qp / 6;
352 for (
int i = 0;
i < 64;
i++)
367 VkBufferMemoryBarrier2 buf_bar[4];
388 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
390 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
398 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
399 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
401 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
408 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
409 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
411 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
412 VK_MEMORY_PROPERTY_HOST_CACHED_BIT));
416 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
418 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
419 VK_MEMORY_PROPERTY_HOST_CACHED_BIT));
428 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
429 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
434 img_bar, &nb_img_bar,
435 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
436 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
437 VK_ACCESS_SHADER_READ_BIT,
438 VK_IMAGE_LAYOUT_GENERAL,
439 VK_QUEUE_FAMILY_IGNORED);
441 vk->CmdPipelineBarrier2(exec->
buf, &(VkDependencyInfo) {
442 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
443 .pImageMemoryBarriers = img_bar,
444 .imageMemoryBarrierCount = nb_img_bar,
452 coeffs_buf, 0, coeffs_buf->
size,
453 VK_FORMAT_UNDEFINED);
457 VK_IMAGE_LAYOUT_GENERAL,
462 VK_SHADER_STAGE_COMPUTE_BIT,
465 vk->CmdDispatch(exec->
buf,
471 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT,
NONE,
472 COMPUTE_SHADER_BIT, SHADER_READ_BIT,
NONE,
473 0, coeffs_buf->
size);
475 vk->CmdPipelineBarrier2(exec->
buf, &(VkDependencyInfo) {
476 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
477 .pBufferMemoryBarriers = buf_bar,
478 .bufferMemoryBarrierCount = nb_buf_bar,
491 uint32_t z_comps = (p == 0) ? 1 : ev->
num_comp - 1;
497 .bytestream = bytestream_buf->
address,
501 .comp_base = (uint32_t)p,
511 coeffs_buf, 0, coeffs_buf->
size,
512 VK_FORMAT_UNDEFINED);
514 sizes_buf, 0, sizes_buf->
size,
515 VK_FORMAT_UNDEFINED);
519 VK_SHADER_STAGE_COMPUTE_BIT,
527 if (!ev->headers_only)
529 sizes_buf, 0, ev->tile_count * ev->num_comp,
530 bytestream_buf, ev->slot_size,
531 compacted_buf, 0, 0));
559 static uint8_t headers_only_tile;
564 if (!(compacted_buf->
flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
565 VkMappedMemoryRange
r = {
566 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
567 .memory = compacted_buf->
mem,
569 .size = VK_WHOLE_SIZE,
573 if (!(sizes_buf->
flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
574 VkMappedMemoryRange
r = {
575 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
576 .memory = sizes_buf->
mem,
578 .size = VK_WHOLE_SIZE,
585 memset(raw_frame, 0,
sizeof(*raw_frame));
614 for (
int y = 0; y < 8; y++)
615 for (
int x = 0; x < 8; x++)
626 uint32_t comp_off = 0;
629 uint32_t total_tile_data = 0;
631 tile->tile_header.tile_header_size =
633 tile->tile_header.tile_index = t;
640 tile->tile_data[
c] = &headers_only_tile;
646 tile->tile_header.tile_data_size[
c] = sz;
647 tile->tile_header.tile_qp[
c] =
649 total_tile_data += sz;
651 tile->tile_header.reserved_zero_8bits = 0;
652 tile->tile_dummy_byte_size = 0;
656 tile->tile_header.tile_header_size + total_tile_data;
660 ff_cbs_fragment_reset(&ev->
au);
669 err = ff_cbs_write_packet(ev->
cbc,
pkt, &ev->
au);
674 pkt->size,
pkt->size / (1024.0 * 1024.0));
724 ff_cbs_fragment_free(&ev->
au);
725 ff_cbs_close(&ev->
cbc);
789 "Tile size %dx%d MBs is below the spec minimum of %dx%d: "
790 "NON-CONFORMANT bitstream, most decoders will reject it.\n",
825 "Tile-component has too many transform blocks (%d > 1024).\n",
836 if (ev->
qp_y < 0 || ev->
qp_y > max_qp || ev->
qp_c < 0 || ev->
qp_c > max_qp) {
838 "QP out of range [0, %d]: qp_y=%d, qp_c=%d.\n",
856 "APV Vulkan encoder: %dx%d, %d tiles (%dx%d MBs each), "
857 "qp_y=%d qp_c=%d, coeffs=%zu KiB, bytestream=%zu KiB\n",
868 "APV_VULKAN_HEADERS_ONLY set: tiles will not be downloaded "
869 "or assembled; output packets contain headers only.\n");
872 "APV_VULKAN_SKIP_ENTROPY set: entropy dispatch skipped "
873 "(DCT-only benchmark mode).\n");
930#define OFFSET(x) offsetof(VulkanEncodeAPVContext, x)
931#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
933 {
"qp",
"Quantization parameter (luma)",
OFFSET(qp_y),
935 {
"qp_chroma",
"Chroma quantization parameter (0 = same as luma qp)",
OFFSET(qp_c),
937 {
"qmatrix",
"Quantization matrix",
OFFSET(qmatrix),
939 {
"flat",
"Uniform matrix, all 16 (APV spec default)", 0,
941 {
"hevc",
"HEVC default intra scaling list (mild perceptual shaping)", 0,
947 {
"tile_width",
"Tile width in macroblocks (0 = adaptive, auto-sized per frame)",
OFFSET(tile_w_mbs_opt),
949 {
"tile_height",
"Tile height in macroblocks (0 = adaptive, auto-sized per frame)",
OFFSET(tile_h_mbs_opt),
951 {
"async_depth",
"Internal parallelization depth",
OFFSET(async_depth),
962 .class_name =
"apv_vulkan",
974 .p.name =
"apv_vulkan",
993 .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 av_cold void vulkan_encode_apv_flush(AVCodecContext *avctx)
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 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 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)
#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 AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#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.
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.
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
AVColorRange
Visual content value range.
@ AVCOL_RANGE_JPEG
Full range content.
#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
AVColorPrimaries
Chromaticity coordinates of the source primaries.
AVColorTransferCharacteristic
Color Transfer Characteristic.
#define AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUV444P10
AVColorSpace
YUV colorspace type.
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
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.
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.
float qf[APV_MAX_NUM_COMP]
VkDeviceAddress bytestream
VkMemoryPropertyFlagBits flags
Frame loop for compute encoders.
FFVkExecContext * contexts
AVVulkanDeviceContext * hwctx
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props
CodedBitstreamContext * cbc
AVRefStructPool * coeffs_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
enum AVColorTransferCharacteristic color_trc
enum AVColorPrimaries color_primaries
enum AVColorRange color_range
enum AVColorSpace colorspace
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)
int ff_vk_encode_loop_receive_packet(AVCodecContext *avctx, FFVkEncodeLoop *l, AVPacket *pkt)
Call from FFCodec.cb.receive_packet; the packet metadata is carried from the submitted frame to its p...
void ff_vk_encode_loop_uninit(FFVkEncodeLoop *l)
void ff_vk_encode_loop_flush(AVCodecContext *avctx, FFVkEncodeLoop *l)
Waits for and discards every frame in flight.
int ff_vk_encode_loop_init(FFVulkanContext *s, FFVkExecPool *pool, FFVkEncodeLoop *l, int(*submit_frame)(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame), int(*get_packet)(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt))
int ff_vk_seg_gather_init(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Packs fixed-stride segment slots back to back into a contiguous buffer.
int ff_vk_seg_gather(FFVulkanContext *s, FFVkExecContext *exec, FFVulkanShader *shd, FFVkBuffer *sizes, size_t sizes_offset, uint32_t nb_segs, FFVkBuffer *sparse, uint32_t slot_size, FFVkBuffer *compacted, size_t compacted_offset, VkDeviceAddress offset_addr)
Gathers nb_segs slots of slot_size bytes from sparse into compacted, with the segment sizes given as ...