GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/ylc.c Lines: 0 185 0.0 %
Date: 2021-04-22 14:24:15 Branches: 0 80 0.0 %

Line Branch Exec Source
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 <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
25
#define YLC_VLC_BITS 10
26
27
#include "libavutil/imgutils.h"
28
#include "libavutil/internal.h"
29
#include "libavutil/intreadwrite.h"
30
#include "libavutil/mem.h"
31
#include "avcodec.h"
32
#include "bswapdsp.h"
33
#include "get_bits.h"
34
#include "huffyuvdsp.h"
35
#include "internal.h"
36
#include "thread.h"
37
#include "unary.h"
38
39
typedef struct YLCContext {
40
    VLC vlc[4];
41
    uint32_t table[256];
42
    uint8_t *buffer;
43
    int buffer_size;
44
    BswapDSPContext bdsp;
45
} YLCContext;
46
47
static av_cold int decode_init(AVCodecContext *avctx)
48
{
49
    YLCContext *s = avctx->priv_data;
50
51
    avctx->pix_fmt = AV_PIX_FMT_YUYV422;
52
    ff_bswapdsp_init(&s->bdsp);
53
54
    return 0;
55
}
56
57
typedef struct Node {
58
    int16_t  sym;
59
    uint32_t count;
60
    int16_t  l, r;
61
} Node;
62
63
static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat,
64
                           Node *nodes, int node,
65
                           uint32_t pfx, int pl, int *pos)
66
{
67
    int s;
68
69
    s = nodes[node].sym;
70
    if (s != -1) {
71
        bits[*pos] = (~pfx) & ((1ULL << FFMAX(pl, 1)) - 1);
72
        lens[*pos] = FFMAX(pl, 1);
73
        xlat[*pos] = s + (pl == 0);
74
        (*pos)++;
75
    } else {
76
        pfx <<= 1;
77
        pl++;
78
        get_tree_codes(bits, lens, xlat, nodes, nodes[node].l, pfx, pl,
79
                       pos);
80
        pfx |= 1;
81
        get_tree_codes(bits, lens, xlat, nodes, nodes[node].r, pfx, pl,
82
                       pos);
83
    }
84
}
85
86
static int build_vlc(AVCodecContext *avctx, VLC *vlc, const uint32_t *table)
87
{
88
    Node nodes[512];
89
    uint32_t bits[256];
90
    int16_t lens[256];
91
    uint8_t xlat[256];
92
    int cur_node, i, j, pos = 0;
93
94
    ff_free_vlc(vlc);
95
96
    for (i = 0; i < 256; i++) {
97
        nodes[i].count = table[i];
98
        nodes[i].sym   = i;
99
        nodes[i].l     = i;
100
        nodes[i].r     = i;
101
    }
102
103
    cur_node = 256;
104
    j = 0;
105
    do {
106
        for (i = 0; ; i++) {
107
            int new_node = j;
108
            int first_node = cur_node;
109
            int second_node = cur_node;
110
            unsigned nd, st;
111
112
            nodes[cur_node].count = -1;
113
114
            do {
115
                int val = nodes[new_node].count;
116
                if (val && (val < nodes[first_node].count)) {
117
                    if (val >= nodes[second_node].count) {
118
                        first_node = new_node;
119
                    } else {
120
                        first_node = second_node;
121
                        second_node = new_node;
122
                    }
123
                }
124
                new_node += 1;
125
            } while (new_node != cur_node);
126
127
            if (first_node == cur_node)
128
                break;
129
130
            nd = nodes[second_node].count;
131
            st = nodes[first_node].count;
132
            nodes[second_node].count = 0;
133
            nodes[first_node].count  = 0;
134
            if (nd >= UINT32_MAX - st) {
135
                av_log(avctx, AV_LOG_ERROR, "count overflow\n");
136
                return AVERROR_INVALIDDATA;
137
            }
138
            nodes[cur_node].count = nd + st;
139
            nodes[cur_node].sym = -1;
140
            nodes[cur_node].l = first_node;
141
            nodes[cur_node].r = second_node;
142
            cur_node++;
143
        }
144
        j++;
145
    } while (cur_node - 256 == j);
146
147
    get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos);
148
149
    return ff_init_vlc_sparse(vlc, YLC_VLC_BITS, pos, lens, 2, 2,
150
                              bits, 4, 4, xlat, 1, 1, 0);
