]> git.sesse.net Git - ffmpeg/blob - libavcodec/ylc.c
avcodec: Constify AVCodecs
[ffmpeg] / libavcodec / ylc.c
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 const 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 };