Coverage Report

Created: 2026-09-14 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/apv_parser.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 "libavutil/avassert.h"
20
#include "libavutil/buffer.h"
21
#include "libavutil/mem.h"
22
23
#include "avcodec.h"
24
#include "apv.h"
25
#include "cbs.h"
26
#include "cbs_apv.h"
27
#include "parser.h"
28
#include "parser_internal.h"
29
30
typedef struct APVParseContext {
31
    ParseContext pc;
32
33
    CodedBitstreamContext *cbc;
34
    CodedBitstreamFragment au;
35
} APVParseContext;
36
37
static const enum AVPixelFormat apv_format_table[5][5] = {
38
    { AV_PIX_FMT_GRAY8,    AV_PIX_FMT_GRAY10,     AV_PIX_FMT_GRAY12,     AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16 },
39
    { 0 }, // 4:2:0 is not valid.
40
    { AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV422P10,  AV_PIX_FMT_YUV422P12,  AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUV422P16 },
41
    { AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV444P10,  AV_PIX_FMT_YUV444P12,  AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUV444P16 },
42
    { AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUVA444P16 },
43
};
44
45
static int find_frame_end(APVParseContext *p, const uint8_t *buf, int buf_size)
46
156k
{
47
156k
    ParseContext *pc = &p->pc;
48
156k
    int pic_found, i = 0;
49
156k
    uint32_t state;
50
51
156k
    pic_found = pc->frame_start_found;
52
156k
    state = pc->state;
53
54
156k
    if (buf_size == 0) {
55
0
        pc->frame_start_found = 0;
56
0
        pc->state = -1;
57
0
        return 0;
58
0
    }
59
60
156k
    if (!pic_found) {
61
8.45M
        for (; i < buf_size; i++) {
62
8.41M
            state = (state << 8) | buf[i];
63
8.41M
            if (state == APV_SIGNATURE) {
64
64.8k
                i++;
65
64.8k
                pic_found = 1;
66
64.8k
                break;
67
64.8k
            }
68
8.41M
        }
69
105k
    }
70
71
156k
    if (pic_found) {
72
13.3M
        for(; i < buf_size; i++) {
73
13.2M
            state = (state << 8) | buf[i];
74
13.2M
            if (state == APV_SIGNATURE) {
75
64.4k
                pc->frame_start_found = 0;
76
64.4k
                pc->state = -1;
77
64.4k
                return i - 3;
78
64.4k
            }
79
13.2M
        }
80
115k
    }
81
82
92.1k
    pc->frame_start_found = pic_found;
83
92.1k
    pc->state = state;
84
92.1k
    return END_NOT_FOUND;
85
156k
}
86
87
static void dummy_free(void *opaque, uint8_t *data)
88
180k
{
89
180k
    av_assert0(opaque == data);
90
180k
}
91
92
static int parse(AVCodecParserContext *s,
93
                 AVCodecContext *avctx,
94
                 const uint8_t **poutbuf, int *poutbuf_size,
95
                 const uint8_t *buf, int buf_size)
96
275k
{
97
275k
    APVParseContext *p = s->priv_data;
98
275k
    CodedBitstreamFragment *au = &p->au;
99
275k
    AVBufferRef *ref = NULL;
100
275k
    int next, ret;
101
102
275k
    if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
103
118k
        next = buf_size;
104
156k
    } else {
105
156k
        next = find_frame_end(p, buf, buf_size);
106
107
156k
        if (ff_combine_frame(&p->pc, next, &buf, &buf_size) < 0) {
108
92.1k
            *poutbuf      = NULL;
109
92.1k
            *poutbuf_size = 0;
110
92.1k
            return buf_size;
111
92.1k
        }
112
156k
    }
113
114
183k
    *poutbuf      = buf;
115
183k
    *poutbuf_size = buf_size;
116
117
183k
    if (!buf_size)
118
2.31k
        return 0;
119
120
180k
    ref = av_buffer_create((uint8_t *)buf, buf_size, dummy_free,
121
180k
                           (void *)buf, AV_BUFFER_FLAG_READONLY);
122
180k
    if (!ref)
123
0
        return next;
