FFmpeg
Loading...
Searching...
No Matches
proresenc_kostya_vulkan.c
Go to the documentation of this file.
1/*
2 * Apple ProRes encoder
3 *
4 * Copyright (c) 2011 Anatoliy Wasserman
5 * Copyright (c) 2012 Konstantin Shishkov
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include "libavutil/avassert.h"
25#include "libavutil/buffer.h"
26#include "libavutil/macros.h"
27#include "libavutil/mem.h"
29#include "libavutil/opt.h"
30#include "libavutil/pixdesc.h"
33#include "libavutil/vulkan.h"
34#include "avcodec.h"
35#include "codec.h"
36#include "codec_internal.h"
37#include "encode.h"
38#include "packet.h"
39#include "put_bits.h"
40#include "profiles.h"
41#include "bytestream.h"
42#include "proresdata.h"
44#include "hwconfig.h"
45
46#define DCTSIZE 8
47
48typedef struct ProresDataTables {
49 int16_t qmat[128][64];
50 int16_t qmat_chroma[128][64];
52
58
59typedef struct EncodeSliceInfo {
60 VkDeviceAddress bytestream;
61 VkDeviceAddress slice_sizes;
62 uint32_t slot_size;
64
65typedef struct SegGatherPushData {
66 VkDeviceAddress sparse;
67 VkDeviceAddress compacted;
68 uint32_t slot_size;
70
71typedef struct SliceData {
72 uint32_t mbs_per_slice;
74} SliceData;
75
85
106
141
142extern const unsigned char ff_prores_ks_alpha_data_comp_spv_data[];
143extern const unsigned int ff_prores_ks_alpha_data_comp_spv_len;
144
145extern const unsigned char ff_seg_gather_comp_spv_data[];
146extern const unsigned int ff_seg_gather_comp_spv_len;
147
148extern const unsigned char ff_prores_ks_slice_data_comp_spv_data[];
149extern const unsigned int ff_prores_ks_slice_data_comp_spv_len;
150
151extern const unsigned char ff_prores_ks_estimate_slice_comp_spv_data[];
152extern const unsigned int ff_prores_ks_estimate_slice_comp_spv_len;
153
154extern const unsigned char ff_prores_ks_trellis_node_comp_spv_data[];
155extern const unsigned int ff_prores_ks_trellis_node_comp_spv_len;
156
157extern const unsigned char ff_prores_ks_encode_slice_comp_spv_data[];
158extern const unsigned int ff_prores_ks_encode_slice_comp_spv_len;
159
160static int init_slice_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd, int blocks_per_mb)
161{
162 int err = 0;
163 FFVulkanContext *vkctx = &pv->vkctx;
165
166 SPEC_LIST_CREATE(sl, 5, 5 * sizeof(uint32_t))
167 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
168 SPEC_LIST_ADD(sl, 1, 32, blocks_per_mb);
169 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.mb_width);
170 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.pictures_per_frame);
171 SPEC_LIST_ADD(sl, 16, 32, blocks_per_mb * pv->ctx.mbs_per_slice); /* nb_blocks */
172
173 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
174 (uint32_t []) { DCTSIZE, blocks_per_mb, pv->ctx.mbs_per_slice }, 0);
175
177 {
178 .name = "SliceBuffer",
179 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
180 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
181 },
182 {
183 .name = "planes",
184 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
185 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
186 .elems = av_pix_fmt_count_planes(vkctx->frames->sw_format),
187 },
188 };
189 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0);
190
191 ff_vk_shader_add_push_const(shd, 0, sizeof(SliceDataInfo), VK_SHADER_STAGE_COMPUTE_BIT);
192
193 RET(ff_vk_shader_link(vkctx, shd,
196
197 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
198
199fail:
200 return err;
201}
202
204{
205 int err = 0;
206 FFVulkanContext *vkctx = &pv->vkctx;
208
209 SPEC_LIST_CREATE(sl, 4, 4 * sizeof(uint32_t))
210 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.alpha_bits);
211 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.slices_width);
212 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.mb_width);
213 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.mbs_per_slice);
214
215 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
216 (uint32_t []) { 16, 16, 1 }, 0);
217
219 {
220 .name = "SliceBuffer",
221 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
222 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
223 },
224 {
225 .name = "plane",
226 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
227 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
228 },
229 };
230 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0);
231
232 RET(ff_vk_shader_link(vkctx, shd,
235
236 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
237
238fail:
239 return err;
240}
241
243{
244 int err = 0;
245 FFVulkanContext *vkctx = &pv->vkctx;
247 int subgroup_size = vkctx->subgroup_props.maxSubgroupSize;
248 int dim_x = pv->ctx.alpha_bits ? subgroup_size : (subgroup_size / 3) * 3;
249
250 SPEC_LIST_CREATE(sl, 8, 8 * sizeof(uint32_t))
251 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
252 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.chroma_factor);
253 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.alpha_bits);
254 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.num_planes);
255 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.slices_per_picture);
256 SPEC_LIST_ADD(sl, 5, 32, pv->ctx.force_quant ? 0 : pv->ctx.profile_info->min_quant);
257 SPEC_LIST_ADD(sl, 6, 32, pv->ctx.force_quant ? 0 : pv->ctx.profile_info->max_quant);
258 SPEC_LIST_ADD(sl, 7, 32, pv->ctx.bits_per_mb);
259
260 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
261 (uint32_t []) { dim_x, 1, 1 }, 0);
262
264 {
265 .name = "SliceBuffer",
266 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
267 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
268 },
269 {
270 .name = "SliceScores",
271 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
272 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
273 },
274 {
275 .name = "ProresDataTables",
276 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
277 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
278 },
279 };
280 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 3, 0);
281
282 RET(ff_vk_shader_link(vkctx, shd,
285 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
286
287fail:
288 return err;
289}
290
292{
293 int err = 0;
294 FFVulkanContext *vkctx = &pv->vkctx;
296 int subgroup_size = vkctx->subgroup_props.maxSubgroupSize;
297 int num_subgroups = FFALIGN(pv->ctx.mb_height, subgroup_size) / subgroup_size;
298
299 SPEC_LIST_CREATE(sl, 8, 8 * sizeof(uint32_t))
300 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.slices_width);
301 SPEC_LIST_ADD(sl, 1, 32, num_subgroups);
302 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.num_planes);
303 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.force_quant);
304 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.profile_info->min_quant);
305 SPEC_LIST_ADD(sl, 5, 32, pv->ctx.profile_info->max_quant);
306 SPEC_LIST_ADD(sl, 6, 32, pv->ctx.mbs_per_slice);
307 SPEC_LIST_ADD(sl, 7, 32, pv->ctx.bits_per_mb);
308
309 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
310 (uint32_t []) { pv->ctx.mb_height, 1, 1 }, 0);
311
313 {
314 .name = "FrameSize",
315 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
316 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
317 },
318 {
319 .name = "SliceScores",
320 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
321 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
322 },
323 };
324 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0);
325
326 RET(ff_vk_shader_link(vkctx, shd,
329
330 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
331
332fail:
333 return err;
334}
335
337{
338 int err = 0;
339 FFVulkanContext *vkctx = &pv->vkctx;
341
342 SPEC_LIST_CREATE(sl, 6, 6 * sizeof(uint32_t))
343 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
344 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.chroma_factor);
345 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.alpha_bits);
346 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.num_planes);
347 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.slices_per_picture);
349
350 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
351 (uint32_t []) { 64, 1, 1 }, 0);
352
354 {
355 .name = "SliceBuffer",
356 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
357 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
358 },
359 {
360 .name = "SliceScores",
361 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
362 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
363 },
364 {
365 .name = "ProresDataTables",
366 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
367 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
368 },
369 };
370 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 3, 0);
371
372 ff_vk_shader_add_push_const(shd, 0, sizeof(EncodeSliceInfo), VK_SHADER_STAGE_COMPUTE_BIT);
373
374 RET(ff_vk_shader_link(vkctx, shd,
377
378 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
379
380fail:
381 return err;
382}
383
385{
386 int err = 0;
387 FFVulkanContext *vkctx = &pv->vkctx;
389
390 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, NULL,
391 (uint32_t []) { 256, 1, 1 }, 0);
392
394 {
395 .name = "sizes_buf",
396 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
397 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
398 },
399 };
400 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 1, 0);
401
403 VK_SHADER_STAGE_COMPUTE_BIT);
404
405 RET(ff_vk_shader_link(vkctx, shd,
408
409 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
410
411fail:
412 return err;
413}
414
416 AVFrame *frame, int picture_idx)
417{
418 ProresVulkanContext *pv = avctx->priv_data;
419 ProresContext *ctx = &pv->ctx;
421 FFVulkanContext *vkctx = &pv->vkctx;
422 FFVulkanFunctions *vk = &vkctx->vkfn;
423 int err = 0, nb_img_bar = 0, i, is_chroma;
424 int min_quant = ctx->profile_info->min_quant;
425 int max_quant = ctx->profile_info->max_quant;
426 int subgroup_size = vkctx->subgroup_props.maxSubgroupSize;
427 int estimate_dim_x = ctx->alpha_bits ? subgroup_size : (subgroup_size / 3) * 3;
429 VkImageView views[AV_NUM_DATA_POINTERS];
430 VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
431 FFVkBuffer *pkt_vk_buf, *slice_data_buf, *slice_score_buf, *frame_size_buf;
432 SliceDataInfo slice_data_info;
433 EncodeSliceInfo encode_info;
434 FFVulkanShader *shd;
435
436 /* Start recording */
437 err = ff_vk_exec_start(vkctx, exec);
438 if (err < 0)
439 return err;
440
441 /* Sparse slice output: one fixed-stride, device-local slot per slice */
442 RET(ff_vk_get_pooled_buffer(vkctx, &pv->pkt_buf_pool, &pd->out_data_ref[picture_idx],
443 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
444 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
445 ctx->slices_per_picture * pv->slice_slot_size,
446 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
447 pkt_vk_buf = pd->out_data_ref[picture_idx];
448 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->out_data_ref[picture_idx]);
449
450 /* Per-slice sizes: read by the gather pass, and by the CPU to write the
451 * seek table. */
453 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
454 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
455 ctx->slices_per_picture * sizeof(uint32_t),
456 VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
457 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
458 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
459 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_sizes_ref[picture_idx]);
460
461 /* Picture 0 is gathered directly into the packet buffer at its static
462 * offset; picture 1's offset depends on picture 0's encoded size, so it
463 * is gathered to a scratch buffer and moved into place by the CPU. */
464 RET(ff_vk_get_pooled_buffer(vkctx, &pv->gathered_buf_pool, &pd->gathered_ref[picture_idx],
465 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
466 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
467 picture_idx == 0 ? ctx->frame_size_upper_bound + FF_INPUT_BUFFER_MIN_SIZE
468 : ctx->slices_per_picture * pv->slice_slot_size,
469 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
470 vkctx->host_cached_flag));
471 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->gathered_ref[picture_idx]);
472
473 /* Allocate buffer for writing slice data */
474 RET(ff_vk_get_pooled_buffer(vkctx, &pv->slice_data_buf_pool, &pd->slice_data_ref[picture_idx],
475 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
476 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
477 ctx->slices_per_picture * sizeof(SliceData),
478 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
479 slice_data_buf = pd->slice_data_ref[picture_idx];
480 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_data_ref[picture_idx]);
481
482 /* Allocate buffer for writing slice scores */
484 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
485 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
486 ctx->slices_per_picture * sizeof(SliceScore),
487 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
488 slice_score_buf = pd->slice_score_ref[picture_idx];
489 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_score_ref[picture_idx]);
490
491 /* Allocate buffer for writing frame size */
492 RET(ff_vk_get_pooled_buffer(vkctx, &pv->frame_size_buf_pool, &pd->frame_size_ref[picture_idx],
493 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
494 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
495 sizeof(int),
496 VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
497 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
498 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
499 frame_size_buf = pd->frame_size_ref[picture_idx];
500 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->frame_size_ref[picture_idx]);
501
502 /* Generate barriers and image views for frame images. */
504 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
505 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
506 RET(ff_vk_create_imageviews(vkctx, exec, views, frame, FF_VK_REP_INT));
507 ff_vk_frame_barrier(vkctx, exec, frame, img_bar, &nb_img_bar,
508 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
509 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
510 VK_ACCESS_SHADER_READ_BIT,
511 VK_IMAGE_LAYOUT_GENERAL,
512 VK_QUEUE_FAMILY_IGNORED);
513
514 /* Submit the image barriers. */
515 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
516 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
517 .pImageMemoryBarriers = img_bar,
518 .imageMemoryBarrierCount = nb_img_bar,
519 });
520
521 /* Apply FDCT on input image data for future passes */
522 slice_data_info = (SliceDataInfo) {
523 .line_add = ctx->pictures_per_frame == 1 ? 0 : picture_idx ^ !(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST),
524 };
525 for (i = 0; i < ctx->num_planes; i++) {
526 is_chroma = (i == 1 || i == 2);
527 shd = &pv->slice_data_shd[!is_chroma || ctx->chroma_factor == CFACTOR_Y444];
528 if (i < 3) {
529 slice_data_info.plane = i;
530 slice_data_info.bits_per_sample = desc->comp[i].depth;
531 ff_vk_shader_update_desc_buffer(vkctx, exec, shd, 0, 0, 0,
532 slice_data_buf, 0, slice_data_buf->size,
533 VK_FORMAT_UNDEFINED);
534 ff_vk_shader_update_img_array(vkctx, exec, shd, frame, views, 0, 1,
535 VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
536 ff_vk_exec_bind_shader(vkctx, exec, shd);
537 ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
538 0, sizeof(SliceDataInfo), &slice_data_info);
539 vk->CmdDispatch(exec->buf, ctx->slices_width, ctx->mb_height, 1);
540 } else {
541 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->alpha_data_shd, 0, 0, 0,
542 slice_data_buf, 0, slice_data_buf->size,
543 VK_FORMAT_UNDEFINED);
544 ff_vk_shader_update_img(vkctx, exec, &pv->alpha_data_shd, 0, 1, 0, views[3],
545 VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
546 ff_vk_exec_bind_shader(vkctx, exec, &pv->alpha_data_shd);
547 vk->CmdDispatch(exec->buf, ctx->mb_width, ctx->mb_height, 1);
548 }
549 }
550
551 /* Wait for writes to slice buffer. */
552 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
553 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
554 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
555 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
556 .pNext = NULL,
557 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
558 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
559 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
560 .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
561 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
562 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
563 .buffer = slice_data_buf->buf,
564 .offset = 0,
565 .size = slice_data_buf->size,
566 },
567 .bufferMemoryBarrierCount = 1,
568 });
569
570 /* Estimate slice bits and error for each quant */
571 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 0, 0,
572 slice_data_buf, 0, slice_data_buf->size,
573 VK_FORMAT_UNDEFINED);
574 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 1, 0,
575 slice_score_buf, 0, slice_score_buf->size,
576 VK_FORMAT_UNDEFINED);
577 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 2, 0,
578 &pv->prores_data_tables_buf, 0, pv->prores_data_tables_buf.size,
579 VK_FORMAT_UNDEFINED);
580 ff_vk_exec_bind_shader(vkctx, exec, &pv->estimate_slice_shd);
581 vk->CmdDispatch(exec->buf, (ctx->slices_per_picture * ctx->num_planes + estimate_dim_x - 1) / estimate_dim_x,
582 ctx->force_quant ? 1 : (max_quant - min_quant + 1), 1);
583
584 /* Wait for writes to score buffer. */
585 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
586 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
587 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
588 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
589 .pNext = NULL,
590 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
591 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
592 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
593 .dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
594 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
595 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
596 .buffer = slice_score_buf->buf,
597 .offset = 0,
598 .size = slice_score_buf->size,
599 },
600 .bufferMemoryBarrierCount = 1,
601 });
602
603 /* Compute optimal quant value for each slice */
604 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->trellis_node_shd, 0, 0, 0,
605 frame_size_buf, 0, frame_size_buf->size,
606 VK_FORMAT_UNDEFINED);
607 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->trellis_node_shd, 0, 1, 0,
608 slice_score_buf, 0, slice_score_buf->size,
609 VK_FORMAT_UNDEFINED);
610 ff_vk_exec_bind_shader(vkctx, exec, &pv->trellis_node_shd);
611 vk->CmdDispatch(exec->buf, 1, 1, 1);
612
613 /* Wait for writes to quant buffer. */
614 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
615 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
616 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
617 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
618 .pNext = NULL,
619 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
620 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
621 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
622 .dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
623 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
624 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
625 .buffer = frame_size_buf->buf,
626 .offset = 0,
627 .size = frame_size_buf->size,
628 },
629 .bufferMemoryBarrierCount = 1,
630 });
631
632 /* Encode slices. */
633 encode_info = (EncodeSliceInfo) {
634 .bytestream = pkt_vk_buf->address,
635 .slice_sizes = pd->slice_sizes_ref[picture_idx]->address,
636 .slot_size = pv->slice_slot_size,
637 };
638 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 0, 0,
639 slice_data_buf, 0, slice_data_buf->size,
640 VK_FORMAT_UNDEFINED);
641 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 1, 0,
642 slice_score_buf, 0, slice_score_buf->size,
643 VK_FORMAT_UNDEFINED);
644 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 2, 0,
645 &pv->prores_data_tables_buf, 0, pv->prores_data_tables_buf.size,
646 VK_FORMAT_UNDEFINED);
647 ff_vk_exec_bind_shader(vkctx, exec, &pv->encode_slice_shd);
648 ff_vk_shader_update_push_const(vkctx, exec, &pv->encode_slice_shd,
649 VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(encode_info), &encode_info);
650 vk->CmdDispatch(exec->buf, FFALIGN(ctx->slices_per_picture, 64) / 64,
651 ctx->num_planes, 1);
652
653 /* Gather the sparse slots into the contiguous bitstream, in the same
654 * submission. */
655 VkBufferMemoryBarrier2 gather_bar[2] = {
656 {
657 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
658 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
659 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
660 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
661 .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
662 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
663 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
664 .buffer = pkt_vk_buf->buf,
665 .offset = 0,
666 .size = pkt_vk_buf->size,
667 }, {
668 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
669 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
670 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
671 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
672 .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
673 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
674 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
675 .buffer = pd->slice_sizes_ref[picture_idx]->buf,
676 .offset = 0,
677 .size = pd->slice_sizes_ref[picture_idx]->size,
678 },
679 };
680 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
681 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
682 .pBufferMemoryBarriers = gather_bar,
683 .bufferMemoryBarrierCount = 2,
684 });
685
686 SegGatherPushData gather_pd = {
687 .sparse = pkt_vk_buf->address,
688 .compacted = pd->gathered_ref[picture_idx]->address +
689 (picture_idx == 0 ? pv->payload_off : 0),
690 .slot_size = pv->slice_slot_size,
691 };
692 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->gather_shd, 0, 0, 0,
693 pd->slice_sizes_ref[picture_idx],
694 0, ctx->slices_per_picture * sizeof(uint32_t),
695 VK_FORMAT_UNDEFINED);
696 ff_vk_exec_bind_shader(vkctx, exec, &pv->gather_shd);
697 ff_vk_shader_update_push_const(vkctx, exec, &pv->gather_shd,
698 VK_SHADER_STAGE_COMPUTE_BIT,
699 0, sizeof(gather_pd), &gather_pd);
700 vk->CmdDispatch(exec->buf, ctx->slices_per_picture, 1, 1);
701
702 return 0;
703
704fail:
705 ff_vk_exec_discard(vkctx, exec);
706 return err;
707}
708
710 uint8_t **orig_buf, int flags,
712 enum AVColorTransferCharacteristic color_trc,
713 enum AVColorSpace colorspace)
714{
715 uint8_t *buf, *tmp;
716 uint8_t frame_flags;
717
718 // frame atom
719 *orig_buf += 4; // frame size
720 bytestream_put_be32 (orig_buf, FRAME_ID); // frame container ID
721 buf = *orig_buf;
722
723 // frame header
724 tmp = buf;
725 buf += 2; // frame header size will be stored here
726 bytestream_put_be16 (&buf, ctx->chroma_factor != CFACTOR_Y422 || ctx->alpha_bits ? 1 : 0);
727 bytestream_put_buffer(&buf, (uint8_t*)ctx->vendor, 4);
728 bytestream_put_be16 (&buf, avctx->width);
729 bytestream_put_be16 (&buf, avctx->height);
730
731 frame_flags = ctx->chroma_factor << 6;
733 frame_flags |= (flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 0x04 : 0x08;
734 bytestream_put_byte (&buf, frame_flags);
735
736 bytestream_put_byte (&buf, 0); // reserved
737 bytestream_put_byte (&buf, color_primaries);
738 bytestream_put_byte (&buf, color_trc);
739 bytestream_put_byte (&buf, colorspace);
740 bytestream_put_byte (&buf, ctx->alpha_bits >> 3);
741 bytestream_put_byte (&buf, 0); // reserved
742 if (ctx->quant_sel != QUANT_MAT_DEFAULT) {
743 bytestream_put_byte (&buf, 0x03); // matrix flags - both matrices are present
744 bytestream_put_buffer(&buf, ctx->quant_mat, 64); // luma quantisation matrix
745 bytestream_put_buffer(&buf, ctx->quant_chroma_mat, 64); // chroma quantisation matrix
746 } else {
747 bytestream_put_byte (&buf, 0x00); // matrix flags - default matrices are used
748 }
749 bytestream_put_be16 (&tmp, buf - *orig_buf); // write back frame header size
750 return buf;
751}
752
753/* Return the assembled-frame buffer to its pool when the packet is freed. */
754static void prores_vk_packet_free(void *opaque, uint8_t *data)
755{
756 av_refstruct_unref(&opaque);
757}
758
760{
761 ProresVulkanContext *pv = avctx->priv_data;
762 ProresContext *ctx = &pv->ctx;
764 FFVulkanContext *vkctx = &pv->vkctx;
765 FFVulkanFunctions *vk = &vkctx->vkfn;
766 FFVkBuffer *wrap_buf = pd->gathered_ref[0];
767 uint8_t *orig_buf, *buf, *slice_sizes;
768 uint8_t *picture_size_pos;
769 int picture_idx;
770 int frame_size, picture_size;
771 FFVkBuffer *frame_size_buf;
772 VkMappedMemoryRange invalidate_data;
773
774 /* Make sure encoding's done */
775 ff_vk_exec_wait(vkctx, exec);
776
777 /* Invalidate the gathered bitstream if needed */
778 invalidate_data = (VkMappedMemoryRange) {
779 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
780 .offset = 0,
781 .size = VK_WHOLE_SIZE,
782 };
783 if (!(wrap_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
784 invalidate_data.memory = wrap_buf->mem;
785 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
786 }
787
788 /* Write frame atom */
789 orig_buf = wrap_buf->mapped_mem;
790 buf = write_frame_header(avctx, ctx, &orig_buf, pd->flags,
791 pd->color_primaries, pd->color_trc,
792 pd->colorspace);
793
794 for (picture_idx = 0; picture_idx < ctx->pictures_per_frame; picture_idx++) {
795 FFVkBuffer *slice_sizes_buf = pd->slice_sizes_ref[picture_idx];
796 const uint32_t *sizes;
797
798 frame_size_buf = pd->frame_size_ref[picture_idx];
799
800 /* Invalidate slice sizes if needed */
801 if (!(frame_size_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
802 invalidate_data.memory = frame_size_buf->mem;
803 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
804 }
805 if (!(slice_sizes_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
806 invalidate_data.memory = slice_sizes_buf->mem;
807 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
808 }
809
810 /* Write picture header */
811 picture_size_pos = buf + 1;
812 bytestream_put_byte(&buf, 0x40); // picture header size (in bits)
813 buf += 4; // picture data size will be stored here
814 bytestream_put_be16(&buf, ctx->slices_per_picture);
815 bytestream_put_byte(&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs
816
817 /* Write the seek table from the per-slice sizes; the payload itself
818 * was already packed to match by the gather pass. */
819 slice_sizes = buf;
820 sizes = (const uint32_t *)slice_sizes_buf->mapped_mem;
821 for (int i = 0; i < ctx->slices_per_picture; i++)
822 bytestream_put_be16(&buf, sizes[i]);
823
824 /* Calculate final size */
825 buf += *(int*)frame_size_buf->mapped_mem;
826
827 if (picture_idx == 0) {
828 av_assert1(((slice_sizes + ctx->slices_per_picture * 2) -
829 wrap_buf->mapped_mem) == pv->payload_off);
830 } else {
831 /* Relocate the second picture's payload from its scratch buffer */
832 FFVkBuffer *scratch = pd->gathered_ref[1];
833 if (!(scratch->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
834 invalidate_data.memory = scratch->mem;
835 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
836 }
837 memcpy(slice_sizes + ctx->slices_per_picture * 2, scratch->mapped_mem,
838 buf - (slice_sizes + ctx->slices_per_picture * 2));
840 }
841
842 /* Write picture size with header */
843 picture_size = buf - (picture_size_pos - 1);
844 bytestream_put_be32(&picture_size_pos, picture_size);
845
846 /* Slice output buffers no longer needed */
847 av_refstruct_unref(&pd->out_data_ref[picture_idx]);
848 av_refstruct_unref(&pd->slice_sizes_ref[picture_idx]);
849 av_refstruct_unref(&pd->slice_data_ref[picture_idx]);
850 av_refstruct_unref(&pd->slice_score_ref[picture_idx]);
851 av_refstruct_unref(&pd->frame_size_ref[picture_idx]);
852 }
853
854 /* Write frame size in header */
855 orig_buf -= 8;
856 frame_size = buf - orig_buf;
857 bytestream_put_be32(&orig_buf, frame_size);
858
859 memset(buf, 0, AV_INPUT_BUFFER_PADDING_SIZE);
860
861 /* Hand the buffer to the packet with no copy: pkt->buf references the
862 * pooled Vulkan buffer, returned to its pool when the packet is freed. */
863 pkt->buf = av_buffer_create(wrap_buf->mapped_mem, wrap_buf->size,
865 if (!pkt->buf) {
867 return AVERROR(ENOMEM);
868 }
869 pd->gathered_ref[0] = NULL; /* ownership passed to pkt->buf */
870 pkt->data = wrap_buf->mapped_mem;
871 pkt->size = frame_size;
872
873 pkt->pts = pd->pts;
874 pkt->dts = pd->pts;
875 pkt->duration = pd->duration;
876 pkt->flags |= AV_PKT_FLAG_KEY * pd->key_frame;
877
878 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
879 pkt->opaque = pd->frame_opaque;
880 pkt->opaque_ref = pd->frame_opaque_ref;
882 }
883
884 av_log(avctx, AV_LOG_VERBOSE, "Encoded data: %iMiB\n", pkt->size / (1024*1024));
885
886 return 0;
887}
888
890{
891 int err;
892 ProresVulkanContext *pv = avctx->priv_data;
893 ProresContext *ctx = &pv->ctx;
895 FFVkExecContext *exec;
896 AVFrame *frame;
897
898 while (1) {
899 /* Roll an execution context */
900 exec = ff_vk_exec_get(&pv->vkctx, &pv->e);
901
902 /* If it had a frame, immediately output it */
903 if (exec->had_submission) {
904 exec->had_submission = 0;
905 pv->in_flight--;
906 return get_packet(avctx, exec, pkt);
907 }
908
909 /* Get next frame to encode */
910 frame = pv->frame;
911 err = ff_encode_get_frame(avctx, frame);
912 if (err < 0 && err != AVERROR_EOF) {
913 return err;
914 } else if (err == AVERROR_EOF) {
915 if (!pv->in_flight)
916 return err;
917 continue;
918 }
919
920 /* Encode frame */
921 pd = exec->opaque;
922 pd->color_primaries = frame->color_primaries;
923 pd->color_trc = frame->color_trc;
924 pd->colorspace = frame->colorspace;
925 pd->pts = frame->pts;
926 pd->duration = frame->duration;
927 pd->flags = frame->flags;
928 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
929 pd->frame_opaque = frame->opaque;
930 pd->frame_opaque_ref = frame->opaque_ref;
931 frame->opaque_ref = NULL;
932 }
933
934 err = vulkan_encode_prores_submit_frame(avctx, exec, frame, 0);
935 if (ctx->pictures_per_frame > 1)
937
938 /* Submit execution context */
939 ff_vk_exec_submit(&pv->vkctx, exec);
941 if (err < 0)
942 return err;
943
944 pv->in_flight++;
945 if (pv->in_flight < pv->async_depth)
946 return AVERROR(EAGAIN);
947 }
948
949 return 0;
950}
951
983
985{
986 ProresVulkanContext *pv = avctx->priv_data;
987 ProresContext *ctx = &pv->ctx;
988 int err = 0, i, q;
989 FFVulkanContext *vkctx = &pv->vkctx;
990
991 /* Init vulkan */
992 RET(ff_vk_init(vkctx, avctx, NULL, avctx->hw_frames_ctx));
993
994 pv->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
995 if (!pv->qf) {
996 av_log(avctx, AV_LOG_ERROR, "Device has no compute queues!\n");
997 return AVERROR(ENOTSUP);
998 }
999
1000 RET(ff_vk_exec_pool_init(vkctx, pv->qf, &pv->e, 1, 0, 0, 0, NULL));
1001
1002 /* Init common prores structures */
1003 err = ff_prores_kostya_encode_init(avctx, ctx, vkctx->frames->sw_format);
1004 if (err < 0)
1005 return err;
1006
1007 /* Temporary frame */
1008 pv->frame = av_frame_alloc();
1009 if (!pv->frame)
1010 return AVERROR(ENOMEM);
1011
1012 /* Async data pool */
1013 pv->async_depth = pv->e.pool_size;
1014 pv->exec_ctx_info = av_calloc(pv->async_depth, sizeof(*pv->exec_ctx_info));
1015 if (!pv->exec_ctx_info)
1016 return AVERROR(ENOMEM);
1017 for (int i = 0; i < pv->async_depth; i++)
1018 pv->e.contexts[i].opaque = &pv->exec_ctx_info[i];
1019
1020 /* Compile shaders used by encoder */
1027
1028 /* Size slots for the entropy coder's worst case; bits_per_mb is only a rate-control average */
1029 {
1030 size_t samples = ctx->mbs_per_slice *
1031 (256 + (ctx->chroma_factor == CFACTOR_Y444 ? 512 : 256));
1032 pv->slice_slot_size = 2 + 2 * ctx->num_planes + samples * 8;
1033 if (ctx->alpha_bits)
1034 pv->slice_slot_size += (ctx->mbs_per_slice * 256 *
1035 (1 + ctx->alpha_bits + 1) + 7) >> 3;
1037 UINT16_MAX + 2 + 2 * ctx->num_planes);
1039 }
1040
1041 /* First picture's payload offset: everything before it in the stream has
1042 * a static size, so the gather pass writes the payload directly in place */
1043 {
1044 uint8_t tmp[256];
1045 uint8_t *start = tmp;
1046 uint8_t *end = write_frame_header(avctx, ctx, &start, 0, 0, 0, 0);
1047 pv->payload_off = (end - tmp) + 8 + ctx->slices_per_picture * 2;
1048 }
1049
1050 if (ctx->alpha_bits)
1052
1053 /* Create prores data tables uniform buffer. */
1055 sizeof(ProresDataTables), NULL, NULL,
1056 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
1057 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
1058 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1059 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
1060 RET(ff_vk_map_buffer(vkctx, &pv->prores_data_tables_buf, (void *)&pv->tables, 0));
1061 for (q = 0; q < MAX_STORED_Q; ++q) {
1062 for (i = 0; i < 64; i++) {
1063 pv->tables->qmat[q][i] = ctx->quants[q][ctx->scantable[i]];
1064 pv->tables->qmat_chroma[q][i] = ctx->quants_chroma[q][ctx->scantable[i]];
1065 }
1066 }
1067 for (q = MAX_STORED_Q; q < 128; ++q) {
1068 for (i = 0; i < 64; i++) {
1069 pv->tables->qmat[q][i] = ctx->quant_mat[ctx->scantable[i]] * q;
1070 pv->tables->qmat_chroma[q][i] = ctx->quant_chroma_mat[ctx->scantable[i]] * q;
1071 }
1072 }
1073
1074fail:
1075 return err;
1076}
1077
1078#define OFFSET(x) offsetof(ProresVulkanContext, x)
1079#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1080
1081static const AVOption options[] = {
1082 { "mbs_per_slice", "macroblocks per slice", OFFSET(ctx.mbs_per_slice),
1083 AV_OPT_TYPE_INT, { .i64 = 8 }, 1, MAX_MBS_PER_SLICE, VE },
1084 { "profile", NULL, OFFSET(ctx.profile), AV_OPT_TYPE_INT,
1085 { .i64 = PRORES_PROFILE_AUTO },
1086 PRORES_PROFILE_AUTO, PRORES_PROFILE_4444XQ, VE, .unit = "profile" },
1087 { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_AUTO },
1088 0, 0, VE, .unit = "profile" },
1089 { "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_PROXY },
1090 0, 0, VE, .unit = "profile" },
1091 { "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_LT },
1092 0, 0, VE, .unit = "profile" },
1093 { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_STANDARD },
1094 0, 0, VE, .unit = "profile" },
1095 { "hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_HQ },
1096 0, 0, VE, .unit = "profile" },
1097 { "4444", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_4444 },
1098 0, 0, VE, .unit = "profile" },
1099 { "4444xq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_4444XQ },
1100 0, 0, VE, .unit = "profile" },
1101 { "vendor", "vendor ID", OFFSET(ctx.vendor),
1102 AV_OPT_TYPE_STRING, { .str = "Lavc" }, 0, 0, VE },
1103 { "bits_per_mb", "desired bits per macroblock", OFFSET(ctx.bits_per_mb),
1104 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8192, VE },
1105 { "quant_mat", "quantiser matrix", OFFSET(ctx.quant_sel), AV_OPT_TYPE_INT,
1106 { .i64 = -1 }, -1, QUANT_MAT_DEFAULT, VE, .unit = "quant_mat" },
1107 { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 },
1108 0, 0, VE, .unit = "quant_mat" },
1109 { "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_PROXY },
1110 0, 0, VE, .unit = "quant_mat" },
1111 { "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_LT },
1112 0, 0, VE, .unit = "quant_mat" },
1113 { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_STANDARD },
1114 0, 0, VE, .unit = "quant_mat" },
1115 { "hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_HQ },
1116 0, 0, VE, .unit = "quant_mat" },
1117 { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_DEFAULT },
1118 0, 0, VE, .unit = "quant_mat" },
1119 { "alpha_bits", "bits for alpha plane", OFFSET(ctx.alpha_bits), AV_OPT_TYPE_INT,
1120 { .i64 = 16 }, 0, 16, VE },
1121 { "async_depth", "Internal parallelization depth", OFFSET(async_depth), AV_OPT_TYPE_INT,
1122 { .i64 = 1 }, 1, INT_MAX, VE },
1123 { NULL }
1124};
1125
1126static const AVClass proresenc_class = {
1127 .class_name = "ProRes vulkan encoder",
1128 .item_name = av_default_item_name,
1129 .option = options,
1130 .version = LIBAVUTIL_VERSION_INT,
1131};
1132
1134 HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
1136 NULL,
1137};
1138
1140 .p.name = "prores_ks_vulkan",
1141 CODEC_LONG_NAME("Apple ProRes (iCodec Pro)"),
1142 .p.type = AVMEDIA_TYPE_VIDEO,
1143 .p.id = AV_CODEC_ID_PRORES,
1144 .priv_data_size = sizeof(ProresVulkanContext),
1145 .init = encode_init,
1148 .p.capabilities = AV_CODEC_CAP_DELAY |
1153 .hw_configs = prores_ks_hw_configs,
1154 .color_ranges = AVCOL_RANGE_MPEG,
1155 .p.priv_class = &proresenc_class,
1158};
const FFCodec ff_prores_ks_vulkan_encoder
#define VE
Definition amfenc_av1.c:30
static AVFormatContext * ctx
const unsigned char ff_seg_gather_comp_spv_data[]
const unsigned int ff_seg_gather_comp_spv_len
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
static av_cold int encode_init(AVCodecContext *avctx)
Definition asvenc.c:373
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
Libavcodec external API header.
refcounted data buffer API
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition bytestream.h:372
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#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...
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static const AVColorPrimariesDesc color_primaries[AVCOL_PRI_NB]
Definition csp.c:76
static av_cold int encode_close(AVCodecContext *avctx)
Definition dcaenc.c:354
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
Definition encode.c:218
#define FF_INPUT_BUFFER_MIN_SIZE
Used by some encoders as upper bound for the length of headers.
Definition encode.h:34
#define MAX_PLANES
Definition ffv1.h:44
#define AV_NUM_DATA_POINTERS
Definition frame.h:473
static const uint8_t frame_size[4]
Definition g723_1.h:222
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition codec.h:147
#define AV_CODEC_CAP_ENCODER_FLUSH
This encoder can be flushed using avcodec_flush_buffers().
Definition codec.h:154
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition codec.h:79
#define AV_CODEC_FLAG_INTERLACED_DCT
Use interlaced DCT.
Definition avcodec.h:310
#define AV_CODEC_CAP_HARDWARE
Codec is backed by a hardware implementation.
Definition codec.h:133
#define AV_CODEC_FLAG_COPY_OPAQUE
Definition avcodec.h:279
@ AV_CODEC_ID_PRORES
Definition codec_id.h:198
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:55
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition frame.h:700
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define HW_CONFIG_ENCODER_DEVICE(format, device_type_)
Definition hwconfig.h:97
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition hwconfig.h:100
API-specific header for AV_HWDEVICE_TYPE_VULKAN.
static const int sizes[][2]
Definition img2dec.c:62
#define av_log2
Definition intmath.h:84
#define DCTSIZE
Definition jfdctfst.c:73
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
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.
Definition vulkan.c:2719
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.
Definition vulkan.c:2240
void ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, const FFVulkanDescriptorSetBinding *desc, int nb, int singular)
Add descriptor to a shader.
Definition vulkan.c:2550
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition vulkan.c:331
int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNext, void *alloc_pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
Definition vulkan.c:1186
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.
Definition vulkan.c:395
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:645
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition vulkan.c:1613
int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind, int offs, VkImageView view, VkImageLayout layout, VkSampler sampler)
Sets an image descriptor for specified shader and binding.
Definition vulkan.c:2694
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2815
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.
Definition vulkan.c:2831
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Definition vulkan.c:1400
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)
Definition vulkan.c:2197
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition vulkan.c:660
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.
Definition vulkan.c:2128
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition vulkan.c:2791
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition vulkan.c:2584
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition vulkan.c:622
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:969
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, const FFVulkanShader *shd)
Bind a shader.
Definition vulkan.c:2768
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.
Definition vulkan.c:2732
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition vulkan.c:316
void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Execution dependency management.
Definition vulkan.c:779
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.
Definition vulkan.c:1426
void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:763
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.
Definition vulkan.c:2444
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition vulkan.c:867
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.
Definition vulkan.c:2758
const char * desc
Definition libsvtav1.c:83
Utility Preprocessor macros.
#define FFMIN(a, b)
Definition macros.h:49
#define FFALIGN(x, a)
Definition macros.h:78
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
const char data[16]
Definition mxf.c:149
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition pixfmt.h:642
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition pixfmt.h:672
AVColorSpace
YUV colorspace type.
Definition pixfmt.h:706
const AVProfile ff_prores_profiles[]
Definition profiles.c:175
#define FRAME_ID
Definition proresdata.h:28
static const AVClass proresenc_class
av_cold int ff_prores_kostya_encode_init(AVCodecContext *avctx, ProresContext *ctx, enum AVPixelFormat pix_fmt)
@ QUANT_MAT_STANDARD
@ QUANT_MAT_DEFAULT
#define CFACTOR_Y444
#define CFACTOR_Y422
@ PRORES_PROFILE_4444
@ PRORES_PROFILE_STANDARD
@ PRORES_PROFILE_LT
@ PRORES_PROFILE_4444XQ
@ PRORES_PROFILE_AUTO
@ PRORES_PROFILE_HQ
@ PRORES_PROFILE_PROXY
#define MAX_MBS_PER_SLICE
#define MAX_STORED_Q
const unsigned int ff_prores_ks_alpha_data_comp_spv_len
const unsigned char ff_prores_ks_alpha_data_comp_spv_data[]
static int init_estimate_slice_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static int get_packet(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt)
const unsigned int ff_prores_ks_slice_data_comp_spv_len
const unsigned int ff_prores_ks_encode_slice_comp_spv_len
static int init_gather_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static av_cold int encode_init(AVCodecContext *avctx)
static av_cold int encode_close(AVCodecContext *avctx)
const unsigned int ff_prores_ks_trellis_node_comp_spv_len
static int init_alpha_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static const AVCodecHWConfigInternal *const prores_ks_hw_configs[]
static int vulkan_encode_prores_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
static int init_trellis_node_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static void prores_vk_packet_free(void *opaque, uint8_t *data)
static int init_slice_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd, int blocks_per_mb)
#define OFFSET(x)
static int vulkan_encode_prores_submit_frame(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame, int picture_idx)
const unsigned char ff_prores_ks_trellis_node_comp_spv_data[]
static uint8_t * write_frame_header(AVCodecContext *avctx, ProresContext *ctx, uint8_t **orig_buf, int flags, enum AVColorPrimaries color_primaries, enum AVColorTransferCharacteristic color_trc, enum AVColorSpace colorspace)
const unsigned int ff_prores_ks_estimate_slice_comp_spv_len
static int init_encode_slice_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
const unsigned char ff_prores_ks_estimate_slice_comp_spv_data[]
const unsigned char ff_prores_ks_slice_data_comp_spv_data[]
const unsigned char ff_prores_ks_encode_slice_comp_spv_data[]
bitstream writer API
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition refstruct.h:292
A reference to a data buffer.
Definition buffer.h:82
Describe the class of an AVClass context structure.
Definition log.h:76
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition avcodec.h:1471
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
AVRefStructPool is an API for a thread-safe pool of objects managed via the RefStruct API.
Definition refstruct.c:183
VkDevice act_dev
Active device.
VkDeviceAddress slice_sizes
VkDeviceAddress bytestream
size_t size
Definition vulkan.h:98
VkMemoryPropertyFlagBits flags
Definition vulkan.h:97
VkDeviceMemory mem
Definition vulkan.h:96
uint8_t * mapped_mem
Definition vulkan.h:103
void * opaque
Definition vulkan.h:154
int had_submission
Definition vulkan.h:134
VkCommandBuffer buf
Definition vulkan.h:142
FFVkExecContext * contexts
Definition vulkan.h:273
int pool_size
Definition vulkan.h:278
AVHWFramesContext * frames
Definition vulkan.h:343
AVVulkanDeviceContext * hwctx
Definition vulkan.h:339
VkMemoryPropertyFlagBits host_cached_flag
Definition vulkan.h:335
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props
Definition vulkan.h:306
FFVulkanFunctions vkfn
Definition vulkan.h:298
unsigned mb_height
height of the current picture in mb
Definition proresdec.h:54
const struct prores_profile * profile_info
unsigned mb_width
width of the current picture in mb
Definition proresdec.h:53
int16_t qmat_chroma[128][64]
AVRefStructPool * frame_size_buf_pool
AVRefStructPool * slice_data_buf_pool
AVRefStructPool * gathered_buf_pool
AVRefStructPool * slice_sizes_buf_pool
AVVulkanDeviceQueueFamily * qf
VulkanEncodeProresFrameData * exec_ctx_info
FFVulkanShader slice_data_shd[2]
AVRefStructPool * slice_score_buf_pool
VkDeviceAddress sparse
VkDeviceAddress compacted
int16_t rows[MAX_PLANES *MAX_MBS_PER_SLICE *256]
int error[MAX_STORED_Q][4]
int total_bits[MAX_STORED_Q]
int total_error[MAX_STORED_Q]
int bits[MAX_STORED_Q][4]
enum AVColorTransferCharacteristic color_trc
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define NONE
Definition vf_drawvg.c:262
@ FF_VK_REP_INT
Definition vulkan.h:443
#define RET(x)
Definition vulkan.h:37
#define SPEC_LIST_ADD(name, idx, val_bits, val)
Definition vulkan.h:55
#define SPEC_LIST_CREATE(name, max_length, max_size)
Definition vulkan.h:45
static int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem, int invalidate)
Definition vulkan.h:642