Coverage Report

Created: 2025-08-28 07:12

/src/ffmpeg/libavcodec/ylc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * YUY2 Lossless Codec
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#include <string.h>
22
23
53.9M
#define YLC_VLC_BITS 10
24
25
#include "libavutil/intreadwrite.h"
26
#include "libavutil/mem.h"
27
#include "libavutil/pixfmt.h"
28
#include "avcodec.h"
29
#include "bswapdsp.h"
30
#include "codec_internal.h"
31
#include "get_bits.h"
32
#include "thread.h"
33
#include "unary.h"
34
35
typedef struct YLCContext {
36
    VLC vlc[4];
37
    uint32_t table[256];
38
    uint8_t *buffer;
39
    int buffer_size;
40
    BswapDSPContext bdsp;
41
} YLCContext;
42
43
static av_cold int decode_init(AVCodecContext *avctx)
44
1.50k
{
45
1.50k
    YLCContext *s = avctx->priv_data;
46
47
1.50k
    avctx->pix_fmt = AV_PIX_FMT_YUYV422;
48
1.50k
    ff_bswapdsp_init(&s->bdsp);
49
50
1.50k
    return 0;
51
1.50k
}
52
53
typedef struct Node {
54
    int16_t  sym;
55
    uint32_t count;
56
    int16_t  l, r;
57
} Node;
58
59
static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat,
60
                           Node *nodes, int node,
61
                           uint32_t pfx, int pl, int *pos)
62
3.01M
{
63
3.01M
    int s;
64
65
3.01M
    s = nodes[node].sym;
66
3.01M
    if (s != -1) {
67
1.69M
        bits[*pos] = (~pfx) & ((1ULL << FFMAX(pl, 1)) - 1);
68
1.69M
        lens[*pos] = FFMAX(pl, 1);
69
1.69M
        xlat[*pos] = s + (pl == 0);
70
1.69M
        (*pos)++;
71
1.69M
    } else {
72
1.31M
        pfx <<= 1;
73
1.31M
        pl++;
74
1.31M
        get_tree_codes(bits, lens, xlat, nodes, nodes[node].l, pfx, pl,
75
1.31M
                       pos);
76
1.31M
        pfx |= 1;
77
1.31M
        get_tree_codes(bits, lens, xlat, nodes, nodes[node].r, pfx, pl,
78
1.31M
                       pos);
79
1.31M
    }
80
3.01M
}
81
82
static int build_vlc(AVCodecContext *avctx, VLC *vlc, const uint32_t *table)
83
376k
{
84
376k
    Node nodes[512];
85
376k
    uint32_t bits[256];
86
376k
    int16_t lens[256];
87
376k
    uint8_t xlat[256];
88
376k
    int cur_node, i, j, pos = 0;
89
90
376k
    ff_vlc_free(vlc);
91
92
96.7M
    for (i = 0; i < 256; i++) {
93
96.3M
        nodes[i].count = table[i];
94
96.3M
        nodes[i].sym   = i;
95
96.3M
        nodes[i].l     = i;
96
96.3M
        nodes[i].r     = i;
97
96.3M
    }
98
99
376k
    cur_node = 256;
100
376k
    j = 0;
101
390k
    do {
102
2.17M
        for (i = 0; ; i++) {
103
2.17M
            int new_node = j;
104
2.17M
            int first_node = cur_node;
105
2.17M
            int second_node = cur_node;
106
2.17M
            unsigned nd, st;
107
108
2.17M
            nodes[cur_node].count = -1;
109
110
629M
            do {
111
629M
                int val = nodes[new_node].count;
112
629M
                if (val && (val < nodes[first_node].count)) {
113
7.66M
                    if (val >= nodes[second_node].count) {
114
3.20M
                        first_node = new_node;
115
4.45M
                    } else {
116
4.45M
                        first_node = second_node;
117
4.45M
                        second_node = new_node;
118
4.45M
                    }
119
7.66M
                }
120
629M
                new_node += 1;
121
629M
            } while (new_node != cur_node);
122
123
2.17M
            if (first_node == cur_node)
124
386k
                break;
125
126
1.78M
            nd = nodes[second_node].count;
127
1.78M
            st = nodes[first_node].count;
128
1.78M
            nodes[second_node].count = 0;
129
1.78M
            nodes[first_node].count  = 0;
130
1.78M
            if (nd >= UINT32_MAX - st) {
131
4.21k
                av_log(avctx, AV_LOG_ERROR, "count overflow\n");
132
4.21k
                return AVERROR_INVALIDDATA;
133
4.21k
            }
134
1.78M
            nodes[cur_node].count = nd + st;
135
1.78M
            nodes[cur_node].sym = -1;
136
1.78M
            nodes[cur_node].l = first_node;
137
1.78M
            nodes[cur_node].r = second_node;
138
1.78M
            cur_node++;
139
1.78M
        }
140
386k
        j++;
141
386k
    } while (cur_node - 256 == j);
142
143
372k
    get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos);
