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
20
22
23 /* Maximum number of tiles specified by any defined level */
25
29 .decode_op = VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR,
30 .ext_props = {
31 .extensionName = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME,
32 .specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION,
33 },
34 };
35
38
39 /* TODO: investigate if this can be removed to make decoding completely
40 * independent. */
42
44
45 /* Current picture */
62
63 /* Picture refs */
67
72
74 VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */
75 VkVideoPictureResourceInfoKHR *
ref,
/* Goes in ^ */
76 StdVideoDecodeAV1ReferenceInfo *vkav1_std_ref,
77 VkVideoDecodeAV1DpbSlotInfoKHR *vkav1_ref, /* Goes in ^ */
78 const AV1Frame *pic,
int is_current,
int has_grain,
79 const uint8_t *saved_order_hints)
80 {
84
87 if (err < 0)
88 return err;
89
90 *vkav1_std_ref = (StdVideoDecodeAV1ReferenceInfo) {
91 .flags = (StdVideoDecodeAV1ReferenceInfoFlags) {
94 },
98 };
99
100 if (saved_order_hints) {
102 for (
int i = 1;
i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME;
i++)
103 vkav1_std_ref->SavedOrderHints[
i - 1] = saved_order_hints[
i];
104 else
105 for (
int i = 0;
i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME;
i++)
106 vkav1_std_ref->SavedOrderHints[
i] = saved_order_hints[
i];
107 }
108
109 *vkav1_ref = (VkVideoDecodeAV1DpbSlotInfoKHR) {
110 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR,
111 .pStdReferenceInfo = vkav1_std_ref,
112 };
113
117
118 *
ref = (VkVideoPictureResourceInfoKHR) {
119 .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
120 .codedOffset = (VkOffset2D){ 0, 0 },
121 .codedExtent = (VkExtent2D){ pic->
f->
width, pic->
f->
height },
125 };
126
127 *ref_slot = (VkVideoReferenceSlotInfoKHR) {
128 .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
129 .pNext = vkav1_ref,
131 .pPictureResource =
ref,
132 };
133
134 if (ref_src)
135 *ref_src = pic;
136
137 return 0;
138 }
139
141 {
145
147
148 StdVideoAV1SequenceHeader av1_sequence_header;
149 StdVideoAV1TimingInfo av1_timing_info;
150 StdVideoAV1ColorConfig av1_color_config;
151 VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params;
152 VkVideoSessionParametersCreateInfoKHR session_params_create;
153
154 int err;
155
156 av1_timing_info = (StdVideoAV1TimingInfo) {
157 .flags = (StdVideoAV1TimingInfoFlags) {
159 },
163 };
164
165 av1_color_config = (StdVideoAV1ColorConfig) {
166 .flags = (StdVideoAV1ColorConfigFlags) {
170 },
178 };
179
180 av1_sequence_header = (StdVideoAV1SequenceHeader) {
181 .flags = (StdVideoAV1SequenceHeaderFlags) {
201 },
212 .pTimingInfo = &av1_timing_info,
213 .pColorConfig = &av1_color_config,
214 };
215
216 av1_params = (VkVideoDecodeAV1SessionParametersCreateInfoKHR) {
217 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
218 .pStdSequenceHeader = &av1_sequence_header,
219 };
220 session_params_create = (VkVideoSessionParametersCreateInfoKHR) {
221 .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
222 .pNext = &av1_params,
223 .videoSession =
ctx->common.session,
224 .videoSessionParametersTemplate = VK_NULL_HANDLE,
225 };
226
228 if (err < 0)
229 return err;
230
232
233 return 0;
234 }
235
239 {
240 int err;
241 int ref_count = 0;
247
250
253 StdVideoAV1FrameRestorationType remap_lr_type[4] = { STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
254 STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SWITCHABLE,
255 STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_WIENER,
256 STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SGRPROJ };
257
258 if (!dec->session_params) {
260 if (err < 0)
261 return err;
262 }
263
264 if (!ap->frame_id_set) {
265 unsigned slot_idx = 0;
266 for (
unsigned i = 0;
i < 32;
i++) {
267 if (!(dec->frame_id_alloc_mask & (1 <<
i))) {
269 break;
270 }
271 }
272 ap->frame_id = slot_idx;
273 ap->frame_id_set = 1;
274 dec->frame_id_alloc_mask |= (1 << slot_idx);
275 }
276
277 ap->ref_frame_sign_bias_mask = 0x0;
278 for (
int i = 0;
i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME;
i++)
279 ap->ref_frame_sign_bias_mask |= pic->ref_frame_sign_bias[
i] <<
i;
280
281 for (
int i = 0;
i < STD_VIDEO_AV1_REFS_PER_FRAME;
i++) {
282 const int idx = pic->raw_frame_header->ref_frame_idx[
i];
285 int found = 0;
286
288 continue;
289
290 for (int j = 0; j < ref_count; j++) {
291 if (vp->ref_slots[j].slotIndex == hp->
frame_id) {
292 found = 1;
293 break;
294 }
295 }
296 if (found)
297 continue;
298
299 err =
vk_av1_fill_pict(avctx, &ap->ref_src[ref_count], &vp->ref_slots[ref_count],
300 &vp->refs[ref_count], &ap->std_refs[ref_count], &ap->vkav1_refs[ref_count],
302 if (err < 0)
303 return err;
304
305 ref_count++;
306 }
307
309 &ap->std_ref,
310 &ap->vkav1_ref,
311 pic, 1, apply_grain,
NULL);
312 if (err < 0)
313 return err;
314
315 ap->av1_pic_info = (VkVideoDecodeAV1PictureInfoKHR) {
316 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PICTURE_INFO_KHR,
317 .pStdPictureInfo = &ap->std_pic_info,
318 .frameHeaderOffset = 0,
319 .tileCount = 0,
320 .pTileOffsets =
NULL,
321 .pTileSizes = ap->tile_sizes,
322 };
323
324 for (
int i = 0;
i < STD_VIDEO_AV1_REFS_PER_FRAME;
i++) {
325 const int idx = pic->raw_frame_header->ref_frame_idx[
i];
328
331 else
332 ap->av1_pic_info.referenceNameSlotIndices[
i] = hp->
frame_id;
333 }
334
335 vp->decode_info = (VkVideoDecodeInfoKHR) {
336 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
337 .pNext = &ap->av1_pic_info,
338 .flags = 0x0,
339 .pSetupReferenceSlot = &vp->ref_slot,
340 .referenceSlotCount = ref_count,
341 .pReferenceSlots = vp->ref_slots,
342 .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
343 .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
344 .codedOffset = (VkOffset2D){ 0, 0 },
345 .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
346 .baseArrayLayer = 0,
347 .imageViewBinding = vp->img_view_out,
348 },
349 };
350
351 ap->tile_info = (StdVideoAV1TileInfo) {
352 .flags = (StdVideoAV1TileInfoFlags) {
353 .uniform_tile_spacing_flag =
frame_header->uniform_tile_spacing_flag,
354 },
357 .context_update_tile_id =
frame_header->context_update_tile_id,
358 .tile_size_bytes_minus_1 =
frame_header->tile_size_bytes_minus1,
359 .pWidthInSbsMinus1 = ap->width_in_sbs_minus1,
360 .pHeightInSbsMinus1 = ap->height_in_sbs_minus1,
361 .pMiColStarts = ap->mi_col_starts,
362 .pMiRowStarts = ap->mi_row_starts,
363 };
364
365 ap->quantization = (StdVideoAV1Quantization) {
377 };
378
379 ap->loop_filter = (StdVideoAV1LoopFilter) {
380 .
flags = (StdVideoAV1LoopFilterFlags) {
381 .loop_filter_delta_enabled =
frame_header->loop_filter_delta_enabled,
382 .loop_filter_delta_update =
frame_header->loop_filter_delta_update,
383 },
384 .loop_filter_sharpness =
frame_header->loop_filter_sharpness,
385 };
386
387 for (
int i = 0;
i < STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS;
i++)
388 ap->loop_filter.loop_filter_level[
i] =
frame_header->loop_filter_level[
i];
389 for (
int i = 0;
i < STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS;
i++)
390 ap->loop_filter.loop_filter_mode_deltas[
i] =
frame_header->loop_filter_mode_deltas[
i];
391
392 ap->cdef = (StdVideoAV1CDEF) {
393 .cdef_damping_minus_3 =
frame_header->cdef_damping_minus_3,
395 };
396
397 ap->loop_restoration = (StdVideoAV1LoopRestoration) {
398 .FrameRestorationType[0] = remap_lr_type[
frame_header->lr_type[0]],
399 .FrameRestorationType[1] = remap_lr_type[
frame_header->lr_type[1]],
400 .FrameRestorationType[2] = remap_lr_type[
frame_header->lr_type[2]],
401 .LoopRestorationSize[0] = 1 +
frame_header->lr_unit_shift,
404 };
405
406 ap->film_grain = (StdVideoAV1FilmGrain) {
407 .
flags = (StdVideoAV1FilmGrainFlags) {
408 .chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma,
409 .overlap_flag = film_grain->overlap_flag,
410 .clip_to_restricted_range = film_grain->clip_to_restricted_range,
411 },
412 .grain_scaling_minus_8 = film_grain->grain_scaling_minus_8,
413 .ar_coeff_lag = film_grain->ar_coeff_lag,
414 .ar_coeff_shift_minus_6 = film_grain->ar_coeff_shift_minus_6,
415 .grain_scale_shift = film_grain->grain_scale_shift,
416 .grain_seed = film_grain->grain_seed,
417 .film_grain_params_ref_idx = film_grain->film_grain_params_ref_idx,
418 .num_y_points = film_grain->num_y_points,
419 .num_cb_points = film_grain->num_cb_points,
420 .num_cr_points = film_grain->num_cr_points,
421 .cb_mult = film_grain->cb_mult,
422 .cb_luma_mult = film_grain->cb_luma_mult,
423 .cb_offset = film_grain->cb_offset,
424 .cr_mult = film_grain->cr_mult,
425 .cr_luma_mult = film_grain->cr_luma_mult,
426 .cr_offset = film_grain->cr_offset,
427 };
428
429 /* Setup frame header */
430 ap->std_pic_info = (StdVideoDecodeAV1PictureInfo) {
431 .flags = (StdVideoDecodeAV1PictureInfoFlags) {
432 .error_resilient_mode =
frame_header->error_resilient_mode,
435 .render_and_frame_size_different =
frame_header->render_and_frame_size_different,
436 .allow_screen_content_tools =
frame_header->allow_screen_content_tools,
437 .is_filter_switchable =
frame_header->is_filter_switchable,
438 .force_integer_mv = pic->force_integer_mv,
439 .frame_size_override_flag =
frame_header->frame_size_override_flag,
440 .buffer_removal_time_present_flag =
frame_header->buffer_removal_time_present_flag,
442 .frame_refs_short_signaling =
frame_header->frame_refs_short_signaling,
443 .allow_high_precision_mv =
frame_header->allow_high_precision_mv,
444 .is_motion_mode_switchable =
frame_header->is_motion_mode_switchable,
446 .disable_frame_end_update_cdf =
frame_header->disable_frame_end_update_cdf,
447 .allow_warped_motion =
frame_header->allow_warped_motion,
454 .segmentation_enabled =
frame_header->segmentation_enabled,
455 .segmentation_update_map =
frame_header->segmentation_update_map,
456 .segmentation_temporal_update =
frame_header->segmentation_temporal_update,
457 .segmentation_update_data =
frame_header->segmentation_update_data,
459 .apply_grain = apply_grain,
460 },
465 .refresh_frame_flags =
frame_header->refresh_frame_flags,
466 .interpolation_filter =
frame_header->interpolation_filter,
470 .SkipModeFrame[0] =
s->cur_frame.skip_mode_frame_idx[0],
471 .SkipModeFrame[1] =
s->cur_frame.skip_mode_frame_idx[1],
473 .pTileInfo = &ap->tile_info,
474 .pQuantization = &ap->quantization,
475 .pSegmentation = &ap->segmentation,
476 .pLoopFilter = &ap->loop_filter,
477 .pCDEF = &ap->cdef,
478 .pLoopRestoration = &ap->loop_restoration,
479 .pGlobalMotion = &ap->global_motion,
480 .pFilmGrain = apply_grain ? &ap->film_grain :
NULL,
481 };
482
483 for (
int i = 0;
i < 64;
i++) {
484 ap->width_in_sbs_minus1[
i] =
frame_header->width_in_sbs_minus_1[
i];
485 ap->height_in_sbs_minus1[
i] =
frame_header->height_in_sbs_minus_1[
i];
488 }
489
490 for (
int i = 0;
i < STD_VIDEO_AV1_MAX_SEGMENTS;
i++) {
491 ap->segmentation.FeatureEnabled[
i] = 0x0;
492 for (int j = 0; j < STD_VIDEO_AV1_SEG_LVL_MAX; j++) {
493 ap->segmentation.FeatureEnabled[
i] |= (
frame_header->feature_enabled[
i][j] << j);
494 ap->segmentation.FeatureData[
i][j] =
frame_header->feature_value[
i][j];
495 }
496 }
497
498 if (dec->quirk_av1_offset)
499 for (
int i = 1;
i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME;
i++)
500 ap->std_pic_info.OrderHints[
i - 1] = pic->order_hints[
i];
501 else
502 for (
int i = 0;
i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME;
i++)
503 ap->std_pic_info.OrderHints[
i] = pic->order_hints[
i];
504
505 for (
int i = 0;
i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME;
i++) {
506 ap->loop_filter.loop_filter_ref_deltas[
i] =
frame_header->loop_filter_ref_deltas[
i];
507 ap->global_motion.GmType[
i] =
s->cur_frame.gm_type[
i];
508 for (int j = 0; j < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS; j++) {
509 ap->global_motion.gm_params[
i][j] =
s->cur_frame.gm_params[
i][j];
510 }
511 }
512
513 for (
int i = 0;
i < STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS;
i++) {
514 ap->cdef.cdef_y_pri_strength[
i] =
frame_header->cdef_y_pri_strength[
i];
515 ap->cdef.cdef_y_sec_strength[
i] =
frame_header->cdef_y_sec_strength[
i];
516 ap->cdef.cdef_uv_pri_strength[
i] =
frame_header->cdef_uv_pri_strength[
i];
517 ap->cdef.cdef_uv_sec_strength[
i] =
frame_header->cdef_uv_sec_strength[
i];
518 }
519
520 if (apply_grain) {
521 for (
int i = 0;
i < STD_VIDEO_AV1_MAX_NUM_Y_POINTS;
i++) {
522 ap->film_grain.point_y_value[
i] = film_grain->point_y_value[
i];
523 ap->film_grain.point_y_scaling[
i] = film_grain->point_y_scaling[
i];
524 }
525
526 for (
int i = 0;
i < STD_VIDEO_AV1_MAX_NUM_CB_POINTS;
i++) {
527 ap->film_grain.point_cb_value[
i] = film_grain->point_cb_value[
i];
528 ap->film_grain.point_cb_scaling[
i] = film_grain->point_cb_scaling[
i];
529 ap->film_grain.point_cr_value[
i] = film_grain->point_cr_value[
i];
530 ap->film_grain.point_cr_scaling[
i] = film_grain->point_cr_scaling[
i];
531 }
532
533 for (
int i = 0;
i < STD_VIDEO_AV1_MAX_NUM_POS_LUMA;
i++)
534 ap->film_grain.ar_coeffs_y_plus_128[
i] = film_grain->ar_coeffs_y_plus_128[
i];
535
536 for (
int i = 0;
i < STD_VIDEO_AV1_MAX_NUM_POS_CHROMA;
i++) {
537 ap->film_grain.ar_coeffs_cb_plus_128[
i] = film_grain->ar_coeffs_cb_plus_128[
i];
538 ap->film_grain.ar_coeffs_cr_plus_128[
i] = film_grain->ar_coeffs_cr_plus_128[
i];
539 }
540 }
541
542 ap->dec = dec;
543
544 return 0;
545 }
546
550 {
551 int err;
555
556 /* Too many tiles, exceeding all defined levels in the AV1 spec */
559
560 for (
int i =
s->tg_start; i <= s->tg_end;
i++) {
562
564 data +
s->tile_group_info[
i].tile_offset,
565 s->tile_group_info[
i].tile_size, 0,
568 if (err < 0)
569 return err;
570 }
571
572 return 0;
573 }
574
576 {
584
586 return 0;
587
590 if (err < 0)
591 return err;
592 }
593
597
600 }
601
604
606 }
607
609 {
612
613 /* Workaround for a spec issue. */
616
617 /* Free frame resources, this also destroys the session parameters. */
619 }
620
622 .
p.
name =
"av1_vulkan",
638
639 /* NOTE: Threading is intentionally disabled here. Due to the design of Vulkan,
640 * where frames are opaque to users, and mostly opaque for driver developers,
641 * there's an issue with current hardware accelerator implementations of AV1,
642 * where they require an internal index. With regular hwaccel APIs, this index
643 * is given to users as an opaque handle directly. With Vulkan, due to increased
644 * flexibility, this index cannot be present anywhere.
645 * The current implementation tracks the index for the driver and submits it
646 * as necessary information. Due to needing to modify the decoding context,
647 * which is not thread-safe, on frame free, threading is disabled. */
649 };