History

lavc: add an av1_vulkan encoder

This commit adds a Vulkan AV1 encoder, using the native acceleration API.

Lynne committed 1 year ago

Commit b2928971 parent 2caf23e9 files · +1477 −0Browse files

Showing the changes to libavcodec (5 of 9 files). Show all

Unified · Split

5 files
  1. libavcodec/Makefile +2 −0
  2. libavcodec/allcodecs.c +1 −0
  3. libavcodec/vulkan_encode_av1.c +1409 −0
  4. libavcodec/vulkan_video.c +41 −0
  5. libavcodec/vulkan_video.h +2 −0
libavcodec/Makefile+2−0
@@ -272,6 +272,8 @@ OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) += mediacodecenc.o · 271 unmodified lines
272272 OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o
273273 OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o
274274 OBJS-$(CONFIG_AV1_VAAPI_ENCODER) += vaapi_encode_av1.o av1_levels.o
275+OBJS-$(CONFIG_AV1_VULKAN_ENCODER) += vulkan_encode.o vulkan_encode_av1.o \
276+ hw_base_encode.o av1_levels.o
275277 OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o
276278 OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o
277279 OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o
libavcodec/allcodecs.c+1−0
@@ -853,6 +853,7 @@ extern const FFCodec ff_av1_amf_encoder; · 852 unmodified lines
853853 extern const FFCodec ff_av1_amf_decoder;
854854 extern const FFCodec ff_av1_mf_encoder;
855855 extern const FFCodec ff_av1_vaapi_encoder;
856+extern const FFCodec ff_av1_vulkan_encoder;
856857 extern const FFCodec ff_libopenh264_encoder;
857858 extern const FFCodec ff_libopenh264_decoder;
858859 extern const FFCodec ff_h264_amf_encoder;
libavcodec/vulkan_encode_av1.c+1409−0
@@ -0,0 +1,1409 @@
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/opt.h"
20+#include "libavutil/mem.h"
21+
22+#include "cbs.h"
23+#include "cbs_av1.h"
24+#include "av1_levels.h"
25+#include "libavutil/mastering_display_metadata.h"
26+
27+#include "codec_internal.h"
28+#include "vulkan_encode.h"
29+
30+#include "libavutil/avassert.h"
31+
32+const FFVulkanEncodeDescriptor ff_vk_enc_av1_desc = {
33+ .codec_id = AV_CODEC_ID_AV1,
34+ .encode_extension = FF_VK_EXT_VIDEO_ENCODE_AV1,
35+ .encode_op = VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR,
36+ .ext_props = {
37+ .extensionName = VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_EXTENSION_NAME,
38+ .specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_ENCODE_SPEC_VERSION,
39+ },
40+};
41+
42+enum UnitElems {
43+ UNIT_MASTERING_DISPLAY = 1 << 0,
44+ UNIT_CONTENT_LIGHT_LEVEL = 1 << 1,
45+};
46+
47+typedef struct VulkanEncodeAV1Picture {
48+ int slot;
49+ int64_t last_idr_frame;
50+
51+ enum UnitElems units_needed;
52+
53+ StdVideoAV1TileInfo tile_info;
54+ StdVideoAV1Quantization quantization;
55+ StdVideoAV1Segmentation segmentation;
56+ StdVideoAV1LoopFilter loop_filter;
57+ StdVideoAV1CDEF cdef;
58+ StdVideoAV1LoopRestoration loop_restoration;
59+ StdVideoAV1GlobalMotion global_motion;
60+
61+ StdVideoEncodeAV1PictureInfo av1pic_info;
62+ VkVideoEncodeAV1PictureInfoKHR vkav1pic_info;
63+
64+ StdVideoEncodeAV1ExtensionHeader ext_header;
65+ StdVideoEncodeAV1ReferenceInfo av1dpb_info;
66+ VkVideoEncodeAV1DpbSlotInfoKHR vkav1dpb_info;
67+
68+ VkVideoEncodeAV1RateControlInfoKHR vkrc_info;
69+ VkVideoEncodeAV1RateControlLayerInfoKHR vkrc_layer_info;
70+ VkVideoEncodeAV1GopRemainingFrameInfoKHR vkrc_remaining;
71+} VulkanEncodeAV1Picture;
72+
73+typedef struct VulkanEncodeAV1Context {
74+ FFVulkanEncodeContext common;
75+
76+ CodedBitstreamContext *cbs;
77+ CodedBitstreamFragment current_access_unit;
78+
79+ enum UnitElems unit_elems;
80+ AV1RawOBU seq_hdr_obu;
81+ AV1RawOBU meta_cll_obu;
82+ AV1RawOBU meta_mastering_obu;
83+
84+ VkVideoEncodeAV1ProfileInfoKHR profile;
85+
86+ VkVideoEncodeAV1CapabilitiesKHR caps;
87+ VkVideoEncodeAV1QualityLevelPropertiesKHR quality_props;
88+
89+ uint64_t hrd_buffer_size;
90+ uint64_t initial_buffer_fullness;
91+
92+ int uniform_tile;
93+ int tile_cols;
94+ int tile_rows;
95+
96+ int seq_tier;
97+ int seq_level_idx;
98+
99+ int q_idx_idr;
100+ int q_idx_p;
101+ int q_idx_b;
102+
103+ uint8_t *padding_payload;
104+} VulkanEncodeAV1Context;
105+
106+static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
107+ VkVideoEncodeRateControlInfoKHR *rc_info,
108+ VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
109+{
110+ VulkanEncodeAV1Context *enc = avctx->priv_data;
111+ FFVulkanEncodeContext *ctx = &enc->common;
112+ VulkanEncodeAV1Picture *ap = pic->codec_priv;
113+
114+ /* This can be easy to calculate */
115+ ap->vkrc_remaining = (VkVideoEncodeAV1GopRemainingFrameInfoKHR) {
116+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_GOP_REMAINING_FRAME_INFO_KHR,
117+ .useGopRemainingFrames = 0,
118+ .gopRemainingIntra = 0,
119+ .gopRemainingPredictive = 0,
120+ .gopRemainingBipredictive = 0,
121+ };
122+
123+ ap->vkrc_info = (VkVideoEncodeAV1RateControlInfoKHR) {
124+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_RATE_CONTROL_INFO_KHR,
125+ .flags = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
126+ VK_VIDEO_ENCODE_AV1_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
127+ .gopFrameCount = ctx->base.gop_size,
128+ .keyFramePeriod = ctx->base.gop_size,
129+ .consecutiveBipredictiveFrameCount = FFMAX(ctx->base.b_per_p - 1, 0),
130+ .temporalLayerCount = 0,
131+ };
132+ rc_info->pNext = &ap->vkrc_info;
133+
134+ if (rc_info->rateControlMode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
135+ rc_info->virtualBufferSizeInMs = (enc->hrd_buffer_size * 1000LL) / avctx->bit_rate;
136+ rc_info->initialVirtualBufferSizeInMs = (enc->initial_buffer_fullness * 1000LL) / avctx->bit_rate;
137+
138+ ap->vkrc_layer_info = (VkVideoEncodeAV1RateControlLayerInfoKHR) {
139+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_RATE_CONTROL_LAYER_INFO_KHR,
140+
141+ .useMinQIndex = avctx->qmin > 0,
142+ .minQIndex.intraQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
143+ .minQIndex.predictiveQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
144+ .minQIndex.bipredictiveQIndex = avctx->qmin > 0 ? avctx->qmin : 0,
145+
146+ .useMaxQIndex = avctx->qmax > 0,
147+ .maxQIndex.intraQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
148+ .maxQIndex.predictiveQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
149+ .maxQIndex.bipredictiveQIndex = avctx->qmax > 0 ? avctx->qmax : 0,
150+
151+ .useMaxFrameSize = 0,
152+ };
153+ rc_layer->pNext = &ap->vkrc_layer_info;
154+ ap->vkrc_info.temporalLayerCount = 1;
155+ }
156+
157+ return 0;
158+}
159+
160+static void set_name_slot(int slot, int *slot_indices, uint32_t allowed_idx, int group)
161+{
162+ int from = group ? AV1_REF_FRAME_GOLDEN : 0;
163+ int to = group ? AV1_REFS_PER_FRAME : AV1_REF_FRAME_GOLDEN;
164+
165+ for (int i = from; i < to; i++) {
166+ if ((slot_indices[i] == -1) && (allowed_idx & (1 << i))) {
167+ slot_indices[i] = slot;
168+ return;
169+ }
170+ }
171+
172+ av_assert0(0);
173+}
174+
175+
176+static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
177+ VkVideoEncodeInfoKHR *encode_info)
178+{
179+ VulkanEncodeAV1Context *enc = avctx->priv_data;
180+ FFVulkanEncodeContext *ctx = &enc->common;
181+ FFHWBaseEncodeContext *base_ctx = &ctx->base;
182+
183+ FFVulkanEncodePicture *vp = pic->priv;
184+ VulkanEncodeAV1Picture *ap = pic->codec_priv;
185+ FFHWBaseEncodePicture *ref;
186+ VulkanEncodeAV1Picture *ap_ref;
187+ VkVideoReferenceSlotInfoKHR *ref_slot;
188+
189+ AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
190+ AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
191+
192+ uint32_t ref_name_mask = 0x0;
193+ int name_slots[STD_VIDEO_AV1_REFS_PER_FRAME];
194+
195+ StdVideoAV1Segmentation *segmentation = &ap->segmentation;
196+ StdVideoAV1LoopFilter *loop_filter = &ap->loop_filter;
197+ StdVideoAV1Quantization *quantization = &ap->quantization;
198+ StdVideoAV1CDEF *cdef = &ap->cdef;
199+ StdVideoAV1LoopRestoration *loop_restoration = &ap->loop_restoration;
200+ StdVideoAV1GlobalMotion *global_motion = &ap->global_motion;
201+ StdVideoAV1TileInfo *tile_info = &ap->tile_info;
202+ static const int8_t default_loop_filter_ref_deltas[STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME] =
203+ { 1, 0, 0, 0, -1, 0, -1, -1 };
204+
205+ VkVideoEncodeAV1PredictionModeKHR pred_mode;
206+ VkVideoEncodeAV1RateControlGroupKHR rc_group;
207+ int lr_unit_shift = 0;
208+ int lr_uv_shift = 0;
209+
210+ ap->ext_header = (StdVideoEncodeAV1ExtensionHeader) {
211+ .temporal_id = 0,
212+ .spatial_id = 0,
213+ };
214+
215+ *tile_info = (StdVideoAV1TileInfo) {
216+ .flags = (StdVideoAV1TileInfoFlags) {
217+ .uniform_tile_spacing_flag = enc->uniform_tile,
218+ },
219+ .TileCols = enc->tile_cols,
220+ .TileRows = enc->tile_rows,
221+ .context_update_tile_id = 0,
222+ .tile_size_bytes_minus_1 = 0,
223+ };
224+
225+ for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME; i++) {
226+ global_motion->GmType[i] = 0;
227+ for (int j = 0; j < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS; j++) {
228+ global_motion->gm_params[i][j] = 0;
229+ }
230+ }
231+
232+ for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; i++)
233+ name_slots[i] = -1;
234+
235+ *loop_restoration = (StdVideoAV1LoopRestoration) {
236+ .FrameRestorationType[0] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
237+ .FrameRestorationType[1] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
238+ .FrameRestorationType[2] = STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
239+ .LoopRestorationSize[0] = 1 + lr_unit_shift,
240+ .LoopRestorationSize[1] = 1 + lr_unit_shift - lr_uv_shift,
241+ .LoopRestorationSize[2] = 1 + lr_unit_shift - lr_uv_shift,
242+ };
243+
244+ *cdef = (StdVideoAV1CDEF) {
245+ .cdef_damping_minus_3 = 0,
246+ .cdef_bits = 0,
247+ };
248+
249+ for (int i = 0; i < STD_VIDEO_AV1_MAX_SEGMENTS; i++) {
250+ segmentation->FeatureEnabled[i] = 0x0;
251+ for (int j = 0; j < STD_VIDEO_AV1_SEG_LVL_MAX; j++) {
252+ segmentation->FeatureEnabled[i] |= 0x0;
253+ segmentation->FeatureData[i][j] = 0;
254+ }
255+ }
256+
257+ *loop_filter = (StdVideoAV1LoopFilter) {
258+ .flags = (StdVideoAV1LoopFilterFlags) {
259+ .loop_filter_delta_enabled = 0,
260+ .loop_filter_delta_update = 0,
261+ },
262+ .loop_filter_level = { 0 },
263+ .loop_filter_sharpness = 0,
264+ .update_ref_delta = 0,
265+ .loop_filter_ref_deltas = { 0 },
266+ .update_mode_delta = 0,
267+ .loop_filter_mode_deltas = { 0 },
268+ };
269+ loop_filter->update_mode_delta = 1;
270+ memcpy(loop_filter->loop_filter_ref_deltas, default_loop_filter_ref_deltas,
271+ STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
272+
273+ *quantization = (StdVideoAV1Quantization) {
274+ .flags = (StdVideoAV1QuantizationFlags) {
275+ .using_qmatrix = 0,
276+ .diff_uv_delta = 0,
277+ /* Reserved */
278+ },
279+ .base_q_idx = 0, /* Set later */
280+ .DeltaQYDc = 0,
281+ .DeltaQUDc = 0,
282+ .DeltaQUAc = 0,
283+ .DeltaQVDc = 0,
284+ .DeltaQVAc = 0,
285+ .qm_y = 0,
286+ .qm_u = 0,
287+ .qm_v = 0,
288+ };
289+
290+ ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
291+ ap->av1pic_info = (StdVideoEncodeAV1PictureInfo) {
292+ .flags = (StdVideoEncodeAV1PictureInfoFlags) {
293+ .error_resilient_mode = (pic->type == FF_HW_PICTURE_TYPE_I ||
294+ pic->type == FF_HW_PICTURE_TYPE_IDR) &&
295+ (pic->display_order <= pic->encode_order),
296+ .disable_cdf_update = 0,
297+ .use_superres = 0,
298+ .render_and_frame_size_different = 0,
299+ .allow_screen_content_tools = 0,
300+ .is_filter_switchable = 0,
301+ .force_integer_mv = 0,
302+ .frame_size_override_flag = 0,
303+ .buffer_removal_time_present_flag = 0,
304+ .allow_intrabc = 0,
305+ .frame_refs_short_signaling = 0,
306+ .allow_high_precision_mv = 0,
307+ .is_motion_mode_switchable = 0,
308+ .use_ref_frame_mvs = 0,
309+ .disable_frame_end_update_cdf = 0,
310+ .allow_warped_motion = 0,
311+ .reduced_tx_set = 0,
312+ .skip_mode_present = 0,
313+ .delta_q_present = 0,
314+ .delta_lf_present = 0,
315+ .delta_lf_multi = 0,
316+ .segmentation_enabled = 0,
317+ .segmentation_update_map = 0,
318+ .segmentation_temporal_update = 0,
319+ .segmentation_update_data = 0,
320+ .UsesLr = 0,
321+ .usesChromaLr = 0,
322+ .show_frame = pic->display_order <= pic->encode_order,
323+ .showable_frame = 0,
324+ /* Reserved */
325+ },
326+ .frame_type = 0, // set later
327+ .frame_presentation_time = 0,
328+ .current_frame_id = ref_slot->slotIndex,
329+ .order_hint = 0, // set later
330+ .primary_ref_frame = 0, // set later
331+ .refresh_frame_flags = 0x0, // set later
332+ .coded_denom = 0,
333+ .render_width_minus_1 = base_ctx->surface_width - 1,
334+ .render_height_minus_1 = base_ctx->surface_height - 1,
335+ .interpolation_filter = 0,
336+ .TxMode = STD_VIDEO_AV1_TX_MODE_SELECT,
337+ .delta_q_res = 0,
338+ .delta_lf_res = 0,
339+ .ref_order_hint = { 0 }, // set later
340+ .ref_frame_idx = { 0 }, // set later
341+ /* Reserved */
342+ .delta_frame_id_minus_1 = { 0 },
343+
344+// .pTileInfo = tile_info, TODO FIX
345+ .pQuantization = quantization,
346+ .pSegmentation = segmentation,
347+ .pLoopFilter = loop_filter,
348+ .pCDEF = cdef,
349+ .pLoopRestoration = loop_restoration,
350+ .pGlobalMotion = global_motion,
351+ .pExtensionHeader = &ap->ext_header,
352+ .pBufferRemovalTimes = NULL,
353+ };
354+
355+ switch (pic->type) {
356+ case FF_HW_PICTURE_TYPE_I:
357+ case FF_HW_PICTURE_TYPE_IDR:
358+ av_assert0(pic->nb_refs[0] == 0 || pic->nb_refs[1]);
359+ ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_KEY;
360+ ap->av1pic_info.refresh_frame_flags = 0xFF;
361+ quantization->base_q_idx = enc->q_idx_idr;
362+ ap->slot = 0;
363+ ap->last_idr_frame = pic->display_order;
364+ pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_INTRA_ONLY_KHR;
365+ rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_INTRA_KHR;
366+ break;
367+ case FF_HW_PICTURE_TYPE_P:
368+ ref = pic->refs[0][pic->nb_refs[0] - 1];
369+ ap_ref = ref->codec_priv;
370+
371+ ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_INTER;
372+ quantization->base_q_idx = enc->q_idx_p;
373+
374+ ap->last_idr_frame = ap_ref->last_idr_frame;
375+ ap->slot = !ap_ref->slot;
376+
377+ ap->av1pic_info.refresh_frame_flags = 1 << ap->slot;
378+
379+ /** set the nearest frame in L0 as all reference frame. */
380+ for (int i = 0; i < AV1_REFS_PER_FRAME; i++)
381+ ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
382+
383+ ap->av1pic_info.primary_ref_frame = ap_ref->slot;
384+ ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
385+ rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_PREDICTIVE_KHR;
386+ pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_SINGLE_REFERENCE_KHR;
387+ ref_name_mask = enc->caps.singleReferenceNameMask;
388+ set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
389+
390+// vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
391+
392+ /** set the 2nd nearest frame in L0 as Golden frame. */
393+ if ((pic->nb_refs[0] > 1) &&
394+ ((enc->caps.maxSingleReferenceCount > 1) ||
395+ (enc->caps.maxUnidirectionalCompoundReferenceCount > 0))) {
396+ if (enc->caps.maxUnidirectionalCompoundReferenceCount) {
397+ pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_UNIDIRECTIONAL_COMPOUND_KHR;
398+ ref_name_mask = enc->caps.unidirectionalCompoundReferenceNameMask;
399+ }
400+ ref = pic->refs[0][pic->nb_refs[0] - 2];
401+ ap_ref = ref->codec_priv;
402+ ap->av1pic_info.ref_frame_idx[3] = ap_ref->slot;
403+ ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
404+// vpic->ref_frame_ctrl_l0.fields.search_idx1 = AV1_REF_FRAME_GOLDEN;
405+ set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
406+ }
407+ break;
408+ case FF_HW_PICTURE_TYPE_B:
409+ ap->av1pic_info.frame_type = STD_VIDEO_AV1_FRAME_TYPE_INTER;
410+ quantization->base_q_idx = enc->q_idx_b;
411+ ap->av1pic_info.refresh_frame_flags = 0x0;
412+
413+ rc_group = VK_VIDEO_ENCODE_AV1_RATE_CONTROL_GROUP_BIPREDICTIVE_KHR;
414+ pred_mode = VK_VIDEO_ENCODE_AV1_PREDICTION_MODE_BIDIRECTIONAL_COMPOUND_KHR;
415+ ref_name_mask = enc->caps.bidirectionalCompoundReferenceNameMask;
416+
417+// fh->reference_select = 1;
418+ /** B frame will not be referenced, disable its recon frame. */
419+// vpic->picture_flags.bits.disable_frame_recon = 1;
420+
421+ /** Use LAST_FRAME and BWDREF_FRAME for reference. */
422+// vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
423+// vpic->ref_frame_ctrl_l1.fields.search_idx0 = AV1_REF_FRAME_BWDREF;
424+
425+ ref = pic->refs[0][pic->nb_refs[0] - 1];
426+ ap_ref = ref->codec_priv;
427+ ap->last_idr_frame = ap_ref->last_idr_frame;
428+ ap->av1pic_info.primary_ref_frame = ap_ref->slot;
429+ ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
430+ for (int i = 0; i < AV1_REF_FRAME_GOLDEN; i++)
431+ ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
432+ set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 0);
433+
434+ ref = pic->refs[1][pic->nb_refs[1] - 1];
435+ ap_ref = ref->codec_priv;
436+ ap->av1pic_info.ref_order_hint[ap_ref->slot] = ref->display_order - ap_ref->last_idr_frame;
437+ for (int i = AV1_REF_FRAME_GOLDEN; i < AV1_REFS_PER_FRAME; i++)
438+ ap->av1pic_info.ref_frame_idx[i] = ap_ref->slot;
439+ set_name_slot(ap_ref->av1pic_info.current_frame_id, name_slots, ref_name_mask, 1);
440+ break;
441+ }
442+
443+ ap->av1pic_info.flags.showable_frame = ap->av1pic_info.frame_type != STD_VIDEO_AV1_FRAME_TYPE_KEY;
444+ ap->av1pic_info.order_hint = pic->display_order - ap->last_idr_frame;
445+
446+ ap->vkav1pic_info = (VkVideoEncodeAV1PictureInfoKHR) {
447+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_PICTURE_INFO_KHR,
448+ .pNext = NULL,
449+ .predictionMode = pred_mode,
450+ .rateControlGroup = rc_group,
451+ .constantQIndex = quantization->base_q_idx,
452+ .pStdPictureInfo = &ap->av1pic_info,
453+ // .referenceNameSlotIndices is set below
454+ .primaryReferenceCdfOnly = 0,
455+ .generateObuExtensionHeader = 0,
456+ };
457+ encode_info->pNext = &ap->vkav1pic_info;
458+
459+ for (int i = 0; i < FF_ARRAY_ELEMS(ap->vkav1pic_info.referenceNameSlotIndices); i++)
460+ ap->vkav1pic_info.referenceNameSlotIndices[i] = name_slots[i];
461+
462+ ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
463+ ref_slot->pNext = &ap->vkav1dpb_info;
464+
465+ ap->av1dpb_info = (StdVideoEncodeAV1ReferenceInfo) {
466+ .flags = (StdVideoEncodeAV1ReferenceInfoFlags) {
467+ .disable_frame_end_update_cdf = 0,
468+ .segmentation_enabled = 0,
469+ /* Reserved */
470+ },
471+ .RefFrameId = ref_slot->slotIndex,
472+ .frame_type = ap->av1pic_info.frame_type,
473+ .OrderHint = pic->display_order - ap->last_idr_frame,
474+ /* Reserved */
475+ .pExtensionHeader = &ap->ext_header,
476+ };
477+
478+ ap->vkav1dpb_info = (VkVideoEncodeAV1DpbSlotInfoKHR) {
479+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_DPB_SLOT_INFO_KHR,
480+ .pStdReferenceInfo = &ap->av1dpb_info,
481+ };
482+
483+ ap->units_needed = 0;
484+ if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
485+ AVFrameSideData *sd = NULL;
486+ if (enc->unit_elems & UNIT_MASTERING_DISPLAY)
487+ sd = av_frame_get_side_data(pic->input_image,
488+ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
489+ if (sd) {
490+ AVMasteringDisplayMetadata *mdm =
491+ (AVMasteringDisplayMetadata *)sd->data;
492+ if (mdm->has_primaries && mdm->has_luminance) {
493+ AV1RawOBU *obu = &enc->meta_mastering_obu;
494+ AV1RawMetadata *md = &obu->obu.metadata;
495+ AV1RawMetadataHDRMDCV *mdcv = &md->metadata.hdr_mdcv;
496+ const int chroma_den = 1 << 16;
497+ const int max_luma_den = 1 << 8;
498+ const int min_luma_den = 1 << 14;
499+
500+ memset(obu, 0, sizeof(*obu));
501+ obu->header.obu_type = AV1_OBU_METADATA;
502+ md->metadata_type = AV1_METADATA_TYPE_HDR_MDCV;
503+
504+ for (int i = 0; i < 3; i++) {
505+ mdcv->primary_chromaticity_x[i] =
506+ av_rescale(mdm->display_primaries[i][0].num, chroma_den,
507+ mdm->display_primaries[i][0].den);
508+ mdcv->primary_chromaticity_y[i] =
509+ av_rescale(mdm->display_primaries[i][1].num, chroma_den,
510+ mdm->display_primaries[i][1].den);
511+ }
512+
513+ mdcv->white_point_chromaticity_x =
514+ av_rescale(mdm->white_point[0].num, chroma_den,
515+ mdm->white_point[0].den);
516+ mdcv->white_point_chromaticity_y =
517+ av_rescale(mdm->white_point[1].num, chroma_den,
518+ mdm->white_point[1].den);
519+
520+ mdcv->luminance_max =
521+ av_rescale(mdm->max_luminance.num, max_luma_den,
522+ mdm->max_luminance.den);
523+ mdcv->luminance_min =
524+ av_rescale(mdm->min_luminance.num, min_luma_den,
525+ mdm->min_luminance.den);
526+ ap->units_needed |= UNIT_MASTERING_DISPLAY;
527+ }
528+ }
529+
530+ if (enc->unit_elems & UNIT_CONTENT_LIGHT_LEVEL)
531+ sd = av_frame_get_side_data(pic->input_image,
532+ AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
533+ if (sd) {
534+ AVContentLightMetadata *cllm = (AVContentLightMetadata *)sd->data;
535+ AV1RawOBU *obu = &enc->meta_cll_obu;
536+ AV1RawMetadata *md = &obu->obu.metadata;
537+ AV1RawMetadataHDRCLL *cll = &md->metadata.hdr_cll;
538+
539+ memset(obu, 0, sizeof(*obu));
540+ obu->header.obu_type = AV1_OBU_METADATA;
541+ md->metadata_type = AV1_METADATA_TYPE_HDR_CLL;
542+ cll->max_cll = cllm->MaxCLL;
543+ cll->max_fall = cllm->MaxFALL;
544+
545+ ap->units_needed |= UNIT_CONTENT_LIGHT_LEVEL;
546+ }
547+ }
548+
549+ return 0;
550+}
551+
552+static int init_profile(AVCodecContext *avctx,
553+ VkVideoProfileInfoKHR *profile, void *pnext)
554+{
555+ VkResult ret;
556+ VulkanEncodeAV1Context *enc = avctx->priv_data;
557+ FFVulkanEncodeContext *ctx = &enc->common;
558+ FFVulkanContext *s = &ctx->s;
559+ FFVulkanFunctions *vk = &ctx->s.vkfn;
560+ FFHWBaseEncodeContext *base_ctx = &ctx->base;
561+
562+ VkVideoEncodeAV1CapabilitiesKHR av1_caps = {
563+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_CAPABILITIES_KHR,
564+ };
565+ VkVideoEncodeCapabilitiesKHR enc_caps = {
566+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR,
567+ .pNext = &av1_caps,
568+ };
569+ VkVideoCapabilitiesKHR caps = {
570+ .sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR,
571+ .pNext = &enc_caps,
572+ };
573+
574+ /* In order of preference */
575+ int last_supported = AV_PROFILE_UNKNOWN;
576+ static const int known_profiles[] = {
577+ AV_PROFILE_AV1_MAIN,
578+ AV_PROFILE_AV1_HIGH,
579+ AV_PROFILE_AV1_PROFESSIONAL,
580+ };
581+ int nb_profiles = FF_ARRAY_ELEMS(known_profiles);
582+
583+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
584+ if (!desc)
585+ return AVERROR(EINVAL);
586+
587+ if (s->frames->sw_format == AV_PIX_FMT_NV12 ||
588+ s->frames->sw_format == AV_PIX_FMT_P010)
589+ nb_profiles = 1;
590+
591+ enc->profile = (VkVideoEncodeAV1ProfileInfoKHR) {
592+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_PROFILE_INFO_KHR,
593+ .pNext = pnext,
594+ .stdProfile = ff_vk_av1_profile_to_vk(avctx->profile),
595+ };
596+ profile->pNext = &enc->profile;
597+
598+ /* Set level */
599+ if (avctx->level == AV_LEVEL_UNKNOWN) {
600+ const AV1LevelDescriptor *level;
601+ float framerate;
602+
603+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
604+ framerate = avctx->framerate.num / avctx->framerate.den;
605+ else
606+ framerate = 0;
607+ level = ff_av1_guess_level(avctx->bit_rate, enc->seq_tier,
608+ base_ctx->surface_width, base_ctx->surface_height,
609+ enc->tile_rows * enc->tile_cols,
610+ enc->tile_cols, framerate);
611+ if (level) {
612+ av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
613+ enc->seq_level_idx = ff_vk_av1_level_to_vk(level->level_idx);
614+ } else {
615+ av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
616+ "any normal level, using level 7.3 by default.\n");
617+ enc->seq_level_idx = STD_VIDEO_AV1_LEVEL_7_3;
618+ enc->seq_tier = 1;
619+ }
620+ } else {
621+ enc->seq_level_idx = ff_vk_av1_level_to_vk(avctx->level);
622+ }
623+
624+ /* User has explicitly specified a profile. */
625+ if (avctx->profile != AV_PROFILE_UNKNOWN)
626+ return 0;
627+
628+ av_log(avctx, AV_LOG_DEBUG, "Supported profiles:\n");
629+ for (int i = 0; i < nb_profiles; i++) {
630+ enc->profile.stdProfile = ff_vk_av1_profile_to_vk(known_profiles[i]);
631+ ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
632+ profile,
633+ &caps);
634+ if (ret == VK_SUCCESS) {
635+ av_log(avctx, AV_LOG_DEBUG, " %s\n",
636+ avcodec_profile_name(avctx->codec_id, known_profiles[i]));
637+ last_supported = known_profiles[i];
638+ }
639+ }
640+
641+ if (last_supported == AV_PROFILE_UNKNOWN) {
642+ av_log(avctx, AV_LOG_ERROR, "No supported profiles for given format\n");
643+ return AVERROR(ENOTSUP);
644+ }
645+
646+ enc->profile.stdProfile = ff_vk_av1_profile_to_vk(last_supported);
647+ av_log(avctx, AV_LOG_VERBOSE, "Using profile %s\n",
648+ avcodec_profile_name(avctx->codec_id, last_supported));
649+ avctx->profile = last_supported;
650+
651+ return 0;
652+}
653+
654+static int init_enc_options(AVCodecContext *avctx)
655+{
656+ VulkanEncodeAV1Context *enc = avctx->priv_data;
657+
658+ if (avctx->rc_buffer_size)
659+ enc->hrd_buffer_size = avctx->rc_buffer_size;
660+ else if (avctx->rc_max_rate > 0)
661+ enc->hrd_buffer_size = avctx->rc_max_rate;
662+ else
663+ enc->hrd_buffer_size = avctx->bit_rate;
664+
665+ if (avctx->rc_initial_buffer_occupancy) {
666+ if (avctx->rc_initial_buffer_occupancy > enc->hrd_buffer_size) {
667+ av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
668+ "must have initial buffer size (%d) <= "
669+ "buffer size (%"PRId64").\n",
670+ avctx->rc_initial_buffer_occupancy, enc->hrd_buffer_size);
671+ return AVERROR(EINVAL);
672+ }
673+ enc->initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
674+ } else {
675+ enc->initial_buffer_fullness = enc->hrd_buffer_size * 3 / 4;
676+ }
677+
678+ if (enc->common.opts.rc_mode == VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR &&
679+ avctx->global_quality) {
680+ enc->q_idx_p = av_clip_intp2(avctx->global_quality / FF_QP2LAMBDA, 8);
681+ if (fabs(avctx->i_quant_factor) > 0.0)
682+ enc->q_idx_idr =
683+ av_clip((fabs(avctx->i_quant_factor) * enc->q_idx_p +
684+ avctx->i_quant_offset) + 0.5,
685+ 0, 255);
686+ else
687+ enc->q_idx_idr = enc->q_idx_p;
688+
689+ if (fabs(avctx->b_quant_factor) > 0.0)
690+ enc->q_idx_b =
691+ av_clip((fabs(avctx->b_quant_factor) * enc->q_idx_p +
692+ avctx->b_quant_offset) + 0.5,
693+ 0, 255);
694+ else
695+ enc->q_idx_b = enc->q_idx_p;
696+ } else {
697+ /** Arbitrary value */
698+ enc->q_idx_idr = enc->q_idx_p = enc->q_idx_b = 128;
699+ }
700+
701+ return 0;
702+}
703+
704+static av_cold int init_sequence_headers(AVCodecContext *avctx)
705+{
706+ int err;
707+ VulkanEncodeAV1Context *enc = avctx->priv_data;
708+ FFVulkanEncodeContext *ctx = &enc->common;
709+ FFVulkanContext *s = &ctx->s;
710+ FFHWBaseEncodeContext *base_ctx = &ctx->base;
711+
712+ AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
713+ AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
714+
715+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
716+ if (!desc)
717+ return AVERROR(EINVAL);
718+
719+ seq_obu->header.obu_type = AV1_OBU_SEQUENCE_HEADER;
720+ *seq = (AV1RawSequenceHeader) {
721+ .seq_profile = avctx->profile,
722+ .seq_force_integer_mv = seq->seq_force_screen_content_tools ?
723+ AV1_SELECT_SCREEN_CONTENT_TOOLS :
724+ AV1_SELECT_INTEGER_MV,
725+ .frame_width_bits_minus_1 = av_log2(base_ctx->surface_width),
726+ .frame_height_bits_minus_1 = av_log2(base_ctx->surface_height),
727+ .max_frame_width_minus_1 = base_ctx->surface_width - 1,
728+ .max_frame_height_minus_1 = base_ctx->surface_height - 1,
729+ .enable_order_hint = 1,
730+ .order_hint_bits_minus_1 = av_clip_intp2(av_log2(ctx->base.gop_size), 3),
731+ .use_128x128_superblock = !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR),
732+ .color_config = (AV1RawColorConfig) {
733+ .high_bitdepth = desc->comp[0].depth > 8,
734+ .color_primaries = avctx->color_primaries,
735+ .transfer_characteristics = avctx->color_trc,
736+ .matrix_coefficients = avctx->colorspace,
737+ .color_description_present_flag = (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
738+ avctx->color_trc != AVCOL_TRC_UNSPECIFIED ||
739+ avctx->colorspace != AVCOL_SPC_UNSPECIFIED),
740+ .subsampling_x = desc->log2_chroma_w,
741+ .subsampling_y = desc->log2_chroma_h,
742+ .chroma_sample_position = avctx->chroma_sample_location == AVCHROMA_LOC_LEFT ?
743+ AV1_CSP_VERTICAL :
744+ avctx->chroma_sample_location == AVCHROMA_LOC_TOPLEFT ?
745+ AV1_CSP_COLOCATED :
746+ AV1_CSP_UNKNOWN,
747+ },
748+
749+ /* Operating point */
750+ .seq_tier = { enc->seq_tier },
751+ .seq_level_idx = { enc->seq_level_idx },
752+ .decoder_buffer_delay = { base_ctx->decode_delay },
753+ .encoder_buffer_delay = { base_ctx->output_delay },
754+ .operating_points_cnt_minus_1 = 1 - 1,
755+ };
756+
757+ return 0;
758+}
759+
760+typedef struct VulkanAV1Units {
761+ StdVideoAV1SequenceHeader seq_hdr;
762+ StdVideoAV1TimingInfo timing_info;
763+ StdVideoAV1ColorConfig color_config;
764+
765+ StdVideoEncodeAV1DecoderModelInfo decoder_model;
766+ StdVideoEncodeAV1OperatingPointInfo operating_points[AV1_MAX_OPERATING_POINTS];
767+ int nb_operating_points;
768+} VulkanAV1Units;
769+
770+static av_cold int base_unit_to_vk(AVCodecContext *avctx, VulkanAV1Units *vk_units)
771+{
772+ VulkanEncodeAV1Context *enc = avctx->priv_data;
773+
774+ AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
775+ AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
776+
777+ StdVideoAV1SequenceHeader *seq_hdr = &vk_units->seq_hdr;
778+ StdVideoAV1TimingInfo *timing_info = &vk_units->timing_info;
779+ StdVideoAV1ColorConfig *color_config = &vk_units->color_config;
780+
781+ StdVideoEncodeAV1OperatingPointInfo *operating_points = vk_units->operating_points;
782+
783+ *timing_info = (StdVideoAV1TimingInfo) {
784+ .flags = (StdVideoAV1TimingInfoFlags) {
785+ .equal_picture_interval = seq->timing_info.equal_picture_interval,
786+ },
787+ .num_units_in_display_tick = seq->timing_info.num_units_in_display_tick,
788+ .time_scale = seq->timing_info.time_scale,
789+ .num_ticks_per_picture_minus_1 = seq->timing_info.num_ticks_per_picture_minus_1,
790+ };
791+
792+ *color_config = (StdVideoAV1ColorConfig) {
793+ .flags = (StdVideoAV1ColorConfigFlags) {
794+ .mono_chrome = seq->color_config.mono_chrome,
795+ .color_range = seq->color_config.color_range,
796+ .separate_uv_delta_q = seq->color_config.separate_uv_delta_q,
797+ },
798+ .BitDepth = seq->color_config.twelve_bit ? 12 :
799+ seq->color_config.high_bitdepth ? 10 : 8,
800+ .subsampling_x = seq->color_config.subsampling_x,
801+ .subsampling_y = seq->color_config.subsampling_y,
802+ .color_primaries = seq->color_config.color_primaries,
803+ .transfer_characteristics = seq->color_config.transfer_characteristics,
804+ .matrix_coefficients = seq->color_config.matrix_coefficients,
805+ };
806+
807+ *seq_hdr = (StdVideoAV1SequenceHeader) {
808+ .flags = (StdVideoAV1SequenceHeaderFlags) {
809+ .still_picture = seq->still_picture,
810+ .reduced_still_picture_header = seq->reduced_still_picture_header,
811+ .use_128x128_superblock = seq->use_128x128_superblock,
812+ .enable_filter_intra = seq->enable_filter_intra,
813+ .enable_intra_edge_filter = seq->enable_intra_edge_filter,
814+ .enable_interintra_compound = seq->enable_interintra_compound,
815+ .enable_masked_compound = seq->enable_masked_compound,
816+ .enable_warped_motion = seq->enable_warped_motion,
817+ .enable_dual_filter = seq->enable_dual_filter,
818+ .enable_order_hint = seq->enable_order_hint,
819+ .enable_jnt_comp = seq->enable_jnt_comp,
820+ .enable_ref_frame_mvs = seq->enable_ref_frame_mvs,
821+ .frame_id_numbers_present_flag = seq->frame_id_numbers_present_flag,
822+ .enable_superres = seq->enable_superres,
823+ .enable_cdef = seq->enable_cdef,
824+ .enable_restoration = seq->enable_restoration,
825+ .film_grain_params_present = seq->film_grain_params_present,
826+ .timing_info_present_flag = seq->timing_info_present_flag,
827+ .initial_display_delay_present_flag = seq->initial_display_delay_present_flag,
828+ },
829+ .seq_profile = seq->seq_profile,
830+ .frame_width_bits_minus_1 = seq->frame_width_bits_minus_1,
831+ .frame_height_bits_minus_1 = seq->frame_height_bits_minus_1,
832+ .max_frame_width_minus_1 = seq->max_frame_width_minus_1,
833+ .max_frame_height_minus_1 = seq->max_frame_height_minus_1,
834+ .delta_frame_id_length_minus_2 = seq->delta_frame_id_length_minus_2,
835+ .additional_frame_id_length_minus_1 = seq->additional_frame_id_length_minus_1,
836+ .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1,
837+ .seq_force_integer_mv = seq->seq_force_integer_mv,
838+ .seq_force_screen_content_tools = seq->seq_force_screen_content_tools,
839+ .pTimingInfo = timing_info,
840+ .pColorConfig = color_config,
841+ };
842+
843+ for (int i = 0; i <= seq->operating_points_cnt_minus_1; i++) {
844+ operating_points[i] = (StdVideoEncodeAV1OperatingPointInfo) {
845+ .flags = (StdVideoEncodeAV1OperatingPointInfoFlags) {
846+ .decoder_model_present_for_this_op = seq->decoder_model_present_for_this_op[i],
847+ .low_delay_mode_flag = seq->low_delay_mode_flag[i],
848+ .initial_display_delay_present_for_this_op = seq->initial_display_delay_present_for_this_op[i],
849+ /* Reserved */
850+ },
851+ .operating_point_idc = seq->operating_point_idc[i],
852+ .seq_level_idx = seq->seq_level_idx[i],
853+ .seq_tier = seq->seq_tier[i],
854+ .decoder_buffer_delay = seq->decoder_buffer_delay[i],
855+ .encoder_buffer_delay = seq->encoder_buffer_delay[i],
856+ .initial_display_delay_minus_1 = seq->initial_display_delay_minus_1[i],
857+ };
858+ }
859+ vk_units->nb_operating_points = seq->operating_points_cnt_minus_1 + 1;
860+
861+ return 0;
862+}
863+
864+static int create_session_params(AVCodecContext *avctx)
865+{
866+ int err;
867+ VulkanEncodeAV1Context *enc = avctx->priv_data;
868+ FFVulkanEncodeContext *ctx = &enc->common;
869+ FFVulkanContext *s = &ctx->s;
870+ FFVulkanFunctions *vk = &ctx->s.vkfn;
871+
872+ VulkanAV1Units vk_units = { 0 };
873+
874+ VkVideoEncodeAV1SessionParametersCreateInfoKHR av1_params;
875+
876+ /* Convert it to Vulkan */
877+ err = base_unit_to_vk(avctx, &vk_units);
878+ if (err < 0) {
879+ av_log(avctx, AV_LOG_ERROR, "Unable to convert sequence header to Vulkan: %s\n",
880+ av_err2str(err));
881+ return err;
882+ }
883+
884+ /* Destroy the session params */
885+ if (ctx->session_params)
886+ vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
887+ ctx->session_params,
888+ s->hwctx->alloc);
889+
890+ av1_params = (VkVideoEncodeAV1SessionParametersCreateInfoKHR) {
891+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
892+ .pStdSequenceHeader = &vk_units.seq_hdr,
893+ .pStdDecoderModelInfo = &vk_units.decoder_model,
894+ .pStdOperatingPoints = vk_units.operating_points,
895+ .stdOperatingPointCount = vk_units.nb_operating_points,
896+ };
897+
898+ return ff_vulkan_encode_create_session_params(avctx, ctx, &av1_params);
899+}
900+
901+static int parse_feedback_units(AVCodecContext *avctx,
902+ const uint8_t *data, size_t size)
903+{
904+ int err;
905+ VulkanEncodeAV1Context *enc = avctx->priv_data;
906+ AV1RawOBU *seq_obu = &enc->seq_hdr_obu;
907+ AV1RawSequenceHeader *seq = &seq_obu->obu.sequence_header;
908+
909+ CodedBitstreamContext *cbs;
910+ CodedBitstreamFragment obu = { 0 };
911+
912+ err = ff_cbs_init(&cbs, AV_CODEC_ID_AV1, avctx);
913+ if (err < 0)
914+ return err;
915+
916+ err = ff_cbs_read(cbs, &obu, NULL, data, size);
917+ if (err < 0) {
918+ av_log(avctx, AV_LOG_ERROR, "Unable to parse feedback units, bad drivers: %s\n",
919+ av_err2str(err));
920+ return err;
921+ }
922+
923+ /* If PPS has an override, just copy it entirely. */
924+ for (int i = 0; i < obu.nb_units; i++) {
925+ if (obu.units[i].type == AV1_OBU_SEQUENCE_HEADER) {
926+ AV1RawOBU *f_seq_obu = obu.units[i].content;
927+ AV1RawSequenceHeader *f_seq = &f_seq_obu->obu.sequence_header;
928+ seq->frame_width_bits_minus_1 = f_seq->frame_width_bits_minus_1;
929+ seq->frame_height_bits_minus_1 = f_seq->frame_height_bits_minus_1;
930+ seq->max_frame_width_minus_1 = f_seq->max_frame_width_minus_1;
931+ seq->max_frame_height_minus_1 = f_seq->max_frame_height_minus_1;
932+ seq->seq_choose_screen_content_tools = f_seq->seq_choose_screen_content_tools;
933+ seq->seq_force_screen_content_tools = f_seq->seq_force_screen_content_tools;
934+ seq->seq_choose_integer_mv = f_seq->seq_choose_integer_mv;
935+ seq->seq_force_integer_mv = f_seq->seq_force_integer_mv;
936+ }
937+ }
938+
939+ ff_cbs_fragment_free(&obu);
940+ ff_cbs_close(&cbs);
941+
942+ return 0;
943+}
944+
945+static int init_base_units(AVCodecContext *avctx)
946+{
947+ int err;
948+ VkResult ret;
949+ VulkanEncodeAV1Context *enc = avctx->priv_data;
950+ FFVulkanEncodeContext *ctx = &enc->common;
951+ FFVulkanContext *s = &ctx->s;
952+ FFVulkanFunctions *vk = &ctx->s.vkfn;
953+
954+ VkVideoEncodeSessionParametersGetInfoKHR params_info;
955+ VkVideoEncodeSessionParametersFeedbackInfoKHR params_feedback;
956+
957+ void *data = NULL;
958+ size_t data_size = 0;
959+
960+ /* Generate SPS/PPS unit info */
961+ err = init_sequence_headers(avctx);
962+ if (err < 0) {
963+ av_log(avctx, AV_LOG_ERROR, "Unable to initialize sequence header: %s\n",
964+ av_err2str(err));
965+ return err;
966+ }
967+
968+ /* Create session parameters from them */
969+ err = create_session_params(avctx);
970+ if (err < 0)
971+ return err;
972+
973+ params_info = (VkVideoEncodeSessionParametersGetInfoKHR) {
974+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR,
975+ .videoSessionParameters = ctx->session_params,
976+ };
977+ params_feedback = (VkVideoEncodeSessionParametersFeedbackInfoKHR) {
978+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
979+ };
980+
981+ ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
982+ &params_feedback,
983+ &data_size, data);
984+ if (ret == VK_INCOMPLETE ||
985+ (ret == VK_SUCCESS) && (data_size > 0)) {
986+ data = av_mallocz(data_size);
987+ if (!data)
988+ return AVERROR(ENOMEM);
989+ } else {
990+ av_log(avctx, AV_LOG_ERROR, "Unable to get feedback for AV1 sequence header = %lu\n",
991+ data_size);
992+ return err;
993+ }
994+
995+ ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
996+ &params_feedback,
997+ &data_size, data);
998+ if (ret != VK_SUCCESS) {
999+ av_log(avctx, AV_LOG_ERROR, "Error writing feedback units\n");
1000+ return err;
1001+ }
1002+
1003+ av_log(avctx, AV_LOG_VERBOSE, "Feedback units written, overrides: %i\n",
1004+ params_feedback.hasOverrides);
1005+
1006+ params_feedback.hasOverrides = 1;
1007+
1008+ /* No need to sync any overrides */
1009+ if (!params_feedback.hasOverrides)
1010+ return 0;
1011+
1012+ /* Parse back tne units and override */
1013+ err = parse_feedback_units(avctx, data, data_size);
1014+ if (err < 0)
1015+ return err;
1016+
1017+ /* Create final session parameters */
1018+ err = create_session_params(avctx);
1019+ if (err < 0)
1020+ return err;
1021+
1022+ return 0;
1023+}
1024+
1025+static int vulkan_encode_av1_add_obu(AVCodecContext *avctx,
1026+ CodedBitstreamFragment *au,
1027+ uint8_t type, void *obu_unit)
1028+{
1029+ int err;
1030+
1031+ err = ff_cbs_insert_unit_content(au, -1,
1032+ type, obu_unit, NULL);
1033+ if (err < 0) {
1034+ av_log(avctx, AV_LOG_ERROR, "Failed to add OBU unit: "
1035+ "type = %d.\n", type);
1036+ return err;
1037+ }
1038+
1039+ return err;
1040+}
1041+
1042+static int vulkan_encode_av1_write_obu(AVCodecContext *avctx,
1043+ uint8_t *data, size_t *data_len,
1044+ CodedBitstreamFragment *obu)
1045+{
1046+ VulkanEncodeAV1Context *enc = avctx->priv_data;
1047+ int ret;
1048+
1049+ ret = ff_cbs_write_fragment_data(enc->cbs, obu);
1050+ if (ret < 0) {
1051+ av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
1052+ return ret;
1053+ }
1054+
1055+ memcpy(data, obu->data, obu->data_size);
1056+ *data_len = obu->data_size;
1057+
1058+ return 0;
1059+}
1060+
1061+static int write_sequence_header(AVCodecContext *avctx,
1062+ FFHWBaseEncodePicture *base_pic,
1063+ uint8_t *data, size_t *data_len)
1064+{
1065+ int err;
1066+ VulkanEncodeAV1Context *enc = avctx->priv_data;
1067+ CodedBitstreamFragment *obu = &enc->current_access_unit;
1068+
1069+ err = vulkan_encode_av1_add_obu(avctx, obu,
1070+ AV1_OBU_SEQUENCE_HEADER, &enc->seq_hdr_obu);
1071+ if (err < 0)
1072+ goto fail;
1073+
1074+ err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
1075+
1076+fail:
1077+ ff_cbs_fragment_reset(obu);
1078+ return err;
1079+}
1080+
1081+static int write_extra_headers(AVCodecContext *avctx,
1082+ FFHWBaseEncodePicture *base_pic,
1083+ uint8_t *data, size_t *data_len)
1084+{
1085+ int err;
1086+ VulkanEncodeAV1Context *enc = avctx->priv_data;
1087+ VulkanEncodeAV1Picture *ap = base_pic->codec_priv;
1088+ CodedBitstreamFragment *obu = &enc->current_access_unit;
1089+
1090+ if (ap->units_needed & AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
1091+ err = vulkan_encode_av1_add_obu(avctx, obu,
1092+ AV1_OBU_METADATA,
1093+ &enc->meta_mastering_obu);
1094+ if (err < 0)
1095+ goto fail;
1096+ }
1097+
1098+ if (ap->units_needed & UNIT_CONTENT_LIGHT_LEVEL) {
1099+ err = vulkan_encode_av1_add_obu(avctx, obu,
1100+ AV1_OBU_METADATA,
1101+ &enc->meta_cll_obu);
1102+ if (err < 0)
1103+ goto fail;
1104+ }
1105+
1106+ if (ap->units_needed) {
1107+ err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
1108+ if (err < 0)
1109+ goto fail;
1110+ } else {
1111+ *data_len = 0;
1112+ }
1113+
1114+fail:
1115+ ff_cbs_fragment_reset(obu);
1116+ return err;
1117+}
1118+
1119+static int write_padding(AVCodecContext *avctx, uint32_t padding,
1120+ uint8_t *data, size_t *data_len)
1121+{
1122+ int err;
1123+ VulkanEncodeAV1Context *enc = avctx->priv_data;
1124+ CodedBitstreamFragment *obu = &enc->current_access_unit;
1125+
1126+ AV1RawOBU padding_obu = { 0 };
1127+ AV1RawPadding *raw_padding = &padding_obu.obu.padding;
1128+
1129+ if (!padding)
1130+ padding = 16;
1131+
1132+ /* 2 byte header + 1 byte trailing bits */
1133+ padding_obu.header.obu_type = AV1_OBU_PADDING;
1134+ *raw_padding = (AV1RawPadding) {
1135+ .payload = enc->padding_payload,
1136+ .payload_size = padding,
1137+ };
1138+
1139+ err = vulkan_encode_av1_add_obu(avctx, obu, AV1_OBU_PADDING, &padding_obu);
1140+ if (err < 0)
1141+ goto fail;
1142+
1143+ err = vulkan_encode_av1_write_obu(avctx, data, data_len, obu);
1144+fail:
1145+ ff_cbs_fragment_reset(obu);
1146+ return err;
1147+}
1148+
1149+static const FFVulkanCodec enc_cb = {
1150+ .flags = FF_HW_FLAG_B_PICTURES |
1151+ FF_HW_FLAG_B_PICTURE_REFERENCES |
1152+ VK_ENC_FLAG_NO_DELAY |
1153+ FF_HW_FLAG_SLICE_CONTROL,
1154+ .picture_priv_data_size = sizeof(VulkanEncodeAV1Picture),
1155+ .filler_header_size = 4,
1156+ .init_profile = init_profile,
1157+ .init_pic_rc = init_pic_rc,
1158+ .init_pic_params = init_pic_params,
1159+ .write_sequence_headers = write_sequence_header,
1160+ .write_extra_headers = write_extra_headers,
1161+ .write_filler = write_padding,
1162+};
1163+
1164+static av_cold int vulkan_encode_av1_init(AVCodecContext *avctx)
1165+{
1166+ int err;
1167+ VulkanEncodeAV1Context *enc = avctx->priv_data;
1168+ FFVulkanEncodeContext *ctx = &enc->common;
1169+ FFVulkanContext *s = &ctx->s;
1170+ FFHWBaseEncodeContext *base_ctx = &ctx->base;
1171+ int flags;
1172+
1173+ if (avctx->profile == AV_PROFILE_UNKNOWN)
1174+ avctx->profile = enc->common.opts.profile;
1175+
1176+ enc->caps = (VkVideoEncodeAV1CapabilitiesKHR) {
1177+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_CAPABILITIES_KHR,
1178+ };
1179+
1180+ enc->quality_props = (VkVideoEncodeAV1QualityLevelPropertiesKHR) {
1181+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_AV1_QUALITY_LEVEL_PROPERTIES_KHR,
1182+ };
1183+
1184+ err = ff_vulkan_encode_init(avctx, &enc->common,
1185+ &ff_vk_enc_av1_desc, &enc_cb,
1186+ &enc->caps, &enc->quality_props);
1187+ if (err < 0)
1188+ return err;
1189+
1190+ av_log(avctx, AV_LOG_VERBOSE, "AV1 encoder capabilities:\n");
1191+ av_log(avctx, AV_LOG_VERBOSE, " Standard capability flags:\n");
1192+ av_log(avctx, AV_LOG_VERBOSE, " per_rate_control_group_min_max_q_index: %i\n",
1193+ !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_PER_RATE_CONTROL_GROUP_MIN_MAX_Q_INDEX_BIT_KHR));
1194+ av_log(avctx, AV_LOG_VERBOSE, " generate_obu_extension_header: %i\n",
1195+ !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_GENERATE_OBU_EXTENSION_HEADER_BIT_KHR));
1196+ av_log(avctx, AV_LOG_VERBOSE, " primary_reference_cdf_only: %i\n",
1197+ !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_PRIMARY_REFERENCE_CDF_ONLY_BIT_KHR));
1198+ av_log(avctx, AV_LOG_VERBOSE, " frame_size_override: %i\n",
1199+ !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_FRAME_SIZE_OVERRIDE_BIT_KHR));
1200+ av_log(avctx, AV_LOG_VERBOSE, " motion_vector_scaling: %i\n",
1201+ !!(enc->caps.flags & VK_VIDEO_ENCODE_AV1_CAPABILITY_MOTION_VECTOR_SCALING_BIT_KHR));
1202+ av_log(avctx, AV_LOG_VERBOSE, " Capabilities:\n");
1203+ av_log(avctx, AV_LOG_VERBOSE, " 64x64 superblocks: %i\n",
1204+ !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_64_BIT_KHR));
1205+ av_log(avctx, AV_LOG_VERBOSE, " 128x128 superblocks: %i\n",
1206+ !!(enc->caps.superblockSizes & VK_VIDEO_ENCODE_AV1_SUPERBLOCK_SIZE_128_BIT_KHR));
1207+ av_log(avctx, AV_LOG_VERBOSE, " maxSingleReferenceCount: %i\n",
1208+ enc->caps.maxSingleReferenceCount);
1209+ av_log(avctx, AV_LOG_VERBOSE, " singleReferenceNameMask: 0x%x\n",
1210+ enc->caps.singleReferenceNameMask);
1211+ av_log(avctx, AV_LOG_VERBOSE, " maxUnidirectionalCompoundReferenceCount: %i\n",
1212+ enc->caps.maxUnidirectionalCompoundReferenceCount);
1213+ av_log(avctx, AV_LOG_VERBOSE, " maxUnidirectionalCompoundGroup1ReferenceCount: %i\n",
1214+ enc->caps.maxUnidirectionalCompoundGroup1ReferenceCount);
1215+ av_log(avctx, AV_LOG_VERBOSE, " unidirectionalCompoundReferenceNameMask: 0x%x\n",
1216+ enc->caps.unidirectionalCompoundReferenceNameMask);
1217+ av_log(avctx, AV_LOG_VERBOSE, " maxBidirectionalCompoundReferenceCount: %i\n",
1218+ enc->caps.maxBidirectionalCompoundReferenceCount);
1219+ av_log(avctx, AV_LOG_VERBOSE, " maxBidirectionalCompoundGroup1ReferenceCount: %i\n",
1220+ enc->caps.maxBidirectionalCompoundGroup1ReferenceCount);
1221+ av_log(avctx, AV_LOG_VERBOSE, " maxBidirectionalCompoundGroup2ReferenceCount: %i\n",
1222+ enc->caps.maxBidirectionalCompoundGroup2ReferenceCount);
1223+ av_log(avctx, AV_LOG_VERBOSE, " bidirectionalCompoundReferenceNameMask: 0x%x\n",
1224+ enc->caps.bidirectionalCompoundReferenceNameMask);
1225+ av_log(avctx, AV_LOG_VERBOSE, " maxTemporalLayerCount: %i\n",
1226+ enc->caps.maxTemporalLayerCount);
1227+ av_log(avctx, AV_LOG_VERBOSE, " maxSpatialLayerCount: %i\n",
1228+ enc->caps.maxSpatialLayerCount);
1229+ av_log(avctx, AV_LOG_VERBOSE, " maxOperatingPoints: %i\n",
1230+ enc->caps.maxOperatingPoints);
1231+ av_log(avctx, AV_LOG_VERBOSE, " min/max Qindex: [%i, %i]\n",
1232+ enc->caps.minQIndex, enc->caps.maxQIndex);
1233+ av_log(avctx, AV_LOG_VERBOSE, " prefersGopRemainingFrames: %i\n",
1234+ enc->caps.prefersGopRemainingFrames);
1235+ av_log(avctx, AV_LOG_VERBOSE, " requiresGopRemainingFrames: %i\n",
1236+ enc->caps.requiresGopRemainingFrames);
1237+ av_log(avctx, AV_LOG_VERBOSE, " maxLevel: %i\n",
1238+ enc->caps.maxLevel);
1239+ av_log(avctx, AV_LOG_VERBOSE, " codedPictureAlignment: %ix%i\n",
1240+ enc->caps.codedPictureAlignment.width, enc->caps.codedPictureAlignment.height);
1241+ av_log(avctx, AV_LOG_VERBOSE, " maxTiles: %ix%i\n",
1242+ enc->caps.maxTiles.width, enc->caps.maxTiles.height);
1243+ av_log(avctx, AV_LOG_VERBOSE, " Tile size: %ix%i to %ix%i\n",
1244+ enc->caps.minTileSize.width, enc->caps.minTileSize.height,
1245+ enc->caps.maxTileSize.width, enc->caps.maxTileSize.height);
1246+
1247+ err = init_enc_options(avctx);
1248+ if (err < 0)
1249+ return err;
1250+
1251+ flags = ctx->codec->flags;
1252+ err = ff_hw_base_init_gop_structure(base_ctx, avctx,
1253+ ctx->caps.maxDpbSlots,
1254+ enc->caps.maxBidirectionalCompoundReferenceCount,
1255+ flags, 0);
1256+ if (err < 0)
1257+ return err;
1258+
1259+ base_ctx->output_delay = base_ctx->b_per_p;
1260+ base_ctx->decode_delay = base_ctx->max_b_depth;
1261+
1262+ /* Create units and session parameters */
1263+ err = init_base_units(avctx);
1264+ if (err < 0)
1265+ return err;
1266+
1267+ /* Init CBS */
1268+ err = ff_cbs_init(&enc->cbs, AV_CODEC_ID_AV1, avctx);
1269+ if (err < 0)
1270+ return err;
1271+
1272+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
1273+ uint8_t data[4096];
1274+ size_t data_len = sizeof(data);
1275+
1276+ err = write_sequence_header(avctx, NULL, data, &data_len);
1277+ if (err < 0) {
1278+ av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
1279+ "for extradata: %d.\n", err);
1280+ return err;
1281+ } else {
1282+ avctx->extradata_size = data_len;
1283+ avctx->extradata = av_mallocz(avctx->extradata_size +
1284+ AV_INPUT_BUFFER_PADDING_SIZE);
1285+ if (!avctx->extradata) {
1286+ err = AVERROR(ENOMEM);
1287+ return err;
1288+ }
1289+ memcpy(avctx->extradata, data, avctx->extradata_size);
1290+ }
1291+ }
1292+
1293+ enc->padding_payload = av_mallocz(2*ctx->caps.minBitstreamBufferOffsetAlignment);
1294+ if (!enc->padding_payload)
1295+ return AVERROR(ENOMEM);
1296+
1297+ memset(enc->padding_payload, 0xaa, 2*ctx->caps.minBitstreamBufferOffsetAlignment);
1298+
1299+ return 0;
1300+}
1301+
1302+static av_cold int vulkan_encode_av1_close(AVCodecContext *avctx)
1303+{
1304+ VulkanEncodeAV1Context *enc = avctx->priv_data;
1305+ av_free(enc->padding_payload);
1306+ ff_vulkan_encode_uninit(&enc->common);
1307+ return 0;
1308+}
1309+
1310+#define OFFSET(x) offsetof(VulkanEncodeAV1Context, x)
1311+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1312+static const AVOption vulkan_encode_av1_options[] = {
1313+ HW_BASE_ENCODE_COMMON_OPTIONS,
1314+ VULKAN_ENCODE_COMMON_OPTIONS,
1315+
1316+ { "profile", "Set profile",
1317+ OFFSET(common.opts.profile), AV_OPT_TYPE_INT,
1318+ { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xffff, FLAGS, .unit = "profile" },
1319+
1320+#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1321+ { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
1322+ { PROFILE("main", AV_PROFILE_AV1_MAIN) },
1323+ { PROFILE("high", AV_PROFILE_AV1_HIGH) },
1324+ { PROFILE("professional", AV_PROFILE_AV1_PROFESSIONAL) },
1325+#undef PROFILE
1326+
1327+ { "tier", "Set tier (seq_tier)",
1328+ OFFSET(common.opts.tier), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "tier" },
1329+ { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, .unit = "tier" },
1330+ { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "tier" },
1331+
1332+ { "level", "Set level (level_idc)",
1333+ OFFSET(common.opts.level), AV_OPT_TYPE_INT,
1334+ { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, .unit = "level" },
1335+
1336+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1337+ { .i64 = value }, 0, 0, FLAGS, .unit = "level"
1338+ { LEVEL("20", 0) },
1339+ { LEVEL("21", 1) },
1340+ { LEVEL("22", 2) },
1341+ { LEVEL("23", 3) },
1342+ { LEVEL("30", 4) },
1343+ { LEVEL("31", 5) },
1344+ { LEVEL("32", 6) },
1345+ { LEVEL("33", 7) },
1346+ { LEVEL("40", 8) },
1347+ { LEVEL("41", 9) },
1348+ { LEVEL("42", 10) },
1349+ { LEVEL("43", 11) },
1350+ { LEVEL("50", 12) },
1351+ { LEVEL("51", 13) },
1352+ { LEVEL("52", 14) },
1353+ { LEVEL("53", 15) },
1354+ { LEVEL("60", 16) },
1355+ { LEVEL("61", 17) },
1356+ { LEVEL("62", 18) },
1357+ { LEVEL("63", 19) },
1358+ { LEVEL("70", 20) },
1359+ { LEVEL("71", 21) },
1360+ { LEVEL("72", 22) },
1361+ { LEVEL("73", 23) },
1362+#undef LEVEL
1363+
1364+ { "units", "Set units to include", OFFSET(unit_elems), AV_OPT_TYPE_FLAGS, { .i64 = UNIT_MASTERING_DISPLAY | UNIT_CONTENT_LIGHT_LEVEL }, 0, INT_MAX, FLAGS, "units" },
1365+ { "hdr", "Include HDR metadata for mastering display colour volume and content light level information", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_MASTERING_DISPLAY | UNIT_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "units" },
1366+
1367+ { NULL },
1368+};
1369+
1370+static const FFCodecDefault vulkan_encode_av1_defaults[] = {
1371+ { "b", "0" },
1372+ { "bf", "2" },
1373+ { "g", "300" },
1374+ { "qmin", "1" },
1375+ { "qmax", "255" },
1376+ { NULL },
1377+};
1378+
1379+static const AVClass vulkan_encode_av1_class = {
1380+ .class_name = "av1_vulkan",
1381+ .item_name = av_default_item_name,
1382+ .option = vulkan_encode_av1_options,
1383+ .version = LIBAVUTIL_VERSION_INT,
1384+};
1385+
1386+const FFCodec ff_av1_vulkan_encoder = {
1387+ .p.name = "av1_vulkan",
1388+ CODEC_LONG_NAME("AV1 (Vulkan)"),
1389+ .p.type = AVMEDIA_TYPE_VIDEO,
1390+ .p.id = AV_CODEC_ID_AV1,
1391+ .priv_data_size = sizeof(VulkanEncodeAV1Context),
1392+ .init = &vulkan_encode_av1_init,
1393+ FF_CODEC_RECEIVE_PACKET_CB(&ff_vulkan_encode_receive_packet),
1394+ .close = &vulkan_encode_av1_close,
1395+ .p.priv_class = &vulkan_encode_av1_class,
1396+ .p.capabilities = AV_CODEC_CAP_DELAY |
1397+ AV_CODEC_CAP_HARDWARE |
1398+ AV_CODEC_CAP_DR1 |
1399+ AV_CODEC_CAP_ENCODER_FLUSH |
1400+ AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
1401+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1402+ .defaults = vulkan_encode_av1_defaults,
1403+ .p.pix_fmts = (const enum AVPixelFormat[]) {
1404+ AV_PIX_FMT_VULKAN,
1405+ AV_PIX_FMT_NONE,
1406+ },
1407+ .hw_configs = ff_vulkan_encode_hw_configs,
1408+ .p.wrapper_name = "vulkan",
1409+};
libavcodec/vulkan_video.c+41−0
@@ -226,6 +226,37 @@ StdVideoH265LevelIdc ff_vk_h265_level_to_vk(int level_idc) · 225 unmodified lines
226226 }
227227 }
228228
229+StdVideoAV1Level ff_vk_av1_level_to_vk(int level)
230+{
231+ switch (level) {
232+ case 20: return STD_VIDEO_AV1_LEVEL_2_0;
233+ case 21: return STD_VIDEO_AV1_LEVEL_2_1;
234+ case 22: return STD_VIDEO_AV1_LEVEL_2_2;
235+ case 23: return STD_VIDEO_AV1_LEVEL_2_3;
236+ case 30: return STD_VIDEO_AV1_LEVEL_3_0;
237+ case 31: return STD_VIDEO_AV1_LEVEL_3_1;
238+ case 32: return STD_VIDEO_AV1_LEVEL_3_2;
239+ case 33: return STD_VIDEO_AV1_LEVEL_3_3;
240+ case 40: return STD_VIDEO_AV1_LEVEL_4_0;
241+ case 41: return STD_VIDEO_AV1_LEVEL_4_1;
242+ case 42: return STD_VIDEO_AV1_LEVEL_4_2;
243+ case 43: return STD_VIDEO_AV1_LEVEL_4_3;
244+ case 50: return STD_VIDEO_AV1_LEVEL_5_0;
245+ case 51: return STD_VIDEO_AV1_LEVEL_5_1;
246+ case 52: return STD_VIDEO_AV1_LEVEL_5_2;
247+ case 53: return STD_VIDEO_AV1_LEVEL_5_3;
248+ case 60: return STD_VIDEO_AV1_LEVEL_6_0;
249+ case 61: return STD_VIDEO_AV1_LEVEL_6_1;
250+ case 62: return STD_VIDEO_AV1_LEVEL_6_2;
251+ case 63: return STD_VIDEO_AV1_LEVEL_6_3;
252+ case 70: return STD_VIDEO_AV1_LEVEL_7_0;
253+ case 71: return STD_VIDEO_AV1_LEVEL_7_1;
254+ case 72: return STD_VIDEO_AV1_LEVEL_7_2;
255+ default:
256+ case 73: return STD_VIDEO_AV1_LEVEL_7_3;
257+ }
258+}
259+
229260 StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile)
230261 {
231262 switch (profile) {
@@ -247,6 +278,16 @@ StdVideoH265ProfileIdc ff_vk_h265_profile_to_vk(int profile) · 15 unmodified lines
247278 }
248279 }
249280
281+StdVideoAV1Profile ff_vk_av1_profile_to_vk(int profile)
282+{
283+ switch (profile) {
284+ case AV_PROFILE_AV1_MAIN: return STD_VIDEO_AV1_PROFILE_MAIN;
285+ case AV_PROFILE_AV1_HIGH: return STD_VIDEO_AV1_PROFILE_HIGH;
286+ case AV_PROFILE_AV1_PROFESSIONAL: return STD_VIDEO_AV1_PROFILE_PROFESSIONAL;
287+ default: return STD_VIDEO_AV1_PROFILE_INVALID;
288+ }
289+}
290+
250291 int ff_vk_create_view(FFVulkanContext *s, FFVkVideoCommon *common,
251292 VkImageView *view, VkImageAspectFlags *aspect,
252293 AVVkFrame *src, VkFormat vkf, int is_dpb)
libavcodec/vulkan_video.h+2−0
@@ -71,12 +71,14 @@ int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level); · 70 unmodified lines
7171
7272 StdVideoH264LevelIdc ff_vk_h264_level_to_vk(int level_idc);
7373 StdVideoH265LevelIdc ff_vk_h265_level_to_vk(int level_idc);
74+StdVideoAV1Level ff_vk_av1_level_to_vk(int level);
7475
7576 /**
7677 * Convert profile from/to AV to Vulkan
7778 */
7879 StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile);
7980 StdVideoH265ProfileIdc ff_vk_h265_profile_to_vk(int profile);
81+StdVideoAV1Profile ff_vk_av1_profile_to_vk(int profile);
8082
8183 /**
8284 * Creates image views for video frames.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t