FFmpeg
Loading...
Searching...
No Matches
vulkan_h264.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "libavutil/mem.h"
20
21#include "h264dec.h"
22#include "h264_ps.h"
23
24#include "vulkan_decode.h"
25
27 .codec_id = AV_CODEC_ID_H264,
28 .decode_extension = FF_VK_EXT_VIDEO_DECODE_H264,
29 .queue_flags = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
30 .decode_op = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR,
31 .ext_props = {
32 .extensionName = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME,
33 .specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION,
34 },
35};
36
39
40 /* DPB slot the picture was decoded into, and a PICT_* mask of what was */
41 int slot;
43
44 /* Current picture */
45 StdVideoDecodeH264ReferenceInfo h264_ref;
46 VkVideoDecodeH264DpbSlotInfoKHR vkh264_ref;
47
48 /* Picture refs */
50 StdVideoDecodeH264ReferenceInfo h264_refs [H264_MAX_PICTURE_COUNT];
51 VkVideoDecodeH264DpbSlotInfoKHR vkh264_refs[H264_MAX_PICTURE_COUNT];
52
53 /* Current picture (contd.) */
54 StdVideoDecodeH264PictureInfo h264pic;
55 VkVideoDecodeH264PictureInfoKHR h264_pic_info;
57
58const static int h264_scaling_list8_order[] = { 0, 3, 1, 4, 2, 5 };
59
60/* Returns 1 if the picture was bound, 0 if it cannot be */
61static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src,
62 VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */
63 VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */
64 VkVideoDecodeH264DpbSlotInfoKHR *vkh264_ref, /* Goes in ^ */
65 StdVideoDecodeH264ReferenceInfo *h264_ref, /* Goes in ^ */
66 H264Picture *pic, int is_current,
67 int is_field, int picture_structure)
68{
69 const H264Context *h = avctx->priv_data;
73 FFVulkanDecodePicture *vkpic = &hp->vp;
74 int err;
75
76 if (is_current) {
77 /* Frame num gap dummies carry the duplicated picture's state, and with
78 * it its slot, which thus outlives that picture's DPB entry. Slots
79 * cannot follow DPB indices then: take the lowest one no reference
80 * holds when the picture is first decoded. */
81 if (!hp->decoded) {
82 uint32_t used = 0, free_slots;
83
84 for (int i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
85 const H264VulkanDecodePicture *p = h->DPB[i].hwaccel_picture_private;
86 if ((h->DPB[i].reference & PICT_FRAME) && p && p->decoded)
87 used |= 1U << p->slot;
88 }
89
90 /* ff_ctz(0) is undefined; a fully-set mask means no slot is free */
91 free_slots = ~used;
92 hp->slot = free_slots ? ff_ctz(free_slots) : ctx->caps.maxDpbSlots;
93 if (hp->slot >= ctx->caps.maxDpbSlots) {
94 av_log(avctx, AV_LOG_ERROR, "Not enough DPB slots for the "
95 "stream's references\n");
96 return AVERROR(ENOTSUP);
97 }
98 }
99 } else {
100 H264VulkanDecodePicture *cur = h->cur_pic_ptr->hwaccel_picture_private;
101
102 /* A slot only holds what was decoded into it: not the pictures the
103 * decoder synthesizes to fill frame_num gaps or to stand in for
104 * missing references, nor fields lost to a seek. */
105 picture_structure &= hp->decoded;
106 if (!picture_structure)
107 return 0;
108
109 /* Frame_num gap dummies share the duplicated picture's state, and a
110 * slot can only be bound once. */
111 for (H264Picture **p = cur->ref_src; p < ref_src; p++)
112 if ((*p)->hwaccel_picture_private == hp)
113 return 0;
114 }
115
116 err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
117 dec->dedicated_dpb);
118 if (err < 0)
119 return err;
120
121 *h264_ref = (StdVideoDecodeH264ReferenceInfo) {
122 .FrameNum = pic->long_ref ? pic->pic_id : pic->frame_num,
123 .PicOrderCnt = { pic->field_poc[0], pic->field_poc[1] },
124 .flags = (StdVideoDecodeH264ReferenceInfoFlags) {
125 .top_field_flag = is_field ? !!(picture_structure & PICT_TOP_FIELD) : 0,
126 .bottom_field_flag = is_field ? !!(picture_structure & PICT_BOTTOM_FIELD) : 0,
127 .used_for_long_term_reference = pic->reference && pic->long_ref,
128 /*
129 * flags.is_non_existing is used to indicate whether the picture is marked as
130 * “non-existing” as defined in section 8.2.5.2 of the ITU-T H.264 Specification;
131 * 8.2.5.2 Decoding process for gaps in frame_num
132 * corresponds to the code in h264_slice.c:h264_field_start,
133 * which sets the invalid_gap flag when decoding.
134 */
135 .is_non_existing = pic->invalid_gap,
136 },
137 };
138
139 *vkh264_ref = (VkVideoDecodeH264DpbSlotInfoKHR) {
140 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR,
141 .pStdReferenceInfo = h264_ref,
142 };
143
144 *ref = (VkVideoPictureResourceInfoKHR) {
145 .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
146 .codedOffset = (VkOffset2D){ 0, 0 },
147 .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
148 .baseArrayLayer = ctx->common.layered_dpb ? hp->slot : 0,
149 .imageViewBinding = vkpic->view.ref,
150 };
151
152 *ref_slot = (VkVideoReferenceSlotInfoKHR) {
153 .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
154 .pNext = vkh264_ref,
155 .slotIndex = hp->slot,
156 .pPictureResource = ref,
157 };
158
159 if (ref_src)
160 *ref_src = pic;
161
162 return 1;
163}
164
165static StdVideoH264LevelIdc convert_to_vk_level_idc(int level_idc)
166{
167 switch (level_idc) {
168 case 10: return STD_VIDEO_H264_LEVEL_IDC_1_0;
169 case 11: return STD_VIDEO_H264_LEVEL_IDC_1_1;
170 case 12: return STD_VIDEO_H264_LEVEL_IDC_1_2;
171 case 13: return STD_VIDEO_H264_LEVEL_IDC_1_3;
172 case 20: return STD_VIDEO_H264_LEVEL_IDC_2_0;
173 case 21: return STD_VIDEO_H264_LEVEL_IDC_2_1;
174 case 22: return STD_VIDEO_H264_LEVEL_IDC_2_2;
175 case 30: return STD_VIDEO_H264_LEVEL_IDC_3_0;
176 case 31: return STD_VIDEO_H264_LEVEL_IDC_3_1;
177 case 32: return STD_VIDEO_H264_LEVEL_IDC_3_2;
178 case 40: return STD_VIDEO_H264_LEVEL_IDC_4_0;
179 case 41: return STD_VIDEO_H264_LEVEL_IDC_4_1;
180 case 42: return STD_VIDEO_H264_LEVEL_IDC_4_2;
181 case 50: return STD_VIDEO_H264_LEVEL_IDC_5_0;
182 case 51: return STD_VIDEO_H264_LEVEL_IDC_5_1;
183 case 52: return STD_VIDEO_H264_LEVEL_IDC_5_2;
184 case 60: return STD_VIDEO_H264_LEVEL_IDC_6_0;
185 case 61: return STD_VIDEO_H264_LEVEL_IDC_6_1;
186 default:
187 case 62: return STD_VIDEO_H264_LEVEL_IDC_6_2;
188 }
189}
190
191static void set_sps(const SPS *sps,
192 StdVideoH264ScalingLists *vksps_scaling,
193 StdVideoH264HrdParameters *vksps_vui_header,
194 StdVideoH264SequenceParameterSetVui *vksps_vui,
195 StdVideoH264SequenceParameterSet *vksps)
196{
197 *vksps_scaling = (StdVideoH264ScalingLists) {
198 .scaling_list_present_mask = sps->scaling_matrix_present_mask,
199 .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */
200 };
201
202 for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
203 for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS; j++)
204 vksps_scaling->ScalingList4x4[i][j] = sps->scaling_matrix4[i][ff_zigzag_scan[j]];
205
206 for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++)
207 for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS; j++)
208 vksps_scaling->ScalingList8x8[i][j] =
209 sps->scaling_matrix8[h264_scaling_list8_order[i]][ff_zigzag_direct[j]];
210
211 *vksps_vui_header = (StdVideoH264HrdParameters) {
212 .cpb_cnt_minus1 = sps->cpb_cnt - 1,
213 .bit_rate_scale = sps->bit_rate_scale,
214 .initial_cpb_removal_delay_length_minus1 = sps->initial_cpb_removal_delay_length - 1,
215 .cpb_removal_delay_length_minus1 = sps->cpb_removal_delay_length - 1,
216 .dpb_output_delay_length_minus1 = sps->dpb_output_delay_length - 1,
217 .time_offset_length = sps->time_offset_length,
218 };
219
220 for (int i = 0; i < sps->cpb_cnt; i++) {
221 vksps_vui_header->bit_rate_value_minus1[i] = sps->bit_rate_value[i] - 1;
222 vksps_vui_header->cpb_size_value_minus1[i] = sps->cpb_size_value[i] - 1;
223 vksps_vui_header->cbr_flag[i] = (sps->cpr_flag >> i) & 0x1;
224 }
225
226 *vksps_vui = (StdVideoH264SequenceParameterSetVui) {
227 .aspect_ratio_idc = sps->vui.aspect_ratio_idc,
228 .sar_width = sps->vui.sar.num,
229 .sar_height = sps->vui.sar.den,
230 .video_format = sps->vui.video_format,
231 .colour_primaries = sps->vui.colour_primaries,
232 .transfer_characteristics = sps->vui.transfer_characteristics,
233 .matrix_coefficients = sps->vui.matrix_coeffs,
234 .num_units_in_tick = sps->num_units_in_tick,
235 .time_scale = sps->time_scale,
236 .pHrdParameters = vksps_vui_header,
237 .max_num_reorder_frames = sps->num_reorder_frames,
238 .max_dec_frame_buffering = sps->max_dec_frame_buffering,
239 .flags = (StdVideoH264SpsVuiFlags) {
240 .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag,
241 .overscan_info_present_flag = sps->vui.overscan_info_present_flag,
242 .overscan_appropriate_flag = sps->vui.overscan_appropriate_flag,
243 .video_signal_type_present_flag = sps->vui.video_signal_type_present_flag,
244 .video_full_range_flag = sps->vui.video_full_range_flag,
245 .color_description_present_flag = sps->vui.colour_description_present_flag,
246 .chroma_loc_info_present_flag = sps->vui.chroma_loc_info_present_flag,
247 .timing_info_present_flag = sps->timing_info_present_flag,
248 .fixed_frame_rate_flag = sps->fixed_frame_rate_flag,
249 .bitstream_restriction_flag = sps->bitstream_restriction_flag,
250 .nal_hrd_parameters_present_flag = sps->nal_hrd_parameters_present_flag,
251 .vcl_hrd_parameters_present_flag = sps->vcl_hrd_parameters_present_flag,
252 },
253 };
254
255 *vksps = (StdVideoH264SequenceParameterSet) {
256 .profile_idc = sps->profile_idc,
257 .level_idc = convert_to_vk_level_idc(sps->level_idc),
258 .seq_parameter_set_id = sps->sps_id,
259 .chroma_format_idc = sps->chroma_format_idc,
260 .bit_depth_luma_minus8 = sps->bit_depth_luma - 8,
261 .bit_depth_chroma_minus8 = sps->bit_depth_chroma - 8,
262 .log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4,
263 .pic_order_cnt_type = sps->poc_type,
264 .log2_max_pic_order_cnt_lsb_minus4 = sps->poc_type ? 0 : sps->log2_max_poc_lsb - 4,
265 .offset_for_non_ref_pic = sps->offset_for_non_ref_pic,
266 .offset_for_top_to_bottom_field = sps->offset_for_top_to_bottom_field,
267 .num_ref_frames_in_pic_order_cnt_cycle = sps->poc_cycle_length,
268 .max_num_ref_frames = sps->ref_frame_count,
269 .pic_width_in_mbs_minus1 = sps->mb_width - 1,
270 .pic_height_in_map_units_minus1 = (sps->mb_height/(2 - sps->frame_mbs_only_flag)) - 1,
271 .frame_crop_left_offset = sps->crop_left,
272 .frame_crop_right_offset = sps->crop_right,
273 .frame_crop_top_offset = sps->crop_top,
274 .frame_crop_bottom_offset = sps->crop_bottom,
275 .flags = (StdVideoH264SpsFlags) {
276 .constraint_set0_flag = (sps->constraint_set_flags >> 0) & 0x1,
277 .constraint_set1_flag = (sps->constraint_set_flags >> 1) & 0x1,
278 .constraint_set2_flag = (sps->constraint_set_flags >> 2) & 0x1,
279 .constraint_set3_flag = (sps->constraint_set_flags >> 3) & 0x1,
280 .constraint_set4_flag = (sps->constraint_set_flags >> 4) & 0x1,
281 .constraint_set5_flag = (sps->constraint_set_flags >> 5) & 0x1,
282 .direct_8x8_inference_flag = sps->direct_8x8_inference_flag,
283 .mb_adaptive_frame_field_flag = sps->mb_aff,
284 .frame_mbs_only_flag = sps->frame_mbs_only_flag,
285 .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag,
286 .separate_colour_plane_flag = sps->residual_color_transform_flag,
287 .gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag,
288 .qpprime_y_zero_transform_bypass_flag = sps->transform_bypass,
289 .frame_cropping_flag = sps->crop,
290 .seq_scaling_matrix_present_flag = sps->scaling_matrix_present,
291 .vui_parameters_present_flag = sps->vui_parameters_present_flag,
292 },
293 .pOffsetForRefFrame = sps->offset_for_ref_frame,
294 .pScalingLists = vksps_scaling,
295 .pSequenceParameterSetVui = vksps_vui,
296 };
297}
298
299static void set_pps(const PPS *pps, const SPS *sps,
300 StdVideoH264ScalingLists *vkpps_scaling,
301 StdVideoH264PictureParameterSet *vkpps)
302{
303 *vkpps_scaling = (StdVideoH264ScalingLists) {
304 .scaling_list_present_mask = pps->pic_scaling_matrix_present_mask,
305 .use_default_scaling_matrix_mask = 0, /* We already fill in the default matrix */
306 };
307
308 for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS; i++)
309 for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS; j++)
310 vkpps_scaling->ScalingList4x4[i][j] = pps->scaling_matrix4[i][ff_zigzag_scan[j]];
311
312 for (int i = 0; i < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS; i++)
313 for (int j = 0; j < STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS; j++)
314 vkpps_scaling->ScalingList8x8[i][j] =
315 pps->scaling_matrix8[h264_scaling_list8_order[i]][ff_zigzag_direct[j]];
316
317 *vkpps = (StdVideoH264PictureParameterSet) {
318 .seq_parameter_set_id = pps->sps_id,
319 .pic_parameter_set_id = pps->pps_id,
320 .num_ref_idx_l0_default_active_minus1 = pps->ref_count[0] - 1,
321 .num_ref_idx_l1_default_active_minus1 = pps->ref_count[1] - 1,
322 .weighted_bipred_idc = pps->weighted_bipred_idc,
323 .pic_init_qp_minus26 = pps->init_qp - 26,
324 .pic_init_qs_minus26 = pps->init_qs - 26,
325 .chroma_qp_index_offset = pps->chroma_qp_index_offset[0],
326 .second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1],
327 .flags = (StdVideoH264PpsFlags) {
328 .transform_8x8_mode_flag = pps->transform_8x8_mode,
329 .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present,
330 .constrained_intra_pred_flag = pps->constrained_intra_pred,
331 .deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present,
332 .weighted_pred_flag = pps->weighted_pred,
333 .bottom_field_pic_order_in_frame_present_flag = pps->pic_order_present,
334 .entropy_coding_mode_flag = pps->cabac,
335 .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag,
336 },
337 .pScalingLists = vkpps_scaling,
338 };
339}
340
341/* Too large to put on the stack: musl's default thread stack is 128KiB */
342typedef struct VulkanH264Params {
343 /* SPS */
344 StdVideoH264ScalingLists vksps_scaling[MAX_SPS_COUNT];
345 StdVideoH264HrdParameters vksps_vui_header[MAX_SPS_COUNT];
346 StdVideoH264SequenceParameterSetVui vksps_vui[MAX_SPS_COUNT];
347 StdVideoH264SequenceParameterSet vksps[MAX_SPS_COUNT];
348
349 /* PPS */
350 StdVideoH264ScalingLists vkpps_scaling[MAX_PPS_COUNT];
351 StdVideoH264PictureParameterSet vkpps[MAX_PPS_COUNT];
353
354static int vk_h264_create_params(AVCodecContext *avctx, VkVideoSessionParametersKHR **buf)
355{
356 int err;
359 const H264Context *h = avctx->priv_data;
360
361 VulkanH264Params *par = av_malloc(sizeof(*par));
362 if (!par)
363 return AVERROR(ENOMEM);
364
365 VkVideoDecodeH264SessionParametersAddInfoKHR h264_params_info = {
366 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR,
367 .pStdSPSs = par->vksps,
368 .stdSPSCount = 0,
369 .pStdPPSs = par->vkpps,
370 .stdPPSCount = 0,
371 };
372 VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
373 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
374 .pParametersAddInfo = &h264_params_info,
375 };
376 VkVideoSessionParametersCreateInfoKHR session_params_create = {
377 .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
378 .pNext = &h264_params,
379 .videoSession = ctx->common.session,
380 .videoSessionParametersTemplate = VK_NULL_HANDLE,
381 };
382
383 /* SPS list */
384 for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) {
385 if (h->ps.sps_list[i]) {
386 const SPS *sps_l = h->ps.sps_list[i];
387 int idx = h264_params_info.stdSPSCount;
388 set_sps(sps_l, &par->vksps_scaling[idx], &par->vksps_vui_header[idx],
389 &par->vksps_vui[idx], &par->vksps[idx]);
390 h264_params_info.stdSPSCount++;
391 }
392 }
393
394 /* PPS list */
395 for (int i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) {
396 if (h->ps.pps_list[i]) {
397 const PPS *pps_l = h->ps.pps_list[i];
398 int idx = h264_params_info.stdPPSCount;
399 set_pps(pps_l, pps_l->sps, &par->vkpps_scaling[idx], &par->vkpps[idx]);
400 h264_params_info.stdPPSCount++;
401 }
402 }
403
404 h264_params.maxStdSPSCount = h264_params_info.stdSPSCount;
405 h264_params.maxStdPPSCount = h264_params_info.stdPPSCount;
406
407 err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create);
408 av_free(par);
409 if (err < 0)
410 return err;
411
412 av_log(avctx, AV_LOG_DEBUG, "Created frame parameters: %i SPS %i PPS\n",
413 h264_params_info.stdSPSCount, h264_params_info.stdPPSCount);
414
415 return 0;
416}
417
419 av_unused const AVBufferRef *buffer_ref,
420 av_unused const uint8_t *buffer,
421 av_unused uint32_t size)
422{
423 int err;
424 int nb_refs = 0;
425 H264Context *h = avctx->priv_data;
426
427 H264Picture *pic = h->cur_pic_ptr;
429 FFVulkanDecodePicture *vp = &hp->vp;
430
431 /* Fill in main slot */
432 err = vk_h264_fill_pict(avctx, NULL, &vp->ref_slot, &vp->ref,
433 &hp->vkh264_ref, &hp->h264_ref, pic, 1,
434 FIELD_PICTURE(h), h->picture_structure);
435 if (err < 0)
436 return err;
437
438 /* Fill in short-term references */
439 for (int i = 0; i < h->short_ref_count; i++) {
440 H264Picture *ref = h->short_ref[i];
441 err = vk_h264_fill_pict(avctx, &hp->ref_src[nb_refs], &vp->ref_slots[nb_refs],
442 &vp->refs[nb_refs], &hp->vkh264_refs[nb_refs],
443 &hp->h264_refs[nb_refs], ref, 0,
444 ref->field_picture, ref->reference);
445 if (err < 0)
446 return err;
447 nb_refs += err;
448 }
449
450 /* Fill in long-term refs */
451 for (int r = 0, i = 0; r < H264_MAX_DPB_FRAMES && i < h->long_ref_count; r++) {
452 H264Picture *ref = h->long_ref[r];
453 if (!ref)
454 continue;
455 err = vk_h264_fill_pict(avctx, &hp->ref_src[nb_refs], &vp->ref_slots[nb_refs],
456 &vp->refs[nb_refs], &hp->vkh264_refs[nb_refs],
457 &hp->h264_refs[nb_refs], ref, 0,
458 ref->field_picture, ref->reference);
459 if (err < 0)
460 return err;
461 nb_refs += err;
462 i++;
463 }
464
465 hp->h264pic = (StdVideoDecodeH264PictureInfo) {
466 .seq_parameter_set_id = pic->pps->sps_id,
467 .pic_parameter_set_id = pic->pps->pps_id,
468 .frame_num = 0, /* Set later */
469 .idr_pic_id = 0, /* Set later */
470 .PicOrderCnt[0] = pic->field_poc[0],
471 .PicOrderCnt[1] = pic->field_poc[1],
472 .flags = (StdVideoDecodeH264PictureInfoFlags) {
473 .field_pic_flag = FIELD_PICTURE(h),
474 .is_intra = 1, /* Set later */
475 .IdrPicFlag = h->picture_idr,
476 .bottom_field_flag = h->picture_structure != PICT_FRAME &&
477 h->picture_structure & PICT_BOTTOM_FIELD,
478 .is_reference = h->nal_ref_idc != 0,
479 .complementary_field_pair = h->first_field && FIELD_PICTURE(h),
480 },
481 };
482
483 hp->h264_pic_info = (VkVideoDecodeH264PictureInfoKHR) {
484 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR,
485 .pStdPictureInfo = &hp->h264pic,
486 };
487
488 vp->decode_info = (VkVideoDecodeInfoKHR) {
489 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
490 .pNext = &hp->h264_pic_info,
491 .flags = 0x0,
492 .pSetupReferenceSlot = &vp->ref_slot,
493 .referenceSlotCount = nb_refs,
494 .pReferenceSlots = vp->ref_slots,
495 .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
496 .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
497 .codedOffset = (VkOffset2D){ 0, 0 },
498 .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
499 .baseArrayLayer = 0,
500 .imageViewBinding = vp->view.out,
501 },
502 };
503
504 return 0;
505}
506
508 const uint8_t *data,
509 uint32_t size)
510{
511 const H264Context *h = avctx->priv_data;
512 const H264SliceContext *sl = &h->slice_ctx[0];
513 H264VulkanDecodePicture *hp = h->cur_pic_ptr->hwaccel_picture_private;
514 FFVulkanDecodePicture *vp = &hp->vp;
515
516 int err = ff_vk_decode_add_slice(avctx, vp, data, size, 1,
517 &hp->h264_pic_info.sliceCount,
518 &hp->h264_pic_info.pSliceOffsets);
519 if (err < 0)
520 return err;
521
522 hp->h264pic.frame_num = sl->frame_num;
523 hp->h264pic.idr_pic_id = sl->idr_pic_id;
524
525 /* Frame is only intra of all slices are marked as intra */
527 hp->h264pic.flags.is_intra = 0;
528
529 return 0;
530}
531
533{
534 const H264Context *h = avctx->priv_data;
537
538 H264Picture *pic = h->cur_pic_ptr;
540 FFVulkanDecodePicture *vp = &hp->vp;
542 AVFrame *rav[H264_MAX_PICTURE_COUNT] = { 0 };
543 int err;
544
545#ifdef VK_KHR_video_maintenance2
546 StdVideoH264ScalingLists vksps_scaling;
547 StdVideoH264HrdParameters vksps_vui_header;
548 StdVideoH264SequenceParameterSetVui vksps_vui;
549 StdVideoH264SequenceParameterSet vksps;
550 StdVideoH264ScalingLists vkpps_scaling;
551 StdVideoH264PictureParameterSet vkpps;
552 VkVideoDecodeH264InlineSessionParametersInfoKHR h264_params;
553
554 if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2) {
555 set_sps(h->ps.sps, &vksps_scaling,
556 &vksps_vui_header, &vksps_vui, &vksps);
557 set_pps(h->ps.pps, h->ps.sps, &vkpps_scaling, &vkpps);
558 h264_params = (VkVideoDecodeH264InlineSessionParametersInfoKHR) {
559 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_INLINE_SESSION_PARAMETERS_INFO_KHR,
560 .pStdSPS = &vksps,
561 .pStdPPS = &vkpps,
562 };
563 hp->h264_pic_info.pNext = &h264_params;
564 }
565#endif
566
567 if (!hp->h264_pic_info.sliceCount)
568 return 0;
569
570 if (!vp->slices_buf)
571 return AVERROR(EINVAL);
572
573 if (!dec->session_params &&
574 !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
575 err = vk_h264_create_params(avctx, &dec->session_params);
576 if (err < 0)
577 return err;
578
579 hp->h264pic.seq_parameter_set_id = pic->pps->sps_id;
580 hp->h264pic.pic_parameter_set_id = pic->pps->pps_id;
581 }
582
583 for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
584 H264Picture *rp = hp->ref_src[i];
586
587 rvp[i] = &rhp->vp;
588 rav[i] = hp->ref_src[i]->f;
589 }
590
591 av_log(avctx, AV_LOG_DEBUG, "Decoding frame, %zu bytes, %i slices\n",
592 vp->slices_size, hp->h264_pic_info.sliceCount);
593
594 err = ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
595 if (err < 0)
596 return err;
597
598 hp->decoded |= h->picture_structure;
599
600 return 0;
601}
602
604{
605 AVHWDeviceContext *hwctx = _hwctx.nc;
607
608 /* Free frame resources, this also destroys the session parameters. */
609 ff_vk_decode_free_frame(hwctx, &hp->vp);
610}
611
613 .p.name = "h264_vulkan",
614 .p.type = AVMEDIA_TYPE_VIDEO,
615 .p.id = AV_CODEC_ID_H264,
616 .p.pix_fmt = AV_PIX_FMT_VULKAN,
617 .start_frame = &vk_h264_start_frame,
618 .decode_slice = &vk_h264_decode_slice,
619 .end_frame = &vk_h264_end_frame,
620 .free_frame_priv = &vk_h264_free_frame_priv,
621 .frame_priv_data_size = sizeof(H264VulkanDecodePicture),
623 .update_thread_context = &ff_vk_update_thread_context,
624 .decode_params = &ff_vk_params_invalidate,
626 .frame_params = &ff_vk_frame_params,
627 .priv_data_size = sizeof(FFVulkanDecodeContext),
628 .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
629};
static AVFormatContext * ctx
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
#define NULL
Definition coverity.c:32
uint64_t pps
Definition dovi_rpuenc.c:36
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
@ AV_CODEC_ID_H264
Definition codec_id.h:77
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
#define ff_ctz
Definition intmath.h:105
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
@ AV_PICTURE_TYPE_I
Intra.
Definition avutil.h:278
@ AV_PICTURE_TYPE_SI
Switching Intra.
Definition avutil.h:282
@ H264_MAX_DPB_FRAMES
Definition h264.h:76
H.264 parameter set handling.
#define MAX_SPS_COUNT
Definition h264_ps.h:37
#define MAX_PPS_COUNT
Definition h264_ps.h:38
H.264 / AVC / MPEG-4 part10 codec.
#define H264_MAX_PICTURE_COUNT
Definition h264dec.h:47
#define FIELD_PICTURE(h)
Definition h264dec.h:65
#define HWACCEL_CAP_ASYNC_SAFE
Header providing the internals of AVHWAccel.
const struct FFHWAccel ff_h264_vulkan_hwaccel
#define r
Definition input.c:42
static av_cold void uninit(AVBitStreamFilterContext *ctx)
#define av_unused
Definition attributes.h:164
const uint8_t ff_zigzag_direct[64]
Definition mathtables.c:137
const uint8_t ff_zigzag_scan[16+1]
Definition mathtables.c:148
Memory handling functions.
#define PICT_TOP_FIELD
Definition mpegutils.h:31
#define PICT_BOTTOM_FIELD
Definition mpegutils.h:32
#define PICT_FRAME
Definition mpegutils.h:33
const char data[16]
Definition mxf.c:149
#define av_malloc(s)
Definition ops_static.c:52
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
main external API structure.
Definition avcodec.h:443
struct AVCodecInternal * internal
Private context used for internal data.
Definition avcodec.h:478
void * priv_data
Definition avcodec.h:470
void * hwaccel_priv_data
hwaccel-specific private data
Definition internal.h:130
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int width
Definition frame.h:544
int height
Definition frame.h:544
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
VkVideoSessionParametersKHR * session_params
FFVulkanDecodeShared * shared_ctx
struct FFVulkanDecodePicture::@321376256110110067000314232201030232256240036361 view
VkVideoReferenceSlotInfoKHR ref_slot
VkVideoPictureResourceInfoKHR refs[36]
VkVideoReferenceSlotInfoKHR ref_slots[36]
VkVideoDecodeInfoKHR decode_info
H264Context.
Definition h264dec.h:347
const PPS * pps
Definition h264dec.h:156
int invalid_gap
Definition h264dec.h:152
int reference
Definition h264dec.h:150
int pic_id
pic_num (short -> no wrap version of pic_num, pic_num & max_pic_num; long -> long_pic_num)
Definition h264dec.h:137
int frame_num
frame_num (raw frame_num from slice header)
Definition h264dec.h:134
int long_ref
1->long term reference 0->short term reference
Definition h264dec.h:139
void * hwaccel_picture_private
RefStruct reference for hardware accelerator private data.
Definition h264dec.h:128
AVFrame * f
Definition h264dec.h:113
int field_poc[2]
top/bottom POC
Definition h264dec.h:132
VkVideoDecodeH264DpbSlotInfoKHR vkh264_refs[H264_MAX_PICTURE_COUNT]
Definition vulkan_h264.c:51
VkVideoDecodeH264PictureInfoKHR h264_pic_info
Definition vulkan_h264.c:55
StdVideoDecodeH264PictureInfo h264pic
Definition vulkan_h264.c:54
StdVideoDecodeH264ReferenceInfo h264_ref
Definition vulkan_h264.c:45
FFVulkanDecodePicture vp
Definition vulkan_h264.c:38
H264Picture * ref_src[H264_MAX_PICTURE_COUNT]
Definition vulkan_h264.c:49
VkVideoDecodeH264DpbSlotInfoKHR vkh264_ref
Definition vulkan_h264.c:46
StdVideoDecodeH264ReferenceInfo h264_refs[H264_MAX_PICTURE_COUNT]
Definition vulkan_h264.c:50
Picture parameter set.
Definition h264_ps.h:110
unsigned int sps_id
Definition h264_ps.h:112
unsigned int pps_id
Definition h264_ps.h:111
const SPS * sps
RefStruct reference.
Definition h264_ps.h:141
Sequence parameter set.
Definition h264_ps.h:44
StdVideoH264PictureParameterSet vkpps[MAX_PPS_COUNT]
StdVideoH264ScalingLists vksps_scaling[MAX_SPS_COUNT]
StdVideoH264ScalingLists vkpps_scaling[MAX_PPS_COUNT]
StdVideoH264SequenceParameterSetVui vksps_vui[MAX_SPS_COUNT]
StdVideoH264SequenceParameterSet vksps[MAX_SPS_COUNT]
StdVideoH264HrdParameters vksps_vui_header[MAX_SPS_COUNT]
#define av_free(p)
#define av_log(a,...)
int level_idc
Definition h264_levels.c:29
static int ref[MAX_W *MAX_W]
static char buffer[20]
Definition seek.c:32
int size
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition refstruct.h:58
int ff_vk_decode_frame(AVCodecContext *avctx, AVFrame *pic, FFVulkanDecodePicture *vp, AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
Decode a frame.
int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
Synchronize the contexts between 2 threads.
int ff_vk_decode_init(AVCodecContext *avctx)
Initialize decoder.
int ff_vk_decode_create_params(VkVideoSessionParametersKHR **par_ref, void *logctx, FFVulkanDecodeShared *ctx, const VkVideoSessionParametersCreateInfoKHR *session_params_create)
Create VkVideoSessionParametersKHR wrapped in an AVBufferRef.
int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s)
Removes current session parameters to recreate them.
int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
Initialize hw_frames_ctx with the parameters needed to decode the stream using the parameters from av...
int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, const uint8_t *data, size_t size, int add_startcode, uint32_t *nb_slices, const uint32_t **offsets)
Add slice data to frame.
void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp)
Free a frame and its state.
int ff_vk_decode_uninit(AVCodecContext *avctx)
Free decoder.
int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic, FFVulkanDecodePicture *vkpic, int is_current, int alloc_dpb)
Prepare a frame, creates the image view, and sets up the dpb fields.
#define FF_VK_EXT_VIDEO_DECODE_H264
#define FF_VK_EXT_VIDEO_MAINTENANCE_2
static StdVideoH264LevelIdc convert_to_vk_level_idc(int level_idc)
static void vk_h264_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
static void set_sps(const SPS *sps, StdVideoH264ScalingLists *vksps_scaling, StdVideoH264HrdParameters *vksps_vui_header, StdVideoH264SequenceParameterSetVui *vksps_vui, StdVideoH264SequenceParameterSet *vksps)
static void set_pps(const PPS *pps, const SPS *sps, StdVideoH264ScalingLists *vkpps_scaling, StdVideoH264PictureParameterSet *vkpps)
static const int h264_scaling_list8_order[]
Definition vulkan_h264.c:58
static int vk_h264_start_frame(AVCodecContext *avctx, av_unused const AVBufferRef *buffer_ref, av_unused const uint8_t *buffer, av_unused uint32_t size)
static int vk_h264_end_frame(AVCodecContext *avctx)
static int vk_h264_fill_pict(AVCodecContext *avctx, H264Picture **ref_src, VkVideoReferenceSlotInfoKHR *ref_slot, VkVideoPictureResourceInfoKHR *ref, VkVideoDecodeH264DpbSlotInfoKHR *vkh264_ref, StdVideoDecodeH264ReferenceInfo *h264_ref, H264Picture *pic, int is_current, int is_field, int picture_structure)
Definition vulkan_h264.c:61
static int vk_h264_create_params(AVCodecContext *avctx, VkVideoSessionParametersKHR **buf)
const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc
Definition vulkan_h264.c:26
static int vk_h264_decode_slice(AVCodecContext *avctx, const uint8_t *data, uint32_t size)