FFmpeg
Loading...
Searching...
No Matches
vulkan_encode.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "libavutil/mem.h"
20#include "libavutil/avassert.h"
21#include "vulkan_encode.h"
22#include "config.h"
23
25
30
33{
34 FFVulkanFunctions *vk = &ctx->s.vkfn;
35
36 FFVulkanEncodePicture *vp = pic->priv;
37
38 if (vp->in.view)
39 vk->DestroyImageView(ctx->s.hwctx->act_dev, vp->in.view,
40 ctx->s.hwctx->alloc);
41
42 vp->in.view = VK_NULL_HANDLE;
43
44 ctx->slots[vp->dpb_slot.slotIndex] = NULL;
45}
46
48{
49 FFVulkanContext *s = &ctx->s;
50 FFVulkanFunctions *vk = &s->vkfn;
51
52 /* Wait on and free execution pool */
53 ff_vk_exec_pool_free(s, &ctx->enc_pool);
54
55 /* Destroy the session params */
56 if (ctx->session_params)
57 vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
58 ctx->session_params,
59 s->hwctx->alloc);
60
61 /* Destroy the image views of any pictures still in the queue,
62 * as ff_hw_base_encode_close() only frees the picture structs */
63 for (FFHWBaseEncodePicture *pic = ctx->base.pic_start; pic; pic = pic->next)
65
66 av_refstruct_pool_uninit(&ctx->buf_pool);
67
69
71
73}
74
76{
77 int err;
79 FFVulkanEncodePicture *vp = pic->priv;
80
81 AVFrame *f = pic->input_image;
82 AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
83 AVVulkanFramesContext *vkfc = hwfc->hwctx;
84 AVVkFrame *vkf = (AVVkFrame *)f->data[0];
85
86 if (ctx->codec->picture_priv_data_size > 0) {
87 pic->codec_priv = av_mallocz(ctx->codec->picture_priv_data_size);
88 if (!pic->codec_priv)
89 return AVERROR(ENOMEM);
90 }
91
92 /* Input image view */
93 err = ff_vk_create_view(&ctx->s,
94 &vp->in.view, &vp->in.aspect,
95 vkf->img[0], vkfc->format[0],
96 VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, 0);
97 if (err < 0)
98 return err;
99
100 /* Reference view: owned by the DPB pool entry */
101 if (!ctx->common.layered_dpb) {
103 vp->dpb.view = di->view;
104 vp->dpb.aspect = di->aspect;
105 } else {
106 vp->dpb.view = ctx->common.layered_view;
107 vp->dpb.aspect = ctx->common.layered_aspect;
108 }
109
110 return 0;
111}
112
114{
116
118
119 return 0;
120}
121
123 VkVideoEncodeRateControlInfoKHR *rc_info,
124 VkVideoEncodeRateControlLayerInfoKHR *rc_layer /* Goes in ^ */)
125{
127
128 *rc_info = (VkVideoEncodeRateControlInfoKHR) {
129 .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR,
130 .rateControlMode = ctx->opts.rc_mode,
131 };
132
133 if (ctx->opts.rc_mode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
134 *rc_layer = (VkVideoEncodeRateControlLayerInfoKHR) {
135 .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR,
136 .averageBitrate = avctx->bit_rate,
137 .maxBitrate = avctx->rc_max_rate ? avctx->rc_max_rate : avctx->bit_rate,
138 .frameRateNumerator = avctx->framerate.num,
139 .frameRateDenominator = avctx->framerate.den,
140 };
141 rc_info->layerCount++;
142 rc_info->pLayers = rc_layer;
143 }
144
145 return ctx->codec->init_pic_rc(avctx, pic, rc_info, rc_layer);
146}
147
149 FFHWBaseEncodePicture *base_pic)
150{
152 FFVulkanFunctions *vk = &ctx->s.vkfn;
153
154 const size_t size_align = ctx->caps.minBitstreamBufferSizeAlignment;
155
156 FFVulkanEncodePicture *vp = base_pic->priv;
157 AVFrame *src = (AVFrame *)base_pic->input_image;
158 AVVkFrame *vkf = (AVVkFrame *)src->data[0];
159
160 int err, max_pkt_size;
161
162 FFVkBuffer *sd_buf;
163
164 int slot_index = -1;
165 FFVkExecContext *exec;
166 VkCommandBuffer cmd_buf;
167 VkImageMemoryBarrier2 img_bar[37];
168 int nb_img_bar = 0;
169
170 /* Coding start/end */
171 VkVideoBeginCodingInfoKHR encode_start;
172 VkVideoEndCodingInfoKHR encode_end = {
173 .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
174 };
175
176 VkVideoEncodeRateControlLayerInfoKHR rc_layer;
177 VkVideoEncodeRateControlInfoKHR rc_info;
178 VkVideoEncodeQualityLevelInfoKHR q_info;
179 VkVideoCodingControlInfoKHR encode_ctrl;
180
181 VkVideoReferenceSlotInfoKHR ref_slot[37];
182 VkVideoEncodeInfoKHR encode_info;
183
184 /* Create packet data buffer */
185 max_pkt_size = FFALIGN(3 * ctx->base.surface_width * ctx->base.surface_height + (1 << 16),
186 ctx->caps.minBitstreamBufferSizeAlignment);
187
188 err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &vp->pkt_buf,
189 VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR,
190 &ctx->profile_list, max_pkt_size,
191 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
192 ctx->s.host_cached_flag);
193 if (err < 0)
194 return err;
195
196 sd_buf = vp->pkt_buf;
197
198 /* Setup rate control */
199 err = init_pic_rc(avctx, base_pic, &rc_info, &rc_layer);
200 if (err < 0)
201 return err;
202
203 q_info = (VkVideoEncodeQualityLevelInfoKHR) {
204 .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
205 .pNext = &rc_info,
206 .qualityLevel = ctx->opts.quality,
207 };
208 encode_ctrl = (VkVideoCodingControlInfoKHR) {
209 .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
210 .pNext = &q_info,
211 .flags = VK_VIDEO_CODING_CONTROL_ENCODE_QUALITY_LEVEL_BIT_KHR |
212 VK_VIDEO_CODING_CONTROL_ENCODE_RATE_CONTROL_BIT_KHR |
213 VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
214 };
215
216 for (int i = 0; i < ctx->caps.maxDpbSlots; i++) {
217 if (ctx->slots[i] == NULL) {
218 slot_index = i;
219 ctx->slots[i] = base_pic;
220 break;
221 }
222 }
223 av_assert0(slot_index >= 0);
224
225 /* Current picture's ref slot */
226 vp->dpb_res = (VkVideoPictureResourceInfoKHR) {
227 .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
228 .pNext = NULL,
229 .codedOffset = { 0 },
230 .codedExtent = (VkExtent2D){ avctx->width, avctx->height },
231 .baseArrayLayer = ctx->common.layered_dpb ? slot_index : 0,
232 .imageViewBinding = vp->dpb.view,
233 };
234
235 vp->dpb_slot = (VkVideoReferenceSlotInfoKHR) {
236 .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
237 .pNext = NULL, // Set later
238 .slotIndex = slot_index,
239 .pPictureResource = &vp->dpb_res,
240 };
241
242 encode_info = (VkVideoEncodeInfoKHR) {
243 .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR,
244 .pNext = NULL, // Set later
245 .flags = 0x0,
246 .srcPictureResource = (VkVideoPictureResourceInfoKHR) {
247 .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
248 .pNext = NULL,
249 .codedOffset = { 0, 0 },
250 .codedExtent = (VkExtent2D){ base_pic->input_image->width,
251 base_pic->input_image->height },
252 .baseArrayLayer = 0,
253 .imageViewBinding = vp->in.view,
254 },
255 .pSetupReferenceSlot = &vp->dpb_slot,
256 .referenceSlotCount = 0,
257 .pReferenceSlots = ref_slot,
258 .dstBuffer = sd_buf->buf,
259 .dstBufferOffset = 0,
260 .dstBufferRange = sd_buf->size,
261 .precedingExternallyEncodedBytes = 0,
262 };
263
264 for (int i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
265 for (int j = 0; j < base_pic->nb_refs[i]; j++) {
266 FFHWBaseEncodePicture *ref = base_pic->refs[i][j];
267 FFVulkanEncodePicture *rvp = ref->priv;
268 ref_slot[encode_info.referenceSlotCount++] = rvp->dpb_slot;
269 }
270 }
271
272 /* Calling vkCmdBeginVideoCodingKHR requires to declare all references
273 * being enabled upfront, including the current frame's output ref. */
274 ref_slot[encode_info.referenceSlotCount] = vp->dpb_slot;
275 ref_slot[encode_info.referenceSlotCount].slotIndex = -1;
276
277 /* Setup picture parameters */
278 err = ctx->codec->init_pic_params(avctx, base_pic,
279 &encode_info);
280 if (err < 0)
281 return err;
282
283 encode_start = (VkVideoBeginCodingInfoKHR) {
284 .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
285 .pNext = !base_pic->force_idr ? &rc_info : NULL,
286 .videoSession = ctx->common.session,
287 .videoSessionParameters = ctx->session_params,
288 .referenceSlotCount = encode_info.referenceSlotCount + 1,
289 .pReferenceSlots = ref_slot,
290 };
291
292 /* Write header */
293 if (base_pic->type == FF_HW_PICTURE_TYPE_IDR) {
294 uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
295 size_t data_size = encode_info.dstBufferRange;
296 err = ctx->codec->write_sequence_headers(avctx, base_pic, hdr_dst, &data_size);
297 if (err < 0)
298 goto fail;
299 encode_info.dstBufferOffset += data_size;
300 encode_info.dstBufferRange -= data_size;
301 }
302
303 /* Write extra units */
304 if (ctx->codec->write_extra_headers) {
305 uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
306 size_t data_size = encode_info.dstBufferRange;
307 err = ctx->codec->write_extra_headers(avctx, base_pic, hdr_dst, &data_size);
308 if (err < 0)
309 goto fail;
310 encode_info.dstBufferOffset += data_size;
311 encode_info.dstBufferRange -= data_size;
312 }
313
314 /* Align buffer offset to the required value with filler units */
315 if (ctx->codec->write_filler) {
316 uint8_t *hdr_dst = sd_buf->mapped_mem + encode_info.dstBufferOffset;
317 size_t data_size = encode_info.dstBufferRange;
318
319 uint32_t offset = encode_info.dstBufferOffset;
320 size_t offset_align = ctx->caps.minBitstreamBufferOffsetAlignment;
321
322 uint32_t filler_data = FFALIGN(offset, offset_align) - offset;
323
324 if (filler_data) {
325 while (filler_data < ctx->codec->filler_header_size)
326 filler_data += offset_align;
327
328 filler_data -= ctx->codec->filler_header_size;
329
330 err = ctx->codec->write_filler(avctx, filler_data,
331 hdr_dst, &data_size);
332 if (err < 0)
333 goto fail;
334
335 encode_info.dstBufferOffset += data_size;
336 encode_info.dstBufferRange -= data_size;
337 }
338 }
339
340 vp->slices_offset = encode_info.dstBufferOffset;
341
342 /* Align buffer size to the nearest lower alignment requirement. */
343 encode_info.dstBufferRange -= size_align;
344 encode_info.dstBufferRange = FFALIGN(encode_info.dstBufferRange,
345 size_align);
346
347 /* Start command buffer recording */
348 exec = vp->exec = ff_vk_exec_get(&ctx->s, &ctx->enc_pool);
349 err = ff_vk_exec_start(&ctx->s, exec);
350 if (err < 0)
351 goto fail;
352 cmd_buf = exec->buf;
353
354 /* Output packet buffer */
356
357 /* Source image */
358 err = ff_vk_exec_add_dep_frame(&ctx->s, exec, src,
359 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
360 VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR);
361 if (err < 0) {
362 ff_vk_exec_discard(&ctx->s, exec);
363 goto fail;
364 }
365
366 /* Source image layout conversion. Writes to it happened on other
367 * queues, and were made available by the semaphore wait: their access
368 * flags are not to be carried over, and may not even be valid on this
369 * queue. */
370 img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
371 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
372 .pNext = NULL,
373 .srcStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
374 .srcAccessMask = VK_ACCESS_2_NONE,
375 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
376 .dstAccessMask = VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR,
377 .oldLayout = vkf->layout[0],
378 .newLayout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR,
379 .srcQueueFamilyIndex = vkf->queue_family[0],
380 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
381 .image = vkf->img[0],
382 .subresourceRange = (VkImageSubresourceRange) {
383 .aspectMask = vp->in.aspect,
384 .layerCount = 1,
385 .levelCount = 1,
386 },
387 };
389 &img_bar[nb_img_bar], &nb_img_bar);
390
391 /* DPB image barriers are only needed for initial transitions: the
392 * layered image at creation, per-picture recon images here */
393 if (!ctx->common.layered_dpb) {
395
396 if (di->layout != VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR) {
397 img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
398 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
399 .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
400 .srcAccessMask = VK_ACCESS_2_NONE,
401 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
402 .dstAccessMask = VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR |
403 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR,
404 .oldLayout = di->layout,
405 .newLayout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR,
406 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
407 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
408 .image = di->img,
409 .subresourceRange = (VkImageSubresourceRange) {
410 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
411 .layerCount = 1,
412 .levelCount = 1,
413 },
414 };
415 nb_img_bar++;
416 di->layout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR;
417 }
418 }
419
420 /* One encode-stage memory barrier per submission orders all prior
421 * encode work, references included */
422 VkMemoryBarrier2 mem_bar = {
423 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
424 .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
425 .srcAccessMask = VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR,
426 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
427 .dstAccessMask = VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR |
428 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR,
429 };
430
431 /* Change image layouts, and synchronize the DPB */
432 vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
433 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
434 .pMemoryBarriers = &mem_bar,
435 .memoryBarrierCount = 1,
436 .pImageMemoryBarriers = img_bar,
437 .imageMemoryBarrierCount = nb_img_bar,
438 });
439
440 /* Start, use parameters */
441 vk->CmdBeginVideoCodingKHR(cmd_buf, &encode_start);
442
443 /* Send control data */
444 if (!ctx->session_reset) {
445 vk->CmdControlVideoCodingKHR(cmd_buf, &encode_ctrl);
446 ctx->session_reset++;
447 }
448
449 /* Encode */
450 vk->CmdBeginQuery(cmd_buf, ctx->enc_pool.query_pool, exec->query_idx + 0, 0);
451 vk->CmdEncodeVideoKHR(cmd_buf, &encode_info);
452 vk->CmdEndQuery(cmd_buf, ctx->enc_pool.query_pool, exec->query_idx + 0);
453
454 /* End encoding */
455 vk->CmdEndVideoCodingKHR(cmd_buf, &encode_end);
456
457 /* End recording and submit for execution */
458 err = ff_vk_exec_submit(&ctx->s, vp->exec);
459 if (err < 0)
460 goto fail;
461
462 /* We don't need to keep the input image any longer, its already ref'd */
463 av_frame_free(&base_pic->input_image);
464
465 return 0;
466
467fail:
468 return err;
469}
470
471static void pkt_buf_free(void *opaque, uint8_t *data)
472{
473 av_refstruct_unref(&opaque);
474}
475
477 FFHWBaseEncodePicture *base_pic)
478{
480 FFVulkanEncodePicture *vp = base_pic->priv;
481
482 av_assert0(base_pic->encode_issued);
483
484 if (base_pic->encode_complete)
485 return;
486
487 ff_vk_exec_wait(&ctx->s, vp->exec);
488 base_pic->encode_complete = 1;
489}
490
493{
494 VkResult ret;
495 FFVulkanEncodePicture *vp = base_pic->priv;
497 FFHWBaseEncodeContext *base_ctx = &ctx->base;
498 AVPacket *pkt_ptr = pkt;
499
500 FFVkBuffer *sd_buf = vp->pkt_buf;
501 uint32_t *query_data;
502
503 vulkan_encode_wait(avctx, base_pic);
504
505 ret = ff_vk_exec_get_query(&ctx->s, vp->exec, (void **)&query_data, 0);
506 if (ret == VK_NOT_READY) {
507 av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n",
508 ff_vk_ret2str(ret));
509 return AVERROR(EINVAL);
510 }
511
512 if (ret != VK_NOT_READY && ret != VK_SUCCESS) {
513 av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n",
514 ff_vk_ret2str(ret));
515 return AVERROR_EXTERNAL;
516 }
517
518 if (query_data[2] != VK_QUERY_RESULT_STATUS_COMPLETE_KHR) {
519 av_log(avctx, AV_LOG_ERROR, "Unable to encode: %u\n", query_data[2]);
520 return AVERROR_EXTERNAL;
521 }
522
523 /* Invalidate buffer if needed */
524 if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
525 FFVulkanFunctions *vk = &ctx->s.vkfn;
526 VkMappedMemoryRange invalidate_buf;
527
528 int offs = vp->slices_offset;
529 /* If the non-coherent alignment is greater than the bitstream buffer
530 * offset's alignment, and the offs value is not aligned already,
531 * align it to the previous alignment point. */
532 if (ctx->s.props.properties.limits.nonCoherentAtomSize >
533 ctx->caps.minBitstreamBufferOffsetAlignment && offs &&
534 (FFALIGN(offs, ctx->s.props.properties.limits.nonCoherentAtomSize) != offs)) {
535 offs -= ctx->s.props.properties.limits.nonCoherentAtomSize;
536 offs = FFALIGN(FFMAX(offs, 0), ctx->s.props.properties.limits.nonCoherentAtomSize);
537 }
538
539 invalidate_buf = (VkMappedMemoryRange) {
540 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
541 .memory = sd_buf->mem,
542 .offset = offs,
543 .size = VK_WHOLE_SIZE,
544 };
545
546 vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &invalidate_buf);
547 }
548
549 if (vp->non_independent_frame) {
550 av_assert0(!ctx->prev_buf_ref);
551 size_t prev_buf_size = vp->slices_offset + query_data[0] + query_data[1];
552 ctx->prev_buf_ref = vp->pkt_buf;
553 ctx->prev_buf_size = prev_buf_size;
554 vp->pkt_buf = NULL;
555
556 if (vp->tail_size) {
557 if (base_ctx->tail_pkt->size)
558 return AVERROR_BUG;
559
560 ret = ff_get_encode_buffer(avctx, base_ctx->tail_pkt, vp->tail_size, 0);
561 if (ret < 0)
562 return ret;
563
564 memcpy(base_ctx->tail_pkt->data, vp->tail_data, vp->tail_size);
565 pkt_ptr = base_ctx->tail_pkt;
566 }
567 } else {
568 if (ctx->prev_buf_ref) {
569 FFVkBuffer *prev_sd_buf = ctx->prev_buf_ref;
570 size_t prev_size = ctx->prev_buf_size;
571 size_t size = (vp->slices_offset + query_data[0] + query_data[1]);
572
573 ret = ff_get_encode_buffer(avctx, pkt, prev_size + size, 0);
574 if (ret < 0)
575 return ret;
576
577 memcpy(pkt->data, prev_sd_buf->mapped_mem, prev_size);
578 memcpy(pkt->data + prev_size, sd_buf->mapped_mem, size);
579
580 av_refstruct_unref(&ctx->prev_buf_ref);
582 } else {
583 pkt->data = sd_buf->mapped_mem;
584 pkt->size = vp->slices_offset + /* base offset */
585 query_data[0] /* secondary offset */ +
586 query_data[1] /* size */;
587
588 /* Hand the pooled buffer to the packet with no copy */
589 pkt->buf = av_buffer_create(sd_buf->mapped_mem, pkt->size,
590 pkt_buf_free, vp->pkt_buf, 0);
591 if (!pkt->buf)
592 return AVERROR(ENOMEM);
593 vp->pkt_buf = NULL; /* ownership passed to pkt->buf */
594 }
595 }
596
597 av_log(avctx, AV_LOG_DEBUG, "Frame %"PRId64"/%"PRId64 " encoded\n",
598 base_pic->display_order, base_pic->encode_order);
599
600 return ff_hw_base_encode_set_output_property(&ctx->base, avctx,
601 base_pic, pkt_ptr,
602 ctx->codec->flags & VK_ENC_FLAG_NO_DELAY);
603}
604
606 .priv_size = sizeof(FFVulkanEncodePicture),
608 .issue = &vulkan_encode_issue,
609 .output = &vulkan_encode_output,
610 .free = &vulkan_encode_free,
611};
612
618
619static void vulkan_encode_recon_free(void *opaque, uint8_t *data)
620{
622 /* No wait: pool reuse is ordered by the DPB barrier */
624}
625
627{
630
631 di = av_refstruct_pool_get(ctx->common.dpb->img_pool);
632 if (!di)
633 return AVERROR(ENOMEM);
634
635 /* The frame only carries the pool entry through the base layer */
636 frame->buf[0] = av_buffer_create((uint8_t *)di, sizeof(*di),
638 if (!frame->buf[0]) {
640 return AVERROR(ENOMEM);
641 }
642 frame->data[0] = (uint8_t *)di;
643
644 return 0;
645}
646
648{
649 int err;
650 FFHWBaseEncodeContext *base_ctx = &ctx->base;
651
652 /* Reconstruction images are queue-exclusive; allocate them internally */
653 err = ff_vk_video_dpb_init(&ctx->s, &ctx->common, ctx->pic_format,
654 VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR,
655 VK_IMAGE_TILING_OPTIMAL, &ctx->profile_list,
656 avctx->width, avctx->height,
657 ctx->common.layered_dpb ?
658 ctx->caps.maxDpbSlots : 1);
659 if (err < 0) {
660 av_log(avctx, AV_LOG_ERROR, "Failed to initialise DPB image pool: %s\n",
661 av_err2str(err));
662 return err;
663 }
664
665 if (ctx->common.layered_dpb) {
666 FFVulkanFunctions *vk = &ctx->s.vkfn;
667 FFVkExecContext *exec;
668 VkImageMemoryBarrier2 img_bar;
669
670 ctx->common.layered_img = av_refstruct_pool_get(ctx->common.dpb->img_pool);
671 if (!ctx->common.layered_img)
672 return AVERROR(ENOMEM);
673
674 ctx->common.layered_view = ctx->common.layered_img->view;
675 ctx->common.layered_aspect = ctx->common.layered_img->aspect;
676
677 /* Created eagerly, so transitioned eagerly, matching the decoder */
678 exec = ff_vk_exec_get(&ctx->s, &ctx->enc_pool);
679 err = ff_vk_exec_start(&ctx->s, exec);
680 if (err < 0)
681 return err;
682
683 img_bar = (VkImageMemoryBarrier2) {
684 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
685 .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
686 .srcAccessMask = VK_ACCESS_2_NONE,
687 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR,
688 .dstAccessMask = VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR |
689 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR,
690 .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
691 .newLayout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR,
692 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
693 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
694 .image = ctx->common.layered_img->img,
695 .subresourceRange = (VkImageSubresourceRange) {
696 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
697 .layerCount = VK_REMAINING_ARRAY_LAYERS,
698 .levelCount = 1,
699 },
700 };
701 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
702 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
703 .pImageMemoryBarriers = &img_bar,
704 .imageMemoryBarrierCount = 1,
705 });
706
707 err = ff_vk_exec_submit(&ctx->s, exec);
708 if (err < 0)
709 return err;
710
711 ctx->common.layered_img->layout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR;
712 } else {
714 }
715
716 return 0;
717}
718
720{
721 if (ctx->opts.qp) {
722 ctx->explicit_qp = ctx->opts.qp;
723 } else if (avctx->global_quality > 0) {
724 if (avctx->flags & AV_CODEC_FLAG_QSCALE)
725 ctx->explicit_qp = avctx->global_quality / FF_QP2LAMBDA;
726 else
727 ctx->explicit_qp = avctx->global_quality;
728 }
729
730 if (ctx->opts.rc_mode == FF_VK_RC_MODE_AUTO) {
731 if (ctx->explicit_qp >= 0) {
732 ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
733 } else if (avctx->global_quality > 0) {
734 if (avctx->flags & AV_CODEC_FLAG_QSCALE)
735 ctx->explicit_qp = avctx->global_quality / FF_QP2LAMBDA;
736 else
737 ctx->explicit_qp = avctx->global_quality;
738 ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
739 } else if (avctx->bit_rate) {
740 if (ctx->enc_caps.rateControlModes & VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR)
741 ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR;
742 else if (ctx->enc_caps.rateControlModes & VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR)
743 ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR;
744 else
745 ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR;
746 } else {
747 ctx->explicit_qp = 18;
748 ctx->opts.rc_mode = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
749 av_log(avctx, AV_LOG_WARNING, "No rate control settings specified, using fixed QP = %i\n",
750 ctx->explicit_qp);
751 }
752 } else if (ctx->opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR &&
753 !avctx->bit_rate) {
754 av_log(avctx, AV_LOG_WARNING, "No bitrate specified!\n");
755 return AVERROR(EINVAL);
756 }
757
758 if (ctx->opts.rc_mode && !(ctx->enc_caps.rateControlModes & ctx->opts.rc_mode)) {
759 static const char *rc_modes[] = {
760 [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DEFAULT_KHR] = "default",
761 [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR] = "cqp",
762 [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR] = "cbr",
763 [VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR] = "vbr",
764 };
765 av_log(avctx, AV_LOG_ERROR, "Unsupported rate control mode %s, supported are:\n",
766 rc_modes[FFMIN(FF_ARRAY_ELEMS(rc_modes), ctx->opts.rc_mode)]);
767 av_log(avctx, AV_LOG_ERROR, " %s\n", rc_modes[0]);
768 for (int i = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
769 i <= VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; i <<= 1) {
770 if (!(ctx->enc_caps.rateControlModes & i))
771 continue;
772 av_log(avctx, AV_LOG_ERROR, " %s\n", rc_modes[i]);
773 }
774 return AVERROR(ENOTSUP);
775 }
776
777 return 0;
778}
779
782{
783 int err;
784
785 /* Write extradata if needed */
786 if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
787 uint8_t data[4096];
788 size_t data_len = sizeof(data);
789
790 err = ctx->codec->write_sequence_headers(avctx, NULL, data, &data_len);
791 if (err < 0) {
792 av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
793 "for extradata: %d.\n", err);
794 return err;
795 } else {
796 avctx->extradata_size = data_len;
797 avctx->extradata = av_mallocz(avctx->extradata_size +
799 if (!avctx->extradata) {
800 err = AVERROR(ENOMEM);
801 return err;
802 }
803 memcpy(avctx->extradata, data, avctx->extradata_size);
804 }
805 }
806
807 return 0;
808}
809
811 const FFVulkanEncodeDescriptor *vk_desc,
812 const FFVulkanCodec *codec,
813 void *codec_caps, void *quality_pnext)
814{
815 int i, err;
816 VkResult ret;
817 FFVulkanFunctions *vk = &ctx->s.vkfn;
818 FFVulkanContext *s = &ctx->s;
819 FFHWBaseEncodeContext *base_ctx = &ctx->base;
820
822
823 VkVideoFormatPropertiesKHR *ret_info;
824 uint32_t nb_out_fmts = 0;
825 const uint32_t feedback_flags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR |
826 VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
827
828 VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR quality_info;
829
830 VkQueryPoolVideoEncodeFeedbackCreateInfoKHR query_create;
831
832 VkVideoSessionCreateInfoKHR session_create = {
833 .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
834 };
835 VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
836 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
837 .pNext = &ctx->profile_list,
838 };
839
840 if (!avctx->hw_frames_ctx) {
841 av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
842 "required to associate the encoding device.\n");
843 return AVERROR(EINVAL);
844 }
845
846 ctx->base.op = &vulkan_base_encode_ops;
847 ctx->codec = codec;
848
849 s->frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
850 s->frames = (AVHWFramesContext *)s->frames_ref->data;
851 s->hwfc = s->frames->hwctx;
852
853 s->device = (AVHWDeviceContext *)s->frames->device_ref->data;
854 s->hwctx = s->device->hwctx;
855
857 if (!desc)
858 return AVERROR(EINVAL);
859
860 s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
861 s->hwctx->nb_enabled_dev_extensions);
862
863 if (!(s->extensions & FF_VK_EXT_VIDEO_ENCODE_QUEUE)) {
864 av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
865 VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
866 return AVERROR(ENOSYS);
867 } else if (!(s->extensions & FF_VK_EXT_VIDEO_MAINTENANCE_1)) {
868 av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
869 VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME);
870 return AVERROR(ENOSYS);
871 } else if (!(s->extensions & vk_desc->encode_extension)) {
872 av_log(avctx, AV_LOG_ERROR, "Device does not support encoding %s!\n",
873 avcodec_get_name(avctx->codec_id));
874 return AVERROR(ENOSYS);
875 }
876
877 /* Load functions */
878 err = ff_vk_load_functions(s->device, vk, s->extensions, 1, 1);
879 if (err < 0)
880 return err;
881
882 /* Create queue context */
883 ctx->qf_enc = ff_vk_qf_find(s, VK_QUEUE_VIDEO_ENCODE_BIT_KHR, vk_desc->encode_op);
884 if (!ctx->qf_enc) {
885 av_log(avctx, AV_LOG_ERROR, "Encoding of %s is not supported by this device\n",
886 avcodec_get_name(avctx->codec_id));
887 return err;
888 }
889
890 /* Load all properties */
891 err = ff_vk_load_props(s);
892 if (err < 0)
893 return err;
894
895 /* Set tuning */
896 ctx->usage_info = (VkVideoEncodeUsageInfoKHR) {
897 .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_USAGE_INFO_KHR,
898 .videoUsageHints = ctx->opts.usage,
899 .videoContentHints = ctx->opts.content,
900 .tuningMode = ctx->opts.tune,
901 };
902
903 /* Load up the profile now, needed for caps and to create a query pool */
904 ctx->profile.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
905 ctx->profile.pNext = &ctx->usage_info;
906 ctx->profile.videoCodecOperation = vk_desc->encode_op;
907 ctx->profile.chromaSubsampling = ff_vk_subsampling_from_av_desc(desc);
908 ctx->profile.lumaBitDepth = ff_vk_depth_from_av_depth(desc->comp[0].depth);
909 ctx->profile.chromaBitDepth = ctx->profile.lumaBitDepth;
910
911 /* Setup a profile */
912 err = codec->init_profile(avctx, &ctx->profile, &ctx->usage_info);
913 if (err < 0)
914 return err;
915
916 ctx->profile_list.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
917 ctx->profile_list.profileCount = 1;
918 ctx->profile_list.pProfiles = &ctx->profile;
919
920 /* Get the capabilities of the encoder for the given profile */
921 ctx->enc_caps.sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR;
922 ctx->enc_caps.pNext = codec_caps;
923 ctx->caps.sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
924 ctx->caps.pNext = &ctx->enc_caps;
925
926 ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
927 &ctx->profile,
928 &ctx->caps);
929 if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
930 av_log(avctx, AV_LOG_ERROR, "Unable to initialize encoding: "
931 "%s profile \"%s\" not supported!\n",
933 avcodec_profile_name(avctx->codec_id, avctx->profile));
934 return AVERROR(EINVAL);
935 } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
936 av_log(avctx, AV_LOG_ERROR, "Unable to initialize encoding: "
937 "format (%s) not supported!\n",
939 return AVERROR(EINVAL);
940 } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
941 ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
942 return AVERROR(EINVAL);
943 } else if (ret != VK_SUCCESS) {
944 return AVERROR_EXTERNAL;
945 }
946
947 if ((ctx->enc_caps.supportedEncodeFeedbackFlags & feedback_flags) !=
948 feedback_flags) {
949 av_log(avctx, AV_LOG_ERROR,
950 "Driver does not support required encode feedback flags "
951 "(BUFFER_OFFSET and BYTES_WRITTEN).\n");
952 return AVERROR(ENOTSUP);
953 }
954
955 err = init_rc(avctx, ctx);
956 if (err < 0)
957 return err;
958
959 /* Create command and query pool */
960 query_create = (VkQueryPoolVideoEncodeFeedbackCreateInfoKHR) {
961 .sType = VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR,
962 .pNext = &ctx->profile,
963 .encodeFeedbackFlags = feedback_flags,
964 };
965 err = ff_vk_exec_pool_init(s, ctx->qf_enc, &ctx->enc_pool, base_ctx->async_depth,
966 1, VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR, 0,
967 &query_create);
968 if (err < 0)
969 return err;
970
971 if (ctx->opts.quality > ctx->enc_caps.maxQualityLevels) {
972 av_log(avctx, AV_LOG_ERROR, "Invalid quality level %i: allowed range is "
973 "0 to %i\n",
974 ctx->opts.quality, ctx->enc_caps.maxQualityLevels);
975 return AVERROR(EINVAL);
976 }
977
978 /* Get quality properties for the profile and quality level */
979 quality_info = (VkPhysicalDeviceVideoEncodeQualityLevelInfoKHR) {
980 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
981 .pVideoProfile = &ctx->profile,
982 .qualityLevel = ctx->opts.quality,
983 };
984 ctx->quality_props = (VkVideoEncodeQualityLevelPropertiesKHR) {
985 .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_PROPERTIES_KHR,
986 .pNext = quality_pnext,
987 };
988 ret = vk->GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR(s->hwctx->phys_dev,
989 &quality_info,
990 &ctx->quality_props);
991 if (ret != VK_SUCCESS)
992 return AVERROR_EXTERNAL;
993
994 /* Printout informative properties */
995 av_log(avctx, AV_LOG_VERBOSE, "Encoder capabilities for %s profile \"%s\":\n",
997 avcodec_profile_name(avctx->codec_id, avctx->profile));
998 av_log(avctx, AV_LOG_VERBOSE, " Width: from %i to %i\n",
999 ctx->caps.minCodedExtent.width, ctx->caps.maxCodedExtent.width);
1000 av_log(avctx, AV_LOG_VERBOSE, " Height: from %i to %i\n",
1001 ctx->caps.minCodedExtent.height, ctx->caps.maxCodedExtent.height);
1002 av_log(avctx, AV_LOG_VERBOSE, " Width alignment: %i\n",
1003 ctx->caps.pictureAccessGranularity.width);
1004 av_log(avctx, AV_LOG_VERBOSE, " Height alignment: %i\n",
1005 ctx->caps.pictureAccessGranularity.height);
1006 av_log(avctx, AV_LOG_VERBOSE, " Bitstream offset alignment: %"PRIu64"\n",
1007 ctx->caps.minBitstreamBufferOffsetAlignment);
1008 av_log(avctx, AV_LOG_VERBOSE, " Bitstream size alignment: %"PRIu64"\n",
1009 ctx->caps.minBitstreamBufferSizeAlignment);
1010 av_log(avctx, AV_LOG_VERBOSE, " Maximum references: %u\n",
1011 ctx->caps.maxDpbSlots);
1012 av_log(avctx, AV_LOG_VERBOSE, " Maximum active references: %u\n",
1013 ctx->caps.maxActiveReferencePictures);
1014 av_log(avctx, AV_LOG_VERBOSE, " Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
1015 CODEC_VER(ctx->caps.stdHeaderVersion.specVersion),
1016 CODEC_VER(vk_desc->ext_props.specVersion));
1017 av_log(avctx, AV_LOG_VERBOSE, " Encoder max quality: %i\n",
1018 ctx->enc_caps.maxQualityLevels);
1019 av_log(avctx, AV_LOG_VERBOSE, " Encoder image width alignment: %i\n",
1020 ctx->enc_caps.encodeInputPictureGranularity.width);
1021 av_log(avctx, AV_LOG_VERBOSE, " Encoder image height alignment: %i\n",
1022 ctx->enc_caps.encodeInputPictureGranularity.height);
1023 av_log(avctx, AV_LOG_VERBOSE, " Capability flags:%s%s%s\n",
1024 ctx->caps.flags ? "" :
1025 " none",
1026 ctx->caps.flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
1027 " protected" : "",
1028 ctx->caps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
1029 " separate_references" : "");
1030
1031 /* Setup width/height alignment */
1032 base_ctx->surface_width = avctx->coded_width =
1033 FFALIGN(avctx->width, ctx->enc_caps.encodeInputPictureGranularity.width);
1034 base_ctx->surface_height = avctx->coded_height =
1035 FFALIGN(avctx->height, ctx->enc_caps.encodeInputPictureGranularity.height);
1036
1037 /* Setup slice width/height */
1038 base_ctx->slice_block_width = ctx->enc_caps.encodeInputPictureGranularity.width;
1039 base_ctx->slice_block_height = ctx->enc_caps.encodeInputPictureGranularity.height;
1040
1041 /* Check if encoding is possible with the given parameters */
1042 if (avctx->coded_width < ctx->caps.minCodedExtent.width ||
1043 avctx->coded_height < ctx->caps.minCodedExtent.height ||
1044 avctx->coded_width > ctx->caps.maxCodedExtent.width ||
1045 avctx->coded_height > ctx->caps.maxCodedExtent.height) {
1046 av_log(avctx, AV_LOG_ERROR, "Input of %ix%i too large for encoder limits: %ix%i max\n",
1047 avctx->coded_width, avctx->coded_height,
1048 ctx->caps.minCodedExtent.width, ctx->caps.minCodedExtent.height);
1049 return AVERROR(EINVAL);
1050 }
1051
1052 fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR;
1053
1054 ctx->common.layered_dpb = !(ctx->caps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
1055
1056 /* Get the supported image formats */
1057 ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(s->hwctx->phys_dev,
1058 &fmt_info,
1059 &nb_out_fmts, NULL);
1060 if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
1061 (!nb_out_fmts && ret == VK_SUCCESS)) {
1062 return AVERROR(EINVAL);
1063 } else if (ret != VK_SUCCESS) {
1064 av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
1065 ff_vk_ret2str(ret));
1066 return AVERROR_EXTERNAL;
1067 }
1068
1069 ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
1070 if (!ret_info)
1071 return AVERROR(ENOMEM);
1072
1073 for (int i = 0; i < nb_out_fmts; i++)
1074 ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
1075
1076 ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(s->hwctx->phys_dev,
1077 &fmt_info,
1078 &nb_out_fmts, ret_info);
1079 if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
1080 (!nb_out_fmts && ret == VK_SUCCESS)) {
1081 av_free(ret_info);
1082 return AVERROR(EINVAL);
1083 } else if (ret != VK_SUCCESS) {
1084 av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
1085 ff_vk_ret2str(ret));
1086 av_free(ret_info);
1087 return AVERROR_EXTERNAL;
1088 }
1089
1090 av_log(avctx, AV_LOG_VERBOSE, "Supported input formats:\n");
1091 for (i = 0; i < nb_out_fmts; i++)
1092 av_log(avctx, AV_LOG_VERBOSE, " %i: %i\n", i, ret_info[i].format);
1093
1094 for (i = 0; i < nb_out_fmts; i++) {
1095 if (ff_vk_pix_fmt_from_vkfmt(ret_info[i].format) == s->frames->sw_format) {
1096 ctx->pic_format = ret_info[i].format;
1097 break;
1098 }
1099 }
1100
1101 av_free(ret_info);
1102
1103 if (i == nb_out_fmts) {
1104 av_log(avctx, AV_LOG_ERROR, "Pixel format %s of input frames not supported!\n",
1105 av_get_pix_fmt_name(s->frames->sw_format));
1106 return AVERROR(EINVAL);
1107 }
1108
1109 /* Create session */
1110 session_create.pVideoProfile = &ctx->profile;
1111 session_create.flags = VK_VIDEO_SESSION_CREATE_ALLOW_ENCODE_PARAMETER_OPTIMIZATIONS_BIT_KHR;
1112 session_create.queueFamilyIndex = ctx->qf_enc->idx;
1113 session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
1114 session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
1115 session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
1116 session_create.pictureFormat = ctx->pic_format;
1117 session_create.referencePictureFormat = session_create.pictureFormat;
1118 session_create.pStdHeaderVersion = &vk_desc->ext_props;
1119
1120 err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
1121 if (err < 0)
1122 return err;
1123
1124 err = ff_hw_base_encode_init(avctx, &ctx->base);
1125 if (err < 0)
1126 return err;
1127
1128 err = vulkan_encode_create_dpb(avctx, ctx);
1129 if (err < 0)
1130 return err;
1131
1132 base_ctx->async_encode = 1;
1133 base_ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth,
1134 sizeof(FFVulkanEncodePicture *), 0);
1135 if (!base_ctx->encode_fifo)
1136 return AVERROR(ENOMEM);
1137
1138 return 0;
1139}
1140
1142 void *codec_params_pnext)
1143{
1144 VkResult ret;
1145 FFVulkanFunctions *vk = &ctx->s.vkfn;
1146 FFVulkanContext *s = &ctx->s;
1147
1148 VkVideoEncodeQualityLevelInfoKHR q_info;
1149 VkVideoSessionParametersCreateInfoKHR session_params_create;
1150
1151 q_info = (VkVideoEncodeQualityLevelInfoKHR) {
1152 .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_QUALITY_LEVEL_INFO_KHR,
1153 .pNext = codec_params_pnext,
1154 .qualityLevel = ctx->opts.quality,
1155 };
1156 session_params_create = (VkVideoSessionParametersCreateInfoKHR) {
1157 .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
1158 .pNext = &q_info,
1159 .videoSession = ctx->common.session,
1160 .videoSessionParametersTemplate = VK_NULL_HANDLE,
1161 };
1162
1163 /* Create session parameters */
1164 ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
1165 s->hwctx->alloc, &ctx->session_params);
1166 if (ret != VK_SUCCESS) {
1167 av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
1168 ff_vk_ret2str(ret));
1169 return AVERROR_EXTERNAL;
1170 }
1171
1172 return 0;
1173}
static const char *const format[]
Definition af_aiir.c:444
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition encode.c:106
#define fail
Definition test.h:479
const char * avcodec_profile_name(enum AVCodecID codec_id, int profile)
Return a name for the specified profile, if available.
Definition utils.c:446
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition avcodec.h:213
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition avcodec.h:318
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition utils.c:421
#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
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:103
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 FF_QP2LAMBDA
factor to convert from H.263 QP to lambda
Definition avutil.h:226
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition fifo.c:47
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#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
static av_cold int encode_end(AVCodecContext *avctx)
Definition huffyuvenc.c:978
int ff_hw_base_encode_receive_packet(FFHWBaseEncodeContext *ctx, AVCodecContext *avctx, AVPacket *pkt)
int ff_hw_base_encode_set_output_property(FFHWBaseEncodeContext *ctx, AVCodecContext *avctx, FFHWBaseEncodePicture *pic, AVPacket *pkt, int flag_no_delay)
int ff_hw_base_encode_init(AVCodecContext *avctx, FFHWBaseEncodeContext *ctx)
int ff_hw_base_encode_close(FFHWBaseEncodeContext *ctx)
@ FF_HW_PICTURE_TYPE_IDR
#define MAX_REFERENCE_LIST_NUM
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition hwconfig.h:100
unsigned offset
Definition libaomenc.c:763
#define av_cold
Definition attributes.h:117
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition vulkan.c:331
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
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2815
int ff_vk_load_props(FFVulkanContext *s)
Loads props/mprops/driver_props.
Definition vulkan.c:151
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
Definition vulkan.c:42
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition vulkan.c:660
VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, void **data, VkQueryResultFlagBits flags)
Performs nb_queries queries and returns their results and statuses.
Definition vulkan.c:594
void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
Definition vulkan.c:925
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
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_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition vulkan.c:867
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
const char data[16]
Definition mxf.c:149
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.
Definition pixdesc.c:3380
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
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
void * av_refstruct_pool_get(AVRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
Definition refstruct.c:297
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition refstruct.h:292
#define FF_ARRAY_ELEMS(a)
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:650
int global_quality
Global quality for codecs which cannot change it per frame.
Definition avcodec.h:1235
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition avcodec.h:1471
AVRational framerate
Definition avcodec.h:563
int64_t bit_rate
the average bitrate
Definition avcodec.h:493
int profile
profile
Definition avcodec.h:1636
int64_t rc_max_rate
maximum bitrate
Definition avcodec.h:1288
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition avcodec.h:526
enum AVCodecID codec_id
Definition avcodec.h:453
int extradata_size
Definition avcodec.h:527
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition avcodec.h:619
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
int height
Definition frame.h:544
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition hwcontext.h:153
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
VkImageLayout layout[AV_NUM_DATA_POINTERS]
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
VkFormat format[AV_NUM_DATA_POINTERS]
Vulkan format for each image.
int(* get_recon_frame)(AVCodecContext *avctx, AVFrame *frame)
AVPacket * tail_pkt
Tail data of a pic, now only used for av1 repeat frame header.
int nb_refs[MAX_REFERENCE_LIST_NUM]
struct FFHWBaseEncodePicture * refs[MAX_REFERENCE_LIST_NUM][MAX_PICTURE_REFERENCES]
VkBuffer buf
Definition vulkan.h:95
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
VkCommandBuffer buf
Definition vulkan.h:142
VkImageLayout layout
VkImageAspectFlags aspect
VkImageView view
int(* init_profile)(AVCodecContext *avctx, VkVideoProfileInfoKHR *profile, void *pnext)
Initialize codec-specific structs in a Vulkan profile.
VkVideoCodecOperationFlagBitsKHR encode_op
VkExtensionProperties ext_props
FFVulkanExtensions encode_extension
struct FFVulkanEncodePicture::@241153336102273375156314120123002360217156257341 in
VkVideoPictureResourceInfoKHR dpb_res
FFVkExecContext * exec
VkImageAspectFlags aspect
struct FFVulkanEncodePicture::@211005011031223012316203343327310203116057373135 dpb
VkVideoReferenceSlotInfoKHR dpb_slot
#define av_free(p)
#define av_mallocz(s)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static int ref[MAX_W *MAX_W]
int size
static int vulkan_encode_init(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
static int vulkan_encode_free(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
const AVCodecHWConfigInternal *const ff_vulkan_encode_hw_configs[]
Paperwork.
av_cold int ff_vulkan_encode_init(AVCodecContext *avctx, FFVulkanEncodeContext *ctx, const FFVulkanEncodeDescriptor *vk_desc, const FFVulkanCodec *codec, void *codec_caps, void *quality_pnext)
Initialize encoder.
static void vulkan_encode_free_pic(FFVulkanEncodeContext *ctx, FFHWBaseEncodePicture *pic)
static int vulkan_encode_output(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
static int vulkan_encode_create_dpb(AVCodecContext *avctx, FFVulkanEncodeContext *ctx)
static int vulkan_encode_get_recon_frame(AVCodecContext *avctx, AVFrame *frame)
static void vulkan_encode_wait(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic)
static int vulkan_encode_issue(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic)
static const FFHWEncodePictureOperation vulkan_base_encode_ops
av_cold void ff_vulkan_encode_uninit(FFVulkanEncodeContext *ctx)
Uninitialize encoder.
static void vulkan_encode_recon_free(void *opaque, uint8_t *data)
static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic, VkVideoEncodeRateControlInfoKHR *rc_info, VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
int ff_vulkan_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
Encode.
av_cold int ff_vulkan_write_global_header(AVCodecContext *avctx, FFVulkanEncodeContext *ctx)
Write out the extradata in case its needed.
static av_cold int init_rc(AVCodecContext *avctx, FFVulkanEncodeContext *ctx)
static void pkt_buf_free(void *opaque, uint8_t *data)
int ff_vulkan_encode_create_session_params(AVCodecContext *avctx, FFVulkanEncodeContext *ctx, void *codec_params_pnext)
Create session parameters.
#define FF_VK_RC_MODE_AUTO
#define VK_ENC_FLAG_NO_DELAY
#define FF_VK_EXT_VIDEO_MAINTENANCE_1
#define FF_VK_EXT_VIDEO_ENCODE_QUEUE
static uint64_t ff_vk_extensions_to_mask(const char *const *extensions, int nb_extensions)
static int ff_vk_load_functions(AVHWDeviceContext *ctx, FFVulkanFunctions *vk, uint64_t extensions_mask, int has_inst, int has_dev)
Function loader.
VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth)
Get Vulkan's bit depth from an [8:12] integer.
VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc)
Get Vulkan's chroma subsampling from a pixfmt descriptor.
int ff_vk_create_view(FFVulkanContext *s, VkImageView *view, VkImageAspectFlags *aspect, VkImage img, VkFormat vkf, VkImageUsageFlags usage, int layered)
Creates image views for video frames.
av_cold void ff_vk_video_common_uninit(FFVulkanContext *s, FFVkVideoCommon *common)
Free video session and required resources.
av_cold int ff_vk_video_dpb_init(FFVulkanContext *s, FFVkVideoCommon *common, VkFormat format, VkImageUsageFlags usage, VkImageTiling tiling, void *create_pnext, int width, int height, int nb_layers)
Initialize the internal DPB image pool.
enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf)
Get pixfmt from a Vulkan format.
av_cold int ff_vk_video_common_init(AVCodecContext *avctx, FFVulkanContext *s, FFVkVideoCommon *common, VkVideoSessionCreateInfoKHR *session_create)
Initialize video session, allocating and binding necessary memory.
#define CODEC_VER(ver)