FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/apv_decode.c
Date: 2026-10-29 07:45:57
Exec Total Coverage
Lines: 200 298 67.1%
Functions: 12 14 85.7%
Branches: 67 120 55.8%

Line Branch Exec Source
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 <stdatomic.h>
20
21 #include "libavutil/attributes.h"
22 #include "libavutil/avassert.h"
23 #include "libavutil/mastering_display_metadata.h"
24 #include "libavutil/mem_internal.h"
25 #include "libavutil/pixdesc.h"
26 #include "libavutil/thread.h"
27
28 #include "apv.h"
29 #include "apv_decode.h"
30 #include "avcodec.h"
31 #include "cbs_apv.h"
32 #include "codec_internal.h"
33 #include "decode.h"
34 #include "internal.h"
35 #include "thread.h"
36 #include "hwconfig.h"
37 #include "hwaccel_internal.h"
38 #include "config_components.h"
39
40 static const enum AVPixelFormat apv_format_table[5][4] = {
41 { AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16 },
42 { AV_PIX_FMT_NONE, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE }, // 4:2:0 is not valid.
43 { AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV422P16 },
44 { AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16 },
45 { AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_NONE, AV_PIX_FMT_YUVA444P16 },
46 };
47
48 APVVLCLUT ff_apv_decode_lut;
49
50 10 static enum AVPixelFormat get_pixel_format(AVCodecContext *avctx,
51 enum AVPixelFormat pix_fmt)
52 {
53 10 enum AVPixelFormat pix_fmts[] = {
54 #if CONFIG_APV_VULKAN_HWACCEL
55 AV_PIX_FMT_VULKAN,
56 #endif
57 pix_fmt,
58 AV_PIX_FMT_NONE,
59 };
60
61 10 return ff_get_format(avctx, pix_fmts);
62 }
63
64 16 static int apv_decode_check_format(AVCodecContext *avctx,
65 const APVRawFrameHeader *header)
66 {
67 int err, bit_depth;
68 enum AVPixelFormat pix_fmt;
69 16 int coded_width = FFALIGN(header->frame_info.frame_width, 16);
70 16 int coded_height = FFALIGN(header->frame_info.frame_height, 16);
71 16 APVDecodeContext *apv = avctx->priv_data;
72
73 16 avctx->profile = header->frame_info.profile_idc;
74 16 avctx->level = header->frame_info.level_idc;
75
76 16 bit_depth = header->frame_info.bit_depth_minus8 + 8;
77 av_assert1(bit_depth >= 10 && bit_depth <= 16); // checked by CBS
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (bit_depth % 2) {
79 ✗ avpriv_request_sample(avctx, "Bit depth %d", bit_depth);
80 ✗ return AVERROR_PATCHWELCOME;
81 }
82
83 16 pix_fmt = apv_format_table[header->frame_info.chroma_format_idc][(bit_depth - 10) >> 1];
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (pix_fmt == AV_PIX_FMT_NONE) {
85 ✗ avpriv_request_sample(avctx, "YUVA444P14");
86 ✗ return AVERROR_PATCHWELCOME;
87 }
88
89
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (avctx->coded_width != coded_width ||
90
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 avctx->coded_height != coded_height) {
91 10 err = ff_set_dimensions(avctx, coded_width, coded_height);
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (err < 0) {
93 // Unsupported frame size.
94 ✗ return err;
95 }
96 }
97
98 16 avctx->width = header->frame_info.frame_width;
99 16 avctx->height = header->frame_info.frame_height;
100
101
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 if (pix_fmt != apv->pix_fmt) {
102 10 apv->pix_fmt = pix_fmt;
103
104 10 err = get_pixel_format(avctx, pix_fmt);
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (err < 0)
106 ✗ return err;
107
108 10 avctx->pix_fmt = err;
109 }
110
111 16 avctx->sample_aspect_ratio = (AVRational){ 1, 1 };
112
113 16 avctx->color_primaries = header->color_primaries;
114 16 avctx->color_trc = header->transfer_characteristics;
115 16 avctx->colorspace = header->matrix_coefficients;
116 32 avctx->color_range = header->full_range_flag ? AVCOL_RANGE_JPEG
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 : AVCOL_RANGE_MPEG;
118 16 avctx->chroma_sample_location = AVCHROMA_LOC_TOPLEFT;
119
120 16 avctx->refs = 0;
121 16 avctx->has_b_frames = 0;
122
123 16 return 0;
124 }
125
126 static const CodedBitstreamUnitType apv_decompose_unit_types[] = {
127 APV_PBU_PRIMARY_FRAME,
128 APV_PBU_METADATA,
129 };
130
131 static AVOnce apv_entropy_once = AV_ONCE_INIT;
132
133 7 static av_cold void apv_entropy_build_decode_lut(void)
134 {
135 7 ff_apv_entropy_build_decode_lut(&ff_apv_decode_lut);
136 7 }
137
138 10 static av_cold int apv_decode_init(AVCodecContext *avctx)
139 {
140 10 APVDecodeContext *apv = avctx->priv_data;
141 int err;
142
143 10 apv->pix_fmt = AV_PIX_FMT_NONE;
144
145 10 ff_thread_once(&apv_entropy_once, apv_entropy_build_decode_lut);
146
147 10 err = ff_cbs_init(&apv->cbc, AV_CODEC_ID_APV, avctx);
148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (err < 0)
149 ✗ return err;
150
151 10 apv->cbc->decompose_unit_types =
152 apv_decompose_unit_types;
153 10 apv->cbc->nb_decompose_unit_types =
154 FF_ARRAY_ELEMS(apv_decompose_unit_types);
155
156 // Extradata could be set here, but is ignored by the decoder.
157
158 10 apv->pkt = avctx->internal->in_pkt;
159 10 ff_apv_dsp_init(&apv->dsp);
160
161 10 atomic_init(&apv->tile_errors, 0);
162
163 10 return 0;
164 }
165
166 ✗ static av_cold void apv_decode_flush(AVCodecContext *avctx)
167 {
168 ✗ APVDecodeContext *apv = avctx->priv_data;
169
170 ✗ apv->nb_unit = 0;
171 ✗ av_packet_unref(apv->pkt);
172 ✗ ff_cbs_fragment_reset(&apv->au);
173 ✗ ff_cbs_flush(apv->cbc);
174 ✗ }
175
176 10 static av_cold int apv_decode_close(AVCodecContext *avctx)
177 {
178 10 APVDecodeContext *apv = avctx->priv_data;
179
180 10 ff_cbs_fragment_free(&apv->au);
181 10 ff_cbs_close(&apv->cbc);
182
183 10 return 0;
184 }
185
186 14400 static int apv_decode_block(AVCodecContext *avctx,
187 void *output,
188 ptrdiff_t pitch,
189 GetBitContext *gbc,
190 APVEntropyState *entropy_state,
191 int bit_depth,
192 int qp_shift,
193 const uint16_t *qmatrix)
194 {
195 14400 APVDecodeContext *apv = avctx->priv_data;
196 int err;
197
198 14400 LOCAL_ALIGNED_32(int16_t, coeff, [64]);
199 14400 memset(coeff, 0, 64 * sizeof(int16_t));
200
201 14400 err = ff_apv_entropy_decode_block(coeff, gbc, entropy_state);
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14400 times.
14400 if (err < 0)
203 ✗ return err;
204
205 14400 apv->dsp.decode_transquant(output, pitch,
206 coeff, qmatrix,
207 bit_depth, qp_shift);
208
209 14400 return 0;
210 }
211
212 42 static int apv_decode_tile_component(AVCodecContext *avctx, void *data,
213 int job, int thread)
214 {
215 42 APVRawFrame *input = data;
216 42 APVDecodeContext *apv = avctx->priv_data;
217 42 const APVDerivedTileInfo *tile_info = &apv->tile_info;
218 const AVPixFmtDescriptor *pix_fmt_desc =
219 42 av_pix_fmt_desc_get(apv->pix_fmt);
220 42 int nb_components = pix_fmt_desc->nb_components;
221
222 42 int tile_index = job / nb_components;
223 42 int comp_index = job % nb_components;
224
225
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 18 times.
42 int sub_w_shift = comp_index == 0 ? 0 : pix_fmt_desc->log2_chroma_w;
226
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 18 times.
42 int sub_h_shift = comp_index == 0 ? 0 : pix_fmt_desc->log2_chroma_h;
227
228 42 APVRawTile *tile = &input->tile[tile_index];
229
230 42 int tile_y = tile_index / tile_info->tile_cols;
231 42 int tile_x = tile_index % tile_info->tile_cols;
232
233 42 int tile_start_x = tile_info->col_starts[tile_x];
234 42 int tile_start_y = tile_info->row_starts[tile_y];
235
236 42 int tile_width = tile_info->col_starts[tile_x + 1] - tile_start_x;
237 42 int tile_height = tile_info->row_starts[tile_y + 1] - tile_start_y;
238
239 42 int tile_mb_width = tile_width / APV_MB_WIDTH;
240 42 int tile_mb_height = tile_height / APV_MB_HEIGHT;
241
242 42 int blk_mb_width = 2 >> sub_w_shift;
243 42 int blk_mb_height = 2 >> sub_h_shift;
244
245 int bit_depth;
246 int qp_shift;
247 42 LOCAL_ALIGNED_32(uint16_t, qmatrix_scaled, [64]);
248
249 GetBitContext gbc;
250
251 42 APVEntropyState entropy_state = {
252 .log_ctx = avctx,
253 .decode_lut = &ff_apv_decode_lut,
254 .prev_dc = 0,
255 .prev_k_dc = 5,
256 .prev_k_level = 0,
257 };
258
259 int err;
260
261 42 err = init_get_bits8(&gbc, tile->tile_data[comp_index],
262 42 tile->tile_header.tile_data_size[comp_index]);
263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (err < 0)
264 ✗ goto fail;
265
266 // Combine the bitstream quantisation matrix with the qp scaling
267 // in advance. (Including qp_shift as well would overflow 16 bits.)
268 // Fix the row ordering at the same time.
269 {
270 static const uint8_t apv_level_scale[6] = { 40, 45, 51, 57, 64, 71 };
271 42 int qp = tile->tile_header.tile_qp[comp_index];
272 42 int level_scale = apv_level_scale[qp % 6];
273
274 42 bit_depth = input->frame_header.frame_info.bit_depth_minus8 + 8;
275 42 qp_shift = qp / 6;
276
277
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 42 times.
378 for (int y = 0; y < 8; y++) {
278
2/2
✓ Branch 0 taken 2688 times.
✓ Branch 1 taken 336 times.
3024 for (int x = 0; x < 8; x++)
279 2688 qmatrix_scaled[y * 8 + x] = level_scale *
280 2688 input->frame_header.quantization_matrix.q_matrix[comp_index][x][y];
281 }
282 }
283
284
2/2
✓ Branch 0 taken 504 times.
✓ Branch 1 taken 42 times.
546 for (int mb_y = 0; mb_y < tile_mb_height; mb_y++) {
285
2/2
✓ Branch 0 taken 5040 times.
✓ Branch 1 taken 504 times.
5544 for (int mb_x = 0; mb_x < tile_mb_width; mb_x++) {
286
2/2
✓ Branch 0 taken 10080 times.
✓ Branch 1 taken 5040 times.
15120 for (int blk_y = 0; blk_y < blk_mb_height; blk_y++) {
287
2/2
✓ Branch 0 taken 14400 times.
✓ Branch 1 taken 10080 times.
24480 for (int blk_x = 0; blk_x < blk_mb_width; blk_x++) {
288 14400 int frame_y = (tile_start_y +
289 14400 APV_MB_HEIGHT * mb_y +
290 14400 APV_TR_SIZE * blk_y) >> sub_h_shift;
291 14400 int frame_x = (tile_start_x +
292 14400 APV_MB_WIDTH * mb_x +
293 14400 APV_TR_SIZE * blk_x) >> sub_w_shift;
294
295 14400 ptrdiff_t frame_pitch = apv->output_frame->linesize[comp_index];
296 14400 uint8_t *block_start = apv->output_frame->data[comp_index] +
297 14400 frame_y * frame_pitch + 2 * frame_x;
298
299 14400 err = apv_decode_block(avctx,
300 block_start, frame_pitch,
301 &gbc, &entropy_state,
302 bit_depth,
303 qp_shift,
304 qmatrix_scaled);
305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14400 times.
14400 if (err < 0) {
306 // Error in block decode means entropy desync,
307 // so this is not recoverable.
308 ✗ goto fail;
309 }
310 }
311 }
312 }
313 }
314
315 42 av_log(avctx, AV_LOG_TRACE,
316 "Decoded tile %d component %d: %dx%d MBs starting at (%d,%d)\n",
317 tile_index, comp_index, tile_mb_width, tile_mb_height,
318 tile_start_x, tile_start_y);
319
320 42 return 0;
321
322 ✗ fail:
323 ✗ av_log(avctx, AV_LOG_VERBOSE,
324 "Decode error in tile %d component %d.\n",
325 tile_index, comp_index);
326 ✗ atomic_fetch_add_explicit(&apv->tile_errors, 1, memory_order_relaxed);
327 ✗ return err;
328 }
329
330 9 static void apv_derive_tile_info(APVDerivedTileInfo *ti,
331 const APVRawFrameHeader *fh)
332 {
333 9 int frame_width_in_mbs = (fh->frame_info.frame_width + (APV_MB_WIDTH - 1)) >> 4;
334 9 int frame_height_in_mbs = (fh->frame_info.frame_height + (APV_MB_HEIGHT - 1)) >> 4;
335 int start_mb, i;
336
337 9 start_mb = 0;
338
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 9 times.
27 for (i = 0; start_mb < frame_width_in_mbs; i++) {
339 18 ti->col_starts[i] = start_mb * APV_MB_WIDTH;
340 18 start_mb += fh->tile_info.tile_width_in_mbs;
341 }
342 9 ti->col_starts[i] = frame_width_in_mbs * APV_MB_WIDTH;
343 9 ti->tile_cols = i;
344
345 9 start_mb = 0;
346
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (i = 0; start_mb < frame_height_in_mbs; i++) {
347 9 ti->row_starts[i] = start_mb * APV_MB_HEIGHT;
348 9 start_mb += fh->tile_info.tile_height_in_mbs;
349 }
350 9 ti->row_starts[i] = frame_height_in_mbs * APV_MB_HEIGHT;
351 9 ti->tile_rows = i;
352
353 9 ti->num_tiles = ti->tile_cols * ti->tile_rows;
354 9 }
355
356 16 static int apv_decode(AVCodecContext *avctx, AVFrame *output,
357 APVRawFrame *input)
358 {
359 16 APVDecodeContext *apv = avctx->priv_data;
360 16 const AVPixFmtDescriptor *desc = NULL;
361 16 APVDerivedTileInfo *tile_info = &apv->tile_info;
362 int err, job_count;
363
364 16 err = apv_decode_check_format(avctx, &input->frame_header);
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (err < 0) {
366 ✗ av_log(avctx, AV_LOG_ERROR, "Unsupported format parameters.\n");
367 ✗ return err;
368 }
369
370
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9 times.
16 if (avctx->skip_frame == AVDISCARD_ALL)
371 7 return 0;
372
373 9 desc = av_pix_fmt_desc_get(apv->pix_fmt);
374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 av_assert0(desc);
375
376 9 err = ff_thread_get_buffer(avctx, output, 0);
377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
378 ✗ return err;
379
380 9 apv->cur_raw_frame = input;
381 9 apv->output_frame = output;
382 9 atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed);
383
384 9 apv_derive_tile_info(tile_info, &input->frame_header);
385
386 9 err = ff_hwaccel_frame_priv_alloc(avctx, &apv->hwaccel_picture_private);
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err < 0)
388 ✗ return err;
389
390 9 ff_thread_finish_setup(avctx);
391
392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (avctx->hwaccel) {
393 ✗ const FFHWAccel *hwaccel = ffhwaccel(avctx->hwaccel);
394
395 ✗ err = hwaccel->start_frame(avctx, apv->pkt->buf,
396 ✗ apv->pkt->data, apv->pkt->size);
397 ✗ if (err < 0)
398 ✗ return err;
399
400 ✗ for (int j = 0; j < desc->nb_components; j++) {
401 ✗ for (int i = 0; i < tile_info->num_tiles; i++) {
402 ✗ APVRawTile *tile = &input->tile[i];
403 ✗ err = hwaccel->decode_slice(avctx, tile->tile_data[j],
404 tile->tile_header.tile_data_size[j]);
405 ✗ if (err < 0)
406 ✗ return err;
407 }
408 }
409
410 ✗ err = hwaccel->end_frame(avctx);
411 ✗ if (err < 0)
412 ✗ return err;
413
414 ✗ av_refstruct_unref(&apv->hwaccel_picture_private);
415 } else {
416 // Each component within a tile is independent of every other,
417 // so we can decode all in parallel.
418 9 job_count = tile_info->num_tiles * desc->nb_components;
419
420 9 avctx->execute2(avctx, apv_decode_tile_component,
421 input, NULL, job_count);
422
423 9 err = atomic_load_explicit(&apv->tile_errors, memory_order_relaxed);
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (err > 0) {
425 ✗ av_log(avctx, AV_LOG_ERROR,
426 "Decode errors in %d tile components.\n", err);
427 ✗ if (avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) {
428 // Output the frame anyway.
429 ✗ output->flags |= AV_FRAME_FLAG_CORRUPT;
430 } else {
431 ✗ return AVERROR_INVALIDDATA;
432 }
433 }
434 }
435
436 9 return 0;
437 }
438
439 16 static int apv_decode_metadata(AVCodecContext *avctx, AVFrame *frame,
440 const APVRawMetadata *md)
441 {
442 int err;
443
444
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
48 for (int i = 0; i < md->metadata_count; i++) {
445 32 const APVRawMetadataPayload *pl = &md->payloads[i];
446
447
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 switch (pl->payload_type) {
448 ✗ case APV_METADATA_MDCV:
449 {
450 ✗ const APVRawMetadataMDCV *mdcv = &pl->mdcv;
451 AVMasteringDisplayMetadata *mdm;
452
453 ✗ err = ff_decode_mastering_display_new(avctx, frame, &mdm);
454 ✗ if (err < 0)
455 ✗ return err;
456
457 ✗ if (mdm) {
458 ✗ for (int j = 0; j < 3; j++) {
459 ✗ mdm->display_primaries[j][0] =
460 ✗ av_make_q(mdcv->primary_chromaticity_x[j], 1 << 16);
461 ✗ mdm->display_primaries[j][1] =
462 ✗ av_make_q(mdcv->primary_chromaticity_y[j], 1 << 16);
463 }
464
465 ✗ mdm->white_point[0] =
466 ✗ av_make_q(mdcv->white_point_chromaticity_x, 1 << 16);
467 ✗ mdm->white_point[1] =
468 ✗ av_make_q(mdcv->white_point_chromaticity_y, 1 << 16);
469
470 ✗ mdm->max_luminance =
471 ✗ av_make_q(mdcv->max_mastering_luminance, 1 << 8);
472 ✗ mdm->min_luminance =
473 ✗ av_make_q(mdcv->min_mastering_luminance, 1 << 14);
474
475 ✗ mdm->has_primaries = 1;
476 ✗ mdm->has_luminance = 1;
477 }
478 }
479 ✗ break;
480 ✗ case APV_METADATA_CLL:
481 {
482 ✗ const APVRawMetadataCLL *cll = &pl->cll;
483 AVContentLightMetadata *clm;
484
485 ✗ err = ff_decode_content_light_new(avctx, frame, &clm);
486 ✗ if (err < 0)
487 ✗ return err;
488
489 ✗ if (clm) {
490 ✗ clm->MaxCLL = cll->max_cll;
491 ✗ clm->MaxFALL = cll->max_fall;
492 }
493 }
494 ✗ break;
495 32 default:
496 // Ignore other types of metadata.
497 32 break;
498 }
499 }
500
501 16 return 0;
502 }
503
504 32 static int apv_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
505 {
506 32 APVDecodeContext *apv = avctx->priv_data;
507 32 CodedBitstreamFragment *au = &apv->au;
508 int i, err;
509
510
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
48 for (i = apv->nb_unit; i < au->nb_units; i++) {
511 32 CodedBitstreamUnit *pbu = &au->units[i];
512
513
2/5
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
32 switch (pbu->type) {
514 16 case APV_PBU_PRIMARY_FRAME:
515 16 err = apv_decode(avctx, frame, pbu->content);
516 16 frame->pkt_dts = apv->pkt->dts;
517 16 i++;
518 16 goto end;
519 16 case APV_PBU_METADATA:
520 16 apv_decode_metadata(avctx, frame, pbu->content);
521 16 break;
522 ✗ case APV_PBU_NON_PRIMARY_FRAME:
523 case APV_PBU_PREVIEW_FRAME:
524 case APV_PBU_DEPTH_FRAME:
525 case APV_PBU_ALPHA_FRAME:
526 ✗ if (!avctx->internal->is_copy &&
527 ✗ !apv->warned_additional_frames) {
528 ✗ av_log(avctx, AV_LOG_WARNING,
529 "Stream contains additional non-primary frames "
530 "which will be ignored by the decoder.\n");
531 ✗ apv->warned_additional_frames = 1;
532 }
533 ✗ break;
534 ✗ case APV_PBU_ACCESS_UNIT_INFORMATION:
535 case APV_PBU_FILLER:
536 // Not relevant to the decoder.
537 ✗ break;
538 ✗ default:
539 ✗ if (!avctx->internal->is_copy &&
540 ✗ !apv->warned_unknown_pbu_types) {
541 ✗ av_log(avctx, AV_LOG_WARNING,
542 "Stream contains PBUs with unknown types "
543 "which will be ignored by the decoder.\n");
544 ✗ apv->warned_unknown_pbu_types = 1;
545 }
546 ✗ break;
547 }
548 }
549
550 16 err = AVERROR(EAGAIN);
551 32 end:
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 av_assert0(i <= apv->au.nb_units);
553 32 apv->nb_unit = i;
554
555
5/6
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 16 times.
32 if ((err < 0 && err != AVERROR(EAGAIN)) || apv->au.nb_units == i) {
556 16 av_packet_unref(apv->pkt);
557 16 ff_cbs_fragment_reset(&apv->au);
558 16 apv->nb_unit = 0;
559 }
560
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 9 times.
32 if (!err && !frame->buf[0])
561 7 err = AVERROR(EAGAIN);
562
563 32 return err;
564 }
565
566 35 static int apv_receive_frame(AVCodecContext *avctx, AVFrame *frame)
567 {
568 35 APVDecodeContext *apv = avctx->priv_data;
569 int err;
570
571 do {
572
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 16 times.
58 if (!apv->au.nb_units) {
573 42 err = ff_decode_get_packet(avctx, apv->pkt);
574
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 16 times.
42 if (err < 0)
575 26 return err;
576
577 16 err = ff_cbs_read_packet(apv->cbc, &apv->au, apv->pkt);
578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (err < 0) {
579 ✗ ff_cbs_fragment_reset(&apv->au);
580 ✗ av_packet_unref(apv->pkt);
581 ✗ av_log(avctx, AV_LOG_ERROR, "Failed to read packet.\n");
582 ✗ return err;
583 }
584
585 16 apv->nb_unit = 0;
586 16 av_log(avctx, AV_LOG_DEBUG, "Total PBUs on this packet: %d.\n",
587 apv->au.nb_units);
588 }
589
590 32 err = apv_receive_frame_internal(avctx, frame);
591
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 9 times.
32 } while (err == AVERROR(EAGAIN));
592
593 9 return err;
594 }
595
596 #if HAVE_THREADS
597 ✗ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
598 {
599 ✗ APVDecodeContext *asrc = src->priv_data;
600 ✗ APVDecodeContext *adst = dst->priv_data;
601
602 ✗ adst->pix_fmt = asrc->pix_fmt;
603
604 ✗ return 0;
605 }
606 #endif
607
608 const FFCodec ff_apv_decoder = {
609 .p.name = "apv",
610 CODEC_LONG_NAME("Advanced Professional Video"),
611 .p.type = AVMEDIA_TYPE_VIDEO,
612 .p.id = AV_CODEC_ID_APV,
613 .priv_data_size = sizeof(APVDecodeContext),
614 .init = apv_decode_init,
615 .flush = apv_decode_flush,
616 .close = apv_decode_close,
617 FF_CODEC_RECEIVE_FRAME_CB(apv_receive_frame),
618 UPDATE_THREAD_CONTEXT(update_thread_context),
619 .p.capabilities = AV_CODEC_CAP_DR1 |
620 AV_CODEC_CAP_SLICE_THREADS |
621 AV_CODEC_CAP_FRAME_THREADS,
622 .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
623 .hw_configs = (const AVCodecHWConfigInternal *const []) {
624 #if CONFIG_APV_VULKAN_HWACCEL
625 HWACCEL_VULKAN(apv),
626 #endif
627 NULL
628 },
629 };
630