Imported Upstream version 6.1
[platform/upstream/ffmpeg.git] / 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 <string.h>
22
23 #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 {
45     YLCContext *s = avctx->priv_data;
46
47     avctx->pix_fmt = AV_PIX_FMT_YUYV422;
48     ff_bswapdsp_init(&s->bdsp);
49
50     return 0;
51 }
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 {
63     int s;
64
65     s = nodes[node].sym;
66     if (s != -1) {
67         bits[*pos] = (~pfx) & ((1ULL << FFMAX(pl, 1)) - 1);
68         lens[*pos] = FFMAX(pl, 1);
69         xlat[*pos] = s + (pl == 0);
70         (*pos)++;
71     } else {
72         pfx <<= 1;
73         pl++;
74         get_tree_codes(bits, lens, xlat, nodes, nodes[node].l, pfx, pl,
75                        pos);
76         pfx |= 1;
77         get_tree_codes(bits, lens, xlat, nodes, nodes[node].r, pfx, pl,
78                        pos);
79     }
80 }
81
82 static int build_vlc(AVCodecContext *avctx, VLC *vlc, const uint32_t *table)
83 {
84     Node nodes[512];
85     uint32_t bits[256];
86     int16_t lens[256];
87     uint8_t xlat[256];
88     int cur_node, i, j, pos = 0;
89
90     ff_vlc_free(vlc);
91
92     for (i = 0; i < 256; i++) {
93         nodes[i].count = table[i];
94         nodes[i].sym   = i;
95         nodes[i].l     = i;
96         nodes[i].r     = i;
97     }
98
99     cur_node = 256;
100     j = 0;
101     do {
102         for (i = 0; ; i++) {
103             int new_node = j;
104             int first_node = cur_node;
105             int second_node = cur_node;
106             unsigned nd, st;
107
108             nodes[cur_node].count = -1;
109
110             do {
111                 int val = nodes[new_node].count;
112                 if (val && (val < nodes[first_node].count)) {
113                     if (val >= nodes[second_node].count) {
114                         first_node = new_node;
115                     } else {
116                         first_node = second_node;
117                         second_node = new_node;
118                     }
119                 }
120                 new_node += 1;
121             } while (new_node != cur_node);
122
123             if (first_node == cur_node)
124                 break;
125
126             nd = nodes[second_node].count;
127             st = nodes[first_node].count;
128             nodes[second_node].count = 0;
129             nodes[first_node].count  = 0;
130             if (nd >= UINT32_MAX - st) {
131                 av_log(avctx, AV_LOG_ERROR, "count overflow\n");
132                 return AVERROR_INVALIDDATA;
133             }
134             nodes[cur_node].count = nd + st;
135             nodes[cur_node].sym = -1;
136             nodes[cur_node].l = first_node;
137             nodes[cur_node].r = second_node;
138             cur_node++;
139         }
140         j++;
141     } while (cur_node - 256 == j);
142
143     get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos);
144
145     return ff_vlc_init_sparse(vlc, YLC_VLC_BITS, pos, lens, 2, 2,
146                               bits, 4, 4, xlat, 1, 1, 0);
147 }
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 {
280     int TL[4] = { 128, 128, 128, 128 };
281     int L[4]  = { 128, 128, 128, 128 };
282     YLCContext *s = avctx->priv_data;
283     const uint8_t *buf = avpkt->data;
284     int ret, x, y, toffset, boffset;
285     GetBitContext gb;
286     uint8_t *dst;
287
288     if (avpkt->size <= 16)
289         return AVERROR_INVALIDDATA;
290
291     if (AV_RL32(buf) != MKTAG('Y', 'L', 'C', '0') ||
292         AV_RL32(buf + 4) != 0)
293         return AVERROR_INVALIDDATA;
294
295     toffset = AV_RL32(buf + 8);
296     if (toffset < 16 || toffset >= avpkt->size)
297         return AVERROR_INVALIDDATA;
298
299     boffset = AV_RL32(buf + 12);
300     if (toffset >= boffset || boffset >= avpkt->size)
301         return AVERROR_INVALIDDATA;
302
303     if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
304         return ret;
305
306     av_fast_malloc(&s->buffer, &s->buffer_size,
307                    FFMAX(boffset - toffset, avpkt->size - boffset)
308                        + AV_INPUT_BUFFER_PADDING_SIZE);
309     if (!s->buffer)
310         return AVERROR(ENOMEM);
311
312     memcpy(s->buffer, avpkt->data + toffset, boffset - toffset);
313     memset(s->buffer + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
314     s->bdsp.bswap_buf((uint32_t *) s->buffer,
315                       (uint32_t *) s->buffer,
316                       (boffset - toffset + 3) >> 2);
317     if ((ret = init_get_bits8(&gb, s->buffer, boffset - toffset)) < 0)
318         return ret;
319
320     for (int i = 0; i < 4; i++) {
321         for (x = 0; x < 256; x++) {
322             unsigned len = get_unary(&gb, 1, 31);
323             uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len);
324
325             s->table[x] = val;
326         }
327
328         ret = build_vlc(avctx, &s->vlc[i], s->table);
329         if (ret < 0)
330             return ret;
331     }
332
333     memcpy(s->buffer, avpkt->data + boffset, avpkt->size - boffset);
334     memset(s->buffer + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
335     s->bdsp.bswap_buf((uint32_t *) s->buffer,
336                       (uint32_t *) s->buffer,
337                       (avpkt->size - boffset) >> 2);
338     if ((ret = init_get_bits8(&gb, s->buffer, avpkt->size - boffset)) < 0)
339         return ret;
340
341     dst = p->data[0];
342     for (y = 0; y < avctx->height; y++) {
343         memset(dst, 0, avctx->width * 2);
344         dst += p->linesize[0];
345     }
346
347     dst = p->data[0];
348     for (y = 0; y < avctx->height; y++) {
349         for (x = 0; x < avctx->width * 2 && y < avctx->height;) {
350             if (get_bits_left(&gb) <= 0)
351                 return AVERROR_INVALIDDATA;
352
353             if (get_bits1(&gb)) {
354                 int val = get_vlc2(&gb, s->vlc[0].table, YLC_VLC_BITS, 3);
355                 if (val < 0) {
356                     return AVERROR_INVALIDDATA;
357                 } else if (val < 0xE1) {
358                     dst[x    ] = table_y1[val];
359                     dst[x + 1] = table_u[val];
360                     dst[x + 2] = table_y2[val];
361                     dst[x + 3] = table_v[val];
362                     x += 4;
363                 } else {
364                     int incr = (val - 0xDF) * 4;
365                     if (x + incr >= avctx->width * 2) {
366                         int iy = ((x + incr) / (avctx->width * 2));
367                         x  = (x + incr) % (avctx->width * 2);
368                         y += iy;
369                         dst += iy * p->linesize[0];
370                     } else {
371                         x += incr;
372                     }
373                 }
374             } else {
375                 int y1, y2, u, v;
376
377                 y1 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
378                 u  = get_vlc2(&gb, s->vlc[2].table, YLC_VLC_BITS, 3);
379                 y2 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
380                 v  = get_vlc2(&gb, s->vlc[3].table, YLC_VLC_BITS, 3);
381                 if (y1 < 0 || y2 < 0 || u < 0 || v < 0)
382                     return AVERROR_INVALIDDATA;
383                 dst[x    ] = y1;
384                 dst[x + 1] = u;
385                 dst[x + 2] = y1 + y2;
386                 dst[x + 3] = v;
387                 x += 4;
388             }
389         }
390         dst += p->linesize[0];
391     }
392
393     dst = p->data[0];
394     for (x = 0; x < avctx->width * 2; x += 4) {
395         dst[x    ] =        dst[x    ] + L[0];
396         dst[x + 2] = L[0] = dst[x + 2] + L[0];
397         L[1] = dst[x + 1] + L[1];
398         dst[x + 1] = L[1];
399         L[2] = dst[x + 3] + L[2];
400         dst[x + 3] = L[2];
401     }
402     dst += p->linesize[0];
403
404     for (y = 1; y < avctx->height; y++) {
405         x = 0;
406         dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
407         dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
408         TL[0] = dst[x + 2 - p->linesize[0]];
409         L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
410         dst[x + 1] = L[1];
411         TL[1] = dst[x + 1 - p->linesize[0]];
412         L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
413         dst[x + 3] = L[2];
414         TL[2] = dst[x + 3 - p->linesize[0]];
415         for (x = 4; x < avctx->width * 2; x += 4) {
416             dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
417             dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
418             TL[0] = dst[x + 2 - p->linesize[0]];
419             L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
420             dst[x + 1] = L[1];
421             TL[1] = dst[x + 1 - p->linesize[0]];
422             L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
423             dst[x + 3] = L[2];
424             TL[2] = dst[x + 3 - p->linesize[0]];
425         }
426         dst += p->linesize[0];
427     }
428
429     p->pict_type = AV_PICTURE_TYPE_I;
430     p->flags |= AV_FRAME_FLAG_KEY;
431     *got_frame   = 1;
432
433     return avpkt->size;
434 }
435
436 static av_cold int decode_end(AVCodecContext *avctx)
437 {
438     YLCContext *s = avctx->priv_data;
439
440     for (int i = 0; i < FF_ARRAY_ELEMS(s->vlc); i++)
441         ff_vlc_free(&s->vlc[i]);
442     av_freep(&s->buffer);
443     s->buffer_size = 0;
444
445     return 0;
446 }
447
448 const FFCodec ff_ylc_decoder = {
449     .p.name         = "ylc",
450     CODEC_LONG_NAME("YUY2 Lossless Codec"),
451     .p.type         = AVMEDIA_TYPE_VIDEO,
452     .p.id           = AV_CODEC_ID_YLC,
453     .priv_data_size = sizeof(YLCContext),
454     .init           = decode_init,
455     .close          = decode_end,
456     FF_CODEC_DECODE_CB(decode_frame),
457     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
458 };