151
}
152
153
static const uint8_t table_y1[] = {
154
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
155
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
156
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
157
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
158
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
159
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
160
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
161
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
162
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
163
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
164
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
165
    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
171
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
172
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
173
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
174
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
175
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
176
    0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
177
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
178
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
179
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
180
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
181
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
182
    0x02, 0x00,
183
};
184
185
static const uint8_t table_u[] = {
186
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
187
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
188
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
190
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
191
    0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF,
192
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
193
    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
194
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195
    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
196
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
197
    0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
198
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
199
    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
202
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF,
203
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
204
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
205
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206
    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
207
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
208
    0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
209
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
210
    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
211
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212
    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
213
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
214
    0x01, 0x00,
215
};
216
217
static const uint8_t table_y2[] = {
218
    0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
219
    0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC,
220
    0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE,
221
    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFC,
222
    0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF,
223
    0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFD,
224
    0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
225
    0x00, 0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE,
226
    0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
227
    0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
228
    0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
229
    0x01, 0x01, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
230
    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
231
    0x02, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00,
232
    0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
233
    0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
234
    0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0xFF,
235
    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
236
    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF,
237
    0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
238
    0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xFF,
239
    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
240
    0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x01,
241
    0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
242
    0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01,
243
    0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04,
244
    0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
245
    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04,
246
    0x04, 0x00,
247
};
248
249
static const uint8_t table_v[] = {
250
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
251
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
252
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
253
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
254
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
255
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
256
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
257
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
258
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
259
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
260
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
261
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
262
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
263
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
264
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
265
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
266
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
267
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
268
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
269
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
270
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
271
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
272
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
273
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
274
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
275
    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
276
    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
277
    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
278
    0x01, 0x00,
279
};
280
281
static int decode_frame(AVCodecContext *avctx,
282
                        void *data, int *got_frame,
283
                        AVPacket *avpkt)
