1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * YUY2 Lossless Codec
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * This file is part of FFmpeg.
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
10cabdff1aSopenharmony_ci *
11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14cabdff1aSopenharmony_ci * Lesser General Public License for more details.
15cabdff1aSopenharmony_ci *
16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19cabdff1aSopenharmony_ci */
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include <stdio.h>
22cabdff1aSopenharmony_ci#include <stdlib.h>
23cabdff1aSopenharmony_ci#include <string.h>
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci#define YLC_VLC_BITS 10
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include "libavutil/imgutils.h"
28cabdff1aSopenharmony_ci#include "libavutil/internal.h"
29cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
30cabdff1aSopenharmony_ci#include "libavutil/mem.h"
31cabdff1aSopenharmony_ci#include "avcodec.h"
32cabdff1aSopenharmony_ci#include "bswapdsp.h"
33cabdff1aSopenharmony_ci#include "codec_internal.h"
34cabdff1aSopenharmony_ci#include "get_bits.h"
35cabdff1aSopenharmony_ci#include "huffyuvdsp.h"
36cabdff1aSopenharmony_ci#include "thread.h"
37cabdff1aSopenharmony_ci#include "unary.h"
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_citypedef struct YLCContext {
40cabdff1aSopenharmony_ci    VLC vlc[4];
41cabdff1aSopenharmony_ci    uint32_t table[256];
42cabdff1aSopenharmony_ci    uint8_t *buffer;
43cabdff1aSopenharmony_ci    int buffer_size;
44cabdff1aSopenharmony_ci    BswapDSPContext bdsp;
45cabdff1aSopenharmony_ci} YLCContext;
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
48cabdff1aSopenharmony_ci{
49cabdff1aSopenharmony_ci    YLCContext *s = avctx->priv_data;
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_ci    avctx->pix_fmt = AV_PIX_FMT_YUYV422;
52cabdff1aSopenharmony_ci    ff_bswapdsp_init(&s->bdsp);
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ci    return 0;
55cabdff1aSopenharmony_ci}
56cabdff1aSopenharmony_ci
57cabdff1aSopenharmony_citypedef struct Node {
58cabdff1aSopenharmony_ci    int16_t  sym;
59cabdff1aSopenharmony_ci    uint32_t count;
60cabdff1aSopenharmony_ci    int16_t  l, r;
61cabdff1aSopenharmony_ci} Node;
62cabdff1aSopenharmony_ci
63cabdff1aSopenharmony_cistatic void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat,
64cabdff1aSopenharmony_ci                           Node *nodes, int node,
65cabdff1aSopenharmony_ci                           uint32_t pfx, int pl, int *pos)
66cabdff1aSopenharmony_ci{
67cabdff1aSopenharmony_ci    int s;
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_ci    s = nodes[node].sym;
70cabdff1aSopenharmony_ci    if (s != -1) {
71cabdff1aSopenharmony_ci        bits[*pos] = (~pfx) & ((1ULL << FFMAX(pl, 1)) - 1);
72cabdff1aSopenharmony_ci        lens[*pos] = FFMAX(pl, 1);
73cabdff1aSopenharmony_ci        xlat[*pos] = s + (pl == 0);
74cabdff1aSopenharmony_ci        (*pos)++;
75cabdff1aSopenharmony_ci    } else {
76cabdff1aSopenharmony_ci        pfx <<= 1;
77cabdff1aSopenharmony_ci        pl++;
78cabdff1aSopenharmony_ci        get_tree_codes(bits, lens, xlat, nodes, nodes[node].l, pfx, pl,
79cabdff1aSopenharmony_ci                       pos);
80cabdff1aSopenharmony_ci        pfx |= 1;
81cabdff1aSopenharmony_ci        get_tree_codes(bits, lens, xlat, nodes, nodes[node].r, pfx, pl,
82cabdff1aSopenharmony_ci                       pos);
83cabdff1aSopenharmony_ci    }
84cabdff1aSopenharmony_ci}
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_cistatic int build_vlc(AVCodecContext *avctx, VLC *vlc, const uint32_t *table)
87cabdff1aSopenharmony_ci{
88cabdff1aSopenharmony_ci    Node nodes[512];
89cabdff1aSopenharmony_ci    uint32_t bits[256];
90cabdff1aSopenharmony_ci    int16_t lens[256];
91cabdff1aSopenharmony_ci    uint8_t xlat[256];
92cabdff1aSopenharmony_ci    int cur_node, i, j, pos = 0;
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_ci    ff_free_vlc(vlc);
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_ci    for (i = 0; i < 256; i++) {
97cabdff1aSopenharmony_ci        nodes[i].count = table[i];
98cabdff1aSopenharmony_ci        nodes[i].sym   = i;
99cabdff1aSopenharmony_ci        nodes[i].l     = i;
100cabdff1aSopenharmony_ci        nodes[i].r     = i;
101cabdff1aSopenharmony_ci    }
102cabdff1aSopenharmony_ci
103cabdff1aSopenharmony_ci    cur_node = 256;
104cabdff1aSopenharmony_ci    j = 0;
105cabdff1aSopenharmony_ci    do {
106cabdff1aSopenharmony_ci        for (i = 0; ; i++) {
107cabdff1aSopenharmony_ci            int new_node = j;
108cabdff1aSopenharmony_ci            int first_node = cur_node;
109cabdff1aSopenharmony_ci            int second_node = cur_node;
110cabdff1aSopenharmony_ci            unsigned nd, st;
111cabdff1aSopenharmony_ci
112cabdff1aSopenharmony_ci            nodes[cur_node].count = -1;
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci            do {
115cabdff1aSopenharmony_ci                int val = nodes[new_node].count;
116cabdff1aSopenharmony_ci                if (val && (val < nodes[first_node].count)) {
117cabdff1aSopenharmony_ci                    if (val >= nodes[second_node].count) {
118cabdff1aSopenharmony_ci                        first_node = new_node;
119cabdff1aSopenharmony_ci                    } else {
120cabdff1aSopenharmony_ci                        first_node = second_node;
121cabdff1aSopenharmony_ci                        second_node = new_node;
122cabdff1aSopenharmony_ci                    }
123cabdff1aSopenharmony_ci                }
124cabdff1aSopenharmony_ci                new_node += 1;
125cabdff1aSopenharmony_ci            } while (new_node != cur_node);
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_ci            if (first_node == cur_node)
128cabdff1aSopenharmony_ci                break;
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_ci            nd = nodes[second_node].count;
131cabdff1aSopenharmony_ci            st = nodes[first_node].count;
132cabdff1aSopenharmony_ci            nodes[second_node].count = 0;
133cabdff1aSopenharmony_ci            nodes[first_node].count  = 0;
134cabdff1aSopenharmony_ci            if (nd >= UINT32_MAX - st) {
135cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_ERROR, "count overflow\n");
136cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
137cabdff1aSopenharmony_ci            }
138cabdff1aSopenharmony_ci            nodes[cur_node].count = nd + st;
139cabdff1aSopenharmony_ci            nodes[cur_node].sym = -1;
140cabdff1aSopenharmony_ci            nodes[cur_node].l = first_node;
141cabdff1aSopenharmony_ci            nodes[cur_node].r = second_node;
142cabdff1aSopenharmony_ci            cur_node++;
143cabdff1aSopenharmony_ci        }
144cabdff1aSopenharmony_ci        j++;
145cabdff1aSopenharmony_ci    } while (cur_node - 256 == j);
146cabdff1aSopenharmony_ci
147cabdff1aSopenharmony_ci    get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos);
148cabdff1aSopenharmony_ci
149cabdff1aSopenharmony_ci    return ff_init_vlc_sparse(vlc, YLC_VLC_BITS, pos, lens, 2, 2,
150cabdff1aSopenharmony_ci                              bits, 4, 4, xlat, 1, 1, 0);
151cabdff1aSopenharmony_ci}
152cabdff1aSopenharmony_ci
153cabdff1aSopenharmony_cistatic const uint8_t table_y1[] = {
154cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
155cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
156cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
157cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
158cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
159cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
160cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
161cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
162cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
163cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
164cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
165cabdff1aSopenharmony_ci    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
171cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
172cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
173cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
174cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
175cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
176cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
177cabdff1aSopenharmony_ci    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
178cabdff1aSopenharmony_ci    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
179cabdff1aSopenharmony_ci    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
180cabdff1aSopenharmony_ci    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
181cabdff1aSopenharmony_ci    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
182cabdff1aSopenharmony_ci    0x02, 0x00,
183cabdff1aSopenharmony_ci};
184cabdff1aSopenharmony_ci
185cabdff1aSopenharmony_cistatic const uint8_t table_u[] = {
186cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
187cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
188cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
190cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
191cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF,
192cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
193cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
194cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
196cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
197cabdff1aSopenharmony_ci    0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
198cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
199cabdff1aSopenharmony_ci    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
202cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF,
203cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
204cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
205cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
207cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
208cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
209cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
210cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
211cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212cabdff1aSopenharmony_ci    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
213cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
214cabdff1aSopenharmony_ci    0x01, 0x00,
215cabdff1aSopenharmony_ci};
216cabdff1aSopenharmony_ci
217cabdff1aSopenharmony_cistatic const uint8_t table_y2[] = {
218cabdff1aSopenharmony_ci    0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
219cabdff1aSopenharmony_ci    0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC,
220cabdff1aSopenharmony_ci    0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE,
221cabdff1aSopenharmony_ci    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFC,
222cabdff1aSopenharmony_ci    0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF,
223cabdff1aSopenharmony_ci    0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFD,
224cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
225cabdff1aSopenharmony_ci    0x00, 0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE,
226cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
227cabdff1aSopenharmony_ci    0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
228cabdff1aSopenharmony_ci    0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
229cabdff1aSopenharmony_ci    0x01, 0x01, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
230cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
231cabdff1aSopenharmony_ci    0x02, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00,
232cabdff1aSopenharmony_ci    0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
233cabdff1aSopenharmony_ci    0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
234cabdff1aSopenharmony_ci    0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0xFF,
235cabdff1aSopenharmony_ci    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
236cabdff1aSopenharmony_ci    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF,
237cabdff1aSopenharmony_ci    0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
238cabdff1aSopenharmony_ci    0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xFF,
239cabdff1aSopenharmony_ci    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
240cabdff1aSopenharmony_ci    0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x01,
241cabdff1aSopenharmony_ci    0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
242cabdff1aSopenharmony_ci    0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01,
243cabdff1aSopenharmony_ci    0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04,
244cabdff1aSopenharmony_ci    0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
245cabdff1aSopenharmony_ci    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04,
246cabdff1aSopenharmony_ci    0x04, 0x00,
247cabdff1aSopenharmony_ci};
248cabdff1aSopenharmony_ci
249cabdff1aSopenharmony_cistatic const uint8_t table_v[] = {
250cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
251cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
252cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
253cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
254cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
255cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
256cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
257cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
258cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
259cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
260cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
261cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
262cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
263cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
264cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
265cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
266cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
267cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
268cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
269cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
270cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
271cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
272cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
273cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
274cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
275cabdff1aSopenharmony_ci    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
276cabdff1aSopenharmony_ci    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
277cabdff1aSopenharmony_ci    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
278cabdff1aSopenharmony_ci    0x01, 0x00,
279cabdff1aSopenharmony_ci};
280cabdff1aSopenharmony_ci
281cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *p,
282cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
283cabdff1aSopenharmony_ci{
284cabdff1aSopenharmony_ci    int TL[4] = { 128, 128, 128, 128 };
285cabdff1aSopenharmony_ci    int L[4]  = { 128, 128, 128, 128 };
286cabdff1aSopenharmony_ci    YLCContext *s = avctx->priv_data;
287cabdff1aSopenharmony_ci    const uint8_t *buf = avpkt->data;
288cabdff1aSopenharmony_ci    int ret, x, y, toffset, boffset;
289cabdff1aSopenharmony_ci    GetBitContext gb;
290cabdff1aSopenharmony_ci    uint8_t *dst;
291cabdff1aSopenharmony_ci
292cabdff1aSopenharmony_ci    if (avpkt->size <= 16)
293cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
294cabdff1aSopenharmony_ci
295cabdff1aSopenharmony_ci    if (AV_RL32(buf) != MKTAG('Y', 'L', 'C', '0') ||
296cabdff1aSopenharmony_ci        AV_RL32(buf + 4) != 0)
297cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
298cabdff1aSopenharmony_ci
299cabdff1aSopenharmony_ci    toffset = AV_RL32(buf + 8);
300cabdff1aSopenharmony_ci    if (toffset < 16 || toffset >= avpkt->size)
301cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
302cabdff1aSopenharmony_ci
303cabdff1aSopenharmony_ci    boffset = AV_RL32(buf + 12);
304cabdff1aSopenharmony_ci    if (toffset >= boffset || boffset >= avpkt->size)
305cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
306cabdff1aSopenharmony_ci
307cabdff1aSopenharmony_ci    if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
308cabdff1aSopenharmony_ci        return ret;
309cabdff1aSopenharmony_ci
310cabdff1aSopenharmony_ci    av_fast_malloc(&s->buffer, &s->buffer_size,
311cabdff1aSopenharmony_ci                   FFMAX(boffset - toffset, avpkt->size - boffset)
312cabdff1aSopenharmony_ci                       + AV_INPUT_BUFFER_PADDING_SIZE);
313cabdff1aSopenharmony_ci    if (!s->buffer)
314cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
315cabdff1aSopenharmony_ci
316cabdff1aSopenharmony_ci    memcpy(s->buffer, avpkt->data + toffset, boffset - toffset);
317cabdff1aSopenharmony_ci    memset(s->buffer + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
318cabdff1aSopenharmony_ci    s->bdsp.bswap_buf((uint32_t *) s->buffer,
319cabdff1aSopenharmony_ci                      (uint32_t *) s->buffer,
320cabdff1aSopenharmony_ci                      (boffset - toffset + 3) >> 2);
321cabdff1aSopenharmony_ci    if ((ret = init_get_bits8(&gb, s->buffer, boffset - toffset)) < 0)
322cabdff1aSopenharmony_ci        return ret;
323cabdff1aSopenharmony_ci
324cabdff1aSopenharmony_ci    for (int i = 0; i < 4; i++) {
325cabdff1aSopenharmony_ci        for (x = 0; x < 256; x++) {
326cabdff1aSopenharmony_ci            unsigned len = get_unary(&gb, 1, 31);
327cabdff1aSopenharmony_ci            uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len);
328cabdff1aSopenharmony_ci
329cabdff1aSopenharmony_ci            s->table[x] = val;
330cabdff1aSopenharmony_ci        }
331cabdff1aSopenharmony_ci
332cabdff1aSopenharmony_ci        ret = build_vlc(avctx, &s->vlc[i], s->table);
333cabdff1aSopenharmony_ci        if (ret < 0)
334cabdff1aSopenharmony_ci            return ret;
335cabdff1aSopenharmony_ci    }
336cabdff1aSopenharmony_ci
337cabdff1aSopenharmony_ci    memcpy(s->buffer, avpkt->data + boffset, avpkt->size - boffset);
338cabdff1aSopenharmony_ci    memset(s->buffer + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
339cabdff1aSopenharmony_ci    s->bdsp.bswap_buf((uint32_t *) s->buffer,
340cabdff1aSopenharmony_ci                      (uint32_t *) s->buffer,
341cabdff1aSopenharmony_ci                      (avpkt->size - boffset) >> 2);
342cabdff1aSopenharmony_ci    if ((ret = init_get_bits8(&gb, s->buffer, avpkt->size - boffset)) < 0)
343cabdff1aSopenharmony_ci        return ret;
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_ci    dst = p->data[0];
346cabdff1aSopenharmony_ci    for (y = 0; y < avctx->height; y++) {
347cabdff1aSopenharmony_ci        memset(dst, 0, avctx->width * 2);
348cabdff1aSopenharmony_ci        dst += p->linesize[0];
349cabdff1aSopenharmony_ci    }
350cabdff1aSopenharmony_ci
351cabdff1aSopenharmony_ci    dst = p->data[0];
352cabdff1aSopenharmony_ci    for (y = 0; y < avctx->height; y++) {
353cabdff1aSopenharmony_ci        for (x = 0; x < avctx->width * 2 && y < avctx->height;) {
354cabdff1aSopenharmony_ci            if (get_bits_left(&gb) <= 0)
355cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci            if (get_bits1(&gb)) {
358cabdff1aSopenharmony_ci                int val = get_vlc2(&gb, s->vlc[0].table, YLC_VLC_BITS, 3);
359cabdff1aSopenharmony_ci                if (val < 0) {
360cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
361cabdff1aSopenharmony_ci                } else if (val < 0xE1) {
362cabdff1aSopenharmony_ci                    dst[x    ] = table_y1[val];
363cabdff1aSopenharmony_ci                    dst[x + 1] = table_u[val];
364cabdff1aSopenharmony_ci                    dst[x + 2] = table_y2[val];
365cabdff1aSopenharmony_ci                    dst[x + 3] = table_v[val];
366cabdff1aSopenharmony_ci                    x += 4;
367cabdff1aSopenharmony_ci                } else {
368cabdff1aSopenharmony_ci                    int incr = (val - 0xDF) * 4;
369cabdff1aSopenharmony_ci                    if (x + incr >= avctx->width * 2) {
370cabdff1aSopenharmony_ci                        int iy = ((x + incr) / (avctx->width * 2));
371cabdff1aSopenharmony_ci                        x  = (x + incr) % (avctx->width * 2);
372cabdff1aSopenharmony_ci                        y += iy;
373cabdff1aSopenharmony_ci                        dst += iy * p->linesize[0];
374cabdff1aSopenharmony_ci                    } else {
375cabdff1aSopenharmony_ci                        x += incr;
376cabdff1aSopenharmony_ci                    }
377cabdff1aSopenharmony_ci                }
378cabdff1aSopenharmony_ci            } else {
379cabdff1aSopenharmony_ci                int y1, y2, u, v;
380cabdff1aSopenharmony_ci
381cabdff1aSopenharmony_ci                y1 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
382cabdff1aSopenharmony_ci                u  = get_vlc2(&gb, s->vlc[2].table, YLC_VLC_BITS, 3);
383cabdff1aSopenharmony_ci                y2 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3);
384cabdff1aSopenharmony_ci                v  = get_vlc2(&gb, s->vlc[3].table, YLC_VLC_BITS, 3);
385cabdff1aSopenharmony_ci                if (y1 < 0 || y2 < 0 || u < 0 || v < 0)
386cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
387cabdff1aSopenharmony_ci                dst[x    ] = y1;
388cabdff1aSopenharmony_ci                dst[x + 1] = u;
389cabdff1aSopenharmony_ci                dst[x + 2] = y1 + y2;
390cabdff1aSopenharmony_ci                dst[x + 3] = v;
391cabdff1aSopenharmony_ci                x += 4;
392cabdff1aSopenharmony_ci            }
393cabdff1aSopenharmony_ci        }
394cabdff1aSopenharmony_ci        dst += p->linesize[0];
395cabdff1aSopenharmony_ci    }
396cabdff1aSopenharmony_ci
397cabdff1aSopenharmony_ci    dst = p->data[0];
398cabdff1aSopenharmony_ci    for (x = 0; x < avctx->width * 2; x += 4) {
399cabdff1aSopenharmony_ci        dst[x    ] =        dst[x    ] + L[0];
400cabdff1aSopenharmony_ci        dst[x + 2] = L[0] = dst[x + 2] + L[0];
401cabdff1aSopenharmony_ci        L[1] = dst[x + 1] + L[1];
402cabdff1aSopenharmony_ci        dst[x + 1] = L[1];
403cabdff1aSopenharmony_ci        L[2] = dst[x + 3] + L[2];
404cabdff1aSopenharmony_ci        dst[x + 3] = L[2];
405cabdff1aSopenharmony_ci    }
406cabdff1aSopenharmony_ci    dst += p->linesize[0];
407cabdff1aSopenharmony_ci
408cabdff1aSopenharmony_ci    for (y = 1; y < avctx->height; y++) {
409cabdff1aSopenharmony_ci        x = 0;
410cabdff1aSopenharmony_ci        dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
411cabdff1aSopenharmony_ci        dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
412cabdff1aSopenharmony_ci        TL[0] = dst[x + 2 - p->linesize[0]];
413cabdff1aSopenharmony_ci        L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
414cabdff1aSopenharmony_ci        dst[x + 1] = L[1];
415cabdff1aSopenharmony_ci        TL[1] = dst[x + 1 - p->linesize[0]];
416cabdff1aSopenharmony_ci        L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
417cabdff1aSopenharmony_ci        dst[x + 3] = L[2];
418cabdff1aSopenharmony_ci        TL[2] = dst[x + 3 - p->linesize[0]];
419cabdff1aSopenharmony_ci        for (x = 4; x < avctx->width * 2; x += 4) {
420cabdff1aSopenharmony_ci            dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
421cabdff1aSopenharmony_ci            dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
422cabdff1aSopenharmony_ci            TL[0] = dst[x + 2 - p->linesize[0]];
423cabdff1aSopenharmony_ci            L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
424cabdff1aSopenharmony_ci            dst[x + 1] = L[1];
425cabdff1aSopenharmony_ci            TL[1] = dst[x + 1 - p->linesize[0]];
426cabdff1aSopenharmony_ci            L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
427cabdff1aSopenharmony_ci            dst[x + 3] = L[2];
428cabdff1aSopenharmony_ci            TL[2] = dst[x + 3 - p->linesize[0]];
429cabdff1aSopenharmony_ci        }
430cabdff1aSopenharmony_ci        dst += p->linesize[0];
431cabdff1aSopenharmony_ci    }
432cabdff1aSopenharmony_ci
433cabdff1aSopenharmony_ci    p->pict_type = AV_PICTURE_TYPE_I;
434cabdff1aSopenharmony_ci    p->key_frame = 1;
435cabdff1aSopenharmony_ci    *got_frame   = 1;
436cabdff1aSopenharmony_ci
437cabdff1aSopenharmony_ci    return avpkt->size;
438cabdff1aSopenharmony_ci}
439cabdff1aSopenharmony_ci
440cabdff1aSopenharmony_cistatic av_cold int decode_end(AVCodecContext *avctx)
441cabdff1aSopenharmony_ci{
442cabdff1aSopenharmony_ci    YLCContext *s = avctx->priv_data;
443cabdff1aSopenharmony_ci
444cabdff1aSopenharmony_ci    for (int i = 0; i < FF_ARRAY_ELEMS(s->vlc); i++)
445cabdff1aSopenharmony_ci        ff_free_vlc(&s->vlc[i]);
446cabdff1aSopenharmony_ci    av_freep(&s->buffer);
447cabdff1aSopenharmony_ci    s->buffer_size = 0;
448cabdff1aSopenharmony_ci
449cabdff1aSopenharmony_ci    return 0;
450cabdff1aSopenharmony_ci}
451cabdff1aSopenharmony_ci
452cabdff1aSopenharmony_ciconst FFCodec ff_ylc_decoder = {
453cabdff1aSopenharmony_ci    .p.name         = "ylc",
454cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"),
455cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
456cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_YLC,
457cabdff1aSopenharmony_ci    .priv_data_size = sizeof(YLCContext),
458cabdff1aSopenharmony_ci    .init           = decode_init,
459cabdff1aSopenharmony_ci    .close          = decode_end,
460cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
461cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
462cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
463cabdff1aSopenharmony_ci};
464