History

lavc: add hevc_vulkan hardware encoder

This commit adds a Vulkan hardware HEVC encoder, with full support of the spec - I, P, and B-frames.

Lynne committed 2 years ago

Commit 4b4f0b61 parent b4283f97 files · +1860 −22Browse files

Unified · Split

7 files
  1. configure +1 −0
  2. libavcodec/Makefile +3 −0
  3. libavcodec/allcodecs.c +1 −0
  4. libavcodec/vulkan_encode_h265.c +1810 −0
  5. libavcodec/vulkan_hevc.c +3 −22
  6. libavcodec/vulkan_video.c +39 −0
  7. libavcodec/vulkan_video.h +3 −0
configure+1−0
@@ -3388,6 +3388,7 @@ hevc_rkmpp_decoder_deps="rkmpp" · 3387 unmodified lines
33883388 hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf"
33893389 hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC"
33903390 hevc_vaapi_encoder_select="atsc_a53 cbs_h265 vaapi_encode"
3391+hevc_vulkan_encoder_select="atsc_a53 cbs_h265 vulkan_encode"
33913392 hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m"
33923393 hevc_v4l2m2m_decoder_select="hevc_mp4toannexb_bsf"
33933394 hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m"
libavcodec/Makefile+3−0
@@ -452,6 +452,9 @@ OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc/ps_enc.o · 451 unmodified lines
452452 OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o
453453 OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o h265_profile_level.o \
454454 h2645data.o hw_base_encode_h265.o
455+OBJS-$(CONFIG_HEVC_VULKAN_ENCODER) += vulkan_encode.o vulkan_encode_h265.o \
456+ hw_base_encode.o hw_base_encode_h265.o \
457+ h265_profile_level.o h2645data.o
455458 OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o
456459 OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
457460 OBJS-$(CONFIG_HEVC_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
libavcodec/allcodecs.c+1−0
@@ -862,6 +862,7 @@ extern const FFCodec ff_hevc_qsv_encoder; · 861 unmodified lines
862862 extern const FFCodec ff_hevc_v4l2m2m_encoder;
863863 extern const FFCodec ff_hevc_vaapi_encoder;
864864 extern const FFCodec ff_hevc_videotoolbox_encoder;
865+extern const FFCodec ff_hevc_vulkan_encoder;
865866 extern const FFCodec ff_libkvazaar_encoder;
866867 extern const FFCodec ff_mjpeg_cuvid_decoder;
867868 extern const FFCodec ff_mjpeg_qsv_encoder;
libavcodec/vulkan_encode_h265.c+1810−0
@@ -0,0 +1,1810 @@
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_h265.h"
24+#include "atsc_a53.h"
25+#include "libavutil/mastering_display_metadata.h"
26+
27+#include "codec_internal.h"
28+#include "version.h"
29+#include "hw_base_encode_h265.h"
30+
31+#include "vulkan_encode.h"
32+
33+enum UnitElems {
34+ UNIT_AUD = 1 << 0,
35+ UNIT_SEI_MASTERING_DISPLAY = 1 << 1,
36+ UNIT_SEI_CONTENT_LIGHT_LEVEL = 1 << 2,
37+ UNIT_SEI_A53_CC = 1 << 3,
38+};
39+
40+const FFVulkanEncodeDescriptor ff_vk_enc_h265_desc = {
41+ .codec_id = AV_CODEC_ID_H265,
42+ .encode_extension = FF_VK_EXT_VIDEO_ENCODE_H265,
43+ .encode_op = VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR,
44+ .ext_props = {
45+ .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME,
46+ .specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION,
47+ },
48+};
49+
50+typedef struct VulkanEncodeH265Picture {
51+ int frame_num;
52+ int64_t last_idr_frame;
53+ uint16_t idr_pic_id;
54+ int primary_pic_type;
55+ int slice_type;
56+ int pic_order_cnt;
57+ int pic_type;
58+
59+ enum UnitElems units_needed;
60+
61+ VkVideoEncodeH265RateControlInfoKHR vkrc_info;
62+ VkVideoEncodeH265RateControlLayerInfoKHR vkrc_layer_info;
63+
64+ StdVideoEncodeH265PictureInfo h265pic_info;
65+ VkVideoEncodeH265PictureInfoKHR vkh265pic_info;
66+
67+ StdVideoEncodeH265WeightTable slice_wt;
68+ StdVideoEncodeH265SliceSegmentHeader slice_hdr;
69+ VkVideoEncodeH265NaluSliceSegmentInfoKHR vkslice;
70+
71+ StdVideoEncodeH265ReferenceInfo h265dpb_info;
72+ VkVideoEncodeH265DpbSlotInfoKHR vkh265dpb_info;
73+
74+ StdVideoEncodeH265ReferenceListsInfo ref_list_info;
75+ StdVideoEncodeH265LongTermRefPics l_rps;
76+ StdVideoH265ShortTermRefPicSet s_rps;
77+} VulkanEncodeH265Picture;
78+
79+typedef struct VulkanEncodeH265Context {
80+ FFVulkanEncodeContext common;
81+
82+ FFHWBaseEncodeH265 units;
83+ FFHWBaseEncodeH265Opts unit_opts;
84+
85+ enum UnitElems unit_elems;
86+
87+ uint8_t fixed_qp_idr;
88+ uint8_t fixed_qp_p;
89+ uint8_t fixed_qp_b;
90+
91+ uint64_t hrd_buffer_size;
92+ uint64_t initial_buffer_fullness;
93+
94+ VkVideoEncodeH265ProfileInfoKHR profile;
95+
96+ VkVideoEncodeH265CapabilitiesKHR caps;
97+ VkVideoEncodeH265QualityLevelPropertiesKHR quality_props;
98+
99+ CodedBitstreamContext *cbs;
100+ CodedBitstreamFragment current_access_unit;
101+
102+ H265RawAUD raw_aud;
103+
104+ SEIRawMasteringDisplayColourVolume sei_mastering_display;
105+ SEIRawContentLightLevelInfo sei_content_light_level;
106+ SEIRawUserDataRegistered sei_a53cc;
107+ void *sei_a53cc_data;
108+} VulkanEncodeH265Context;
109+
110+static int init_pic_rc(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
111+ VkVideoEncodeRateControlInfoKHR *rc_info,
112+ VkVideoEncodeRateControlLayerInfoKHR *rc_layer)
113+{
114+ VulkanEncodeH265Context *enc = avctx->priv_data;
115+ FFVulkanEncodeContext *ctx = &enc->common;
116+ VulkanEncodeH265Picture *hp = pic->codec_priv;
117+
118+ hp->vkrc_info = (VkVideoEncodeH265RateControlInfoKHR) {
119+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_KHR,
120+ .flags = VK_VIDEO_ENCODE_H265_RATE_CONTROL_REFERENCE_PATTERN_FLAT_BIT_KHR |
121+ VK_VIDEO_ENCODE_H265_RATE_CONTROL_REGULAR_GOP_BIT_KHR,
122+ .idrPeriod = ctx->base.gop_size,
123+ .gopFrameCount = ctx->base.gop_size,
124+ .consecutiveBFrameCount = FFMAX(ctx->base.b_per_p - 1, 0),
125+ .subLayerCount = 0,
126+ };
127+
128+ rc_info->pNext = &hp->vkrc_info;
129+ rc_info->virtualBufferSizeInMs = 1000;
130+ rc_info->initialVirtualBufferSizeInMs = 500;
131+
132+ if (rc_info->rateControlMode > VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
133+ hp->vkrc_layer_info = (VkVideoEncodeH265RateControlLayerInfoKHR) {
134+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_KHR,
135+
136+ .useMinQp = avctx->qmin > 0,
137+ .minQp.qpI = avctx->qmin > 0 ? avctx->qmin : 0,
138+ .minQp.qpP = avctx->qmin > 0 ? avctx->qmin : 0,
139+ .minQp.qpB = avctx->qmin > 0 ? avctx->qmin : 0,
140+
141+ .useMaxQp = avctx->qmax > 0,
142+ .maxQp.qpI = avctx->qmax > 0 ? avctx->qmax : 0,
143+ .maxQp.qpP = avctx->qmax > 0 ? avctx->qmax : 0,
144+ .maxQp.qpB = avctx->qmax > 0 ? avctx->qmax : 0,
145+
146+ .useMaxFrameSize = 0,
147+ };
148+ rc_layer->pNext = &hp->vkrc_layer_info;
149+ hp->vkrc_info.subLayerCount = 1;
150+ }
151+
152+ return 0;
153+}
154+
155+static int vk_enc_h265_update_pic_info(AVCodecContext *avctx,
156+ FFHWBaseEncodePicture *pic)
157+{
158+ VulkanEncodeH265Context *enc = avctx->priv_data;
159+ VulkanEncodeH265Picture *hp = pic->codec_priv;
160+ FFHWBaseEncodePicture *prev = pic->prev;
161+ VulkanEncodeH265Picture *hprev = prev ? prev->codec_priv : NULL;
162+
163+ if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
164+ av_assert0(pic->display_order == pic->encode_order);
165+
166+ hp->last_idr_frame = pic->display_order;
167+
168+ hp->slice_type = STD_VIDEO_H265_SLICE_TYPE_I;
169+ hp->pic_type = STD_VIDEO_H265_PICTURE_TYPE_IDR;
170+ } else {
171+ av_assert0(prev);
172+ hp->last_idr_frame = hprev->last_idr_frame;
173+
174+ if (pic->type == FF_HW_PICTURE_TYPE_I) {
175+ hp->slice_type = STD_VIDEO_H265_SLICE_TYPE_I;
176+ hp->pic_type = STD_VIDEO_H265_PICTURE_TYPE_I;
177+ } else if (pic->type == FF_HW_PICTURE_TYPE_P) {
178+ av_assert0(pic->refs[0]);
179+ hp->slice_type = STD_VIDEO_H265_SLICE_TYPE_P;
180+ hp->pic_type = STD_VIDEO_H265_PICTURE_TYPE_P;
181+ } else {
182+ FFHWBaseEncodePicture *irap_ref;
183+ av_assert0(pic->refs[0][0] && pic->refs[1][0]);
184+ for (irap_ref = pic; irap_ref; irap_ref = irap_ref->refs[1][0]) {
185+ if (irap_ref->type == FF_HW_PICTURE_TYPE_I)
186+ break;
187+ }
188+ hp->slice_type = STD_VIDEO_H265_SLICE_TYPE_B;
189+ hp->pic_type = STD_VIDEO_H265_PICTURE_TYPE_B;
190+ }
191+ }
192+ hp->pic_order_cnt = pic->display_order - hp->last_idr_frame;
193+
194+ hp->units_needed = 0;
195+
196+ if (enc->unit_elems & UNIT_AUD) {
197+ hp->units_needed |= UNIT_AUD;
198+ enc->raw_aud = (H265RawAUD) {
199+ .nal_unit_header = {
200+ .nal_unit_type = HEVC_NAL_AUD,
201+ .nuh_layer_id = 0,
202+ .nuh_temporal_id_plus1 = 1,
203+ },
204+ .pic_type = hp->pic_type,
205+ };
206+ }
207+
208+ // Only look for the metadata on I/IDR frame on the output. We
209+ // may force an IDR frame on the output where the medadata gets
210+ // changed on the input frame.
211+ if ((enc->unit_elems & UNIT_SEI_MASTERING_DISPLAY) &&
212+ (pic->type == FF_HW_PICTURE_TYPE_I || pic->type == FF_HW_PICTURE_TYPE_IDR)) {
213+ AVFrameSideData *sd =
214+ av_frame_get_side_data(pic->input_image,
215+ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
216+
217+ if (sd) {
218+ AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data;
219+
220+ // SEI is needed when both the primaries and luminance are set
221+ if (mdm->has_primaries && mdm->has_luminance) {
222+ SEIRawMasteringDisplayColourVolume *mdcv =
223+ &enc->sei_mastering_display;
224+ const int mapping[3] = {1, 2, 0};
225+ const int chroma_den = 50000;
226+ const int luma_den = 10000;
227+
228+ for (int i = 0; i < 3; i++) {
229+ const int j = mapping[i];
230+ mdcv->display_primaries_x[i] =
231+ FFMIN(lrint(chroma_den *
232+ av_q2d(mdm->display_primaries[j][0])),
233+ chroma_den);
234+ mdcv->display_primaries_y[i] =
235+ FFMIN(lrint(chroma_den *
236+ av_q2d(mdm->display_primaries[j][1])),
237+ chroma_den);
238+ }
239+
240+ mdcv->white_point_x =
241+ FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[0])),
242+ chroma_den);
243+ mdcv->white_point_y =
244+ FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[1])),
245+ chroma_den);
246+
247+ mdcv->max_display_mastering_luminance =
248+ lrint(luma_den * av_q2d(mdm->max_luminance));
249+ mdcv->min_display_mastering_luminance =
250+ FFMIN(lrint(luma_den * av_q2d(mdm->min_luminance)),
251+ mdcv->max_display_mastering_luminance);
252+
253+ hp->units_needed |= UNIT_SEI_MASTERING_DISPLAY;
254+ }
255+ }
256+ }
257+
258+ if ((enc->unit_elems & UNIT_SEI_CONTENT_LIGHT_LEVEL) &&
259+ (pic->type == FF_HW_PICTURE_TYPE_I || pic->type == FF_HW_PICTURE_TYPE_IDR)) {
260+ AVFrameSideData *sd = av_frame_get_side_data(pic->input_image,
261+ AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
262+
263+ if (sd) {
264+ AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data;
265+ SEIRawContentLightLevelInfo *clli = &enc->sei_content_light_level;
266+
267+ clli->max_content_light_level = FFMIN(clm->MaxCLL, 65535);
268+ clli->max_pic_average_light_level = FFMIN(clm->MaxFALL, 65535);
269+
270+ hp->units_needed |= UNIT_SEI_CONTENT_LIGHT_LEVEL;
271+ }
272+ }
273+
274+ if (enc->unit_elems & UNIT_SEI_A53_CC) {
275+ int err;
276+ size_t sei_a53cc_len;
277+ av_freep(&enc->sei_a53cc_data);
278+ err = ff_alloc_a53_sei(pic->input_image, 0, &enc->sei_a53cc_data, &sei_a53cc_len);
279+ if (err < 0)
280+ return err;
281+ if (enc->sei_a53cc_data != NULL) {
282+ enc->sei_a53cc.itu_t_t35_country_code = 181;
283+ enc->sei_a53cc.data = (uint8_t *)enc->sei_a53cc_data + 1;
284+ enc->sei_a53cc.data_length = sei_a53cc_len - 1;
285+
286+ hp->units_needed |= UNIT_SEI_A53_CC;
287+ }
288+ }
289+
290+ return 0;
291+}
292+
293+static void setup_slices(AVCodecContext *avctx,
294+ FFHWBaseEncodePicture *pic)
295+{
296+ VulkanEncodeH265Context *enc = avctx->priv_data;
297+ VulkanEncodeH265Picture *hp = pic->codec_priv;
298+
299+ hp->slice_wt = (StdVideoEncodeH265WeightTable) {
300+ .flags = (StdVideoEncodeH265WeightTableFlags) {
301+ .luma_weight_l0_flag = 0,
302+ .chroma_weight_l0_flag = 0,
303+ .luma_weight_l1_flag = 0,
304+ .chroma_weight_l1_flag = 0,
305+ },
306+ .luma_log2_weight_denom = 0,
307+ .delta_chroma_log2_weight_denom = 0,
308+ .delta_luma_weight_l0 = { 0 },
309+ .luma_offset_l0 = { 0 },
310+ .delta_chroma_weight_l0 = { { 0 } },
311+ .delta_chroma_offset_l0 = { { 0 } },
312+ .delta_luma_weight_l1 = { 0 },
313+ .luma_offset_l1 = { 0 },
314+ .delta_chroma_weight_l1 = { { 0 } },
315+ .delta_chroma_offset_l1 = { { 0 } },
316+ };
317+
318+ hp->slice_hdr = (StdVideoEncodeH265SliceSegmentHeader) {
319+ .flags = (StdVideoEncodeH265SliceSegmentHeaderFlags) {
320+ .first_slice_segment_in_pic_flag = 1,
321+ .dependent_slice_segment_flag = 0,
322+ .slice_sao_luma_flag = enc->units.raw_sps.sample_adaptive_offset_enabled_flag,
323+ .slice_sao_chroma_flag = enc->units.raw_sps.sample_adaptive_offset_enabled_flag,
324+ .num_ref_idx_active_override_flag = 0,
325+ .mvd_l1_zero_flag = 0,
326+ .cabac_init_flag = 0,
327+ .cu_chroma_qp_offset_enabled_flag = 0,
328+ .deblocking_filter_override_flag = 0,
329+ .slice_deblocking_filter_disabled_flag = 0,
330+ .collocated_from_l0_flag = 1,
331+ .slice_loop_filter_across_slices_enabled_flag = 0,
332+ /* Reserved */
333+ },
334+ .slice_type = hp->slice_type,
335+ .slice_segment_address = 0,
336+ .collocated_ref_idx = 0,
337+ .MaxNumMergeCand = 5,
338+ .slice_cb_qp_offset = 0,
339+ .slice_cr_qp_offset = 0,
340+ .slice_beta_offset_div2 = 0,
341+ .slice_tc_offset_div2 = 0,
342+ .slice_act_y_qp_offset = 0,
343+ .slice_act_cb_qp_offset = 0,
344+ .slice_act_cr_qp_offset = 0,
345+ .slice_qp_delta = 0, /* Filled in below */
346+ /* Reserved */
347+ .pWeightTable = NULL, // &hp->slice_wt,
348+ };
349+
350+ hp->vkslice = (VkVideoEncodeH265NaluSliceSegmentInfoKHR) {
351+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_INFO_KHR,
352+ .pNext = NULL,
353+ .constantQp = pic->type == FF_HW_PICTURE_TYPE_B ? enc->fixed_qp_b :
354+ pic->type == FF_HW_PICTURE_TYPE_P ? enc->fixed_qp_p :
355+ enc->fixed_qp_idr,
356+ .pStdSliceSegmentHeader = &hp->slice_hdr,
357+ };
358+
359+ if (enc->common.opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR)
360+ hp->vkslice.constantQp = 0;
361+
362+ hp->slice_hdr.slice_qp_delta = hp->vkslice.constantQp -
363+ (enc->units.raw_pps.init_qp_minus26 + 26);
364+
365+ hp->vkh265pic_info.pNaluSliceSegmentEntries = &hp->vkslice;
366+ hp->vkh265pic_info.naluSliceSegmentEntryCount = 1;
367+}
368+
369+static void setup_refs(AVCodecContext *avctx,
370+ FFHWBaseEncodePicture *pic,
371+ VkVideoEncodeInfoKHR *encode_info)
372+{
373+ int i, j;
374+ VulkanEncodeH265Context *enc = avctx->priv_data;
375+ VulkanEncodeH265Picture *hp = pic->codec_priv;
376+
377+ hp->ref_list_info = (StdVideoEncodeH265ReferenceListsInfo) {
378+ .flags = (StdVideoEncodeH265ReferenceListsInfoFlags) {
379+ .ref_pic_list_modification_flag_l0 = 0,
380+ .ref_pic_list_modification_flag_l1 = 0,
381+ /* Reserved */
382+ },
383+ /* May be overridden during setup_slices() */
384+ .num_ref_idx_l0_active_minus1 = pic->nb_refs[0] - 1,
385+ .num_ref_idx_l1_active_minus1 = pic->nb_refs[1] - 1,
386+ /* Reserved */
387+ .list_entry_l0 = { 0 },
388+ .list_entry_l1 = { 0 },
389+ };
390+
391+ for (i = 0; i < STD_VIDEO_H265_MAX_NUM_LIST_REF; i++)
392+ hp->ref_list_info.RefPicList0[i] = hp->ref_list_info.RefPicList1[i] = -1;
393+
394+ /* Note: really not sure */
395+ for (i = 0; i < pic->nb_refs[0]; i++) {
396+ VkVideoReferenceSlotInfoKHR *slot_info;
397+ slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[i];
398+ hp->ref_list_info.RefPicList0[i] = slot_info->slotIndex;
399+ }
400+
401+ /* Note: really not sure */
402+ for (i = 0; i < pic->nb_refs[1]; i++) {
403+ VkVideoReferenceSlotInfoKHR *slot_info;
404+ slot_info = (VkVideoReferenceSlotInfoKHR *)&encode_info->pReferenceSlots[pic->nb_refs[0] + i];
405+ hp->ref_list_info.RefPicList1[i] = slot_info->slotIndex;
406+ }
407+
408+ hp->h265pic_info.pRefLists = &hp->ref_list_info;
409+
410+ if (pic->type != FF_HW_PICTURE_TYPE_IDR) {
411+ StdVideoH265ShortTermRefPicSet *rps;
412+ VulkanEncodeH265Picture *strp;
413+ int rps_poc[MAX_DPB_SIZE];
414+ int rps_used[MAX_DPB_SIZE];
415+ int poc, rps_pics;
416+
417+ hp->h265pic_info.flags.short_term_ref_pic_set_sps_flag = 0;
418+
419+ rps = &hp->s_rps;
420+ memset(rps, 0, sizeof(*rps));
421+
422+ rps_pics = 0;
423+ for (i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
424+ for (j = 0; j < pic->nb_refs[i]; j++) {
425+ strp = pic->refs[i][j]->codec_priv;
426+ rps_poc[rps_pics] = strp->pic_order_cnt;
427+ rps_used[rps_pics] = 1;
428+ ++rps_pics;
429+ }
430+ }
431+
432+ for (i = 0; i < pic->nb_dpb_pics; i++) {
433+ if (pic->dpb[i] == pic)
434+ continue;
435+
436+ for (j = 0; j < pic->nb_refs[0]; j++) {
437+ if (pic->dpb[i] == pic->refs[0][j])
438+ break;
439+ }
440+ if (j < pic->nb_refs[0])
441+ continue;
442+
443+ for (j = 0; j < pic->nb_refs[1]; j++) {
444+ if (pic->dpb[i] == pic->refs[1][j])
445+ break;
446+ }
447+ if (j < pic->nb_refs[1])
448+ continue;
449+
450+ strp = pic->dpb[i]->codec_priv;
451+ rps_poc[rps_pics] = strp->pic_order_cnt;
452+ rps_used[rps_pics] = 0;
453+ ++rps_pics;
454+ }
455+
456+ for (i = 1; i < rps_pics; i++) {
457+ for (j = i; j > 0; j--) {
458+ if (rps_poc[j] > rps_poc[j - 1])
459+ break;
460+ av_assert0(rps_poc[j] != rps_poc[j - 1]);
461+ FFSWAP(int, rps_poc[j], rps_poc[j - 1]);
462+ FFSWAP(int, rps_used[j], rps_used[j - 1]);
463+ }
464+ }
465+
466+ av_log(avctx, AV_LOG_DEBUG, "RPS for POC %d:", hp->pic_order_cnt);
467+ for (i = 0; i < rps_pics; i++)
468+ av_log(avctx, AV_LOG_DEBUG, " (%d,%d)", rps_poc[i], rps_used[i]);
469+
470+ av_log(avctx, AV_LOG_DEBUG, "\n");
471+
472+ for (i = 0; i < rps_pics; i++) {
473+ av_assert0(rps_poc[i] != hp->pic_order_cnt);
474+ if (rps_poc[i] > hp->pic_order_cnt)
475+ break;
476+ }
477+
478+ rps->num_negative_pics = i;
479+ rps->used_by_curr_pic_s0_flag = 0x0;
480+ poc = hp->pic_order_cnt;
481+ for (j = i - 1; j >= 0; j--) {
482+ rps->delta_poc_s0_minus1[i - 1 - j] = poc - rps_poc[j] - 1;
483+ rps->used_by_curr_pic_s0_flag |= rps_used[j] << (i - 1 - j);
484+ poc = rps_poc[j];
485+ }
486+
487+ rps->num_positive_pics = rps_pics - i;
488+ rps->used_by_curr_pic_s1_flag = 0x0;
489+ poc = hp->pic_order_cnt;
490+ for (j = i; j < rps_pics; j++) {
491+ rps->delta_poc_s1_minus1[j - i] = rps_poc[j] - poc - 1;
492+ rps->used_by_curr_pic_s1_flag |= rps_used[j] << (j - i);
493+ poc = rps_poc[j];
494+ }
495+
496+ hp->l_rps.num_long_term_sps = 0;
497+ hp->l_rps.num_long_term_pics = 0;
498+
499+ // when this flag is not present, it is inerred to 1.
500+ hp->slice_hdr.flags.collocated_from_l0_flag = 1;
501+ hp->h265pic_info.flags.slice_temporal_mvp_enabled_flag =
502+ enc->units.raw_sps.sps_temporal_mvp_enabled_flag;
503+ if (hp->h265pic_info.flags.slice_temporal_mvp_enabled_flag) {
504+ if (hp->slice_hdr.slice_type == STD_VIDEO_H265_SLICE_TYPE_B)
505+ hp->slice_hdr.flags.collocated_from_l0_flag = 1;
506+ hp->slice_hdr.collocated_ref_idx = 0;
507+ }
508+
509+ hp->slice_hdr.flags.num_ref_idx_active_override_flag = 0;
510+ hp->ref_list_info.num_ref_idx_l0_active_minus1 = enc->units.raw_pps.num_ref_idx_l0_default_active_minus1;
511+ hp->ref_list_info.num_ref_idx_l1_active_minus1 = enc->units.raw_pps.num_ref_idx_l1_default_active_minus1;
512+ }
513+
514+ hp->h265pic_info.pShortTermRefPicSet = &hp->s_rps;
515+ hp->h265pic_info.pLongTermRefPics = &hp->l_rps;
516+}
517+
518+static int init_pic_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic,
519+ VkVideoEncodeInfoKHR *encode_info)
520+{
521+ int err;
522+ VulkanEncodeH265Context *enc = avctx->priv_data;
523+ FFVulkanEncodePicture *vp = pic->priv;
524+ VulkanEncodeH265Picture *hp = pic->codec_priv;
525+ VkVideoReferenceSlotInfoKHR *ref_slot;
526+
527+ err = vk_enc_h265_update_pic_info(avctx, pic);
528+ if (err < 0)
529+ return err;
530+
531+ hp->vkh265pic_info = (VkVideoEncodeH265PictureInfoKHR) {
532+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PICTURE_INFO_KHR,
533+ .pNext = NULL,
534+ .pNaluSliceSegmentEntries = NULL, // Filled in during setup_slices()
535+ .naluSliceSegmentEntryCount = 0, // Filled in during setup_slices()
536+ .pStdPictureInfo = &hp->h265pic_info,
537+ };
538+
539+ hp->h265pic_info = (StdVideoEncodeH265PictureInfo) {
540+ .flags = (StdVideoEncodeH265PictureInfoFlags) {
541+ .is_reference = pic->is_reference,
542+ .IrapPicFlag = pic->type == FF_HW_PICTURE_TYPE_IDR,
543+ .used_for_long_term_reference = 0,
544+ .discardable_flag = 0,
545+ .cross_layer_bla_flag = 0,
546+ .pic_output_flag = 1,
547+ .no_output_of_prior_pics_flag = 0,
548+ .short_term_ref_pic_set_sps_flag = 0,
549+ .slice_temporal_mvp_enabled_flag = enc->units.raw_sps.sps_temporal_mvp_enabled_flag,
550+ /* Reserved */
551+ },
552+ .pic_type = hp->pic_type,
553+ .sps_video_parameter_set_id = 0,
554+ .pps_seq_parameter_set_id = 0,
555+ .pps_pic_parameter_set_id = 0,
556+ .short_term_ref_pic_set_idx = 0,
557+ .PicOrderCntVal = hp->pic_order_cnt,
558+ .TemporalId = 0,
559+ /* Reserved */
560+ .pRefLists = NULL, // Filled in during setup_refs
561+ .pShortTermRefPicSet = NULL,
562+ .pLongTermRefPics = NULL,
563+ };
564+ encode_info->pNext = &hp->vkh265pic_info;
565+
566+ hp->h265dpb_info = (StdVideoEncodeH265ReferenceInfo) {
567+ .flags = (StdVideoEncodeH265ReferenceInfoFlags) {
568+ .used_for_long_term_reference = 0,
569+ .unused_for_reference = 0,
570+ /* Reserved */
571+ },
572+ .pic_type = hp->h265pic_info.pic_type,
573+ .PicOrderCntVal = hp->h265pic_info.PicOrderCntVal,
574+ .TemporalId = hp->h265pic_info.TemporalId,
575+ };
576+ hp->vkh265dpb_info = (VkVideoEncodeH265DpbSlotInfoKHR) {
577+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_KHR,
578+ .pStdReferenceInfo = &hp->h265dpb_info,
579+ };
580+
581+ vp->dpb_slot.pNext = &hp->vkh265dpb_info;
582+
583+ ref_slot = (VkVideoReferenceSlotInfoKHR *)encode_info->pSetupReferenceSlot;
584+ ref_slot->pNext = &hp->vkh265dpb_info;
585+
586+ setup_refs(avctx, pic, encode_info);
587+
588+ setup_slices(avctx, pic);
589+
590+ return 0;
591+}
592+
593+static int init_profile(AVCodecContext *avctx,
594+ VkVideoProfileInfoKHR *profile, void *pnext)
595+{
596+ VkResult ret;
597+ VulkanEncodeH265Context *enc = avctx->priv_data;
598+ FFVulkanEncodeContext *ctx = &enc->common;
599+ FFVulkanContext *s = &ctx->s;
600+ FFVulkanFunctions *vk = &ctx->s.vkfn;
601+ VkVideoEncodeH265CapabilitiesKHR h265_caps = {
602+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_KHR,
603+ };
604+ VkVideoEncodeCapabilitiesKHR enc_caps = {
605+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR,
606+ .pNext = &h265_caps,
607+ };
608+ VkVideoCapabilitiesKHR caps = {
609+ .sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR,
610+ .pNext = &enc_caps,
611+ };
612+
613+ /* In order of preference */
614+ int last_supported = AV_PROFILE_UNKNOWN;
615+ static const int known_profiles[] = {
616+ AV_PROFILE_HEVC_MAIN,
617+ AV_PROFILE_HEVC_MAIN_10,
618+ AV_PROFILE_HEVC_REXT,
619+ };
620+ int nb_profiles = FF_ARRAY_ELEMS(known_profiles);
621+
622+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->frames->sw_format);
623+ if (!desc)
624+ return AVERROR(EINVAL);
625+
626+ if (s->frames->sw_format == AV_PIX_FMT_NV12)
627+ nb_profiles = 1;
628+ else if (s->frames->sw_format == AV_PIX_FMT_P010)
629+ nb_profiles = 2;
630+
631+ enc->profile = (VkVideoEncodeH265ProfileInfoKHR) {
632+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_KHR,
633+ .pNext = pnext,
634+ .stdProfileIdc = ff_vk_h265_profile_to_vk(avctx->profile),
635+ };
636+ profile->pNext = &enc->profile;
637+
638+ /* Set level */
639+ if (avctx->level == AV_LEVEL_UNKNOWN)
640+ avctx->level = enc->common.opts.level;
641+
642+ /* User has explicitly specified a profile. */
643+ if (avctx->profile != AV_PROFILE_UNKNOWN)
644+ return 0;
645+
646+ av_log(avctx, AV_LOG_DEBUG, "Supported profiles:\n");
647+ for (int i = 0; i < nb_profiles; i++) {
648+ enc->profile.stdProfileIdc = ff_vk_h265_profile_to_vk(known_profiles[i]);
649+ ret = vk->GetPhysicalDeviceVideoCapabilitiesKHR(s->hwctx->phys_dev,
650+ profile,
651+ &caps);
652+ if (ret == VK_SUCCESS) {
653+ av_log(avctx, AV_LOG_DEBUG, " %s\n",
654+ avcodec_profile_name(avctx->codec_id, known_profiles[i]));
655+ last_supported = known_profiles[i];
656+ }
657+ }
658+
659+ if (last_supported == AV_PROFILE_UNKNOWN) {
660+ av_log(avctx, AV_LOG_ERROR, "No supported profiles for given format\n");
661+ return AVERROR(ENOTSUP);
662+ }
663+
664+ enc->profile.stdProfileIdc = ff_vk_h265_profile_to_vk(last_supported);
665+ av_log(avctx, AV_LOG_VERBOSE, "Using profile %s\n",
666+ avcodec_profile_name(avctx->codec_id, last_supported));
667+ avctx->profile = last_supported;
668+
669+ return 0;
670+}
671+
672+static int init_enc_options(AVCodecContext *avctx)
673+{
674+ VulkanEncodeH265Context *enc = avctx->priv_data;
675+
676+ if (avctx->rc_buffer_size)
677+ enc->hrd_buffer_size = avctx->rc_buffer_size;
678+ else if (avctx->rc_max_rate > 0)
679+ enc->hrd_buffer_size = avctx->rc_max_rate;
680+ else
681+ enc->hrd_buffer_size = avctx->bit_rate;
682+
683+ if (avctx->rc_initial_buffer_occupancy) {
684+ if (avctx->rc_initial_buffer_occupancy > enc->hrd_buffer_size) {
685+ av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
686+ "must have initial buffer size (%d) <= "
687+ "buffer size (%"PRId64").\n",
688+ avctx->rc_initial_buffer_occupancy, enc->hrd_buffer_size);
689+ return AVERROR(EINVAL);
690+ }
691+ enc->initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
692+ } else {
693+ enc->initial_buffer_fullness = enc->hrd_buffer_size * 3 / 4;
694+ }
695+
696+ if (enc->common.opts.rc_mode == VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR) {
697+ enc->fixed_qp_p = av_clip(enc->common.opts.qp,
698+ enc->caps.minQp, enc->caps.maxQp);
699+
700+ if (avctx->i_quant_factor > 0.0)
701+ enc->fixed_qp_idr = av_clip((avctx->i_quant_factor * enc->fixed_qp_p +
702+ avctx->i_quant_offset) + 0.5,
703+ enc->caps.minQp, enc->caps.maxQp);
704+ else
705+ enc->fixed_qp_idr = enc->fixed_qp_p;
706+
707+ if (avctx->b_quant_factor > 0.0)
708+ enc->fixed_qp_b = av_clip((avctx->b_quant_factor * enc->fixed_qp_p +
709+ avctx->b_quant_offset) + 0.5,
710+ enc->caps.minQp, enc->caps.maxQp);
711+ else
712+ enc->fixed_qp_b = enc->fixed_qp_p;
713+
714+ av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
715+ "%d / %d / %d for IDR- / P- / B-frames.\n",
716+ enc->fixed_qp_idr, enc->fixed_qp_p, enc->fixed_qp_b);
717+ } else {
718+ enc->fixed_qp_idr = 26;
719+ enc->fixed_qp_p = 26;
720+ enc->fixed_qp_b = 26;
721+ }
722+
723+ return 0;
724+}
725+
726+static av_cold int init_sequence_headers(AVCodecContext *avctx)
727+{
728+ int err;
729+ VulkanEncodeH265Context *enc = avctx->priv_data;
730+ FFVulkanEncodeContext *ctx = &enc->common;
731+ FFHWBaseEncodeContext *base_ctx = &ctx->base;
732+
733+ FFHWBaseEncodeH265 *units = &enc->units;
734+ FFHWBaseEncodeH265Opts *unit_opts = &enc->unit_opts;
735+
736+ int max_ctb_size;
737+ unsigned min_tb_size;
738+ unsigned max_tb_size;
739+ unsigned max_transform_hierarchy;
740+
741+ unit_opts->tier = enc->common.opts.tier;
742+ unit_opts->fixed_qp_idr = enc->fixed_qp_idr;
743+ unit_opts->cu_qp_delta_enabled_flag = enc->common.opts.rc_mode != VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR;
744+
745+ unit_opts->nb_slices = 1;
746+
747+ unit_opts->slice_block_rows = (avctx->height + base_ctx->slice_block_height - 1) /
748+ base_ctx->slice_block_height;
749+ unit_opts->slice_block_cols = (avctx->width + base_ctx->slice_block_width - 1) /
750+ base_ctx->slice_block_width;
751+
752+ /* cabac already set via an option */
753+ /* fixed_qp_idr initialized in init_enc_options() */
754+ /* hrd_buffer_size initialized in init_enc_options() */
755+ /* initial_buffer_fullness initialized in init_enc_options() */
756+
757+ err = ff_hw_base_encode_init_params_h265(&enc->common.base, avctx,
758+ units, unit_opts);
759+ if (err < 0)
760+ return err;
761+
762+ units->raw_sps.sample_adaptive_offset_enabled_flag =
763+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_KHR);
764+ units->raw_pps.transform_skip_enabled_flag =
765+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_KHR);
766+
767+ max_ctb_size = 16;
768+
769+ /* coding blocks from 8x8 to max CTB size. */
770+ if (enc->caps.ctbSizes & VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR)
771+ max_ctb_size = 64;
772+ else if (enc->caps.ctbSizes & VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR)
773+ max_ctb_size = 32;
774+
775+ min_tb_size = 0;
776+ max_tb_size = 0;
777+ if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR)
778+ min_tb_size = 4;
779+ else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR)
780+ min_tb_size = 8;
781+ else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR)
782+ min_tb_size = 16;
783+ else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR)
784+ min_tb_size = 32;
785+
786+ if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR)
787+ max_tb_size = 32;
788+ else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR)
789+ max_tb_size = 16;
790+ else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR)
791+ max_tb_size = 8;
792+ else if (enc->caps.transformBlockSizes & VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR)
793+ max_tb_size = 4;
794+
795+ units->raw_sps.log2_min_luma_coding_block_size_minus3 = 0;
796+ units->raw_sps.log2_diff_max_min_luma_coding_block_size = av_log2(max_ctb_size) - 3;
797+ units->raw_sps.log2_min_luma_transform_block_size_minus2 = av_log2(min_tb_size) - 2;
798+ units->raw_sps.log2_diff_max_min_luma_transform_block_size = av_log2(max_tb_size) - av_log2(min_tb_size);
799+
800+ max_transform_hierarchy = av_log2(max_ctb_size) - av_log2(min_tb_size);
801+ units->raw_sps.max_transform_hierarchy_depth_intra = max_transform_hierarchy;
802+ units->raw_sps.max_transform_hierarchy_depth_intra = max_transform_hierarchy;
803+
804+ units->raw_sps.vui.bitstream_restriction_flag = 0;
805+ units->raw_sps.vui.max_bytes_per_pic_denom = 2;
806+ units->raw_sps.vui.max_bits_per_min_cu_denom = 1;
807+
808+ units->raw_sps.sps_temporal_mvp_enabled_flag = 0;
809+
810+ if (base_ctx->gop_size & base_ctx->gop_size - 1 == 0)
811+ units->raw_sps.log2_max_pic_order_cnt_lsb_minus4 = FFMAX(av_log2(base_ctx->gop_size) - 4, 0);
812+ else
813+ units->raw_sps.log2_max_pic_order_cnt_lsb_minus4 = FFMAX(av_log2(base_ctx->gop_size) - 3, 0);
814+
815+ return 0;
816+}
817+
818+typedef struct VulkanH265Units {
819+ StdVideoH265SequenceParameterSet sps;
820+ StdVideoH265ShortTermRefPicSet str[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE];
821+ StdVideoH265LongTermRefPicsSps ltr;
822+ StdVideoH265ProfileTierLevel ptl_sps;
823+ StdVideoH265DecPicBufMgr dpbm_sps;
824+
825+ StdVideoH265HrdParameters vui_header_sps;
826+ StdVideoH265SequenceParameterSetVui vui_sps;
827+
828+ StdVideoH265SubLayerHrdParameters slhdrnal[HEVC_MAX_SUB_LAYERS];
829+ StdVideoH265SubLayerHrdParameters slhdrvcl[HEVC_MAX_SUB_LAYERS];
830+
831+ StdVideoH265PictureParameterSet pps;
832+ StdVideoH265ScalingLists pps_scaling;
833+
834+ StdVideoH265VideoParameterSet vps;
835+ StdVideoH265ProfileTierLevel ptl_vps;
836+ StdVideoH265DecPicBufMgr dpbm_vps;
837+ StdVideoH265HrdParameters vui_header_vps;
838+} VulkanH265Units;
839+
840+static av_cold int base_unit_to_vk(AVCodecContext *avctx,
841+ VulkanH265Units *vk_units)
842+{
843+ VulkanEncodeH265Context *enc = avctx->priv_data;
844+
845+ H265RawSPS *sps = &enc->units.raw_sps;
846+ StdVideoH265SequenceParameterSet *vksps = &vk_units->sps;
847+ StdVideoH265ShortTermRefPicSet *str = vk_units->str;
848+ StdVideoH265LongTermRefPicsSps *ltr = &vk_units->ltr;
849+ StdVideoH265ProfileTierLevel *ptl_sps = &vk_units->ptl_sps;
850+ StdVideoH265DecPicBufMgr *dpbm_sps = &vk_units->dpbm_sps;
851+
852+ StdVideoH265HrdParameters *vui_header_sps = &vk_units->vui_header_sps;
853+ StdVideoH265SequenceParameterSetVui *vui_sps = &vk_units->vui_sps;
854+
855+ StdVideoH265SubLayerHrdParameters *slhdrnal = vk_units->slhdrnal;
856+ StdVideoH265SubLayerHrdParameters *slhdrvcl = vk_units->slhdrvcl;
857+
858+ H265RawPPS *pps = &enc->units.raw_pps;
859+ StdVideoH265PictureParameterSet *vkpps = &vk_units->pps;
860+
861+ H265RawVPS *vps = &enc->units.raw_vps;
862+ StdVideoH265VideoParameterSet *vkvps = &vk_units->vps;
863+ StdVideoH265ProfileTierLevel *ptl_vps = &vk_units->ptl_vps;
864+ StdVideoH265DecPicBufMgr *dpbm_vps = &vk_units->dpbm_vps;
865+ StdVideoH265HrdParameters *vui_header_vps = &vk_units->vui_header_vps;
866+
867+ /* SPS */
868+ for (int i = 0; i < HEVC_MAX_SUB_LAYERS; i++) {
869+ memcpy(&slhdrnal[i], &sps->vui.hrd_parameters.nal_sub_layer_hrd_parameters[i], sizeof(*slhdrnal));
870+ memcpy(&slhdrvcl[i], &sps->vui.hrd_parameters.vcl_sub_layer_hrd_parameters[i], sizeof(*slhdrvcl));
871+ slhdrnal[i].cbr_flag = 0x0;
872+ slhdrvcl[i].cbr_flag = 0x0;
873+ for (int j = 0; j < HEVC_MAX_CPB_CNT; j++) {
874+ slhdrnal[i].cbr_flag |= sps->vui.hrd_parameters.nal_sub_layer_hrd_parameters[i].cbr_flag[j] << i;
875+ slhdrvcl[i].cbr_flag |= sps->vui.hrd_parameters.vcl_sub_layer_hrd_parameters[i].cbr_flag[j] << i;
876+ }
877+ }
878+
879+ *vui_header_sps = (StdVideoH265HrdParameters) {
880+ .flags = (StdVideoH265HrdFlags) {
881+ .nal_hrd_parameters_present_flag = sps->vui.hrd_parameters.nal_hrd_parameters_present_flag,
882+ .vcl_hrd_parameters_present_flag = sps->vui.hrd_parameters.vcl_hrd_parameters_present_flag,
883+ .sub_pic_hrd_params_present_flag = sps->vui.hrd_parameters.sub_pic_hrd_params_present_flag,
884+ .sub_pic_cpb_params_in_pic_timing_sei_flag = sps->vui.hrd_parameters.sub_pic_cpb_params_in_pic_timing_sei_flag,
885+ .fixed_pic_rate_general_flag = 0x0,
886+ .fixed_pic_rate_within_cvs_flag = 0x0,
887+ .low_delay_hrd_flag = 0x0,
888+ },
889+ .tick_divisor_minus2 = sps->vui.hrd_parameters.tick_divisor_minus2,
890+ .du_cpb_removal_delay_increment_length_minus1 = sps->vui.hrd_parameters.du_cpb_removal_delay_increment_length_minus1,
891+ .dpb_output_delay_du_length_minus1 = sps->vui.hrd_parameters.dpb_output_delay_du_length_minus1,
892+ .bit_rate_scale = sps->vui.hrd_parameters.bit_rate_scale,
893+ .cpb_size_scale = sps->vui.hrd_parameters.cpb_size_scale,
894+ .cpb_size_du_scale = sps->vui.hrd_parameters.cpb_size_du_scale,
895+ .initial_cpb_removal_delay_length_minus1 = sps->vui.hrd_parameters.initial_cpb_removal_delay_length_minus1,
896+ .au_cpb_removal_delay_length_minus1 = sps->vui.hrd_parameters.au_cpb_removal_delay_length_minus1,
897+ .dpb_output_delay_length_minus1 = sps->vui.hrd_parameters.dpb_output_delay_length_minus1,
898+ /* Reserved - 3*16 bits */
899+ .pSubLayerHrdParametersNal = slhdrnal,
900+ .pSubLayerHrdParametersVcl = slhdrvcl,
901+ };
902+
903+ for (int i = 0; i < HEVC_MAX_SUB_LAYERS; i++) {
904+ vui_header_sps->flags.fixed_pic_rate_general_flag |= sps->vui.hrd_parameters.fixed_pic_rate_general_flag[i] << i;
905+ vui_header_sps->flags.fixed_pic_rate_within_cvs_flag |= sps->vui.hrd_parameters.fixed_pic_rate_within_cvs_flag[i] << i;
906+ vui_header_sps->flags.low_delay_hrd_flag |= sps->vui.hrd_parameters.low_delay_hrd_flag[i] << i;
907+ }
908+
909+ for (int i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; i++) {
910+ dpbm_sps->max_latency_increase_plus1[i] = sps->sps_max_latency_increase_plus1[i];
911+ dpbm_sps->max_dec_pic_buffering_minus1[i] = sps->sps_max_dec_pic_buffering_minus1[i];
912+ dpbm_sps->max_num_reorder_pics[i] = sps->sps_max_num_reorder_pics[i];
913+ }
914+
915+ *ptl_sps = (StdVideoH265ProfileTierLevel) {
916+ .flags = (StdVideoH265ProfileTierLevelFlags) {
917+ .general_tier_flag = sps->profile_tier_level.general_tier_flag,
918+ .general_progressive_source_flag = sps->profile_tier_level.general_progressive_source_flag,
919+ .general_interlaced_source_flag = sps->profile_tier_level.general_interlaced_source_flag,
920+ .general_non_packed_constraint_flag = sps->profile_tier_level.general_non_packed_constraint_flag,
921+ .general_frame_only_constraint_flag = sps->profile_tier_level.general_frame_only_constraint_flag,
922+ },
923+ .general_profile_idc = ff_vk_h265_profile_to_vk(sps->profile_tier_level.general_profile_idc),
924+ .general_level_idc = ff_vk_h265_level_to_vk(sps->profile_tier_level.general_level_idc),
925+ };
926+
927+ for (int i = 0; i < STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS; i++) {
928+ const H265RawSTRefPicSet *st_rps = &sps->st_ref_pic_set[i];
929+
930+ str[i] = (StdVideoH265ShortTermRefPicSet) {
931+ .flags = (StdVideoH265ShortTermRefPicSetFlags) {
932+ .inter_ref_pic_set_prediction_flag = st_rps->inter_ref_pic_set_prediction_flag,
933+ .delta_rps_sign = st_rps->delta_rps_sign,
934+ },
935+ .delta_idx_minus1 = st_rps->delta_idx_minus1,
936+ .use_delta_flag = 0x0,
937+ .abs_delta_rps_minus1 = st_rps->abs_delta_rps_minus1,
938+ .used_by_curr_pic_flag = 0x0,
939+ .used_by_curr_pic_s0_flag = 0x0,
940+ .used_by_curr_pic_s1_flag = 0x0,
941+ /* Reserved */
942+ /* Reserved */
943+ /* Reserved */
944+ .num_negative_pics = st_rps->num_negative_pics,
945+ .num_positive_pics = st_rps->num_positive_pics,
946+ };
947+
948+ for (int j = 0; j < HEVC_MAX_REFS; j++) {
949+ str[i].use_delta_flag |= st_rps->use_delta_flag[j] << i;
950+ str[i].used_by_curr_pic_flag |= st_rps->used_by_curr_pic_flag[j] << i;
951+ str[i].used_by_curr_pic_s0_flag |= st_rps->used_by_curr_pic_s0_flag[j] << i;
952+ str[i].used_by_curr_pic_s1_flag |= st_rps->used_by_curr_pic_s1_flag[j] << i;
953+ str[i].delta_poc_s0_minus1[j] = st_rps->delta_poc_s0_minus1[j];
954+ str[i].delta_poc_s1_minus1[j] = st_rps->delta_poc_s1_minus1[j];
955+ }
956+ }
957+
958+ ltr->used_by_curr_pic_lt_sps_flag = 0;
959+ for (int i = 0; i < STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS; i++) {
960+ ltr->used_by_curr_pic_lt_sps_flag |= sps->lt_ref_pic_poc_lsb_sps[i] << i;
961+ ltr->lt_ref_pic_poc_lsb_sps[i] = sps->lt_ref_pic_poc_lsb_sps[i];
962+ }
963+
964+ *vksps = (StdVideoH265SequenceParameterSet) {
965+ .flags = (StdVideoH265SpsFlags) {
966+ .sps_temporal_id_nesting_flag = sps->sps_temporal_id_nesting_flag,
967+ .separate_colour_plane_flag = sps->separate_colour_plane_flag,
968+ .conformance_window_flag = sps->conformance_window_flag,
969+ .sps_sub_layer_ordering_info_present_flag = sps->sps_sub_layer_ordering_info_present_flag,
970+ .scaling_list_enabled_flag = sps->scaling_list_enabled_flag,
971+ .sps_scaling_list_data_present_flag = sps->sps_scaling_list_data_present_flag,
972+ .amp_enabled_flag = sps->amp_enabled_flag,
973+ .sample_adaptive_offset_enabled_flag = sps->sample_adaptive_offset_enabled_flag,
974+ .pcm_enabled_flag = sps->pcm_enabled_flag,
975+ .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag,
976+ .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
977+ .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag,
978+ .strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled_flag,
979+ .vui_parameters_present_flag = sps->vui_parameters_present_flag,
980+ .sps_extension_present_flag = sps->sps_extension_present_flag,
981+ .sps_range_extension_flag = sps->sps_range_extension_flag,
982+ .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled_flag,
983+ .transform_skip_context_enabled_flag = sps->transform_skip_context_enabled_flag,
984+ .implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled_flag,
985+ .explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled_flag,
986+ .extended_precision_processing_flag = sps->extended_precision_processing_flag,
987+ .intra_smoothing_disabled_flag = sps->intra_smoothing_disabled_flag,
988+ .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled_flag,
989+ .persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled_flag,
990+ .cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled_flag,
991+ .sps_scc_extension_flag = sps->sps_scc_extension_flag,
992+ .sps_curr_pic_ref_enabled_flag = sps->sps_curr_pic_ref_enabled_flag,
993+ .palette_mode_enabled_flag = sps->palette_mode_enabled_flag,
994+ .sps_palette_predictor_initializers_present_flag = sps->sps_palette_predictor_initializer_present_flag,
995+ .intra_boundary_filtering_disabled_flag = sps->intra_boundary_filtering_disable_flag,
996+ },
997+ .chroma_format_idc = sps->chroma_format_idc,
998+ .pic_width_in_luma_samples = sps->pic_width_in_luma_samples,
999+ .pic_height_in_luma_samples = sps->pic_height_in_luma_samples,
1000+ .sps_video_parameter_set_id = sps->sps_video_parameter_set_id,
1001+ .sps_max_sub_layers_minus1 = sps->sps_max_sub_layers_minus1,
1002+ .sps_seq_parameter_set_id = sps->sps_seq_parameter_set_id,
1003+ .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
1004+ .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
1005+ .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
1006+ .log2_min_luma_coding_block_size_minus3 = sps->log2_min_luma_coding_block_size_minus3,
1007+ .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size,
1008+ .log2_min_luma_transform_block_size_minus2 = sps->log2_min_luma_transform_block_size_minus2,
1009+ .log2_diff_max_min_luma_transform_block_size = sps->log2_diff_max_min_luma_transform_block_size,
1010+ .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
1011+ .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
1012+ .num_short_term_ref_pic_sets = sps->num_short_term_ref_pic_sets,
1013+ .num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps,
1014+ .pcm_sample_bit_depth_luma_minus1 = sps->pcm_sample_bit_depth_luma_minus1,
1015+ .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_sample_bit_depth_chroma_minus1,
1016+ .log2_min_pcm_luma_coding_block_size_minus3 = sps->log2_min_pcm_luma_coding_block_size_minus3,
1017+ .log2_diff_max_min_pcm_luma_coding_block_size = sps->log2_diff_max_min_pcm_luma_coding_block_size,
1018+ /* Reserved */
1019+ /* Reserved */
1020+ .palette_max_size = sps->palette_max_size,
1021+ .delta_palette_max_predictor_size = sps->delta_palette_max_predictor_size,
1022+ .motion_vector_resolution_control_idc = sps->motion_vector_resolution_control_idc,
1023+ .sps_num_palette_predictor_initializers_minus1 = sps->sps_num_palette_predictor_initializer_minus1,
1024+ .conf_win_left_offset = sps->conf_win_left_offset,
1025+ .conf_win_right_offset = sps->conf_win_right_offset,
1026+ .conf_win_top_offset = sps->conf_win_top_offset,
1027+ .conf_win_bottom_offset = sps->conf_win_bottom_offset,
1028+ .pProfileTierLevel = ptl_sps,
1029+ .pDecPicBufMgr = dpbm_sps,
1030+ .pScalingLists = NULL,
1031+ .pShortTermRefPicSet = str,
1032+ .pLongTermRefPicsSps = ltr,
1033+ .pSequenceParameterSetVui = vui_sps,
1034+ .pPredictorPaletteEntries = NULL,
1035+ };
1036+
1037+ /* PPS */
1038+ *vkpps = (StdVideoH265PictureParameterSet) {
1039+ .flags = (StdVideoH265PpsFlags) {
1040+ .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
1041+ .output_flag_present_flag = pps->output_flag_present_flag,
1042+ .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag,
1043+ .cabac_init_present_flag = pps->cabac_init_present_flag,
1044+ .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
1045+ .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
1046+ .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
1047+ .pps_slice_chroma_qp_offsets_present_flag = pps->pps_slice_chroma_qp_offsets_present_flag,
1048+ .weighted_pred_flag = pps->weighted_pred_flag,
1049+ .weighted_bipred_flag = pps->weighted_bipred_flag,
1050+ .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag,
1051+ .tiles_enabled_flag = pps->tiles_enabled_flag,
1052+ .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
1053+ .uniform_spacing_flag = pps->uniform_spacing_flag,
1054+ .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
1055+ .pps_loop_filter_across_slices_enabled_flag = pps->pps_loop_filter_across_slices_enabled_flag,
1056+ .deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag,
1057+ .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
1058+ .pps_deblocking_filter_disabled_flag = pps->pps_deblocking_filter_disabled_flag,
1059+ .pps_scaling_list_data_present_flag = pps->pps_scaling_list_data_present_flag,
1060+ .lists_modification_present_flag = pps->lists_modification_present_flag,
1061+ .slice_segment_header_extension_present_flag = pps->slice_segment_header_extension_present_flag,
1062+ .pps_extension_present_flag = pps->pps_extension_present_flag,
1063+ .cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag,
1064+ .chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag,
1065+ .pps_curr_pic_ref_enabled_flag = pps->pps_curr_pic_ref_enabled_flag,
1066+ .residual_adaptive_colour_transform_enabled_flag = pps->residual_adaptive_colour_transform_enabled_flag,
1067+ .pps_slice_act_qp_offsets_present_flag = pps->pps_slice_act_qp_offsets_present_flag,
1068+ .pps_palette_predictor_initializers_present_flag = pps->pps_palette_predictor_initializer_present_flag,
1069+ .monochrome_palette_flag = pps->monochrome_palette_flag,
1070+ .pps_range_extension_flag = pps->pps_range_extension_flag,
1071+ },
1072+ .pps_pic_parameter_set_id = pps->pps_pic_parameter_set_id,
1073+ .pps_seq_parameter_set_id = pps->pps_seq_parameter_set_id,
1074+ .sps_video_parameter_set_id = sps->sps_video_parameter_set_id,
1075+ .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
1076+ .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
1077+ .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
1078+ .init_qp_minus26 = pps->init_qp_minus26,
1079+ .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
1080+ .pps_cb_qp_offset = pps->pps_cb_qp_offset,
1081+ .pps_cr_qp_offset = pps->pps_cr_qp_offset,
1082+ .pps_beta_offset_div2 = pps->pps_beta_offset_div2,
1083+ .pps_tc_offset_div2 = pps->pps_tc_offset_div2,
1084+ .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2,
1085+ .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size_minus2,
1086+ .diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth,
1087+ .chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1,
1088+ .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma,
1089+ .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma,
1090+ .pps_act_y_qp_offset_plus5 = pps->pps_act_y_qp_offset_plus5,
1091+ .pps_act_cb_qp_offset_plus5 = pps->pps_act_cb_qp_offset_plus5,
1092+ .pps_act_cr_qp_offset_plus3 = pps->pps_act_cr_qp_offset_plus3,
1093+ .pps_num_palette_predictor_initializers = pps->pps_num_palette_predictor_initializer,
1094+ .luma_bit_depth_entry_minus8 = pps->luma_bit_depth_entry_minus8,
1095+ .chroma_bit_depth_entry_minus8 = pps->chroma_bit_depth_entry_minus8,
1096+ .num_tile_columns_minus1 = pps->num_tile_columns_minus1,
1097+ .num_tile_rows_minus1 = pps->num_tile_rows_minus1,
1098+ .pScalingLists = NULL,
1099+ .pPredictorPaletteEntries = NULL,
1100+ };
1101+
1102+ for (int i = 0; i < pps->num_tile_columns_minus1; i++)
1103+ vkpps->column_width_minus1[i] = pps->column_width_minus1[i];
1104+
1105+ for (int i = 0; i < pps->num_tile_rows_minus1; i++)
1106+ vkpps->row_height_minus1[i] = pps->row_height_minus1[i];
1107+
1108+ for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
1109+ vkpps->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i];
1110+ vkpps->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i];
1111+ }
1112+
1113+ /* VPS */
1114+ for (int i = 0; i < STD_VIDEO_H265_SUBLAYERS_LIST_SIZE; i++) {
1115+ dpbm_vps->max_latency_increase_plus1[i] = vps->vps_max_latency_increase_plus1[i];
1116+ dpbm_vps->max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering_minus1[i];
1117+ dpbm_vps->max_num_reorder_pics[i] = vps->vps_max_num_reorder_pics[i];
1118+ }
1119+
1120+ *ptl_vps = (StdVideoH265ProfileTierLevel) {
1121+ .flags = (StdVideoH265ProfileTierLevelFlags) {
1122+ .general_tier_flag = vps->profile_tier_level.general_tier_flag,
1123+ .general_progressive_source_flag = vps->profile_tier_level.general_progressive_source_flag,
1124+ .general_interlaced_source_flag = vps->profile_tier_level.general_interlaced_source_flag,
1125+ .general_non_packed_constraint_flag = vps->profile_tier_level.general_non_packed_constraint_flag,
1126+ .general_frame_only_constraint_flag = vps->profile_tier_level.general_frame_only_constraint_flag,
1127+ },
1128+ .general_profile_idc = ff_vk_h265_profile_to_vk(vps->profile_tier_level.general_profile_idc),
1129+ .general_level_idc = ff_vk_h265_level_to_vk(vps->profile_tier_level.general_level_idc),
1130+ };
1131+
1132+ *vkvps = (StdVideoH265VideoParameterSet) {
1133+ .flags = (StdVideoH265VpsFlags) {
1134+ .vps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag,
1135+ .vps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag,
1136+ .vps_timing_info_present_flag = vps->vps_timing_info_present_flag,
1137+ .vps_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag,
1138+ },
1139+ .vps_video_parameter_set_id = vps->vps_video_parameter_set_id,
1140+ .vps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1,
1141+ /* Reserved */
1142+ /* Reserved */
1143+ .vps_num_units_in_tick = vps->vps_num_units_in_tick,
1144+ .vps_time_scale = vps->vps_time_scale,
1145+ .vps_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one_minus1,
1146+ /* Reserved */
1147+ .pDecPicBufMgr = dpbm_vps,
1148+ .pHrdParameters = vui_header_vps,
1149+ .pProfileTierLevel = ptl_vps,
1150+ };
1151+
1152+ return 0;
1153+}
1154+
1155+static int create_session_params(AVCodecContext *avctx)
1156+{
1157+ int err;
1158+ VkResult ret;
1159+ VulkanEncodeH265Context *enc = avctx->priv_data;
1160+ FFVulkanEncodeContext *ctx = &enc->common;
1161+ FFVulkanContext *s = &ctx->s;
1162+ FFVulkanFunctions *vk = &ctx->s.vkfn;
1163+
1164+ VulkanH265Units vk_units = { 0 };
1165+
1166+ VkVideoEncodeH265SessionParametersAddInfoKHR h265_params_info;
1167+ VkVideoEncodeH265SessionParametersCreateInfoKHR h265_params;
1168+ VkVideoSessionParametersCreateInfoKHR session_params_create;
1169+
1170+ /* Convert it to Vulkan */
1171+ err = base_unit_to_vk(avctx, &vk_units);
1172+ if (err < 0) {
1173+ av_log(avctx, AV_LOG_ERROR, "Unable to convert SPS/PPS units to Vulkan: %s\n",
1174+ av_err2str(err));
1175+ return err;
1176+ }
1177+
1178+ /* Destroy the session params */
1179+ if (ctx->session_params)
1180+ vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
1181+ ctx->session_params,
1182+ s->hwctx->alloc);
1183+
1184+ h265_params_info = (VkVideoEncodeH265SessionParametersAddInfoKHR) {
1185+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR,
1186+ .pStdSPSs = &vk_units.sps,
1187+ .stdSPSCount = 1,
1188+ .pStdPPSs = &vk_units.pps,
1189+ .stdPPSCount = 1,
1190+ .pStdVPSs = &vk_units.vps,
1191+ .stdVPSCount = 1,
1192+ };
1193+ h265_params = (VkVideoEncodeH265SessionParametersCreateInfoKHR) {
1194+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
1195+ .maxStdSPSCount = 1,
1196+ .maxStdPPSCount = 1,
1197+ .maxStdVPSCount = 1,
1198+ .pParametersAddInfo = &h265_params_info,
1199+ };
1200+ session_params_create = (VkVideoSessionParametersCreateInfoKHR) {
1201+ .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
1202+ .pNext = &h265_params,
1203+ .videoSession = ctx->common.session,
1204+ .videoSessionParametersTemplate = NULL,
1205+ };
1206+
1207+ /* Create session parameters */
1208+ ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
1209+ s->hwctx->alloc, &ctx->session_params);
1210+ if (ret != VK_SUCCESS) {
1211+ av_log(avctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
1212+ ff_vk_ret2str(ret));
1213+ return AVERROR_EXTERNAL;
1214+ }
1215+
1216+ return 0;
1217+}
1218+
1219+static int parse_feedback_units(AVCodecContext *avctx,
1220+ const uint8_t *data, size_t size,
1221+ int sps_override, int pps_override)
1222+{
1223+ int err;
1224+ VulkanEncodeH265Context *enc = avctx->priv_data;
1225+
1226+ CodedBitstreamContext *cbs;
1227+ CodedBitstreamFragment au = { 0 };
1228+
1229+ err = ff_cbs_init(&cbs, AV_CODEC_ID_HEVC, avctx);
1230+ if (err < 0)
1231+ return err;
1232+
1233+ err = ff_cbs_read(cbs, &au, data, size);
1234+ if (err < 0) {
1235+ av_log(avctx, AV_LOG_ERROR, "Unable to parse feedback units, bad drivers: %s\n",
1236+ av_err2str(err));
1237+ return err;
1238+ }
1239+
1240+ if (sps_override) {
1241+ for (int i = 0; i < au.nb_units; i++) {
1242+ if (au.units[i].type == HEVC_NAL_SPS) {
1243+ H265RawSPS *sps = au.units[i].content;
1244+ enc->units.raw_sps.pic_width_in_luma_samples = sps->pic_width_in_luma_samples;
1245+ enc->units.raw_sps.pic_height_in_luma_samples = sps->pic_height_in_luma_samples;
1246+ enc->units.raw_sps.log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size;
1247+ enc->units.raw_sps.max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter;
1248+ enc->units.raw_sps.max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra;
1249+ }
1250+ }
1251+ }
1252+
1253+ /* If PPS has an override, just copy it entirely. */
1254+ if (pps_override) {
1255+ for (int i = 0; i < au.nb_units; i++) {
1256+ if (au.units[i].type == HEVC_NAL_PPS) {
1257+ H265RawPPS *pps = au.units[i].content;
1258+ memcpy(&enc->units.raw_pps, pps, sizeof(*pps));
1259+ enc->fixed_qp_idr = pps->init_qp_minus26 + 26;
1260+ break;
1261+ }
1262+ }
1263+ }
1264+
1265+ ff_cbs_fragment_free(&au);
1266+ ff_cbs_close(&cbs);
1267+
1268+ return 0;
1269+}
1270+
1271+static int init_base_units(AVCodecContext *avctx)
1272+{
1273+ int err;
1274+ VkResult ret;
1275+ VulkanEncodeH265Context *enc = avctx->priv_data;
1276+ FFVulkanEncodeContext *ctx = &enc->common;
1277+ FFVulkanContext *s = &ctx->s;
1278+ FFVulkanFunctions *vk = &ctx->s.vkfn;
1279+
1280+ VkVideoEncodeH265SessionParametersGetInfoKHR h265_params_info;
1281+ VkVideoEncodeSessionParametersGetInfoKHR params_info;
1282+ VkVideoEncodeH265SessionParametersFeedbackInfoKHR h265_params_feedback;
1283+ VkVideoEncodeSessionParametersFeedbackInfoKHR params_feedback;
1284+
1285+ void *data = NULL;
1286+ size_t data_size = 0;
1287+
1288+ /* Generate SPS/PPS unit info */
1289+ err = init_sequence_headers(avctx);
1290+ if (err < 0) {
1291+ av_log(avctx, AV_LOG_ERROR, "Unable to initialize SPS/PPS units: %s\n",
1292+ av_err2str(err));
1293+ return err;
1294+ }
1295+
1296+ /* Create session parameters from them */
1297+ err = create_session_params(avctx);
1298+ if (err < 0)
1299+ return err;
1300+
1301+ h265_params_info = (VkVideoEncodeH265SessionParametersGetInfoKHR) {
1302+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_GET_INFO_KHR,
1303+ .writeStdSPS = 1,
1304+ .writeStdPPS = 1,
1305+ .writeStdVPS = 1,
1306+ .stdSPSId = enc->units.raw_sps.sps_seq_parameter_set_id,
1307+ .stdPPSId = enc->units.raw_pps.pps_pic_parameter_set_id,
1308+ .stdVPSId = enc->units.raw_vps.vps_video_parameter_set_id,
1309+ };
1310+ params_info = (VkVideoEncodeSessionParametersGetInfoKHR) {
1311+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_GET_INFO_KHR,
1312+ .pNext = &h265_params_info,
1313+ .videoSessionParameters = ctx->session_params,
1314+ };
1315+
1316+ h265_params_feedback = (VkVideoEncodeH265SessionParametersFeedbackInfoKHR) {
1317+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
1318+ };
1319+ params_feedback = (VkVideoEncodeSessionParametersFeedbackInfoKHR) {
1320+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_SESSION_PARAMETERS_FEEDBACK_INFO_KHR,
1321+ .pNext = &h265_params_feedback,
1322+ };
1323+
1324+ ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
1325+ &params_feedback,
1326+ &data_size, data);
1327+ if (ret == VK_INCOMPLETE ||
1328+ (ret == VK_SUCCESS) && (data_size > 0)) {
1329+ data = av_mallocz(data_size);
1330+ if (!data)
1331+ return AVERROR(ENOMEM);
1332+ } else {
1333+ av_log(avctx, AV_LOG_ERROR, "Unable to get feedback for H.265 units = %lu\n", data_size);
1334+ return err;
1335+ }
1336+
1337+ ret = vk->GetEncodedVideoSessionParametersKHR(s->hwctx->act_dev, &params_info,
1338+ &params_feedback,
1339+ &data_size, data);
1340+ if (ret != VK_SUCCESS) {
1341+ av_log(avctx, AV_LOG_ERROR, "Error writing feedback units\n");
1342+ return err;
1343+ }
1344+
1345+ av_log(avctx, AV_LOG_VERBOSE, "Feedback units written, overrides: %i (SPS: %i PPS: %i VPS: %i)\n",
1346+ params_feedback.hasOverrides,
1347+ h265_params_feedback.hasStdSPSOverrides,
1348+ h265_params_feedback.hasStdPPSOverrides,
1349+ h265_params_feedback.hasStdVPSOverrides);
1350+
1351+ params_feedback.hasOverrides = 1;
1352+ h265_params_feedback.hasStdSPSOverrides = 1;
1353+ h265_params_feedback.hasStdPPSOverrides = 1;
1354+
1355+ /* No need to sync any overrides */
1356+ if (!params_feedback.hasOverrides)
1357+ return 0;
1358+
1359+ /* Parse back tne units and override */
1360+ err = parse_feedback_units(avctx, data, data_size,
1361+ h265_params_feedback.hasStdSPSOverrides,
1362+ h265_params_feedback.hasStdPPSOverrides);
1363+ if (err < 0)
1364+ return err;
1365+
1366+ /* Create final session parameters */
1367+ err = create_session_params(avctx);
1368+ if (err < 0)
1369+ return err;
1370+
1371+ return 0;
1372+}
1373+
1374+static int vulkan_encode_h265_add_nal(AVCodecContext *avctx,
1375+ CodedBitstreamFragment *au,
1376+ void *nal_unit)
1377+{
1378+ H265RawNALUnitHeader *header = nal_unit;
1379+
1380+ int err = ff_cbs_insert_unit_content(au, -1,
1381+ header->nal_unit_type, nal_unit, NULL);
1382+ if (err < 0)
1383+ av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
1384+ "type = %d.\n", header->nal_unit_type);
1385+
1386+ return err;
1387+}
1388+
1389+static int write_access_unit(AVCodecContext *avctx,
1390+ uint8_t *data, size_t *data_len,
1391+ CodedBitstreamFragment *au)
1392+{
1393+ VulkanEncodeH265Context *enc = avctx->priv_data;
1394+
1395+ int err = ff_cbs_write_fragment_data(enc->cbs, au);
1396+ if (err < 0) {
1397+ av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
1398+ return err;
1399+ }
1400+
1401+ if (*data_len < au->data_size) {
1402+ av_log(avctx, AV_LOG_ERROR, "Access unit too large: %zu < %zu.\n",
1403+ *data_len, au->data_size);
1404+ return AVERROR(ENOSPC);
1405+ }
1406+
1407+ memcpy(data, au->data, au->data_size);
1408+ *data_len = au->data_size;
1409+
1410+ return 0;
1411+}
1412+
1413+static int write_sequence_headers(AVCodecContext *avctx,
1414+ FFHWBaseEncodePicture *base_pic,
1415+ uint8_t *data, size_t *data_len)
1416+{
1417+ int err;
1418+ VulkanEncodeH265Context *enc = avctx->priv_data;
1419+ VulkanEncodeH265Picture *hp = base_pic ? base_pic->codec_priv : NULL;
1420+ CodedBitstreamFragment *au = &enc->current_access_unit;
1421+
1422+ if (hp && hp->units_needed & UNIT_AUD) {
1423+ err = vulkan_encode_h265_add_nal(avctx, au, &enc->raw_aud);
1424+ if (err < 0)
1425+ goto fail;
1426+ hp->units_needed &= ~UNIT_AUD;
1427+ }
1428+
1429+ err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_vps);
1430+ if (err < 0)
1431+ goto fail;
1432+
1433+ err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_sps);
1434+ if (err < 0)
1435+ goto fail;
1436+
1437+ err = vulkan_encode_h265_add_nal(avctx, au, &enc->units.raw_pps);
1438+ if (err < 0)
1439+ goto fail;
1440+
1441+ err = write_access_unit(avctx, data, data_len, au);
1442+fail:
1443+ ff_cbs_fragment_reset(au);
1444+ return err;
1445+}
1446+
1447+static int write_extra_headers(AVCodecContext *avctx,
1448+ FFHWBaseEncodePicture *base_pic,
1449+ uint8_t *data, size_t *data_len)
1450+{
1451+ int err;
1452+ VulkanEncodeH265Context *enc = avctx->priv_data;
1453+ VulkanEncodeH265Picture *hp = base_pic->codec_priv;
1454+ CodedBitstreamFragment *au = &enc->current_access_unit;
1455+
1456+ if (hp->units_needed & UNIT_AUD) {
1457+ err = vulkan_encode_h265_add_nal(avctx, au, &enc->raw_aud);
1458+ if (err < 0)
1459+ goto fail;
1460+ }
1461+
1462+ if (hp->units_needed & UNIT_SEI_MASTERING_DISPLAY) {
1463+ err = ff_cbs_sei_add_message(enc->cbs, au, 1,
1464+ SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME,
1465+ &enc->sei_mastering_display, NULL);
1466+ if (err < 0)
1467+ goto fail;
1468+ }
1469+
1470+ if (hp->units_needed & UNIT_SEI_CONTENT_LIGHT_LEVEL) {
1471+ err = ff_cbs_sei_add_message(enc->cbs, au, 1,
1472+ SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO,
1473+ &enc->sei_content_light_level, NULL);
1474+ if (err < 0)
1475+ goto fail;
1476+ }
1477+ if (hp->units_needed & UNIT_SEI_A53_CC) {
1478+ err = ff_cbs_sei_add_message(enc->cbs, au, 1,
1479+ SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35,
1480+ &enc->sei_a53cc, NULL);
1481+ if (err < 0)
1482+ goto fail;
1483+ }
1484+
1485+ if (hp->units_needed) {
1486+ err = write_access_unit(avctx, data, data_len, au);
1487+ if (err < 0)
1488+ goto fail;
1489+ } else {
1490+ *data_len = 0;
1491+ }
1492+
1493+fail:
1494+ ff_cbs_fragment_reset(au);
1495+ return err;
1496+}
1497+
1498+static int write_filler(AVCodecContext *avctx, uint32_t filler,
1499+ uint8_t *data, size_t *data_len)
1500+{
1501+ int err;
1502+ VulkanEncodeH265Context *enc = avctx->priv_data;
1503+ CodedBitstreamFragment *au = &enc->current_access_unit;
1504+
1505+ H265RawFiller raw_filler = {
1506+ .nal_unit_header =
1507+ {
1508+ .nal_unit_type = HEVC_NAL_FD_NUT,
1509+ .nuh_temporal_id_plus1 = 1,
1510+ },
1511+ .filler_size = filler,
1512+ };
1513+
1514+ err = vulkan_encode_h265_add_nal(avctx, au, &raw_filler);
1515+ if (err < 0)
1516+ goto fail;
1517+
1518+ err = write_access_unit(avctx, data, data_len, au);
1519+fail:
1520+ ff_cbs_fragment_reset(au);
1521+ return err;
1522+}
1523+
1524+static const FFVulkanCodec enc_cb = {
1525+ .flags = FF_HW_FLAG_B_PICTURES |
1526+ FF_HW_FLAG_B_PICTURE_REFERENCES |
1527+ FF_HW_FLAG_NON_IDR_KEY_PICTURES,
1528+ .picture_priv_data_size = sizeof(VulkanEncodeH265Picture),
1529+ .filler_header_size = 7,
1530+ .init_profile = init_profile,
1531+ .init_pic_rc = init_pic_rc,
1532+ .init_pic_params = init_pic_params,
1533+ .write_sequence_headers = write_sequence_headers,
1534+ .write_extra_headers = write_extra_headers,
1535+ .write_filler = write_filler,
1536+};
1537+
1538+static av_cold int vulkan_encode_h265_init(AVCodecContext *avctx)
1539+{
1540+ int err, ref_l0, ref_l1;
1541+ VulkanEncodeH265Context *enc = avctx->priv_data;
1542+ FFVulkanEncodeContext *ctx = &enc->common;
1543+ FFHWBaseEncodeContext *base_ctx = &ctx->base;
1544+ int flags;
1545+
1546+ if (avctx->profile == AV_PROFILE_UNKNOWN)
1547+ avctx->profile = enc->common.opts.profile;
1548+
1549+ enc->caps = (VkVideoEncodeH265CapabilitiesKHR) {
1550+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_KHR,
1551+ };
1552+
1553+ enc->quality_props = (VkVideoEncodeH265QualityLevelPropertiesKHR) {
1554+ .sType = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_QUALITY_LEVEL_PROPERTIES_KHR,
1555+ };
1556+
1557+ err = ff_vulkan_encode_init(avctx, &enc->common,
1558+ &ff_vk_enc_h265_desc, &enc_cb,
1559+ &enc->caps, &enc->quality_props);
1560+ if (err < 0)
1561+ return err;
1562+
1563+ av_log(avctx, AV_LOG_VERBOSE, "H265 encoder capabilities:\n");
1564+ av_log(avctx, AV_LOG_VERBOSE, " Standard capability flags:\n");
1565+ av_log(avctx, AV_LOG_VERBOSE, " separate_color_plane: %i\n",
1566+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SEPARATE_COLOR_PLANE_FLAG_SET_BIT_KHR));
1567+ av_log(avctx, AV_LOG_VERBOSE, " sample_adaptive_offset: %i\n",
1568+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SAMPLE_ADAPTIVE_OFFSET_ENABLED_FLAG_SET_BIT_KHR));
1569+ av_log(avctx, AV_LOG_VERBOSE, " scaling_lists: %i\n",
1570+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SCALING_LIST_DATA_PRESENT_FLAG_SET_BIT_KHR));
1571+ av_log(avctx, AV_LOG_VERBOSE, " pcm: %i\n",
1572+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_PCM_ENABLED_FLAG_SET_BIT_KHR));
1573+ av_log(avctx, AV_LOG_VERBOSE, " temporal_mvp: %i\n",
1574+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SPS_TEMPORAL_MVP_ENABLED_FLAG_SET_BIT_KHR));
1575+ av_log(avctx, AV_LOG_VERBOSE, " init_qp: %i\n",
1576+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_INIT_QP_MINUS26_BIT_KHR));
1577+ av_log(avctx, AV_LOG_VERBOSE, " weighted:%s%s\n",
1578+ enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_WEIGHTED_PRED_FLAG_SET_BIT_KHR ?
1579+ " pred" : "",
1580+ enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_WEIGHTED_BIPRED_FLAG_SET_BIT_KHR ?
1581+ " bipred" : "");
1582+ av_log(avctx, AV_LOG_VERBOSE, " parallel_merge_level: %i\n",
1583+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_KHR));
1584+ av_log(avctx, AV_LOG_VERBOSE, " sign_data_hiding: %i\n",
1585+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SIGN_DATA_HIDING_ENABLED_FLAG_SET_BIT_KHR));
1586+ av_log(avctx, AV_LOG_VERBOSE, " transform_skip:%s%s\n",
1587+ enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_SET_BIT_KHR ?
1588+ " set" : "",
1589+ enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSFORM_SKIP_ENABLED_FLAG_UNSET_BIT_KHR ?
1590+ " unset" : "");
1591+ av_log(avctx, AV_LOG_VERBOSE, " slice_chroma_qp_offsets: %i\n",
1592+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_FLAG_SET_BIT_KHR));
1593+ av_log(avctx, AV_LOG_VERBOSE, " transquant_bypass: %i\n",
1594+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_TRANSQUANT_BYPASS_ENABLED_FLAG_SET_BIT_KHR));
1595+ av_log(avctx, AV_LOG_VERBOSE, " constrained_intra_pred: %i\n",
1596+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_CONSTRAINED_INTRA_PRED_FLAG_SET_BIT_KHR));
1597+ av_log(avctx, AV_LOG_VERBOSE, " entrypy_coding_sync: %i\n",
1598+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_ENTROPY_CODING_SYNC_ENABLED_FLAG_SET_BIT_KHR));
1599+ av_log(avctx, AV_LOG_VERBOSE, " dependent_slice_segment:%s%s\n",
1600+ enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENTS_ENABLED_FLAG_SET_BIT_KHR ?
1601+ " enabled" : "",
1602+ enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DEPENDENT_SLICE_SEGMENT_FLAG_SET_BIT_KHR ?
1603+ " set" : "");
1604+ av_log(avctx, AV_LOG_VERBOSE, " slice_qp_delta: %i\n",
1605+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_SLICE_QP_DELTA_BIT_KHR));
1606+ av_log(avctx, AV_LOG_VERBOSE, " different_slice_qp_delta: %i\n",
1607+ !!(enc->caps.stdSyntaxFlags & VK_VIDEO_ENCODE_H265_STD_DIFFERENT_SLICE_QP_DELTA_BIT_KHR));
1608+
1609+ av_log(avctx, AV_LOG_VERBOSE, " Capability flags:\n");
1610+ av_log(avctx, AV_LOG_VERBOSE, " hdr_compliance: %i\n",
1611+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR));
1612+ av_log(avctx, AV_LOG_VERBOSE, " pred_weight_table_generated: %i\n",
1613+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR));
1614+ av_log(avctx, AV_LOG_VERBOSE, " row_unaligned_slice: %i\n",
1615+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR));
1616+ av_log(avctx, AV_LOG_VERBOSE, " different_slice_type: %i\n",
1617+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR));
1618+ av_log(avctx, AV_LOG_VERBOSE, " b_frame_in_l0_list: %i\n",
1619+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR));
1620+ av_log(avctx, AV_LOG_VERBOSE, " b_frame_in_l1_list: %i\n",
1621+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR));
1622+ av_log(avctx, AV_LOG_VERBOSE, " per_pict_type_min_max_qp: %i\n",
1623+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR));
1624+ av_log(avctx, AV_LOG_VERBOSE, " per_slice_constant_qp: %i\n",
1625+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR));
1626+ av_log(avctx, AV_LOG_VERBOSE, " generate_prefix_nalu: %i\n",
1627+ !!(enc->caps.flags & VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR));
1628+
1629+ av_log(avctx, AV_LOG_VERBOSE, " Capabilities:\n");
1630+ av_log(avctx, AV_LOG_VERBOSE, " maxLevelIdc: %i\n",
1631+ enc->caps.maxLevelIdc);
1632+ av_log(avctx, AV_LOG_VERBOSE, " maxSliceCount: %i\n",
1633+ enc->caps.maxSliceSegmentCount);
1634+ av_log(avctx, AV_LOG_VERBOSE, " maxTiles: %ix%i\n",
1635+ enc->caps.maxTiles.width, enc->caps.maxTiles.height);
1636+ av_log(avctx, AV_LOG_VERBOSE, " cbtSizes: 0x%x\n",
1637+ enc->caps.ctbSizes);
1638+ av_log(avctx, AV_LOG_VERBOSE, " transformBlockSizes: 0x%x\n",
1639+ enc->caps.transformBlockSizes);
1640+ av_log(avctx, AV_LOG_VERBOSE, " max(P/B)PictureL0ReferenceCount: %i P's; %i B's\n",
1641+ enc->caps.maxPPictureL0ReferenceCount,
1642+ enc->caps.maxBPictureL0ReferenceCount);
1643+ av_log(avctx, AV_LOG_VERBOSE, " maxL1ReferenceCount: %i\n",
1644+ enc->caps.maxL1ReferenceCount);
1645+ av_log(avctx, AV_LOG_VERBOSE, " maxSubLayerCount: %i\n",
1646+ enc->caps.maxSubLayerCount);
1647+ av_log(avctx, AV_LOG_VERBOSE, " expectDyadicTemporalLayerPattern: %i\n",
1648+ enc->caps.expectDyadicTemporalSubLayerPattern);
1649+ av_log(avctx, AV_LOG_VERBOSE, " min/max Qp: [%i, %i]\n",
1650+ enc->caps.minQp, enc->caps.maxQp);
1651+ av_log(avctx, AV_LOG_VERBOSE, " prefersGopRemainingFrames: %i\n",
1652+ enc->caps.prefersGopRemainingFrames);
1653+ av_log(avctx, AV_LOG_VERBOSE, " requiresGopRemainingFrames: %i\n",
1654+ enc->caps.requiresGopRemainingFrames);
1655+
1656+ err = init_enc_options(avctx);
1657+ if (err < 0)
1658+ return err;
1659+
1660+ flags = ctx->codec->flags;
1661+ if (!enc->caps.maxPPictureL0ReferenceCount &&
1662+ !enc->caps.maxBPictureL0ReferenceCount &&
1663+ !enc->caps.maxL1ReferenceCount) {
1664+ /* Intra-only */
1665+ flags |= FF_HW_FLAG_INTRA_ONLY;
1666+ ref_l0 = ref_l1 = 0;
1667+ } else if (!enc->caps.maxPPictureL0ReferenceCount) {
1668+ /* No P-frames? How. */
1669+ base_ctx->p_to_gpb = 1;
1670+ ref_l0 = enc->caps.maxBPictureL0ReferenceCount;
1671+ ref_l1 = enc->caps.maxL1ReferenceCount;
1672+ } else if (!enc->caps.maxBPictureL0ReferenceCount &&
1673+ !enc->caps.maxL1ReferenceCount) {
1674+ /* No B-frames */
1675+ flags &= ~(FF_HW_FLAG_B_PICTURES | FF_HW_FLAG_B_PICTURE_REFERENCES);
1676+ ref_l0 = enc->caps.maxPPictureL0ReferenceCount;
1677+ ref_l1 = 0;
1678+ } else {
1679+ /* P and B frames */
1680+ ref_l0 = FFMIN(enc->caps.maxPPictureL0ReferenceCount,
1681+ enc->caps.maxBPictureL0ReferenceCount);
1682+ ref_l1 = enc->caps.maxL1ReferenceCount;
1683+ }
1684+
1685+ err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1,
1686+ flags, 0);
1687+ if (err < 0)
1688+ return err;
1689+
1690+ base_ctx->output_delay = base_ctx->b_per_p;
1691+ base_ctx->decode_delay = base_ctx->max_b_depth;
1692+
1693+ /* Init CBS */
1694+ err = ff_cbs_init(&enc->cbs, AV_CODEC_ID_HEVC, avctx);
1695+ if (err < 0)
1696+ return err;
1697+
1698+ /* Create units and session parameters */
1699+ err = init_base_units(avctx);
1700+ if (err < 0)
1701+ return err;
1702+
1703+ /* Write out extradata */
1704+ err = ff_vulkan_write_global_header(avctx, &enc->common);
1705+ if (err < 0)
1706+ return err;
1707+
1708+ return 0;
1709+}
1710+
1711+static av_cold int vulkan_encode_h265_close(AVCodecContext *avctx)
1712+{
1713+ VulkanEncodeH265Context *enc = avctx->priv_data;
1714+ ff_vulkan_encode_uninit(&enc->common);
1715+ return 0;
1716+}
1717+
1718+#define OFFSET(x) offsetof(VulkanEncodeH265Context, x)
1719+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1720+static const AVOption vulkan_encode_h265_options[] = {
1721+ HW_BASE_ENCODE_COMMON_OPTIONS,
1722+ VULKAN_ENCODE_COMMON_OPTIONS,
1723+
1724+ { "profile", "Set profile (profile_idc and constraint_set*_flag)",
1725+ OFFSET(common.opts.profile), AV_OPT_TYPE_INT,
1726+ { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xffff, FLAGS, .unit = "profile" },
1727+
1728+#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1729+ { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
1730+ { PROFILE("main", AV_PROFILE_HEVC_MAIN) },
1731+ { PROFILE("main10", AV_PROFILE_HEVC_MAIN_10) },
1732+ { PROFILE("rext", AV_PROFILE_HEVC_REXT) },
1733+#undef PROFILE
1734+
1735+ { "tier", "Set tier (general_tier_flag)", OFFSET(common.opts.tier), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "tier" },
1736+ { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, .unit = "tier" },
1737+ { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, .unit = "tier" },
1738+
1739+ { "level", "Set level (general_level_idc)",
1740+ OFFSET(common.opts.level), AV_OPT_TYPE_INT,
1741+ { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, .unit = "level" },
1742+
1743+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1744+ { .i64 = value }, 0, 0, FLAGS, .unit = "level"
1745+ { LEVEL("1", 30) },
1746+ { LEVEL("2", 60) },
1747+ { LEVEL("2.1", 63) },
1748+ { LEVEL("3", 90) },
1749+ { LEVEL("3.1", 93) },
1750+ { LEVEL("4", 120) },
1751+ { LEVEL("4.1", 123) },
1752+ { LEVEL("5", 150) },
1753+ { LEVEL("5.1", 153) },
1754+ { LEVEL("5.2", 156) },
1755+ { LEVEL("6", 180) },
1756+ { LEVEL("6.1", 183) },
1757+ { LEVEL("6.2", 186) },
1758+#undef LEVEL
1759+
1760+ { "units", "Set units to include", OFFSET(unit_elems), AV_OPT_TYPE_FLAGS, { .i64 = UNIT_SEI_MASTERING_DISPLAY | UNIT_SEI_CONTENT_LIGHT_LEVEL | UNIT_SEI_A53_CC }, 0, INT_MAX, FLAGS, "units" },
1761+ { "hdr", "Include HDR metadata for mastering display colour volume and content light level information", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_MASTERING_DISPLAY | UNIT_SEI_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "units" },
1762+ { "a53_cc", "Include A/53 caption data", 0, AV_OPT_TYPE_CONST, { .i64 = UNIT_SEI_A53_CC }, INT_MIN, INT_MAX, FLAGS, "units" },
1763+
1764+ { NULL },
1765+};
1766+
1767+static const FFCodecDefault vulkan_encode_h265_defaults[] = {
1768+ { "b", "0" },
1769+ { "bf", "2" },
1770+ { "g", "300" },
1771+ { "i_qfactor", "1" },
1772+ { "i_qoffset", "0" },
1773+ { "b_qfactor", "6/5" },
1774+ { "b_qoffset", "0" },
1775+ { "qmin", "-1" },
1776+ { "qmax", "-1" },
1777+ { NULL },
1778+};
1779+
1780+static const AVClass vulkan_encode_h265_class = {
1781+ .class_name = "hevc_vulkan",
1782+ .item_name = av_default_item_name,
1783+ .option = vulkan_encode_h265_options,
1784+ .version = LIBAVUTIL_VERSION_INT,
1785+};
1786+
1787+const FFCodec ff_hevc_vulkan_encoder = {
1788+ .p.name = "hevc_vulkan",
1789+ CODEC_LONG_NAME("H.265/HEVC (Vulkan)"),
1790+ .p.type = AVMEDIA_TYPE_VIDEO,
1791+ .p.id = AV_CODEC_ID_HEVC,
1792+ .priv_data_size = sizeof(VulkanEncodeH265Context),
1793+ .init = &vulkan_encode_h265_init,
1794+ FF_CODEC_RECEIVE_PACKET_CB(&ff_vulkan_encode_receive_packet),
1795+ .close = &vulkan_encode_h265_close,
1796+ .p.priv_class = &vulkan_encode_h265_class,
1797+ .p.capabilities = AV_CODEC_CAP_DELAY |
1798+ AV_CODEC_CAP_HARDWARE |
1799+ AV_CODEC_CAP_DR1 |
1800+ AV_CODEC_CAP_ENCODER_FLUSH |
1801+ AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
1802+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1803+ .defaults = vulkan_encode_h265_defaults,
1804+ .p.pix_fmts = (const enum AVPixelFormat[]) {
1805+ AV_PIX_FMT_VULKAN,
1806+ AV_PIX_FMT_NONE,
1807+ },
1808+ .hw_configs = ff_vulkan_encode_hw_configs,
1809+ .p.wrapper_name = "vulkan",
1810+};
libavcodec/vulkan_hevc.c+3−22
@@ -179,25 +179,6 @@ static int vk_hevc_fill_pict(AVCodecContext *avctx, HEVCFrame **ref_src, · 178 unmodified lines
179179 return 0;
180180 }
181181
182−static StdVideoH265LevelIdc convert_to_vk_level_idc(int level_idc)
183−{
184− switch (level_idc) {
185− case 10: return STD_VIDEO_H265_LEVEL_IDC_1_0;
186− case 20: return STD_VIDEO_H265_LEVEL_IDC_2_0;
187− case 21: return STD_VIDEO_H265_LEVEL_IDC_2_1;
188− case 30: return STD_VIDEO_H265_LEVEL_IDC_3_0;
189− case 31: return STD_VIDEO_H265_LEVEL_IDC_3_1;
190− case 40: return STD_VIDEO_H265_LEVEL_IDC_4_0;
191− case 41: return STD_VIDEO_H265_LEVEL_IDC_4_1;
192− case 50: return STD_VIDEO_H265_LEVEL_IDC_5_0;
193− case 51: return STD_VIDEO_H265_LEVEL_IDC_5_1;
194− case 60: return STD_VIDEO_H265_LEVEL_IDC_6_0;
195− case 61: return STD_VIDEO_H265_LEVEL_IDC_6_1;
196− default:
197− case 62: return STD_VIDEO_H265_LEVEL_IDC_6_2;
198− }
199−}
200−
201182 static void copy_scaling_list(const ScalingList *sl, StdVideoH265ScalingLists *vksl)
202183 {
203184 for (int i = 0; i < STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS; i++) {
@@ -338,7 +319,7 @@ static void set_sps(const HEVCSPS *sps, int sps_idx, · 134 unmodified lines
338319 .general_frame_only_constraint_flag = sps->ptl.general_ptl.frame_only_constraint_flag,
339320 },
340321 .general_profile_idc = sps->ptl.general_ptl.profile_idc,
341− .general_level_idc = convert_to_vk_level_idc(sps->ptl.general_ptl.level_idc),
322+ .general_level_idc = ff_vk_h265_level_to_vk(sps->ptl.general_ptl.level_idc),
342323 };
343324
344325 for (int i = 0; i < sps->max_sub_layers; i++) {
@@ -607,8 +588,8 @@ static void set_vps(const HEVCVPS *vps, · 262 unmodified lines
607588 .general_non_packed_constraint_flag = vps->ptl.general_ptl.non_packed_constraint_flag,
608589 .general_frame_only_constraint_flag = vps->ptl.general_ptl.frame_only_constraint_flag,
609590 },
610− .general_profile_idc = vps->ptl.general_ptl.profile_idc,
611− .general_level_idc = convert_to_vk_level_idc(vps->ptl.general_ptl.level_idc),
591+ .general_profile_idc = ff_vk_h265_profile_to_vk(vps->ptl.general_ptl.profile_idc),
592+ .general_level_idc = ff_vk_h265_level_to_vk(vps->ptl.general_ptl.level_idc),
612593 };
613594
614595 for (int i = 0; i < vps->vps_max_sub_layers; i++) {
libavcodec/vulkan_video.c+39−0
@@ -203,6 +203,25 @@ int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level) · 202 unmodified lines
203203 }
204204 }
205205
206+StdVideoH265LevelIdc ff_vk_h265_level_to_vk(int level_idc)
207+{
208+ switch (level_idc) {
209+ case 10: return STD_VIDEO_H265_LEVEL_IDC_1_0;
210+ case 20: return STD_VIDEO_H265_LEVEL_IDC_2_0;
211+ case 21: return STD_VIDEO_H265_LEVEL_IDC_2_1;
212+ case 30: return STD_VIDEO_H265_LEVEL_IDC_3_0;
213+ case 31: return STD_VIDEO_H265_LEVEL_IDC_3_1;
214+ case 40: return STD_VIDEO_H265_LEVEL_IDC_4_0;
215+ case 41: return STD_VIDEO_H265_LEVEL_IDC_4_1;
216+ case 50: return STD_VIDEO_H265_LEVEL_IDC_5_0;
217+ case 51: return STD_VIDEO_H265_LEVEL_IDC_5_1;
218+ case 60: return STD_VIDEO_H265_LEVEL_IDC_6_0;
219+ case 61: return STD_VIDEO_H265_LEVEL_IDC_6_1;
220+ default:
221+ case 62: return STD_VIDEO_H265_LEVEL_IDC_6_2;
222+ }
223+}
224+
206225 StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile)
207226 {
208227 switch (profile) {
@@ -214,6 +233,16 @@ StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile) · 5 unmodified lines
214233 }
215234 }
216235
236+StdVideoH265ProfileIdc ff_vk_h265_profile_to_vk(int profile)
237+{
238+ switch (profile) {
239+ case AV_PROFILE_HEVC_MAIN: return STD_VIDEO_H265_PROFILE_IDC_MAIN;
240+ case AV_PROFILE_HEVC_MAIN_10: return STD_VIDEO_H265_PROFILE_IDC_MAIN_10;
241+ case AV_PROFILE_HEVC_REXT: return STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS;
242+ default: return STD_VIDEO_H265_PROFILE_IDC_INVALID;
243+ }
244+}
245+
217246 int ff_vk_h264_profile_to_av(StdVideoH264ProfileIdc profile)
218247 {
219248 switch (profile) {
@@ -225,6 +254,16 @@ int ff_vk_h264_profile_to_av(StdVideoH264ProfileIdc profile) · 5 unmodified lines
225254 }
226255 }
227256
257+int ff_vk_h265_profile_to_av(StdVideoH264ProfileIdc profile)
258+{
259+ switch (profile) {
260+ case STD_VIDEO_H265_PROFILE_IDC_MAIN: return AV_PROFILE_HEVC_MAIN;
261+ case STD_VIDEO_H265_PROFILE_IDC_MAIN_10: return AV_PROFILE_HEVC_MAIN_10;
262+ case STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS: return AV_PROFILE_HEVC_REXT;
263+ default: return AV_PROFILE_UNKNOWN;
264+ }
265+}
266+
228267 int ff_vk_video_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf,
229268 VkQueueFlagBits family, VkVideoCodecOperationFlagBitsKHR caps)
230269 {
libavcodec/vulkan_video.h+3−0
@@ -76,12 +76,15 @@ int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level); · 75 unmodified lines
7676 int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level);
7777
7878 StdVideoH264LevelIdc ff_vk_h264_level_to_vk(int level_idc);
79+StdVideoH265LevelIdc ff_vk_h265_level_to_vk(int level_idc);
7980
8081 /**
8182 * Convert profile from/to AV to Vulkan
8283 */
8384 StdVideoH264ProfileIdc ff_vk_h264_profile_to_vk(int profile);
85+StdVideoH265ProfileIdc ff_vk_h265_profile_to_vk(int profile);
8486 int ff_vk_h264_profile_to_av(StdVideoH264ProfileIdc profile);
87+int ff_vk_h265_profile_to_av(StdVideoH264ProfileIdc profile);
8588
8689 /**
8790 * 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