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
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,void * data,int * got_frame,AVPacket * avpkt)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
decode_end(AVCodecContext * avctx)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 };
467