124
125
180k
    p->cbc->log_ctx = avctx;
126
127
180k
    ret = ff_cbs_read(p->cbc, au, ref, buf, buf_size);
128
180k
    if (ret < 0) {
129
146k
        av_log(avctx, AV_LOG_ERROR, "Failed to parse access unit.\n");
130
146k
        goto end;
131
146k
    }
132
133
34.0k
    s->key_frame         = 1;
134
34.0k
    s->pict_type         = AV_PICTURE_TYPE_I;
135
34.0k
    s->field_order       = AV_FIELD_UNKNOWN;
136
34.0k
    s->picture_structure = AV_PICTURE_STRUCTURE_FRAME;
137
138
43.3k
    for (int i = 0; i < au->nb_units; i++) {
139
17.0k
        const CodedBitstreamUnit *pbu = &au->units[i];
140
141
17.0k
        switch (pbu->type) {
142
8.62k
        case APV_PBU_PRIMARY_FRAME: {
143
8.62k
            const APVRawFrame *frame        = pbu->content;
144
8.62k
            const APVRawFrameHeader *header = &frame->frame_header;
145
8.62k
            const APVRawFrameInfo *info     = &header->frame_info;
146
8.62k
            int bit_depth = info->bit_depth_minus8 + 8;
147
148
8.62k
            if (bit_depth < 8 || bit_depth > 16 || bit_depth % 2)
149
835
                break;
150
151
7.78k
            s->width                        = info->frame_width;
152
7.78k
            s->height                       = info->frame_height;
153
7.78k
            s->format                       = apv_format_table[info->chroma_format_idc][bit_depth - 4 >> 2];
154
7.78k
            avctx->profile                  = info->profile_idc;
155
7.78k
            avctx->level                    = info->level_idc;
156
7.78k
            avctx->chroma_sample_location   = AVCHROMA_LOC_TOPLEFT;
157
7.78k
            avctx->color_primaries          = header->color_primaries;
158
7.78k
            avctx->color_trc                = header->transfer_characteristics;
159
7.78k
            avctx->colorspace               = header->matrix_coefficients;
160
7.78k
            avctx->color_range              = header->full_range_flag ? AVCOL_RANGE_JPEG
161
7.78k
                                                                      : AVCOL_RANGE_MPEG;
162
7.78k
            goto end;
163
8.62k
        }
164
8.42k
        default:
165
8.42k
            break;
166
17.0k
        }
167
17.0k
    }
168
169
180k
end:
170
180k
    ff_cbs_fragment_reset(au);
171
180k
    av_assert1(av_buffer_get_ref_count(ref) == 1);
172
180k
    av_buffer_unref(&ref);
173
180k
    p->cbc->log_ctx = NULL;
174
175
180k
    return next;
176
34.0k
}
177
178
static const CodedBitstreamUnitType decompose_unit_types[] = {
179
    APV_PBU_PRIMARY_FRAME,
180
};
181
182
static av_cold int init(AVCodecParserContext *s)
183
2.91k
{
184
2.91k
    APVParseContext *p = s->priv_data;
185
2.91k
    int ret;
186
187
2.91k
    ret = ff_cbs_init(&p->cbc, AV_CODEC_ID_APV, NULL);
188
2.91k
    if (ret < 0)
189
0
        return ret;
190
191
2.91k
    p->cbc->decompose_unit_types    = decompose_unit_types;
192
2.91k
    p->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
193
194
2.91k
    return 0;
195
2.91k
}
196
197
static av_cold void close(AVCodecParserContext *s)
198
2.91k
{
199
2.91k
    APVParseContext *p = s->priv_data;
200
2.91k
    ParseContext *pc = &p->pc;
201
202
2.91k
    av_freep(&pc->buffer);
203
2.91k
    ff_cbs_fragment_free(&p->au);
204
2.91k
    ff_cbs_close(&p->cbc);
205
2.91k
}
206
207
const FFCodecParser ff_apv_parser = {
208
    PARSER_CODEC_LIST(AV_CODEC_ID_APV),
209
    .priv_data_size = sizeof(APVParseContext),
210
    .init           = init,
211
    .parse          = parse,
212
    .close          = close,
213
};