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 "codec_internal.h"
34 #include "get_bits.h"
35 #include "huffyuvdsp.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
decode_init(AVCodecContext *avctx)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
get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, Node *nodes, int node, uint32_t pfx, int pl, int *pos)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
build_vlc(AVCodecContext *avctx, VLC *vlc, const uint32_t *table)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
decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt)281 static int decode_frame(AVCodecContext *avctx, AVFrame *p,
282 int *got_frame, AVPacket *avpkt)
283 {
284 int TL[4] = { 128, 128, 128, 128 };
285 int L[4] = { 128, 128, 128, 128 };
286 YLCContext *s = avctx->priv_data;
287 const uint8_t *buf = avpkt->data;
288 int ret, x, y, toffset, boffset;
289 GetBitContext gb;
290 uint8_t *dst;
291
292 if (avpkt->size <= 16)
293 return AVERROR_INVALIDDATA;
294
295 if (AV_RL32(buf) != MKTAG('Y', 'L', 'C', '0') ||
296 AV_RL32(buf + 4) != 0)
297 return AVERROR_INVALIDDATA;
298
299 toffset = AV_RL32(buf + 8);
300 if (toffset < 16 || toffset >= avpkt->size)
301 return AVERROR_INVALIDDATA;
302
303 boffset = AV_RL32(buf + 12);
304 if (toffset >= boffset || boffset >= avpkt->size)
305 return AVERROR_INVALIDDATA;
306
307 if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
308 return ret;
309
310 av_fast_malloc(&s->buffer, &s->buffer_size,
311 FFMAX(boffset - toffset, avpkt->size - boffset)
312 + AV_INPUT_BUFFER_PADDING_SIZE);
313 if (!s->buffer)
314 return AVERROR(ENOMEM);
315
316 memcpy(s->buffer, avpkt->data + toffset, boffset - toffset);
317 memset(s->buffer + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
318 s->bdsp.bswap_buf((uint32_t *) s->buffer,
319 (uint32_t *) s->buffer,
320 (boffset - toffset + 3) >> 2);
321 if ((ret = init_get_bits8(&gb, s->buffer, boffset - toffset)) < 0)
322 return ret;
323
324 for (int i = 0; i < 4; i++) {
325 for (x = 0; x < 256; x++) {
326 unsigned len = get_unary(&gb, 1, 31);
327 uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len);
328
329 s->table[x] = val;
330 }
331
332 ret = build_vlc(avctx, &s->vlc[i], s->table);
333 if (ret < 0)
334 return ret;
335 }
336
337 memcpy(s->buffer, avpkt->data + boffset, avpkt->size - boffset);
338 memset(s->buffer + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
339 s->bdsp.bswap_buf((uint32_t *) s->buffer,
340 (uint32_t *) s->buffer,
341 (avpkt->size - boffset) >> 2);
342 if ((ret = init_get_bits8(&gb, s->buffer, avpkt->size - boffset)) < 0)
343 return ret;
344
345 dst = p->data[0];
346 for (y = 0; y < avctx->height; y++) {
347 memset(dst, 0, avctx->width * 2);
348 dst += p->linesize[0];
349 }
350
351 dst = p->data[0];
352 for (y = 0; y < avctx->height; y++) {
353 for (x = 0; x < avctx->width * 2 && y < avctx->height;) {
354 if (get_bits_left(&gb) <= 0)
355 return AVERROR_INVALIDDATA;
356
357 if (get_bits1(&gb)) {
358 int val = get_vlc2(&gb, s->vlc[0].table, YLC_VLC_BITS, 3);
359 if (val < 0) {
360 return AVERROR_INVALIDDATA;
361 } else if (val < 0xE1) {
362 dst[x ] = table_y1[val];
363 dst[x + 1] = table_u[val];
364 dst[x + 2] = table_y2[val];
365 dst[x + 3] = table_v[val];
366 x += 4;
367 } else {
368 int incr = (val - 0xDF) * 4;
369 if (x + incr >= avctx->width * 2) {
370 int iy = ((x + incr) / (avctx->width * 2));
371 x = (x + incr) % (avctx->width * 2);
372 y += iy;
373 dst += iy * p->linesize[0];
374 } else {
375 x += incr;
376 }
377 }
378 } else {
379 int y1, y2, u, v;
380
381 y1 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
382 u = get_vlc2(&gb, s->vlc[2].table, YLC_VLC_BITS, 3);
383 y2 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
384 v = get_vlc2(&gb, s->vlc[3].table, YLC_VLC_BITS, 3);
385 if (y1 < 0 || y2 < 0 || u < 0 || v < 0)
386 return AVERROR_INVALIDDATA;
387 dst[x ] = y1;
388 dst[x + 1] = u;
389 dst[x + 2] = y1 + y2;
390 dst[x + 3] = v;
391 x += 4;
392 }
393 }
394 dst += p->linesize[0];
395 }
396
397 dst = p->data[0];
398 for (x = 0; x < avctx->width * 2; x += 4) {
399 dst[x ] = dst[x ] + L[0];
400 dst[x + 2] = L[0] = dst[x + 2] + L[0];
401 L[1] = dst[x + 1] + L[1];
402 dst[x + 1] = L[1];
403 L[2] = dst[x + 3] + L[2];
404 dst[x + 3] = L[2];
405 }
406 dst += p->linesize[0];
407
408 for (y = 1; y < avctx->height; y++) {
409 x = 0;
410 dst[x ] = dst[x ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
411 dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
412 TL[0] = dst[x + 2 - p->linesize[0]];
413 L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
414 dst[x + 1] = L[1];
415 TL[1] = dst[x + 1 - p->linesize[0]];
416 L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
417 dst[x + 3] = L[2];
418 TL[2] = dst[x + 3 - p->linesize[0]];
419 for (x = 4; x < avctx->width * 2; x += 4) {
420 dst[x ] = dst[x ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
421 dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
422 TL[0] = dst[x + 2 - p->linesize[0]];
423 L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
424 dst[x + 1] = L[1];
425 TL[1] = dst[x + 1 - p->linesize[0]];
426 L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
427 dst[x + 3] = L[2];
428 TL[2] = dst[x + 3 - p->linesize[0]];
429 }
430 dst += p->linesize[0];
431 }
432
433 p->pict_type = AV_PICTURE_TYPE_I;
434 p->key_frame = 1;
435 *got_frame = 1;
436
437 return avpkt->size;
438 }
439
decode_end(AVCodecContext *avctx)440 static av_cold int decode_end(AVCodecContext *avctx)
441 {
442 YLCContext *s = avctx->priv_data;
443
444 for (int i = 0; i < FF_ARRAY_ELEMS(s->vlc); i++)
445 ff_free_vlc(&s->vlc[i]);
446 av_freep(&s->buffer);
447 s->buffer_size = 0;
448
449 return 0;
450 }
451
452 const FFCodec ff_ylc_decoder = {
453 .p.name = "ylc",
454 .p.long_name = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"),
455 .p.type = AVMEDIA_TYPE_VIDEO,
456 .p.id = AV_CODEC_ID_YLC,
457 .priv_data_size = sizeof(YLCContext),
458 .init = decode_init,
459 .close = decode_end,
460 FF_CODEC_DECODE_CB(decode_frame),
461 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
462 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
463 };
464