FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/apv_decode.c
Date: 2026-04-24 19:58:39
Exec Total Coverage
Lines: 183 259 70.7%
Functions: 11 12 91.7%
Branches: 58 98 59.2%

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