Coverage Report

Created: 2026-05-16 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/notchlc.c
Line
Count
Source
1
/*
2
 * NotchLC decoder
3
 * Copyright (c) 2020 Paul B Mahol
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include <stdio.h>
23
#include <string.h>
24
25
#define BITSTREAM_READER_LE
26
#include "libavutil/mem.h"
27
#include "avcodec.h"
28
#include "bytestream.h"
29
#include "codec_internal.h"
30
#include "decode.h"
31
#include "get_bits.h"
32
#include "lzf.h"
33
#include "thread.h"
34
35
typedef struct NotchLCContext {
36
    unsigned compressed_size;
37
    unsigned format;
38
39
    uint8_t *uncompressed_buffer;
40
    unsigned uncompressed_size;
41
42
    uint8_t *lzf_buffer;
43
    size_t lzf_size;
44
    unsigned lzf_alloc_size;
45
46
    unsigned texture_size_x;
47
    unsigned texture_size_y;
48
    unsigned y_data_row_offsets;
49
    unsigned uv_offset_data_offset;
50
    unsigned y_control_data_offset;
51
    unsigned a_control_word_offset;
52
    unsigned y_data_offset;
53
    unsigned uv_data_offset;
54
    unsigned y_data_size;
55
    unsigned a_data_offset;
56
    unsigned uv_count_offset;
57
    unsigned a_count_size;
58
    unsigned data_end;
59
60
    GetByteContext gb;
61
    PutByteContext pb;
62
} NotchLCContext;
63
64
static av_cold int decode_init(AVCodecContext *avctx)
65
2.73k
{
66
2.73k
    avctx->pix_fmt = AV_PIX_FMT_YUVA444P12;
67
2.73k
    avctx->color_range = AVCOL_RANGE_JPEG;
68
2.73k
    avctx->colorspace = AVCOL_SPC_RGB;
69
2.73k
    avctx->color_primaries = AVCOL_PRI_BT709;
70
2.73k
    avctx->color_trc = AVCOL_TRC_IEC61966_2_1;
71
72
2.73k
    return 0;
73
2.73k
}
74
75
1.25G
#define HISTORY_SIZE (64 * 1024)
76
77
static int lz4_decompress(AVCodecContext *avctx,
78
                          GetByteContext *gb,
79
                          PutByteContext *pb)
80
4.44k
{
81
4.44k
    unsigned reference_pos, delta, pos = 0;
82
4.44k
    uint8_t history[HISTORY_SIZE] = { 0 };
83
4.44k
    int match_length;
84
85
36.8k
    while (bytestream2_get_bytes_left(gb) > 0) {
86
35.8k
        uint8_t token = bytestream2_get_byte(gb);
87
35.8k
        int num_literals = token >> 4;
88
89
35.8k
        if (num_literals == 15) {
90
3.60k
            unsigned char current;
91
1.89M
            do {
92
1.89M
                current = bytestream2_get_byte(gb);
93
1.89M
                if (current > INT_MAX - num_literals)
94
0
                    return AVERROR_INVALIDDATA;
95
1.89M
                num_literals += current;
96
1.89M
            } while (current == 255);
97
3.60k
        }
98
99
35.8k
        if (bytestream2_get_bytes_left(gb) < num_literals)
100
2.25k
            return AVERROR_INVALIDDATA;
101
102
33.6k
        if (pos + num_literals < HISTORY_SIZE) {
103
32.9k
            bytestream2_get_buffer(gb, history + pos, num_literals);
104
32.9k
            pos += num_literals;
105
32.9k
        } else {
106
2.16M
            while (num_literals-- > 0) {
107
2.16M
                history[pos++] = bytestream2_get_byte(gb);
108
2.16M
                if (pos == HISTORY_SIZE) {
109
682
                    bytestream2_put_buffer(pb, history, HISTORY_SIZE);
110
682
                    pos = 0;
111
682
                }
112
2.16M
            }
113
662
        }
114
115
33.6k
        if (bytestream2_get_bytes_left(gb) <= 0)
116
345
            break;
117
118
33.2k
        delta = bytestream2_get_le16(gb);
119
33.2k
        if (delta == 0)
120
874
            return 0;
121
32.4k
        match_length = 4 + (token & 0x0F);
122
32.4k
        if (match_length == 4 + 0x0F) {
123
11.1k
            uint8_t current;
124
125
2.62M
            do {
126
2.62M
                current = bytestream2_get_byte(gb);
127
2.62M
                if (current > INT_MAX - match_length)
128
0
                    return AVERROR_INVALIDDATA;
129
2.62M
                match_length += current;
130
2.62M
            } while (current == 255);
131
11.1k
        }
132
32.4k
        reference_pos = (pos >= delta) ? (pos - delta) : (HISTORY_SIZE + pos - delta);
133
32.4k
        if (pos + match_length < HISTORY_SIZE && reference_pos + match_length < HISTORY_SIZE) {
134
30.1k
            if (pos >= reference_pos + match_length || reference_pos >= pos + match_length) {
135
27.6k
                memcpy(history + pos, history + reference_pos, match_length);
136
27.6k
                pos += match_length;
137
27.6k
            } else {
138
39.3M
                while (match_length-- > 0)
139
39.3M
                    history[pos++] = history[reference_pos++];
140
2.47k
            }
141
30.1k
        } else {
142
626M
            while (match_length-- > 0) {
143
626M
                history[pos++] = history[reference_pos++];
144
626M
                if (pos == HISTORY_SIZE) {
145
9.36k
                    bytestream2_put_buffer(pb, history, HISTORY_SIZE);
146
9.36k
                    pos = 0;
147
9.36k
                }
148
626M
                reference_pos %= HISTORY_SIZE;
149
626M
            }
150
2.27k
        }
151
32.4k
    }
152
153
1.32k
    bytestream2_put_buffer(pb, history, pos);
154
155
1.32k
    return bytestream2_tell_p(pb);
156
4.44k
}
157
158
static int decode_blocks(AVCodecContext *avctx, AVFrame *p,
159
                         unsigned uncompressed_size)
160
93.2k
{
161
93.2k
    NotchLCContext *s = avctx->priv_data;
162
93.2k
    GetByteContext rgb, dgb, *gb = &s->gb;
163
93.2k
    GetBitContext bit;
164
93.2k
    int ylinesize, ulinesize, vlinesize, alinesize;
165
93.2k
    uint16_t *dsty, *dstu, *dstv, *dsta;
166
93.2k
    int ret;
167
168
93.2k
    s->texture_size_x = bytestream2_get_le32(gb);
169
93.2k
    s->texture_size_y = bytestream2_get_le32(gb);
170
171
93.2k
    ret = ff_set_dimensions(avctx, s->texture_size_x, s->texture_size_y);
172
93.2k
    if (ret < 0)
173
2.68k
        return ret;
174
175
90.5k
    s->uv_offset_data_offset = bytestream2_get_le32(gb);
176
90.5k
    if (s->uv_offset_data_offset >= UINT_MAX / 4)
177
304
        return AVERROR_INVALIDDATA;
178
90.2k
    s->uv_offset_data_offset *= 4;
179
90.2k
    if (s->uv_offset_data_offset >= uncompressed_size)
180
227
        return AVERROR_INVALIDDATA;
181
182
90.0k
    s->y_control_data_offset = bytestream2_get_le32(gb);
183
90.0k
    if (s->y_control_data_offset >= UINT_MAX / 4)
184
314
        return AVERROR_INVALIDDATA;
185
89.7k
    s->y_control_data_offset *= 4;
186
89.7k
    if (s->y_control_data_offset >= uncompressed_size)
187
274
        return AVERROR_INVALIDDATA;
188
189
89.4k
    s->a_control_word_offset = bytestream2_get_le32(gb);
190
89.4k
    if (s->a_control_word_offset >= UINT_MAX / 4)
191
307
        return AVERROR_INVALIDDATA;
192
89.1k
    s->a_control_word_offset *= 4;
193
89.1k
    if (s->a_control_word_offset >= uncompressed_size)
194
201
        return AVERROR_INVALIDDATA;
195
196
88.9k
    s->uv_data_offset = bytestream2_get_le32(gb);
197
88.9k
    if (s->uv_data_offset >= UINT_MAX / 4)
198
313
        return AVERROR_INVALIDDATA;
199
88.6k
    s->uv_data_offset *= 4;
200
88.6k
    if (s->uv_data_offset >= uncompressed_size)
201
224
        return AVERROR_INVALIDDATA;
202
203
88.4k
    s->y_data_size = bytestream2_get_le32(gb);
204
88.4k
    if (s->y_data_size >= UINT_MAX / 4)
205
313
        return AVERROR_INVALIDDATA;
206
207
88.0k
    s->a_data_offset = bytestream2_get_le32(gb);
208
88.0k
    if (s->a_data_offset >= UINT_MAX / 4)
209
496
        return AVERROR_INVALIDDATA;
210
87.5k
    s->a_data_offset *= 4;
211
87.5k
    if (s->a_data_offset >= uncompressed_size)
212
323
        return AVERROR_INVALIDDATA;
213
214
87.2k
    s->a_count_size = bytestream2_get_le32(gb);
215
87.2k
    if (s->a_count_size >= UINT_MAX / 4)
216
277
        return AVERROR_INVALIDDATA;
217
86.9k
    s->a_count_size *= 4;
218
86.9k
    if (s->a_count_size >= uncompressed_size)
219
246
        return AVERROR_INVALIDDATA;
220
221
86.7k
    s->data_end = bytestream2_get_le32(gb);
222
86.7k
    if (s->data_end > uncompressed_size)
223
314
        return AVERROR_INVALIDDATA;
224
225
86.4k
    s->y_data_row_offsets = bytestream2_tell(gb);
226
86.4k
    if (s->data_end <= s->y_data_size)
227
1.32k
        return AVERROR_INVALIDDATA;
228
85.1k
    s->y_data_offset = s->data_end - s->y_data_size;
229
85.1k
    if (s->y_data_offset <= s->a_data_offset)
230
473
        return AVERROR_INVALIDDATA;
231
84.6k
    s->uv_count_offset = s->y_data_offset - s->a_data_offset;
232
233
84.6k
    if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
234
299
        return ret;
235
236
84.3k
    rgb = *gb;
237
84.3k
    dgb = *gb;
238
84.3k
    bytestream2_seek(&rgb, s->y_data_row_offsets, SEEK_SET);
239
84.3k
    bytestream2_seek(gb, s->y_control_data_offset, SEEK_SET);
240
241
84.3k
    if (bytestream2_get_bytes_left(gb) < (avctx->height + 3) / 4 * ((avctx->width + 3) / 4) * 4)
242
4.33k
        return AVERROR_INVALIDDATA;
243
244
80.0k
    dsty = (uint16_t *)p->data[0];
245
80.0k
    dsta = (uint16_t *)p->data[3];
246
80.0k
    ylinesize = p->linesize[0] / 2;
247
80.0k
    alinesize = p->linesize[3] / 2;
248
249
970k
    for (int y = 0; y < avctx->height; y += 4) {
250
890k
        const unsigned row_offset = bytestream2_get_le32(&rgb);
251
252
890k
        bytestream2_seek(&dgb, s->y_data_offset + row_offset, SEEK_SET);
253
254
890k
        ret = init_get_bits8(&bit, dgb.buffer, bytestream2_get_bytes_left(&dgb));
255
890k
        if (ret < 0)
256
0
            return ret;
257
2.95M
        for (int x = 0; x < avctx->width; x += 4) {
258
2.06M
            unsigned item = bytestream2_get_le32(gb);
259
2.06M
            unsigned y_min = item & 4095;
260
2.06M
            unsigned y_max = (item >> 12) & 4095;
261
2.06M
            unsigned y_diff = y_max - y_min;
262
2.06M
            unsigned control[4];
263
264
2.06M
            control[0] = (item >> 24) & 3;
265
2.06M
            control[1] = (item >> 26) & 3;
266
2.06M
            control[2] = (item >> 28) & 3;
267
2.06M
            control[3] = (item >> 30) & 3;
268
269
10.3M
            for (int i = 0; i < 4; i++) {
270
8.24M
                const int nb_bits = control[i] + 1;
271
8.24M
                const int div = (1 << nb_bits) - 1;
272
8.24M
                const int add = div - 1;
273
274
8.24M
                dsty[x + i * ylinesize + 0] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12);
275
8.24M
                dsty[x + i * ylinesize + 1] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12);
276
8.24M
                dsty[x + i * ylinesize + 2] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12);
277
8.24M
                dsty[x + i * ylinesize + 3] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12);
278
8.24M
            }
279
2.06M
        }
280
281
890k
        dsty += 4 * ylinesize;
282
890k
    }
283
284
80.0k
    rgb = *gb;
285
80.0k
    dgb = *gb;
286
80.0k
    bytestream2_seek(gb, s->a_control_word_offset, SEEK_SET);
287
80.0k
    if (s->uv_count_offset == s->a_control_word_offset) {
288
2.58M
        for (int y = 0; y < avctx->height; y++) {
289
17.9M
            for (int x = 0; x < avctx->width; x++)
290
15.4M
                dsta[x] = 4095;
291
2.50M
            dsta += alinesize;
292
2.50M
        }
293
76.4k
    } else {
294
3.58k
        if (bytestream2_get_bytes_left(gb) < (avctx->height + 15) / 16 * ((avctx->width + 15) / 16) * 8)
295
637
            return AVERROR_INVALIDDATA;
296
297
5.70k
        for (int y = 0; y < avctx->height; y += 16) {
298
8.70k
            for (int x = 0; x < avctx->width; x += 16) {
299
5.94k
                unsigned m = bytestream2_get_le32(gb);
300
5.94k
                unsigned offset = bytestream2_get_le32(gb);
301
5.94k
                unsigned alpha0, alpha1;
302
5.94k
                uint64_t control;
303
304
5.94k
                if (offset >= UINT_MAX / 4)
305
345
                    return AVERROR_INVALIDDATA;
306
5.60k
                offset = offset * 4 + s->uv_data_offset + s->a_data_offset;
307
5.60k
                if (offset >= s->data_end)
308
250
                    return AVERROR_INVALIDDATA;
309
310
5.35k
                bytestream2_seek(&dgb, offset, SEEK_SET);
311
5.35k
                control = bytestream2_get_le64(&dgb);
312
5.35k
                alpha0 = control & 0xFF;
313
5.35k
                alpha1 = (control >> 8) & 0xFF;
314
5.35k
                control = control >> 16;
315
316
24.4k
                for (int by = 0; by < 4; by++) {
317
97.6k
                    for (int bx = 0; bx < 4; bx++) {
318
78.5k
                        switch (m & 3) {
319
65.5k
                        case 0:
320
327k
                            for (int i = 0; i < 4; i++) {
321
1.31M
                                for (int j = 0; j < 4; j++) {
322
1.04M
                                    dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = 0;
323
1.04M
                                }
324
262k
                            }
325
65.5k
                            break;
326
7.05k
                        case 1:
327
35.2k
                            for (int i = 0; i < 4; i++) {
328
141k
                                for (int j = 0; j < 4; j++) {
329
112k
                                    dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = 4095;
330
112k
                                }
331
28.2k
                            }
332
7.05k
                            break;
333
5.38k
                        case 2:
334
26.9k
                            for (int i = 0; i < 4; i++) {
335
107k
                                for (int j = 0; j < 4; j++) {
336
86.1k
                                    dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = (alpha0 + (alpha1 - alpha0) * (control & 7)) << 4;
337
86.1k
                                }
338
21.5k
                            }
339
5.38k
                            break;
340
593
                        default:
341
593
                            return AVERROR_INVALIDDATA;
342
78.5k
                        }
343
344
77.9k
                        control >>= 3;
345
77.9k
                        m >>= 2;
346
77.9k
                    }
347
19.6k
                }
348
5.35k
            }
349
350
2.75k
            dsta += 16 * alinesize;
351
2.75k
        }
352
2.95k
    }
353
354
78.1k
    bytestream2_seek(&rgb, s->uv_offset_data_offset, SEEK_SET);
355
356
78.1k
    dstu = (uint16_t *)p->data[1];
357
78.1k
    dstv = (uint16_t *)p->data[2];
358
78.1k
    ulinesize = p->linesize[1] / 2;
359
78.1k
    vlinesize = p->linesize[2] / 2;
360
361
266k
    for (int y = 0; y < avctx->height; y += 16) {
362
454k
        for (int x = 0; x < avctx->width; x += 16) {
363
266k
            unsigned offset = bytestream2_get_le32(&rgb) * 4;
364
266k
            int u[16][16] = { 0 }, v[16][16] = { 0 };
365
266k
            int u0, v0, u1, v1, udif, vdif;
366
266k
            unsigned escape, is8x8, loc;
367
368
266k
            bytestream2_seek(&dgb, s->uv_data_offset + offset, SEEK_SET);
369
370
266k
            is8x8 = bytestream2_get_le16(&dgb);
371
266k
            escape = bytestream2_get_le16(&dgb);
372
373
266k
            if (escape == 0 && is8x8 == 0) {
374
171k
                u0 = bytestream2_get_byte(&dgb);
375
171k
                v0 = bytestream2_get_byte(&dgb);
376
171k
                u1 = bytestream2_get_byte(&dgb);
377
171k
                v1 = bytestream2_get_byte(&dgb);
378
171k
                loc = bytestream2_get_le32(&dgb);
379
171k
                u0 = (u0 << 4) | (u0 & 0xF);
380
171k
                v0 = (v0 << 4) | (v0 & 0xF);
381
171k
                u1 = (u1 << 4) | (u1 & 0xF);
382
171k
                v1 = (v1 << 4) | (v1 & 0xF);
383
171k
                udif = u1 - u0;
384
171k
                vdif = v1 - v0;
385
386
857k
                for (int i = 0; i < 16; i += 4) {
387
3.42M
                    for (int j = 0; j < 16; j += 4) {
388
13.7M
                        for (int ii = 0; ii < 4; ii++) {
389
54.8M
                            for (int jj = 0; jj < 4; jj++) {
390
43.9M
                                u[i + ii][j + jj] = u0 + ((udif * (int)(loc & 3) + 2) / 3);
391
43.9M
                                v[i + ii][j + jj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3);
392
43.9M
                            }
393
10.9M
                        }
394
395
2.74M
                        loc >>= 2;
396
2.74M
                    }
397
685k
                }
398
171k
            } else {
399
284k
                for (int i = 0; i < 16; i += 8) {
400
568k
                    for (int j = 0; j < 16; j += 8) {
401
378k
                        if (is8x8 & 1) {
402
106k
                            u0 = bytestream2_get_byte(&dgb);
403
106k
                            v0 = bytestream2_get_byte(&dgb);
404
106k
                            u1 = bytestream2_get_byte(&dgb);
405
106k
                            v1 = bytestream2_get_byte(&dgb);
406
106k
                            loc = bytestream2_get_le32(&dgb);
407
106k
                            u0 = (u0 << 4) | (u0 & 0xF);
408
106k
                            v0 = (v0 << 4) | (v0 & 0xF);
409
106k
                            u1 = (u1 << 4) | (u1 & 0xF);
410
106k
                            v1 = (v1 << 4) | (v1 & 0xF);
411
106k
                            udif = u1 - u0;
412
106k
                            vdif = v1 - v0;
413
414
534k
                            for (int ii = 0; ii < 8; ii += 2) {
415
2.13M
                                for (int jj = 0; jj < 8; jj += 2) {
416
5.13M
                                    for (int iii = 0; iii < 2; iii++) {
417
10.2M
                                        for (int jjj = 0; jjj < 2; jjj++) {
418
6.84M
                                            u[i + ii + iii][j + jj + jjj] = u0 + ((udif * (int)(loc & 3) + 2) / 3);
419
6.84M
                                            v[i + ii + iii][j + jj + jjj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3);
420
6.84M
                                        }
421
3.42M
                                    }
422
423
1.71M
                                    loc >>= 2;
424
1.71M
                                }
425
427k
                            }
426
272k
                        } else if (escape) {
427
491k
                            for (int ii = 0; ii < 8; ii += 4) {
428
982k
                                for (int jj = 0; jj < 8; jj += 4) {
429
654k
                                    u0 = bytestream2_get_byte(&dgb);
430
654k
                                    v0 = bytestream2_get_byte(&dgb);
431
654k
                                    u1 = bytestream2_get_byte(&dgb);
432
654k
                                    v1 = bytestream2_get_byte(&dgb);
433
654k
                                    loc = bytestream2_get_le32(&dgb);
434
654k
                                    u0 = (u0 << 4) | (u0 & 0xF);
435
654k
                                    v0 = (v0 << 4) | (v0 & 0xF);
436
654k
                                    u1 = (u1 << 4) | (u1 & 0xF);
437
654k
                                    v1 = (v1 << 4) | (v1 & 0xF);
438
654k
                                    udif = u1 - u0;
439
654k
                                    vdif = v1 - v0;
440
441
3.27M
                                    for (int iii = 0; iii < 4; iii++) {
442
13.0M
                                        for (int jjj = 0; jjj < 4; jjj++) {
443
10.4M
                                            u[i + ii + iii][j + jj + jjj] = u0 + ((udif * (int)(loc & 3) + 2) / 3);
444
10.4M
                                            v[i + ii + iii][j + jj + jjj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3);
445
446
10.4M
                                            loc >>= 2;
447
10.4M
                                        }
448
2.61M
                                    }
449
654k
                                }
450
327k
                            }
451
163k
                        }
452
453
378k
                        is8x8 >>= 1;
454
378k
                    }
455
189k
                }
456
94.7k
            }
457
458
4.52M
            for (int i = 0; i < 16; i++) {
459
72.4M
                for (int j = 0; j < 16; j++) {
460
68.1M
                    dstu[x + i * ulinesize + j] = u[i][j];
461
68.1M
                    dstv[x + i * vlinesize + j] = v[i][j];
462
68.1M
                }
463
4.25M
            }
464
266k
        }
465
466
188k
        dstu += 16 * ulinesize;
467
188k
        dstv += 16 * vlinesize;
468
188k
    }
469
470
78.1k
    return 0;
471
80.0k
}
472
473
static int decode_frame(AVCodecContext *avctx, AVFrame *p,
474
                        int *got_frame, AVPacket *avpkt)
475
187k
{
476
187k
    NotchLCContext *s = avctx->priv_data;
477
187k
    GetByteContext *gb = &s->gb;
478
187k
    PutByteContext *pb = &s->pb;
479
187k
    unsigned uncompressed_size;
480
187k
    int ret;
481
482
187k
    if (avpkt->size <= 40)
483
85.1k
        return AVERROR_INVALIDDATA;
484
485
102k
    bytestream2_init(gb, avpkt->data, avpkt->size);
486
487
102k
    if (bytestream2_get_le32(gb) != MKBETAG('N','L','C','1'))
488
1.81k
        return AVERROR_INVALIDDATA;
489
490
100k
    uncompressed_size = bytestream2_get_le32(gb);
491
100k
    s->compressed_size = bytestream2_get_le32(gb);
492
100k
    s->format = bytestream2_get_le32(gb);
493
494
100k
    if (s->format > 2)
495
673
        return AVERROR_PATCHWELCOME;
496
497
100k
    if (s->format == 0) {
498
1.93k
        ret = ff_lzf_uncompress(gb, &s->lzf_buffer, &s->lzf_size, &s->lzf_alloc_size);
499
1.93k
        if (ret < 0)
500
899
            return ret;
501
502
1.03k
        if (uncompressed_size > s->lzf_size)
503
456
            return AVERROR_INVALIDDATA;
504
505
577
        bytestream2_init(gb, s->lzf_buffer, uncompressed_size);
506
98.0k
    } else if (s->format == 1) {
507
6.09k
        if (bytestream2_get_bytes_left(gb) < uncompressed_size / 255)
508
1.64k
            return AVERROR_INVALIDDATA;
509
510
4.44k
        av_fast_padded_malloc(&s->uncompressed_buffer, &s->uncompressed_size,
511
4.44k
                              uncompressed_size);
512
4.44k
        if (!s->uncompressed_buffer)
513
0
            return AVERROR(ENOMEM);
514
515
4.44k
        bytestream2_init_writer(pb, s->uncompressed_buffer, s->uncompressed_size);
516
517
4.44k
        ret = lz4_decompress(avctx, gb, pb);
518
4.44k
        if (ret != uncompressed_size)
519
3.76k
            return AVERROR_INVALIDDATA;
520
521
684
        bytestream2_init(gb, s->uncompressed_buffer, uncompressed_size);
522
684
    }
523
524
93.2k
    ret = decode_blocks(avctx, p, uncompressed_size);
525
93.2k
    if (ret < 0)
526
15.0k
        return ret;
527
528
78.1k
    *got_frame = 1;
529
530
78.1k
    return avpkt->size;
531
93.2k
}
532
533
static av_cold int decode_end(AVCodecContext *avctx)
534
2.73k
{
535
2.73k
    NotchLCContext *s = avctx->priv_data;
536
537
2.73k
    av_freep(&s->uncompressed_buffer);
538
2.73k
    s->uncompressed_size = 0;
539
2.73k
    av_freep(&s->lzf_buffer);
540
2.73k
    s->lzf_size = 0;
541
542
2.73k
    return 0;
543
2.73k
}
544
545
const FFCodec ff_notchlc_decoder = {
546
    .p.name           = "notchlc",
547
    CODEC_LONG_NAME("NotchLC"),
548
    .p.type           = AVMEDIA_TYPE_VIDEO,
549
    .p.id             = AV_CODEC_ID_NOTCHLC,
550
    .priv_data_size   = sizeof(NotchLCContext),
551
    .init             = decode_init,
552
    .close            = decode_end,
553
    FF_CODEC_DECODE_CB(decode_frame),
554
    .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
555
};