144
145
372k
    return ff_vlc_init_sparse(vlc, YLC_VLC_BITS, pos, lens, 2, 2,
146
372k
                              bits, 4, 4, xlat, 1, 1, 0);
147
376k
}
148
149
static const uint8_t table_y1[] = {
150
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
151
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
152
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
153
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
154
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
155
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
156
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
157
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
158
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
159
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
160
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
161
    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
167
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
168
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
169
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
170
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
171
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
172
    0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
173
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
174
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
175
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
176
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
177
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
178
    0x02, 0x00,
179
};
180
181
static const uint8_t table_u[] = {
182
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
183
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
184
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
186
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
187
    0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF,
188
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
189
    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
190
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191
    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
192
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
193
    0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
194
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
195
    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
198
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF,
199
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
200
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
201
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202
    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
203
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
204
    0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
205
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
206
    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
207
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208
    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
209
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
210
    0x01, 0x00,
211
};
212
213
static const uint8_t table_y2[] = {
214
    0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
215
    0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC,
216
    0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE,
217
    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFC,
218
    0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF,
219
    0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFD,
220
    0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
221
    0x00, 0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE,
222
    0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
223
    0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
224
    0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
225
    0x01, 0x01, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
226
    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
227
    0x02, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00,
228
    0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
229
    0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
230
    0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0xFF,
231
    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
232
    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF,
233
    0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
234
    0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xFF,
235
    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
236
    0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x01,
237
    0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
238
    0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01,
239
    0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04,
240
    0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
241
    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04,
242
    0x04, 0x00,
243
};
244
245
static const uint8_t table_v[] = {
246
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
247
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
248
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
249
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
250
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
251
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
252
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
253
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
254
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
255
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
256
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
257
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
258
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
259
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
260
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
261
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
262
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
263
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
264
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
265
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
266
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
267
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
268
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
269
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
270
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
271
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
272
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
273
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
274
    0x01, 0x00,
275
};
276
277
static int decode_frame(AVCodecContext *avctx, AVFrame *p,
278
                        int *got_frame, AVPacket *avpkt)
