Coverage Report

Created: 2026-09-14 08:00

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