284
{
285
    int TL[4] = { 128, 128, 128, 128 };
286
    int L[4]  = { 128, 128, 128, 128 };
287
    YLCContext *s = avctx->priv_data;
288
    ThreadFrame frame = { .f = data };
289
    const uint8_t *buf = avpkt->data;
290
    int ret, x, y, toffset, boffset;
291
    AVFrame * const p = data;
292
    GetBitContext gb;
293
    uint8_t *dst;
294
295
    if (avpkt->size <= 16)
296
        return AVERROR_INVALIDDATA;
297
298
    if (AV_RL32(buf) != MKTAG('Y', 'L', 'C', '0') ||
299
        AV_RL32(buf + 4) != 0)
300
        return AVERROR_INVALIDDATA;
301
302
    toffset = AV_RL32(buf + 8);
303
    if (toffset < 16 || toffset >= avpkt->size)
304
        return AVERROR_INVALIDDATA;
305
306
    boffset = AV_RL32(buf + 12);
307
    if (toffset >= boffset || boffset >= avpkt->size)
308
        return AVERROR_INVALIDDATA;
309
310
    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
311
        return ret;
312
313
    av_fast_malloc(&s->buffer, &s->buffer_size,
314
                   FFMAX(boffset - toffset, avpkt->size - boffset)
315
                       + AV_INPUT_BUFFER_PADDING_SIZE);
316
    if (!s->buffer)
317
        return AVERROR(ENOMEM);
318
319
    memcpy(s->buffer, avpkt->data + toffset, boffset - toffset);
320
    memset(s->buffer + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
321
    s->bdsp.bswap_buf((uint32_t *) s->buffer,
322
                      (uint32_t *) s->buffer,
323
                      (boffset - toffset + 3) >> 2);
324
    if ((ret = init_get_bits8(&gb, s->buffer, boffset - toffset)) < 0)
325
        return ret;
326
327
    for (int i = 0; i < 4; i++) {
328
        for (x = 0; x < 256; x++) {
329
            unsigned len = get_unary(&gb, 1, 31);
330
            uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len);
331
332
            s->table[x] = val;
333
        }
334
335
        ret = build_vlc(avctx, &s->vlc[i], s->table);
336
        if (ret < 0)
337
            return ret;
338
    }
339
340
    memcpy(s->buffer, avpkt->data + boffset, avpkt->size - boffset);
341
    memset(s->buffer + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
342
    s->bdsp.bswap_buf((uint32_t *) s->buffer,
343
                      (uint32_t *) s->buffer,
344
                      (avpkt->size - boffset) >> 2);
345
    if ((ret = init_get_bits8(&gb, s->buffer, avpkt->size - boffset)) < 0)
346
        return ret;
347
348
    dst = p->data[0];
349
    for (y = 0; y < avctx->height; y++) {
350
        memset(dst, 0, avctx->width * 2);
351
        dst += p->linesize[0];
352
    }
353
354
    dst = p->data[0];
355
    for (y = 0; y < avctx->height; y++) {
356
        for (x = 0; x < avctx->width * 2 && y < avctx->height;) {
357
            if (get_bits_left(&gb) <= 0)
358
                return AVERROR_INVALIDDATA;
359
360
            if (get_bits1(&gb)) {
361
                int val = get_vlc2(&gb, s->vlc[0].table, YLC_VLC_BITS, 3);
362
                if (val < 0) {
363
                    return AVERROR_INVALIDDATA;
364
                } else if (val < 0xE1) {
365
                    dst[x    ] = table_y1[val];
366
                    dst[x + 1] = table_u[val];
367
                    dst[x + 2] = table_y2[val];
368
                    dst[x + 3] = table_v[val];
369
                    x += 4;
370
                } else {
371
                    int incr = (val - 0xDF) * 4;
372
                    if (x + incr >= avctx->width * 2) {
373
                        int iy = ((x + incr) / (avctx->width * 2));
374
                        x  = (x + incr) % (avctx->width * 2);
375
                        y += iy;
376
                        dst += iy * p->linesize[0];
377
                    } else {
378
                        x += incr;
379
                    }
380
                }
381
            } else {
382
                int y1, y2, u, v;
383
384
                y1 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
385
                u  = get_vlc2(&gb, s->vlc[2].table, YLC_VLC_BITS, 3);
386
                y2 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
387
                v  = get_vlc2(&gb, s->vlc[3].table, YLC_VLC_BITS, 3);
388
                if (y1 < 0 || y2 < 0 || u < 0 || v < 0)
389
                    return AVERROR_INVALIDDATA;
390
                dst[x    ] = y1;
391
                dst[x + 1] = u;
392
                dst[x + 2] = y1 + y2;
393
                dst[x + 3] = v;
394
                x += 4;
395
            }
396
        }
397
        dst += p->linesize[0];
398
    }
399
400
    dst = p->data[0];
401
    for (x = 0; x < avctx->width * 2; x += 4) {
402
        dst[x    ] =        dst[x    ] + L[0];
403
        dst[x + 2] = L[0] = dst[x + 2] + L[0];
404
        L[1] = dst[x + 1] + L[1];
405
        dst[x + 1] = L[1];
406
        L[2] = dst[x + 3] + L[2];
407
        dst[x + 3] = L[2];
408
    }
409
    dst += p->linesize[0];
410
411
    for (y = 1; y < avctx->height; y++) {
412
        x = 0;
413
        dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
414
        dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
415
        TL[0] = dst[x + 2 - p->linesize[0]];
416
        L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
417
        dst[x + 1] = L[1];
418
        TL[1] = dst[x + 1 - p->linesize[0]];
419
        L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
420
        dst[x + 3] = L[2];
421
        TL[2] = dst[x + 3 - p->linesize[0]];
422
        for (x = 4; x < avctx->width * 2; x += 4) {
423
            dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
424
            dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
425
            TL[0] = dst[x + 2 - p->linesize[0]];
426
            L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
427
            dst[x + 1] = L[1];
428
            TL[1] = dst[x + 1 - p->linesize[0]];
429
            L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
430
            dst[x + 3] = L[2];
431
            TL[2] = dst[x + 3 - p->linesize[0]];
432
        }
433
        dst += p->linesize[0];
434
    }
435
436
    p->pict_type = AV_PICTURE_TYPE_I;
437
    p->key_frame = 1;
438
    *got_frame   = 1;
439
440
    return avpkt->size;
441
}
442
443
static av_cold int decode_end(AVCodecContext *avctx)
444
{
445
    YLCContext *s = avctx->priv_data;
446
447
    for (int i = 0; i < FF_ARRAY_ELEMS(s->vlc); i++)
448
        ff_free_vlc(&s->vlc[i]);
449
    av_freep(&s->buffer);
450
    s->buffer_size = 0;
451
452
    return 0;
453
}
454
455
AVCodec ff_ylc_decoder = {
456
    .name           = "ylc",
457
    .long_name      = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"),
458
    .type           = AVMEDIA_TYPE_VIDEO,
459
    .id             = AV_CODEC_ID_YLC,
460
    .priv_data_size = sizeof(YLCContext),
461
    .init           = decode_init,
462
    .close          = decode_end,
463
    .decode         = decode_frame,
464
    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
465
    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
466
};