Coverage Report

Created: 2026-02-14 06:59

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
132k
{
47
132k
    ParseContext *pc = &p->pc;
48
132k
    int pic_found, i = 0;
49
132k
    uint32_t state;
50
51
132k
    pic_found = pc->frame_start_found;
52
132k
    state = pc->state;
53
54
132k
    if (buf_size == 0) {
55
0
        pc->frame_start_found = 0;
56
0
        pc->state = -1;
57
0
        return 0;
58
0
    }
59
60
132k
    if (!pic_found) {
61
8.40M
        for (; i < buf_size; i++) {
62
8.35M
            state = (state << 8) | buf[i];
63
8.35M
            if (state == APV_SIGNATURE) {
64
44.2k
                i++;
65
44.2k
                pic_found = 1;
66
44.2k
                break;
67
44.2k
            }
68
8.35M
        }
69
86.1k
    }
70
71
132k
    if (pic_found) {
72
15.5M
        for(; i < buf_size; i++) {
73
15.5M
            state = (state << 8) | buf[i];
74
15.5M
            if (state == APV_SIGNATURE) {
75
43.7k
                pc->frame_start_found = 0;
76
43.7k
                pc->state = -1;
77
43.7k
                return i - 3;
78
43.7k
            }
79
15.5M
        }
80
90.1k
    }
81
82
88.3k
    pc->frame_start_found = pic_found;
83
88.3k
    pc->state = state;
84
88.3k
    return END_NOT_FOUND;
85
132k
}
86
87
static void dummy_free(void *opaque, uint8_t *data)
88
151k
{
89
151k
    av_assert0(opaque == data);
90
151k
}
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
241k
{
97
241k
    APVParseContext *p = s->priv_data;
98
241k
    CodedBitstreamFragment *au = &p->au;
99
241k
    AVBufferRef *ref = NULL;
100
241k
    int next, ret;
101
102
241k
    if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
103
109k
        next = buf_size;
104
132k
    } else {
105
132k
        next = find_frame_end(p, buf, buf_size);
106
107
132k
        if (ff_combine_frame(&p->pc, next, &buf, &buf_size) < 0) {
108
88.3k
            *poutbuf      = NULL;
109
88.3k
            *poutbuf_size = 0;
110
88.3k
            return buf_size;
111
88.3k
        }
112
132k
    }
113
114
153k
    *poutbuf      = buf;
115
153k
    *poutbuf_size = buf_size;
116
117
153k
    if (!buf_size)
118
2.04k
        return 0;
119
120
151k
    ref = av_buffer_create((uint8_t *)buf, buf_size, dummy_free,
121
151k
                           (void *)buf, AV_BUFFER_FLAG_READONLY);
122
151k
    if (!ref)
123
0
        return next;
124
125
151k
    p->cbc->log_ctx = avctx;
126
127
151k
    ret = ff_cbs_read(p->cbc, au, ref, buf, buf_size);
128
151k
    if (ret < 0) {
129
126k
        av_log(avctx, AV_LOG_ERROR, "Failed to parse access unit.\n");
130
126k
        goto end;
131
126k
    }
132
133
25.5k
    s->key_frame         = 1;
134
25.5k
    s->pict_type         = AV_PICTURE_TYPE_I;
135
25.5k
    s->field_order       = AV_FIELD_UNKNOWN;
136
25.5k
    s->picture_structure = AV_PICTURE_STRUCTURE_FRAME;
137
138
32.6k
    for (int i = 0; i < au->nb_units; i++) {
139
19.9k
        const CodedBitstreamUnit *pbu = &au->units[i];
140
141
19.9k
        switch (pbu->type) {
142
13.4k
        case APV_PBU_PRIMARY_FRAME: {
143
13.4k
            const APVRawFrame *frame        = pbu->content;
144
13.4k
            const APVRawFrameHeader *header = &frame->frame_header;
145
13.4k
            const APVRawFrameInfo *info     = &header->frame_info;
146
13.4k
            int bit_depth = info->bit_depth_minus8 + 8;
147
148
13.4k
            if (bit_depth < 8 || bit_depth > 16 || bit_depth % 2)
149
628
                break;
150
151
12.8k
            s->width                        = info->frame_width;
152
12.8k
            s->height                       = info->frame_height;
153
12.8k
            s->format                       = apv_format_table[info->chroma_format_idc][bit_depth - 4 >> 2];
154
12.8k
            avctx->profile                  = info->profile_idc;
155
12.8k
            avctx->level                    = info->level_idc;
156
12.8k
            avctx->chroma_sample_location   = AVCHROMA_LOC_TOPLEFT;
157
12.8k
            avctx->color_primaries          = header->color_primaries;
158
12.8k
            avctx->color_trc                = header->transfer_characteristics;
159
12.8k
            avctx->colorspace               = header->matrix_coefficients;
160
12.8k
            avctx->color_range              = header->full_range_flag ? AVCOL_RANGE_JPEG
161
12.8k
                                                                      : AVCOL_RANGE_MPEG;
162
12.8k
            goto end;
163
13.4k
        }
164
6.50k
        default:
165
6.50k
            break;
166
19.9k
        }
167
19.9k
    }
168
169
151k
end:
170
151k
    ff_cbs_fragment_reset(au);
171
151k
    av_assert1(av_buffer_get_ref_count(ref) == 1);
172
151k
    av_buffer_unref(&ref);
173
151k
    p->cbc->log_ctx = NULL;
174
175
151k
    return next;
176
25.5k
}
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.66k
{
184
2.66k
    APVParseContext *p = s->priv_data;
185
2.66k
    int ret;
186
187
2.66k
    ret = ff_cbs_init(&p->cbc, AV_CODEC_ID_APV, NULL);
188
2.66k
    if (ret < 0)
189
0
        return ret;
190
191
2.66k
    p->cbc->decompose_unit_types    = decompose_unit_types;
192
2.66k
    p->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
193
194
2.66k
    return 0;
195
2.66k
}
196
197
static av_cold void close(AVCodecParserContext *s)
198
2.66k
{
199
2.66k
    APVParseContext *p = s->priv_data;
200
2.66k
    ParseContext *pc = &p->pc;
201
202
2.66k
    av_freep(&pc->buffer);
203
2.66k
    ff_cbs_fragment_free(&p->au);
204
2.66k
    ff_cbs_close(&p->cbc);
205
2.66k
}
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
};