Bug Summary

File:root/firefox-clang/media/ffvpx/libavcodec/vulkan_av1.c
Warning:line 291, column 9
Value stored to 'frame_id_alloc_mask' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name vulkan_av1.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -include libavutil_visibility.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D HAVE_AV_CONFIG_H -D ASSERT_LEVEL=2 -I /root/firefox-clang/media/ffvpx/libavcodec -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -I /root/firefox-clang/modules/fdlibm/inexact-math-override -I /root/firefox-clang/third_party/khronos/vulkan-headers/include -I /root/firefox-clang/media/mozva -I /root/firefox-clang/media/libopus/include -I /root/firefox-clang/media/libvorbis -I /root/firefox-clang/media/libvpx -I /root/firefox-clang/media/ffvpx -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -Wno-parentheses -Wno-pointer-sign -Wno-sign-compare -Wno-switch -Wno-type-limits -Wno-unused-function -Wno-deprecated-declarations -Wno-absolute-value -Wno-incompatible-pointer-types -Wno-string-conversion -Wno-visibility -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/media/ffvpx/libavcodec/vulkan_av1.c
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 "av1dec.h"
20
21#include "vulkan_decode.h"
22
23/* Maximum number of tiles specified by any defined level */
24#define MAX_TILES256 256
25
26const FFVulkanDecodeDescriptor ff_vk_dec_av1_desc = {
27 .codec_id = AV_CODEC_ID_AV1,
28 .decode_extension = FF_VK_EXT_VIDEO_DECODE_AV1(1ULL << 44),
29 .queue_flags = VK_QUEUE_VIDEO_DECODE_BIT_KHR,
30 .decode_op = VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR,
31 .ext_props = {
32 .extensionName = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME"VK_STD_vulkan_video_codec_av1_decode",
33 .specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION((((uint32_t)(1)) << 22) | (((uint32_t)(0)) << 12
) | ((uint32_t)(0)))
,
34 },
35};
36
37typedef struct AV1VulkanDecodePicture {
38 FFVulkanDecodePicture vp;
39
40 /* TODO: investigate if this can be removed to make decoding completely
41 * independent. */
42 FFVulkanDecodeContext *dec;
43
44 uint32_t tile_sizes[MAX_TILES256];
45
46 /* Current picture */
47 StdVideoDecodeAV1ReferenceInfo std_ref;
48 VkVideoDecodeAV1DpbSlotInfoKHR vkav1_ref;
49 uint16_t width_in_sbs_minus1[64];
50 uint16_t height_in_sbs_minus1[64];
51 uint16_t mi_col_starts[64];
52 uint16_t mi_row_starts[64];
53 StdVideoAV1TileInfo tile_info;
54 StdVideoAV1Quantization quantization;
55 StdVideoAV1Segmentation segmentation;
56 StdVideoAV1LoopFilter loop_filter;
57 StdVideoAV1CDEF cdef;
58 StdVideoAV1LoopRestoration loop_restoration;
59 StdVideoAV1GlobalMotion global_motion;
60 StdVideoAV1FilmGrain film_grain;
61 StdVideoDecodeAV1PictureInfo std_pic_info;
62 VkVideoDecodeAV1PictureInfoKHR av1_pic_info;
63
64 /* Picture refs */
65 const AV1Frame *ref_src [AV1_NUM_REF_FRAMES];
66 StdVideoDecodeAV1ReferenceInfo std_refs [AV1_NUM_REF_FRAMES];
67 VkVideoDecodeAV1DpbSlotInfoKHR vkav1_refs[AV1_NUM_REF_FRAMES];
68
69 uint8_t frame_id_set;
70 uint8_t frame_id;
71 uint8_t ref_frame_sign_bias_mask;
72} AV1VulkanDecodePicture;
73
74static int vk_av1_fill_pict(AVCodecContext *avctx, const AV1Frame **ref_src,
75 VkVideoReferenceSlotInfoKHR *ref_slot, /* Main structure */
76 VkVideoPictureResourceInfoKHR *ref, /* Goes in ^ */
77 StdVideoDecodeAV1ReferenceInfo *vkav1_std_ref,
78 VkVideoDecodeAV1DpbSlotInfoKHR *vkav1_ref, /* Goes in ^ */
79 const AV1Frame *pic, int is_current, int has_grain,
80 const uint8_t *saved_order_hints)
81{
82 FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
83 FFVulkanDecodeShared *ctx = dec->shared_ctx;
84 AV1VulkanDecodePicture *hp = pic->hwaccel_picture_private;
85 FFVulkanDecodePicture *vkpic = &hp->vp;
86
87 int err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
88 has_grain || dec->dedicated_dpb);
89 if (err < 0)
90 return err;
91
92 *vkav1_std_ref = (StdVideoDecodeAV1ReferenceInfo) {
93 .flags = (StdVideoDecodeAV1ReferenceInfoFlags) {
94 .disable_frame_end_update_cdf = pic->raw_frame_header->disable_frame_end_update_cdf,
95 .segmentation_enabled = pic->raw_frame_header->segmentation_enabled,
96 },
97 .frame_type = pic->raw_frame_header->frame_type,
98 .OrderHint = pic->raw_frame_header->order_hint,
99 .RefFrameSignBias = hp->ref_frame_sign_bias_mask,
100 };
101
102 if (saved_order_hints) {
103 if (dec->quirk_av1_offset)
104 for (int i = 1; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME8U; i++)
105 vkav1_std_ref->SavedOrderHints[i - 1] = saved_order_hints[i];
106 else
107 for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME8U; i++)
108 vkav1_std_ref->SavedOrderHints[i] = saved_order_hints[i];
109 }
110
111 *vkav1_ref = (VkVideoDecodeAV1DpbSlotInfoKHR) {
112 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR,
113 .pStdReferenceInfo = vkav1_std_ref,
114 };
115
116 vkav1_std_ref->flags.disable_frame_end_update_cdf = pic->raw_frame_header->disable_frame_end_update_cdf;
117 vkav1_std_ref->flags.segmentation_enabled = pic->raw_frame_header->segmentation_enabled;
118 vkav1_std_ref->frame_type = pic->raw_frame_header->frame_type;
119
120 *ref = (VkVideoPictureResourceInfoKHR) {
121 .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
122 .codedOffset = (VkOffset2D){ 0, 0 },
123 .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
124 .baseArrayLayer = ((has_grain || dec->dedicated_dpb) && ctx->common.layered_dpb) ?
125 hp->frame_id : 0,
126 .imageViewBinding = vkpic->view.ref[0],
127 };
128
129 *ref_slot = (VkVideoReferenceSlotInfoKHR) {
130 .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
131 .pNext = vkav1_ref,
132 .slotIndex = hp->frame_id,
133 .pPictureResource = ref,
134 };
135
136 if (ref_src)
137 *ref_src = pic;
138
139 return 0;
140}
141
142static void vk_av1_params_fill(AVCodecContext *avctx,
143 StdVideoAV1TimingInfo *av1_timing_info,
144 StdVideoAV1ColorConfig *av1_color_config,
145 StdVideoAV1SequenceHeader *av1_sequence_header)
146{
147 const AV1DecContext *s = avctx->priv_data;
148 const AV1RawSequenceHeader *seq = s->raw_seq;
149
150 *av1_timing_info = (StdVideoAV1TimingInfo) {
151 .flags = (StdVideoAV1TimingInfoFlags) {
152 .equal_picture_interval = seq->timing_info.equal_picture_interval,
153 },
154 .num_units_in_display_tick = seq->timing_info.num_units_in_display_tick,
155 .time_scale = seq->timing_info.time_scale,
156 .num_ticks_per_picture_minus_1 = seq->timing_info.num_ticks_per_picture_minus_1,
157 };
158
159 *av1_color_config = (StdVideoAV1ColorConfig) {
160 .flags = (StdVideoAV1ColorConfigFlags) {
161 .mono_chrome = seq->color_config.mono_chrome,
162 .color_range = seq->color_config.color_range,
163 .separate_uv_delta_q = seq->color_config.separate_uv_delta_q,
164 },
165 .BitDepth = seq->color_config.twelve_bit ? 12 :
166 seq->color_config.high_bitdepth ? 10 : 8,
167 .subsampling_x = seq->color_config.subsampling_x,
168 .subsampling_y = seq->color_config.subsampling_y,
169 .color_primaries = seq->color_config.color_primaries,
170 .transfer_characteristics = seq->color_config.transfer_characteristics,
171 .matrix_coefficients = seq->color_config.matrix_coefficients,
172 };
173
174 *av1_sequence_header = (StdVideoAV1SequenceHeader) {
175 .flags = (StdVideoAV1SequenceHeaderFlags) {
176 .still_picture = seq->still_picture,
177 .reduced_still_picture_header = seq->reduced_still_picture_header,
178 .use_128x128_superblock = seq->use_128x128_superblock,
179 .enable_filter_intra = seq->enable_filter_intra,
180 .enable_intra_edge_filter = seq->enable_intra_edge_filter,
181 .enable_interintra_compound = seq->enable_interintra_compound,
182 .enable_masked_compound = seq->enable_masked_compound,
183 .enable_warped_motion = seq->enable_warped_motion,
184 .enable_dual_filter = seq->enable_dual_filter,
185 .enable_order_hint = seq->enable_order_hint,
186 .enable_jnt_comp = seq->enable_jnt_comp,
187 .enable_ref_frame_mvs = seq->enable_ref_frame_mvs,
188 .frame_id_numbers_present_flag = seq->frame_id_numbers_present_flag,
189 .enable_superres = seq->enable_superres,
190 .enable_cdef = seq->enable_cdef,
191 .enable_restoration = seq->enable_restoration,
192 .film_grain_params_present = seq->film_grain_params_present,
193 .timing_info_present_flag = seq->timing_info_present_flag,
194 .initial_display_delay_present_flag = seq->initial_display_delay_present_flag,
195 },
196 .seq_profile = seq->seq_profile,
197 .frame_width_bits_minus_1 = seq->frame_width_bits_minus_1,
198 .frame_height_bits_minus_1 = seq->frame_height_bits_minus_1,
199 .max_frame_width_minus_1 = seq->max_frame_width_minus_1,
200 .max_frame_height_minus_1 = seq->max_frame_height_minus_1,
201 .delta_frame_id_length_minus_2 = seq->delta_frame_id_length_minus_2,
202 .additional_frame_id_length_minus_1 = seq->additional_frame_id_length_minus_1,
203 .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1,
204 .seq_force_integer_mv = seq->seq_force_integer_mv,
205 .seq_force_screen_content_tools = seq->seq_force_screen_content_tools,
206 .pTimingInfo = av1_timing_info,
207 .pColorConfig = av1_color_config,
208 };
209}
210
211static int vk_av1_create_params(AVCodecContext *avctx, AVBufferRef **buf,
212 AV1VulkanDecodePicture *ap)
213{
214 int err;
215 FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
216 FFVulkanDecodeShared *ctx = dec->shared_ctx;
217
218 StdVideoAV1SequenceHeader av1_sequence_header;
219 StdVideoAV1TimingInfo av1_timing_info;
220 StdVideoAV1ColorConfig av1_color_config;
221 VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params;
222 VkVideoSessionParametersCreateInfoKHR session_params_create;
223
224 vk_av1_params_fill(avctx, &av1_timing_info, &av1_color_config,
225 &av1_sequence_header);
226
227 av1_params = (VkVideoDecodeAV1SessionParametersCreateInfoKHR) {
228 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
229 .pStdSequenceHeader = &av1_sequence_header,
230 };
231 session_params_create = (VkVideoSessionParametersCreateInfoKHR) {
232 .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
233 .pNext = &av1_params,
234 .videoSession = ctx->common.session,
235 .videoSessionParametersTemplate = VK_NULL_HANDLE((void*)0),
236 };
237
238 err = ff_vk_decode_create_params(buf, avctx, ctx, &session_params_create);
239 if (err < 0)
240 return err;
241
242 av_log(avctx, AV_LOG_DEBUG48, "Created frame parameters\n");
243
244 return 0;
245}
246
247static int vk_av1_start_frame(AVCodecContext *avctx,
248 av_unused__attribute__((unused)) const AVBufferRef *buffer_ref,
249 av_unused__attribute__((unused)) const uint8_t *buffer,
250 av_unused__attribute__((unused)) uint32_t size)
251{
252 int err;
253 int ref_count = 0;
254 AV1DecContext *s = avctx->priv_data;
255 const AV1RawSequenceHeader *seq = s->raw_seq;
256 const AV1Frame *pic = &s->cur_frame;
257 FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
258 uint32_t frame_id_alloc_mask = 0;
259 uint16_t sb_shift = seq->use_128x128_superblock ? 5 : 4;
260
261 AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private;
262 FFVulkanDecodePicture *vp = &ap->vp;
263
264 const AV1RawFrameHeader *frame_header = s->raw_frame_header;
265 const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain;
266
267 const int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN(1 << 3)) &&
268 film_grain->apply_grain;
269 StdVideoAV1FrameRestorationType remap_lr_type[4] = { STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE,
270 STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SWITCHABLE,
271 STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_WIENER,
272 STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SGRPROJ };
273
274 /* Use the current frame_ids in ref[] to decide occupied frame_ids */
275 for (int i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES8U; i++) {
276 const AV1VulkanDecodePicture* rp = s->ref[i].hwaccel_picture_private;
277 if (rp)
278 frame_id_alloc_mask |= 1 << rp->frame_id;
279 }
280
281 if (!ap->frame_id_set) {
282 unsigned slot_idx = 0;
283 for (unsigned i = 0; i < 32; i++) {
284 if (!(frame_id_alloc_mask & (1 << i))) {
285 slot_idx = i;
286 break;
287 }
288 }
289 ap->frame_id = slot_idx;
290 ap->frame_id_set = 1;
291 frame_id_alloc_mask |= (1 << slot_idx);
Value stored to 'frame_id_alloc_mask' is never read
292 }
293
294 ap->ref_frame_sign_bias_mask = 0x0;
295 for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME8U; i++)
296 ap->ref_frame_sign_bias_mask |= pic->ref_frame_sign_bias[i] << i;
297
298 for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME7U; i++) {
299 const int idx = pic->raw_frame_header->ref_frame_idx[i];
300 const AV1Frame *ref_frame = &s->ref[idx];
301 AV1VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
302 int found = 0;
303
304 if (!ref_frame->f)
305 continue;
306
307 for (int j = 0; j < ref_count; j++) {
308 if (vp->ref_slots[j].slotIndex == hp->frame_id) {
309 found = 1;
310 break;
311 }
312 }
313 if (found)
314 continue;
315
316 err = vk_av1_fill_pict(avctx, &ap->ref_src[ref_count], &vp->ref_slots[ref_count],
317 &vp->refs[ref_count], &ap->std_refs[ref_count], &ap->vkav1_refs[ref_count],
318 ref_frame, 0, 0, ref_frame->order_hints);
319 if (err < 0)
320 return err;
321
322 ref_count++;
323 }
324
325 err = vk_av1_fill_pict(avctx, NULL((void*)0), &vp->ref_slot, &vp->ref,
326 &ap->std_ref,
327 &ap->vkav1_ref,
328 pic, 1, apply_grain, NULL((void*)0));
329 if (err < 0)
330 return err;
331
332 ap->av1_pic_info = (VkVideoDecodeAV1PictureInfoKHR) {
333 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PICTURE_INFO_KHR,
334 .pStdPictureInfo = &ap->std_pic_info,
335 .frameHeaderOffset = 0,
336 .tileCount = 0,
337 .pTileOffsets = NULL((void*)0),
338 .pTileSizes = ap->tile_sizes,
339 };
340
341 for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME7U; i++) {
342 const int idx = pic->raw_frame_header->ref_frame_idx[i];
343 const AV1Frame *ref_frame = &s->ref[idx];
344 AV1VulkanDecodePicture *hp = ref_frame->hwaccel_picture_private;
345
346 if (!ref_frame->f)
347 ap->av1_pic_info.referenceNameSlotIndices[i] = AV1_REF_FRAME_NONE;
348 else
349 ap->av1_pic_info.referenceNameSlotIndices[i] = hp->frame_id;
350 }
351
352 vp->decode_info = (VkVideoDecodeInfoKHR) {
353 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR,
354 .pNext = &ap->av1_pic_info,
355 .flags = 0x0,
356 .pSetupReferenceSlot = &vp->ref_slot,
357 .referenceSlotCount = ref_count,
358 .pReferenceSlots = vp->ref_slots,
359 .dstPictureResource = (VkVideoPictureResourceInfoKHR) {
360 .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
361 .codedOffset = (VkOffset2D){ 0, 0 },
362 .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
363 .baseArrayLayer = 0,
364 .imageViewBinding = vp->view.out[0],
365 },
366 };
367
368 ap->tile_info = (StdVideoAV1TileInfo) {
369 .flags = (StdVideoAV1TileInfoFlags) {
370 .uniform_tile_spacing_flag = frame_header->uniform_tile_spacing_flag,
371 },
372 .TileCols = frame_header->tile_cols,
373 .TileRows = frame_header->tile_rows,
374 .context_update_tile_id = frame_header->context_update_tile_id,
375 .tile_size_bytes_minus_1 = frame_header->tile_size_bytes_minus1,
376 .pWidthInSbsMinus1 = ap->width_in_sbs_minus1,
377 .pHeightInSbsMinus1 = ap->height_in_sbs_minus1,
378 .pMiColStarts = ap->mi_col_starts,
379 .pMiRowStarts = ap->mi_row_starts,
380 };
381
382 ap->quantization = (StdVideoAV1Quantization) {
383 .flags.using_qmatrix = frame_header->using_qmatrix,
384 .flags.diff_uv_delta = frame_header->diff_uv_delta,
385 .base_q_idx = frame_header->base_q_idx,
386 .DeltaQYDc = frame_header->delta_q_y_dc,
387 .DeltaQUDc = frame_header->delta_q_u_dc,
388 .DeltaQUAc = frame_header->delta_q_u_ac,
389 .DeltaQVDc = frame_header->delta_q_v_dc,
390 .DeltaQVAc = frame_header->delta_q_v_ac,
391 .qm_y = frame_header->qm_y,
392 .qm_u = frame_header->qm_u,
393 .qm_v = frame_header->qm_v,
394 };
395
396 ap->loop_filter = (StdVideoAV1LoopFilter) {
397 .flags = (StdVideoAV1LoopFilterFlags) {
398 .loop_filter_delta_enabled = frame_header->loop_filter_delta_enabled,
399 .loop_filter_delta_update = frame_header->loop_filter_delta_update,
400 },
401 .loop_filter_sharpness = frame_header->loop_filter_sharpness,
402 };
403
404 for (int i = 0; i < STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS4U; i++)
405 ap->loop_filter.loop_filter_level[i] = frame_header->loop_filter_level[i];
406 for (int i = 0; i < STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS2U; i++)
407 ap->loop_filter.loop_filter_mode_deltas[i] = frame_header->loop_filter_mode_deltas[i];
408
409 ap->cdef = (StdVideoAV1CDEF) {
410 .cdef_damping_minus_3 = frame_header->cdef_damping_minus_3,
411 .cdef_bits = frame_header->cdef_bits,
412 };
413
414 ap->loop_restoration = (StdVideoAV1LoopRestoration) {
415 .FrameRestorationType[0] = remap_lr_type[frame_header->lr_type[0]],
416 .FrameRestorationType[1] = remap_lr_type[frame_header->lr_type[1]],
417 .FrameRestorationType[2] = remap_lr_type[frame_header->lr_type[2]],
418 .LoopRestorationSize[0] = 1 + frame_header->lr_unit_shift,
419 .LoopRestorationSize[1] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift,
420 .LoopRestorationSize[2] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift,
421 };
422
423 ap->film_grain = (StdVideoAV1FilmGrain) {
424 .flags = (StdVideoAV1FilmGrainFlags) {
425 .chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma,
426 .overlap_flag = film_grain->overlap_flag,
427 .clip_to_restricted_range = film_grain->clip_to_restricted_range,
428 },
429 .grain_scaling_minus_8 = film_grain->grain_scaling_minus_8,
430 .ar_coeff_lag = film_grain->ar_coeff_lag,
431 .ar_coeff_shift_minus_6 = film_grain->ar_coeff_shift_minus_6,
432 .grain_scale_shift = film_grain->grain_scale_shift,
433 .grain_seed = film_grain->grain_seed,
434 .film_grain_params_ref_idx = film_grain->film_grain_params_ref_idx,
435 .num_y_points = film_grain->num_y_points,
436 .num_cb_points = film_grain->num_cb_points,
437 .num_cr_points = film_grain->num_cr_points,
438 .cb_mult = film_grain->cb_mult,
439 .cb_luma_mult = film_grain->cb_luma_mult,
440 .cb_offset = film_grain->cb_offset,
441 .cr_mult = film_grain->cr_mult,
442 .cr_luma_mult = film_grain->cr_luma_mult,
443 .cr_offset = film_grain->cr_offset,
444 };
445
446 /* Setup frame header */
447 ap->std_pic_info = (StdVideoDecodeAV1PictureInfo) {
448 .flags = (StdVideoDecodeAV1PictureInfoFlags) {
449 .error_resilient_mode = frame_header->error_resilient_mode,
450 .disable_cdf_update = frame_header->disable_cdf_update,
451 .use_superres = frame_header->use_superres,
452 .render_and_frame_size_different = frame_header->render_and_frame_size_different,
453 .allow_screen_content_tools = frame_header->allow_screen_content_tools,
454 .is_filter_switchable = frame_header->is_filter_switchable,
455 .force_integer_mv = pic->force_integer_mv,
456 .frame_size_override_flag = frame_header->frame_size_override_flag,
457 .buffer_removal_time_present_flag = frame_header->buffer_removal_time_present_flag,
458 .allow_intrabc = frame_header->allow_intrabc,
459 .frame_refs_short_signaling = frame_header->frame_refs_short_signaling,
460 .allow_high_precision_mv = frame_header->allow_high_precision_mv,
461 .is_motion_mode_switchable = frame_header->is_motion_mode_switchable,
462 .use_ref_frame_mvs = frame_header->use_ref_frame_mvs,
463 .disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf,
464 .allow_warped_motion = frame_header->allow_warped_motion,
465 .reduced_tx_set = frame_header->reduced_tx_set,
466 .reference_select = frame_header->reference_select,
467 .skip_mode_present = frame_header->skip_mode_present,
468 .delta_q_present = frame_header->delta_q_present,
469 .delta_lf_present = frame_header->delta_lf_present,
470 .delta_lf_multi = frame_header->delta_lf_multi,
471 .segmentation_enabled = frame_header->segmentation_enabled,
472 .segmentation_update_map = frame_header->segmentation_update_map,
473 .segmentation_temporal_update = frame_header->segmentation_temporal_update,
474 .segmentation_update_data = frame_header->segmentation_update_data,
475 .UsesLr = frame_header->lr_type[0] || frame_header->lr_type[1] || frame_header->lr_type[2],
476 .apply_grain = apply_grain,
477 },
478 .frame_type = frame_header->frame_type,
479 .current_frame_id = frame_header->current_frame_id,
480 .OrderHint = frame_header->order_hint,
481 .primary_ref_frame = frame_header->primary_ref_frame,
482 .refresh_frame_flags = frame_header->refresh_frame_flags,
483 .interpolation_filter = frame_header->interpolation_filter,
484 .TxMode = frame_header->tx_mode,
485 .delta_q_res = frame_header->delta_q_res,
486 .delta_lf_res = frame_header->delta_lf_res,
487 .SkipModeFrame[0] = s->cur_frame.skip_mode_frame_idx[0],
488 .SkipModeFrame[1] = s->cur_frame.skip_mode_frame_idx[1],
489 .coded_denom = frame_header->coded_denom,
490 .pTileInfo = &ap->tile_info,
491 .pQuantization = &ap->quantization,
492 .pSegmentation = &ap->segmentation,
493 .pLoopFilter = &ap->loop_filter,
494 .pCDEF = &ap->cdef,
495 .pLoopRestoration = &ap->loop_restoration,
496 .pGlobalMotion = &ap->global_motion,
497 .pFilmGrain = apply_grain ? &ap->film_grain : NULL((void*)0),
498 };
499
500 for (int i = 0; i < 64; i++) {
501 ap->width_in_sbs_minus1[i] = frame_header->width_in_sbs_minus_1[i];
502 ap->height_in_sbs_minus1[i] = frame_header->height_in_sbs_minus_1[i];
503 ap->mi_col_starts[i] = frame_header->tile_start_col_sb[i] << sb_shift;
504 ap->mi_row_starts[i] = frame_header->tile_start_row_sb[i] << sb_shift;
505 }
506
507 for (int i = 0; i < STD_VIDEO_AV1_MAX_SEGMENTS8U; i++) {
508 ap->segmentation.FeatureEnabled[i] = 0x0;
509 for (int j = 0; j < STD_VIDEO_AV1_SEG_LVL_MAX8U; j++) {
510 ap->segmentation.FeatureEnabled[i] |= (frame_header->feature_enabled[i][j] << j);
511 ap->segmentation.FeatureData[i][j] = frame_header->feature_value[i][j];
512 }
513 }
514
515 if (dec->quirk_av1_offset)
516 for (int i = 1; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME8U; i++)
517 ap->std_pic_info.OrderHints[i - 1] = pic->order_hints[i];
518 else
519 for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME8U; i++)
520 ap->std_pic_info.OrderHints[i] = pic->order_hints[i];
521
522 for (int i = 0; i < STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME8U; i++) {
523 ap->loop_filter.loop_filter_ref_deltas[i] = frame_header->loop_filter_ref_deltas[i];
524 ap->global_motion.GmType[i] = s->cur_frame.gm_type[i];
525 for (int j = 0; j < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS6U; j++) {
526 ap->global_motion.gm_params[i][j] = s->cur_frame.gm_params[i][j];
527 }
528 }
529
530 for (int i = 0; i < STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS8U; i++) {
531 ap->cdef.cdef_y_pri_strength[i] = frame_header->cdef_y_pri_strength[i];
532 ap->cdef.cdef_y_sec_strength[i] = frame_header->cdef_y_sec_strength[i];
533 ap->cdef.cdef_uv_pri_strength[i] = frame_header->cdef_uv_pri_strength[i];
534 ap->cdef.cdef_uv_sec_strength[i] = frame_header->cdef_uv_sec_strength[i];
535 }
536
537 if (apply_grain) {
538 for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_Y_POINTS14U; i++) {
539 ap->film_grain.point_y_value[i] = film_grain->point_y_value[i];
540 ap->film_grain.point_y_scaling[i] = film_grain->point_y_scaling[i];
541 }
542
543 for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_CB_POINTS10U; i++) {
544 ap->film_grain.point_cb_value[i] = film_grain->point_cb_value[i];
545 ap->film_grain.point_cb_scaling[i] = film_grain->point_cb_scaling[i];
546 ap->film_grain.point_cr_value[i] = film_grain->point_cr_value[i];
547 ap->film_grain.point_cr_scaling[i] = film_grain->point_cr_scaling[i];
548 }
549
550 for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_POS_LUMA24U; i++)
551 ap->film_grain.ar_coeffs_y_plus_128[i] = film_grain->ar_coeffs_y_plus_128[i];
552
553 for (int i = 0; i < STD_VIDEO_AV1_MAX_NUM_POS_CHROMA25U; i++) {
554 ap->film_grain.ar_coeffs_cb_plus_128[i] = film_grain->ar_coeffs_cb_plus_128[i];
555 ap->film_grain.ar_coeffs_cr_plus_128[i] = film_grain->ar_coeffs_cr_plus_128[i];
556 }
557 }
558
559 ap->dec = dec;
560
561 return 0;
562}
563
564static int vk_av1_decode_slice(AVCodecContext *avctx,
565 const uint8_t *data,
566 uint32_t size)
567{
568 int err;
569 const AV1DecContext *s = avctx->priv_data;
570 AV1VulkanDecodePicture *ap = s->cur_frame.hwaccel_picture_private;
571 FFVulkanDecodePicture *vp = &ap->vp;
572
573 /* Too many tiles, exceeding all defined levels in the AV1 spec */
574 if (ap->av1_pic_info.tileCount > MAX_TILES256)
575 return AVERROR(ENOSYS)(-(38));
576
577 for (int i = s->tg_start; i <= s->tg_end; i++) {
578 ap->tile_sizes[ap->av1_pic_info.tileCount] = s->tile_group_info[i].tile_size;
579
580 err = ff_vk_decode_add_slice(avctx, vp,
581 data + s->tile_group_info[i].tile_offset,
582 s->tile_group_info[i].tile_size, 0,
583 &ap->av1_pic_info.tileCount,
584 &ap->av1_pic_info.pTileOffsets);
585 if (err < 0)
586 return err;
587 }
588
589 return 0;
590}
591
592static int vk_av1_end_frame(AVCodecContext *avctx)
593{
594 const AV1DecContext *s = avctx->priv_data;
595 FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data;
596 FFVulkanDecodeShared *ctx = dec->shared_ctx;
597
598 const AV1Frame *pic = &s->cur_frame;
599 AV1VulkanDecodePicture *ap = pic->hwaccel_picture_private;
600 FFVulkanDecodePicture *vp = &ap->vp;
601 FFVulkanDecodePicture *rvp[AV1_NUM_REF_FRAMES] = { 0 };
602 AVFrame *rav[AV1_NUM_REF_FRAMES] = { 0 };
603
604#ifdef VK_KHR_video_maintenance21
605 StdVideoAV1SequenceHeader av1_sequence_header;
606 StdVideoAV1TimingInfo av1_timing_info;
607 StdVideoAV1ColorConfig av1_color_config;
608 VkVideoDecodeAV1InlineSessionParametersInfoKHR av1_params;
609
610 if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2(1ULL << 38)) {
611 vk_av1_params_fill(avctx, &av1_timing_info, &av1_color_config,
612 &av1_sequence_header);
613 av1_params = (VkVideoDecodeAV1InlineSessionParametersInfoKHR) {
614 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_INLINE_SESSION_PARAMETERS_INFO_KHR,
615 .pStdSequenceHeader = &av1_sequence_header,
616 };
617 ap->av1_pic_info.pNext = &av1_params;
618 }
619#endif
620
621 if (!ap->av1_pic_info.tileCount)
622 return 0;
623
624 if (!dec->session_params &&
625 !(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2(1ULL << 38))) {
626 int err = vk_av1_create_params(avctx, &dec->session_params, ap);
627 if (err < 0)
628 return err;
629 }
630
631 for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
632 const AV1Frame *rp = ap->ref_src[i];
633 AV1VulkanDecodePicture *rhp = rp->hwaccel_picture_private;
634
635 rvp[i] = &rhp->vp;
636 rav[i] = ap->ref_src[i]->f;
637 }
638
639 av_log(avctx, AV_LOG_DEBUG48, "Decoding frame, %zu bytes, %i tiles\n",
640 vp->slices_size, ap->av1_pic_info.tileCount);
641
642 return ff_vk_decode_frame(avctx, pic->f, vp, rav, rvp);
643}
644
645static void vk_av1_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
646{
647 AVHWDeviceContext *hwctx = _hwctx.nc;
648 AV1VulkanDecodePicture *ap = data;
649
650 /* Free frame resources, this also destroys the session parameters. */
651 ff_vk_decode_free_frame(hwctx, &ap->vp);
652}
653
654const FFHWAccel ff_av1_vulkan_hwaccel = {
655 .p.name = "av1_vulkan",
656 .p.type = AVMEDIA_TYPE_VIDEO,
657 .p.id = AV_CODEC_ID_AV1,
658 .p.pix_fmt = AV_PIX_FMT_VULKAN,
659 .start_frame = &vk_av1_start_frame,
660 .decode_slice = &vk_av1_decode_slice,
661 .end_frame = &vk_av1_end_frame,
662 .free_frame_priv = &vk_av1_free_frame_priv,
663 .frame_priv_data_size = sizeof(AV1VulkanDecodePicture),
664 .init = &ff_vk_decode_init,
665 .update_thread_context = &ff_vk_update_thread_context,
666 .decode_params = &ff_vk_params_invalidate,
667 .uninit = &ff_vk_decode_uninit,
668 .frame_params = &ff_vk_frame_params,
669 .priv_data_size = sizeof(FFVulkanDecodeContext),
670 .caps_internal = HWACCEL_CAP_ASYNC_SAFE(1 << 0),
671};