summaryrefslogtreecommitdiff
path: root/libavcodec/ylc.c (plain)
blob: 02162a37e7fbd9ed41c88ca1ce43cc22044a2627
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#include "libavutil/imgutils.h"
26#include "libavutil/internal.h"
27#include "libavutil/intreadwrite.h"
28#include "libavutil/mem.h"
29#include "avcodec.h"
30#include "bswapdsp.h"
31#include "get_bits.h"
32#include "huffyuvdsp.h"
33#include "internal.h"
34#include "thread.h"
35#include "unary.h"
36
37typedef struct YLCContext {
38 VLC vlc[4];
39 uint32_t table[1024];
40 uint8_t *table_bits;
41 uint8_t *bitstream_bits;
42 int table_bits_size;
43 int bitstream_bits_size;
44 BswapDSPContext bdsp;
45} YLCContext;
46
47static 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
57typedef struct Node {
58 int16_t sym;
59 int16_t n0;
60 uint32_t count;
61 int16_t l, r;
62} Node;
63
64static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat,
65 Node *nodes, int node,
66 uint32_t pfx, int pl, int *pos)
67{
68 int s;
69
70 s = nodes[node].sym;
71 if (s != -1) {
72 bits[*pos] = (~pfx) & ((1 << FFMAX(pl, 1)) - 1);
73 lens[*pos] = FFMAX(pl, 1);
74 xlat[*pos] = s + (pl == 0);
75 (*pos)++;
76 } else {
77 pfx <<= 1;
78 pl++;
79 get_tree_codes(bits, lens, xlat, nodes, nodes[node].l, pfx, pl,
80 pos);
81 pfx |= 1;
82 get_tree_codes(bits, lens, xlat, nodes, nodes[node].r, pfx, pl,
83 pos);
84 }
85}
86
87static int build_vlc(AVCodecContext *avctx, VLC *vlc, const uint32_t *table)
88{
89 Node nodes[512];
90 uint32_t bits[256];
91 int16_t lens[256];
92 uint8_t xlat[256];
93 int cur_node, i, j, pos = 0;
94
95 ff_free_vlc(vlc);
96
97 for (i = 0; i < 256; i++) {
98 nodes[i].count = table[i];
99 nodes[i].sym = i;
100 nodes[i].n0 = -2;
101 nodes[i].l = i;
102 nodes[i].r = i;
103 }
104
105 cur_node = 256;
106 j = 0;
107 do {
108 for (i = 0; ; i++) {
109 int new_node = j;
110 int first_node = cur_node;
111 int second_node = cur_node;
112 int nd, st;
113
114 nodes[cur_node].count = -1;
115
116 do {
117 int val = nodes[new_node].count;
118 if (val && (val < nodes[first_node].count)) {
119 if (val >= nodes[second_node].count) {
120 first_node = new_node;
121 } else {
122 first_node = second_node;
123 second_node = new_node;
124 }
125 }
126 new_node += 1;
127 } while (new_node != cur_node);
128
129 if (first_node == cur_node)
130 break;
131
132 nd = nodes[second_node].count;
133 st = nodes[first_node].count;
134 nodes[second_node].count = 0;
135 nodes[first_node].count = 0;
136 nodes[cur_node].count = nd + st;
137 nodes[cur_node].sym = -1;
138 nodes[cur_node].n0 = cur_node;
139 nodes[cur_node].l = first_node;
140 nodes[cur_node].r = second_node;
141 cur_node++;
142 }
143 j++;
144 } while (cur_node - 256 == j);
145
146 get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos);
147
148 return ff_init_vlc_sparse(vlc, 10, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0);
149}
150
151static const uint8_t table_y1[] = {
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, 0xFE, 0xFE, 0xFE,
156 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
157 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
162 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
163 0xFF, 0xFF, 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, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0x01, 0x01, 0x01,
173 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
174 0x01, 0x01, 0x01, 0x01, 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, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
179 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
180 0x02, 0x00,
181};
182
183static const uint8_t table_u[] = {
184 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
185 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
188 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
189 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF,
190 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
191 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
194 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
195 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
196 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
197 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
200 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF,
201 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
202 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
205 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
206 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
207 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
208 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
211 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
212 0x01, 0x00,
213};
214
215static const uint8_t table_y2[] = {
216 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
217 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC,
218 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE,
219 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFC,
220 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF,
221 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFD,
222 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
223 0x00, 0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE,
224 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
225 0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
226 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
227 0x01, 0x01, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
228 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
229 0x02, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00,
230 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
231 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
232 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0xFF,
233 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
234 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF,
235 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
236 0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xFF,
237 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
238 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x01,
239 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
240 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01,
241 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04,
242 0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
243 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04,
244 0x04, 0x00,
245};
246
247static const uint8_t table_v[] = {
248 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
249 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
250 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
251 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
252 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
253 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
254 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
255 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
256 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
257 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
258 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
259 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
260 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
261 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
262 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
263 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
264 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
265 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
266 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
267 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
268 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
269 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
270 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
271 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
272 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
273 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
274 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
275 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
276 0x01, 0x00,
277};
278
279static int decode_frame(AVCodecContext *avctx,
280 void *data, int *got_frame,
281 AVPacket *avpkt)
282{
283 int TL[4] = { 128, 128, 128, 128 };
284 int L[4] = { 128, 128, 128, 128 };
285 YLCContext *s = avctx->priv_data;
286 ThreadFrame frame = { .f = data };
287 const uint8_t *buf = avpkt->data;
288 int ret, x, y, toffset, boffset;
289 AVFrame * const p = data;
290 GetBitContext gb;
291 uint8_t *dst;
292
293 if (avpkt->size <= 16)
294 return AVERROR_INVALIDDATA;
295
296 if (AV_RL32(buf) != MKTAG('Y', 'L', 'C', '0') ||
297 AV_RL32(buf + 4) != 0)
298 return AVERROR_INVALIDDATA;
299
300 toffset = AV_RL32(buf + 8);
301 if (toffset < 16 || toffset >= avpkt->size)
302 return AVERROR_INVALIDDATA;
303
304 boffset = AV_RL32(buf + 12);
305 if (toffset >= boffset || boffset >= avpkt->size)
306 return AVERROR_INVALIDDATA;
307
308 if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
309 return ret;
310
311 av_fast_malloc(&s->table_bits, &s->table_bits_size,
312 boffset - toffset + AV_INPUT_BUFFER_PADDING_SIZE);
313 if (!s->table_bits)
314 return AVERROR(ENOMEM);
315
316 memcpy(s->table_bits, avpkt->data + toffset, boffset - toffset);
317 memset(s->table_bits + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
318 s->bdsp.bswap_buf((uint32_t *) s->table_bits,
319 (uint32_t *) s->table_bits,
320 (boffset - toffset + 3) >> 2);
321 if ((ret = init_get_bits8(&gb, s->table_bits, boffset - toffset)) < 0)
322 return ret;
323
324 for (x = 0; x < 1024; x++) {
325 unsigned len = get_unary(&gb, 1, 31);
326 uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len);
327
328 s->table[x] = val;
329 }
330
331 ret = build_vlc(avctx, &s->vlc[0], &s->table[0 ]);
332 if (ret < 0)
333 return ret;
334 ret = build_vlc(avctx, &s->vlc[1], &s->table[256]);
335 if (ret < 0)
336 return ret;
337 ret = build_vlc(avctx, &s->vlc[2], &s->table[512]);
338 if (ret < 0)
339 return ret;
340 ret = build_vlc(avctx, &s->vlc[3], &s->table[768]);
341 if (ret < 0)
342 return ret;
343
344 av_fast_malloc(&s->bitstream_bits, &s->bitstream_bits_size,
345 avpkt->size - boffset + AV_INPUT_BUFFER_PADDING_SIZE);
346 if (!s->bitstream_bits)
347 return AVERROR(ENOMEM);
348
349 memcpy(s->bitstream_bits, avpkt->data + boffset, avpkt->size - boffset);
350 memset(s->bitstream_bits + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
351 s->bdsp.bswap_buf((uint32_t *) s->bitstream_bits,
352 (uint32_t *) s->bitstream_bits,
353 (avpkt->size - boffset) >> 2);
354 if ((ret = init_get_bits8(&gb, s->bitstream_bits, avpkt->size - boffset)) < 0)
355 return ret;
356
357 dst = p->data[0];
358 for (y = 0; y < avctx->height; y++) {
359 memset(dst, 0, avctx->width * 2);
360 dst += p->linesize[0];
361 }
362
363 dst = p->data[0];
364 for (y = 0; y < avctx->height; y++) {
365 for (x = 0; x < avctx->width * 2 && y < avctx->height;) {
366 if (get_bits_left(&gb) <= 0)
367 return AVERROR_INVALIDDATA;
368
369 if (get_bits1(&gb)) {
370 int val = get_vlc2(&gb, s->vlc[0].table, s->vlc[0].bits, 3);
371 if (val < 0) {
372 return AVERROR_INVALIDDATA;
373 } else if (val < 0xE1) {
374 dst[x ] = table_y1[val];
375 dst[x + 1] = table_u[val];
376 dst[x + 2] = table_y2[val];
377 dst[x + 3] = table_v[val];
378 x += 4;
379 } else {
380 int incr = (val - 0xDF) * 4;
381 if (x + incr >= avctx->width * 2) {
382 int iy = ((x + incr) / (avctx->width * 2));
383 x = (x + incr) % (avctx->width * 2);
384 y += iy;
385 dst += iy * p->linesize[0];
386 } else {
387 x += incr;
388 }
389 }
390 } else {
391 int y1, y2, u, v;
392
393 y1 = get_vlc2(&gb, s->vlc[1].table, s->vlc[1].bits, 3);
394 u = get_vlc2(&gb, s->vlc[2].table, s->vlc[2].bits, 3);
395 y2 = get_vlc2(&gb, s->vlc[1].table, s->vlc[1].bits, 3);
396 v = get_vlc2(&gb, s->vlc[3].table, s->vlc[3].bits, 3);
397 if (y1 < 0 || y2 < 0 || u < 0 || v < 0)
398 return AVERROR_INVALIDDATA;
399 dst[x ] = y1;
400 dst[x + 1] = u;
401 dst[x + 2] = y1 + y2;
402 dst[x + 3] = v;
403 x += 4;
404 }
405 }
406 dst += p->linesize[0];
407 }
408
409 dst = p->data[0];
410 for (x = 0; x < avctx->width * 2; x += 4) {
411 dst[x ] = dst[x ] + L[0];
412 dst[x + 2] = L[0] = dst[x + 2] + L[0];
413 L[1] = dst[x + 1] + L[1];
414 dst[x + 1] = L[1];
415 L[2] = dst[x + 3] + L[2];
416 dst[x + 3] = L[2];
417 }
418 dst += p->linesize[0];
419
420 for (y = 1; y < avctx->height; y++) {
421 x = 0;
422 dst[x ] = dst[x ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
423 dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
424 TL[0] = dst[x + 2 - p->linesize[0]];
425 L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
426 dst[x + 1] = L[1];
427 TL[1] = dst[x + 1 - p->linesize[0]];
428 L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
429 dst[x + 3] = L[2];
430 TL[2] = dst[x + 3 - p->linesize[0]];
431 for (x = 4; x < avctx->width * 2; x += 4) {
432 dst[x ] = dst[x ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
433 dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
434 TL[0] = dst[x + 2 - p->linesize[0]];
435 L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
436 dst[x + 1] = L[1];
437 TL[1] = dst[x + 1 - p->linesize[0]];
438 L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
439 dst[x + 3] = L[2];
440 TL[2] = dst[x + 3 - p->linesize[0]];
441 }
442 dst += p->linesize[0];
443 }
444
445 p->pict_type = AV_PICTURE_TYPE_I;
446 p->key_frame = 1;
447 *got_frame = 1;
448
449 return avpkt->size;
450}
451
452#if HAVE_THREADS
453static int init_thread_copy(AVCodecContext *avctx)
454{
455 YLCContext *s = avctx->priv_data;
456
457 memset(&s->vlc[0], 0, sizeof(VLC));
458 memset(&s->vlc[1], 0, sizeof(VLC));
459 memset(&s->vlc[2], 0, sizeof(VLC));
460 memset(&s->vlc[3], 0, sizeof(VLC));
461 s->table_bits = NULL;
462 s->table_bits_size = 0;
463 s->bitstream_bits = NULL;
464 s->bitstream_bits_size = 0;
465
466 return 0;
467}
468#endif
469
470static av_cold int decode_end(AVCodecContext *avctx)
471{
472 YLCContext *s = avctx->priv_data;
473
474 ff_free_vlc(&s->vlc[0]);
475 ff_free_vlc(&s->vlc[1]);
476 ff_free_vlc(&s->vlc[2]);
477 ff_free_vlc(&s->vlc[3]);
478 av_freep(&s->table_bits);
479 s->table_bits_size = 0;
480 av_freep(&s->bitstream_bits);
481 s->bitstream_bits_size = 0;
482
483 return 0;
484}
485
486AVCodec ff_ylc_decoder = {
487 .name = "ylc",
488 .long_name = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"),
489 .type = AVMEDIA_TYPE_VIDEO,
490 .id = AV_CODEC_ID_YLC,
491 .priv_data_size = sizeof(YLCContext),
492 .init = decode_init,
493 .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy),
494 .close = decode_end,
495 .decode = decode_frame,
496 .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
497 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
498};
499