FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/ylc.c
Date: 2022-12-09 07:38:14
Exec Total Coverage
Lines: 0 183 0.0%
Functions: 0 5 0.0%
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 <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_free_vlc(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_init_vlc_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->key_frame = 1;
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_free_vlc(&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 };
459