279
374k
{
280
374k
    int TL[4] = { 128, 128, 128, 128 };
281
374k
    int L[4]  = { 128, 128, 128, 128 };
282
374k
    YLCContext *s = avctx->priv_data;
283
374k
    const uint8_t *buf = avpkt->data;
284
374k
    int ret, x, y, toffset, boffset;
285
374k
    GetBitContext gb;
286
374k
    uint8_t *dst;
287
288
374k
    if (avpkt->size <= 16)
289
267k
        return AVERROR_INVALIDDATA;
290
291
106k
    if (AV_RL32(buf) != MKTAG('Y', 'L', 'C', '0') ||
292
106k
        AV_RL32(buf + 4) != 0)
293
6.33k
        return AVERROR_INVALIDDATA;
294
295
100k
    toffset = AV_RL32(buf + 8);
296
100k
    if (toffset < 16 || toffset >= avpkt->size)
297
1.03k
        return AVERROR_INVALIDDATA;
298
299
99.5k
    boffset = AV_RL32(buf + 12);
300
99.5k
    if (toffset >= boffset || boffset >= avpkt->size)
301
1.51k
        return AVERROR_INVALIDDATA;
302
303
98.0k
    if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
304
781
        return ret;
305
306
97.2k
    av_fast_malloc(&s->buffer, &s->buffer_size,
307
97.2k
                   FFMAX(boffset - toffset, avpkt->size - boffset)
308
97.2k
                       + AV_INPUT_BUFFER_PADDING_SIZE);
309
97.2k
    if (!s->buffer)
310
0
        return AVERROR(ENOMEM);
311
312
97.2k
    memcpy(s->buffer, avpkt->data + toffset, boffset - toffset);
313
97.2k
    memset(s->buffer + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
314
97.2k
    s->bdsp.bswap_buf((uint32_t *) s->buffer,
315
97.2k
                      (uint32_t *) s->buffer,
316
97.2k
                      (boffset - toffset + 3) >> 2);
317
97.2k
    if ((ret = init_get_bits8(&gb, s->buffer, boffset - toffset)) < 0)
318
0
        return ret;
319
320
469k
    for (int i = 0; i < 4; i++) {
321
96.7M
        for (x = 0; x < 256; x++) {
322
96.3M
            unsigned len = get_unary(&gb, 1, 31);
323
96.3M
            uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len);
324
325
96.3M
            s->table[x] = val;
326
96.3M
        }
327
328
376k
        ret = build_vlc(avctx, &s->vlc[i], s->table);
329
376k
        if (ret < 0)
330
4.41k
            return ret;
331
376k
    }
332
333
92.8k
    memcpy(s->buffer, avpkt->data + boffset, avpkt->size - boffset);
334
92.8k
    memset(s->buffer + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
335
92.8k
    s->bdsp.bswap_buf((uint32_t *) s->buffer,
336
92.8k
                      (uint32_t *) s->buffer,
337
92.8k
                      (avpkt->size - boffset) >> 2);
338
92.8k
    if ((ret = init_get_bits8(&gb, s->buffer, avpkt->size - boffset)) < 0)
339
0
        return ret;
340
341
92.8k
    dst = p->data[0];
342
25.5M
    for (y = 0; y < avctx->height; y++) {
343
25.4M
        memset(dst, 0, avctx->width * 2);
344
25.4M
        dst += p->linesize[0];
345
25.4M
    }
346
347
92.8k
    dst = p->data[0];
348
292k
    for (y = 0; y < avctx->height; y++) {
349
21.8M
        for (x = 0; x < avctx->width * 2 && y < avctx->height;) {
350
21.6M
            if (get_bits_left(&gb) <= 0)
351
3.27k
                return AVERROR_INVALIDDATA;
352
353
21.6M
            if (get_bits1(&gb)) {
354
11.0M
                int val = get_vlc2(&gb, s->vlc[0].table, YLC_VLC_BITS, 3);
355
11.0M
                if (val < 0) {
356
235
                    return AVERROR_INVALIDDATA;
357
11.0M
                } else if (val < 0xE1) {
358
10.3M
                    dst[x    ] = table_y1[val];
359
10.3M
                    dst[x + 1] = table_u[val];
360
10.3M
                    dst[x + 2] = table_y2[val];
361
10.3M
                    dst[x + 3] = table_v[val];
362
10.3M
                    x += 4;
363
10.3M
                } else {
364
695k
                    int incr = (val - 0xDF) * 4;
365
695k
                    if (x + incr >= avctx->width * 2) {
366
99.4k
                        int iy = ((x + incr) / (avctx->width * 2));
367
99.4k
                        x  = (x + incr) % (avctx->width * 2);
368
99.4k
                        y += iy;
369
99.4k
                        dst += iy * p->linesize[0];
370
596k
                    } else {
371
596k
                        x += incr;
372
596k
                    }
373
695k
                }
374
11.0M
            } else {
375
10.6M
                int y1, y2, u, v;
376
377
10.6M
                y1 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
378
10.6M
                u  = get_vlc2(&gb, s->vlc[2].table, YLC_VLC_BITS, 3);
379
10.6M
                y2 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
380
10.6M
                v  = get_vlc2(&gb, s->vlc[3].table, YLC_VLC_BITS, 3);
381
10.6M
                if (y1 < 0 || y2 < 0 || u < 0 || v < 0)
382
2.85k
                    return AVERROR_INVALIDDATA;
383
10.6M
                dst[x    ] = y1;
384
10.6M
                dst[x + 1] = u;
385
10.6M
                dst[x + 2] = y1 + y2;
386
10.6M
                dst[x + 3] = v;
387
10.6M
                x += 4;
388
10.6M
            }
389
21.6M
        }
390
199k
        dst += p->linesize[0];
391
199k
    }
392
393
86.4k
    dst = p->data[0];
394
6.56M
    for (x = 0; x < avctx->width * 2; x += 4) {
395
6.48M
        dst[x    ] =        dst[x    ] + L[0];
396
6.48M
        dst[x + 2] = L[0] = dst[x + 2] + L[0];
397
6.48M
        L[1] = dst[x + 1] + L[1];
398
6.48M
        dst[x + 1] = L[1];
399
6.48M
        L[2] = dst[x + 3] + L[2];
400
6.48M
        dst[x + 3] = L[2];
401
6.48M
    }
402
86.4k
    dst += p->linesize[0];
403
404
1.17M
    for (y = 1; y < avctx->height; y++) {
405
1.08M
        x = 0;
406
1.08M
        dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
407
1.08M
        dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
408
1.08M
        TL[0] = dst[x + 2 - p->linesize[0]];
409
1.08M
        L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
410
1.08M
        dst[x + 1] = L[1];
411
1.08M
        TL[1] = dst[x + 1 - p->linesize[0]];
412
1.08M
        L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
413
1.08M
        dst[x + 3] = L[2];
414
1.08M
        TL[2] = dst[x + 3 - p->linesize[0]];
415
7.51M
        for (x = 4; x < avctx->width * 2; x += 4) {
416
6.42M
            dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
417
6.42M
            dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
418
6.42M
            TL[0] = dst[x + 2 - p->linesize[0]];
419
6.42M
            L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
420
6.42M
            dst[x + 1] = L[1];
421
6.42M
            TL[1] = dst[x + 1 - p->linesize[0]];
422
6.42M
            L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
423
6.42M
            dst[x + 3] = L[2];
424
6.42M
            TL[2] = dst[x + 3 - p->linesize[0]];
425
6.42M
        }
426
1.08M
        dst += p->linesize[0];
427
1.08M
    }
428
429
86.4k
    *got_frame   = 1;
430
431
86.4k
    return avpkt->size;
432
92.8k
}
433
434
static av_cold int decode_end(AVCodecContext *avctx)
435
1.50k
{
436
1.50k
    YLCContext *s = avctx->priv_data;
437
438
7.52k
    for (int i = 0; i < FF_ARRAY_ELEMS(s->vlc); i++)
439
6.02k
        ff_vlc_free(&s->vlc[i]);
440
1.50k
    av_freep(&s->buffer);
441
1.50k
    s->buffer_size = 0;
442
443
1.50k
    return 0;
444
1.50k
}
445
446
const FFCodec ff_ylc_decoder = {
447
    .p.name         = "ylc",
448
    CODEC_LONG_NAME("YUY2 Lossless Codec"),
449
    .p.type         = AVMEDIA_TYPE_VIDEO,
450
    .p.id           = AV_CODEC_ID_YLC,
451
    .priv_data_size = sizeof(YLCContext),
452
    .init           = decode_init,
453
    .close          = decode_end,
454
    FF_CODEC_DECODE_CB(decode_frame),
455
    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
456
};