1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Brooktree ProSumer Video decoder
3cabdff1aSopenharmony_ci * Copyright (c) 2018 Paul B Mahol
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include <stdio.h>
23cabdff1aSopenharmony_ci#include <stdlib.h>
24cabdff1aSopenharmony_ci#include <string.h>
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include "libavutil/imgutils.h"
27cabdff1aSopenharmony_ci#include "libavutil/internal.h"
28cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
29cabdff1aSopenharmony_ci#include "libavutil/mem.h"
30cabdff1aSopenharmony_ci
31cabdff1aSopenharmony_ci#include "avcodec.h"
32cabdff1aSopenharmony_ci#include "bytestream.h"
33cabdff1aSopenharmony_ci#include "codec_internal.h"
34cabdff1aSopenharmony_ci#include "internal.h"
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_citypedef struct ProSumerContext {
37cabdff1aSopenharmony_ci    GetByteContext gb;
38cabdff1aSopenharmony_ci    PutByteContext pb;
39cabdff1aSopenharmony_ci
40cabdff1aSopenharmony_ci    unsigned stride;
41cabdff1aSopenharmony_ci    unsigned size;
42cabdff1aSopenharmony_ci    uint32_t lut[0x2000];
43cabdff1aSopenharmony_ci    uint8_t *initial_line;
44cabdff1aSopenharmony_ci    uint8_t *decbuffer;
45cabdff1aSopenharmony_ci} ProSumerContext;
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci#define PAIR(high, low) (((uint64_t)(high) << 32) | low)
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_cistatic int decompress(GetByteContext *gb, int size, PutByteContext *pb, const uint32_t *lut)
50cabdff1aSopenharmony_ci{
51cabdff1aSopenharmony_ci    int pos, idx, cnt, fill;
52cabdff1aSopenharmony_ci    uint32_t a, b, c;
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ci    bytestream2_skip(gb, 32);
55cabdff1aSopenharmony_ci    cnt = 4;
56cabdff1aSopenharmony_ci    a = bytestream2_get_le32(gb);
57cabdff1aSopenharmony_ci    idx = a >> 20;
58cabdff1aSopenharmony_ci    b = lut[2 * idx];
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_ci    while (1) {
61cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left_p(pb) <= 0 || bytestream2_get_eof(pb))
62cabdff1aSopenharmony_ci            return 0;
63cabdff1aSopenharmony_ci        if ((b & 0xFF00u) != 0x8000u || (b & 0xFFu)) {
64cabdff1aSopenharmony_ci            if ((b & 0xFF00u) != 0x8000u) {
65cabdff1aSopenharmony_ci                bytestream2_put_le16(pb, b);
66cabdff1aSopenharmony_ci            } else {
67cabdff1aSopenharmony_ci                idx = 0;
68cabdff1aSopenharmony_ci                for (int i = 0; i < (b & 0xFFu); i++)
69cabdff1aSopenharmony_ci                    bytestream2_put_le32(pb, 0);
70cabdff1aSopenharmony_ci            }
71cabdff1aSopenharmony_ci            c = b >> 16;
72cabdff1aSopenharmony_ci            if (c & 0xFF00u) {
73cabdff1aSopenharmony_ci                fill = lut[2 * idx + 1];
74cabdff1aSopenharmony_ci                if ((c & 0xF000u) == 0x1000) {
75cabdff1aSopenharmony_ci                    bytestream2_put_le16(pb, fill);
76cabdff1aSopenharmony_ci                } else {
77cabdff1aSopenharmony_ci                    bytestream2_put_le32(pb, fill);
78cabdff1aSopenharmony_ci                }
79cabdff1aSopenharmony_ci                c = (c >> 8) & 0x0Fu;
80cabdff1aSopenharmony_ci            }
81cabdff1aSopenharmony_ci            while (c) {
82cabdff1aSopenharmony_ci                a <<= 4;
83cabdff1aSopenharmony_ci                cnt--;
84cabdff1aSopenharmony_ci                if (!cnt) {
85cabdff1aSopenharmony_ci                    if (bytestream2_get_bytes_left(gb) <= 0) {
86cabdff1aSopenharmony_ci                        if (!a)
87cabdff1aSopenharmony_ci                            return 0;
88cabdff1aSopenharmony_ci                    } else {
89cabdff1aSopenharmony_ci                        pos = bytestream2_tell(gb);
90cabdff1aSopenharmony_ci                        bytestream2_seek(gb, pos ^ 2, SEEK_SET);
91cabdff1aSopenharmony_ci                        AV_WN16(&a, bytestream2_peek_le16(gb));
92cabdff1aSopenharmony_ci                        bytestream2_seek(gb, pos + 2, SEEK_SET);
93cabdff1aSopenharmony_ci                    }
94cabdff1aSopenharmony_ci                    cnt = 4;
95cabdff1aSopenharmony_ci                }
96cabdff1aSopenharmony_ci                c--;
97cabdff1aSopenharmony_ci            }
98cabdff1aSopenharmony_ci            idx = a >> 20;
99cabdff1aSopenharmony_ci            b = lut[2 * idx];
100cabdff1aSopenharmony_ci            if (!b)
101cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
102cabdff1aSopenharmony_ci            continue;
103cabdff1aSopenharmony_ci        }
104cabdff1aSopenharmony_ci        idx = 2;
105cabdff1aSopenharmony_ci        while (idx) {
106cabdff1aSopenharmony_ci            a <<= 4;
107cabdff1aSopenharmony_ci            cnt--;
108cabdff1aSopenharmony_ci            if (cnt) {
109cabdff1aSopenharmony_ci                idx--;
110cabdff1aSopenharmony_ci                continue;
111cabdff1aSopenharmony_ci            }
112cabdff1aSopenharmony_ci            if (bytestream2_get_bytes_left(gb) <= 0) {
113cabdff1aSopenharmony_ci                if (a) {
114cabdff1aSopenharmony_ci                    cnt = 4;
115cabdff1aSopenharmony_ci                    idx--;
116cabdff1aSopenharmony_ci                    continue;
117cabdff1aSopenharmony_ci                }
118cabdff1aSopenharmony_ci                return 0;
119cabdff1aSopenharmony_ci            }
120cabdff1aSopenharmony_ci            pos = bytestream2_tell(gb);
121cabdff1aSopenharmony_ci            bytestream2_seek(gb, pos ^ 2, SEEK_SET);
122cabdff1aSopenharmony_ci            AV_WN16(&a, bytestream2_peek_le16(gb));
123cabdff1aSopenharmony_ci            bytestream2_seek(gb, pos + 2, SEEK_SET);
124cabdff1aSopenharmony_ci            cnt = 4;
125cabdff1aSopenharmony_ci            idx--;
126cabdff1aSopenharmony_ci        }
127cabdff1aSopenharmony_ci        b = PAIR(4, a) >> 16;
128cabdff1aSopenharmony_ci    }
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_ci    return 0;
131cabdff1aSopenharmony_ci}
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_cistatic void vertical_predict(uint32_t *dst, int offset, const uint32_t *src, int stride, int height)
134cabdff1aSopenharmony_ci{
135cabdff1aSopenharmony_ci    dst += offset >> 2;
136cabdff1aSopenharmony_ci
137cabdff1aSopenharmony_ci    for (int i = 0; i < height; i++) {
138cabdff1aSopenharmony_ci        for (int j = 0; j < stride >> 2; j++) {
139cabdff1aSopenharmony_ci            dst[j] = (((src[j] >> 3) + (0x3F3F3F3F & dst[j])) << 3) & 0xFCFCFCFC;
140cabdff1aSopenharmony_ci        }
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci        dst += stride >> 2;
143cabdff1aSopenharmony_ci        src += stride >> 2;
144cabdff1aSopenharmony_ci    }
145cabdff1aSopenharmony_ci}
146cabdff1aSopenharmony_ci
147cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame,
148cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
149cabdff1aSopenharmony_ci{
150cabdff1aSopenharmony_ci    ProSumerContext *s = avctx->priv_data;
151cabdff1aSopenharmony_ci    int ret;
152cabdff1aSopenharmony_ci
153cabdff1aSopenharmony_ci    if (avpkt->size <= 32)
154cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
155cabdff1aSopenharmony_ci
156cabdff1aSopenharmony_ci    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
157cabdff1aSopenharmony_ci    bytestream2_init_writer(&s->pb, s->decbuffer, s->size);
158cabdff1aSopenharmony_ci    ret = decompress(&s->gb, AV_RL32(avpkt->data + 28) >> 1, &s->pb, s->lut);
159cabdff1aSopenharmony_ci    if (ret < 0)
160cabdff1aSopenharmony_ci        return ret;
161cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left_p(&s->pb) > s->size * (int64_t)avctx->discard_damaged_percentage / 100)
162cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
163cabdff1aSopenharmony_ci
164cabdff1aSopenharmony_ci    av_assert0(s->size >= bytestream2_get_bytes_left_p(&s->pb));
165cabdff1aSopenharmony_ci    memset(s->decbuffer + bytestream2_tell_p(&s->pb), 0, bytestream2_get_bytes_left_p(&s->pb));
166cabdff1aSopenharmony_ci
167cabdff1aSopenharmony_ci    vertical_predict((uint32_t *)s->decbuffer, 0, (uint32_t *)s->initial_line, s->stride, 1);
168cabdff1aSopenharmony_ci    vertical_predict((uint32_t *)s->decbuffer, s->stride, (uint32_t *)s->decbuffer, s->stride, avctx->height - 1);
169cabdff1aSopenharmony_ci
170cabdff1aSopenharmony_ci    ret = ff_get_buffer(avctx, frame, 0);
171cabdff1aSopenharmony_ci    if (ret < 0)
172cabdff1aSopenharmony_ci        return ret;
173cabdff1aSopenharmony_ci
174cabdff1aSopenharmony_ci    for (int i = avctx->height - 1; i >= 0 ; i--) {
175cabdff1aSopenharmony_ci        uint8_t *y = &frame->data[0][i * frame->linesize[0]];
176cabdff1aSopenharmony_ci        uint8_t *u = &frame->data[1][i * frame->linesize[1]];
177cabdff1aSopenharmony_ci        uint8_t *v = &frame->data[2][i * frame->linesize[2]];
178cabdff1aSopenharmony_ci        const uint8_t *src = s->decbuffer + (avctx->height - 1 - i) * s->stride;
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci        for (int j = 0; j < avctx->width; j += 8) {
181cabdff1aSopenharmony_ci            *(u++) = *src++;
182cabdff1aSopenharmony_ci            *(y++) = *src++;
183cabdff1aSopenharmony_ci            *(v++) = *src++;
184cabdff1aSopenharmony_ci            *(y++) = *src++;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci            *(u++) = *src++;
187cabdff1aSopenharmony_ci            *(y++) = *src++;
188cabdff1aSopenharmony_ci            *(v++) = *src++;
189cabdff1aSopenharmony_ci            *(y++) = *src++;
190cabdff1aSopenharmony_ci
191cabdff1aSopenharmony_ci            *(y++) = *src++;
192cabdff1aSopenharmony_ci            *(y++) = *src++;
193cabdff1aSopenharmony_ci            *(y++) = *src++;
194cabdff1aSopenharmony_ci            *(y++) = *src++;
195cabdff1aSopenharmony_ci        }
196cabdff1aSopenharmony_ci    }
197cabdff1aSopenharmony_ci
198cabdff1aSopenharmony_ci    frame->pict_type = AV_PICTURE_TYPE_I;
199cabdff1aSopenharmony_ci    frame->key_frame = 1;
200cabdff1aSopenharmony_ci    *got_frame = 1;
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_ci    return avpkt->size;
203cabdff1aSopenharmony_ci}
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci#define TB(i) (1 + ((i) > 10) + ((i) > 49))
206cabdff1aSopenharmony_cistatic const uint16_t table[] = {
207cabdff1aSopenharmony_ci    0x0000, 0x100, 0x0101, 0x200, 0x0202, 0x300, 0xFFFF, 0x400, 0xFEFE, 0x500,
208cabdff1aSopenharmony_ci    0x0001, 0x700, 0x0100, 0x800, 0x00FF, 0x900, 0xFF00, 0xA00, 0x8001, 0x600,
209cabdff1aSopenharmony_ci    0x8002, 0xB00, 0xFCFC, 0x010, 0x0404, 0x030, 0x0002, 0xD30, 0xFEFC, 0x020,
210cabdff1aSopenharmony_ci    0xFCFE, 0x040, 0xFEFF, 0xD20, 0x0808, 0x060, 0xFFFE, 0x050, 0x0402, 0xC00,
211cabdff1aSopenharmony_ci    0x0204, 0xC10, 0xF8F8, 0xC30, 0x0201, 0xC40, 0x0102, 0xC60, 0x0804, 0xF30,
212cabdff1aSopenharmony_ci    0x0408, 0xE00, 0xF8FC, 0xE10, 0xFCF8, 0xC70, 0x00FE, 0xD00, 0xFE00, 0xD40,
213cabdff1aSopenharmony_ci    0xFF01, 0xD50, 0x01FF, 0xD60, 0x0200, 0xD70, 0xFCFF, 0xE20, 0x0104, 0xE30,
214cabdff1aSopenharmony_ci    0xF0F0, 0xE50, 0x0401, 0xE70, 0x02FE, 0xF00, 0xFE02, 0xF10, 0xFE01, 0xF20,
215cabdff1aSopenharmony_ci    0x01FE, 0xF40, 0xFF02, 0xF50, 0x02FF, 0xF60, 0x8003, 0xC20, 0x8004, 0x070,
216cabdff1aSopenharmony_ci    0x8005, 0xD10, 0x8006, 0xC50, 0x8007, 0xE60, 0x8008, 0xE40, 0x8009, 0xF70,
217cabdff1aSopenharmony_ci    0xFC02, 0x080, 0xFE04, 0x081, 0xFC00, 0x082, 0x02FC, 0x083, 0x1010, 0x084,
218cabdff1aSopenharmony_ci    0x00FC, 0x085, 0x0004, 0x086, 0x0400, 0x087, 0xFFFC, 0x088, 0x1008, 0x089,
219cabdff1aSopenharmony_ci    0x0810, 0x08A, 0x0802, 0x08B, 0x0208, 0x08C, 0xFEF8, 0x08D, 0xFC01, 0x08E,
220cabdff1aSopenharmony_ci    0x04FF, 0x08F, 0xF8FE, 0x090, 0xFC04, 0x091, 0x04FC, 0x092, 0xFF04, 0x093,
221cabdff1aSopenharmony_ci    0x01FC, 0x094, 0xF0F8, 0x095, 0xF8F0, 0x096, 0x04FE, 0x097, 0xF0FC, 0x098,
222cabdff1aSopenharmony_ci    0x0008, 0x099, 0x08FE, 0x09A, 0x01F8, 0x09B, 0x0800, 0x09C, 0x08FC, 0x09D,
223cabdff1aSopenharmony_ci    0xFE08, 0x09E, 0xFC08, 0x09F, 0xF800, 0x0A0, 0x0108, 0x0A1, 0xF802, 0x0A2,
224cabdff1aSopenharmony_ci    0x0801, 0x0A3, 0x00F8, 0x0A4, 0xF804, 0x0A5, 0xF8FF, 0x0A6, 0xFFF8, 0x0A7,
225cabdff1aSopenharmony_ci    0x04F8, 0x0A8, 0x02F8, 0x0A9, 0x1004, 0x0AA, 0x08F8, 0x0AB, 0xF808, 0x0AC,
226cabdff1aSopenharmony_ci    0x0410, 0x0AD, 0xFF08, 0x0AE, 0x08FF, 0x0AF, 0xFCF0, 0x0B0, 0xF801, 0x0B1,
227cabdff1aSopenharmony_ci    0xE0F0, 0x0B2, 0xF3F3, 0x0B3, 0xF0E0, 0x0B4, 0xFAFA, 0x0B5, 0xF7F7, 0x0B6,
228cabdff1aSopenharmony_ci    0xFEF0, 0x0B7, 0xF0FE, 0x0B8, 0xE9E9, 0x0B9, 0xF9F9, 0x0BA, 0x2020, 0x0BB,
229cabdff1aSopenharmony_ci    0xE0E0, 0x0BC, 0x02F0, 0x0BD, 0x04F0, 0x0BE, 0x2010, 0x0BF, 0xECEC, 0x0C0,
230cabdff1aSopenharmony_ci    0xEFEF, 0x0C1, 0x1020, 0x0C2, 0xF5F5, 0x0C3, 0xF4F4, 0x0C4, 0xEDED, 0x0C5,
231cabdff1aSopenharmony_ci    0xEAEA, 0x0C6, 0xFBFB, 0x0C7, 0x1002, 0x0C8, 0xF2F2, 0x0C9, 0xF6F6, 0x0CA,
232cabdff1aSopenharmony_ci    0xF1F1, 0x0CB, 0xFDFD, 0x0CC, 0x0210, 0x0CD, 0x10FF, 0x0CE, 0xFDFE, 0x0CF,
233cabdff1aSopenharmony_ci    0x10F8, 0x0D0, 0x1000, 0x0D1, 0xF001, 0x0D2, 0x1001, 0x0D3, 0x0010, 0x0D4,
234cabdff1aSopenharmony_ci    0x10FE, 0x0D5, 0xEBEB, 0x0D6, 0xFE10, 0x0D7, 0x0110, 0x0D8, 0xF000, 0x0D9,
235cabdff1aSopenharmony_ci    0x08F0, 0x0DA, 0x01F0, 0x0DB, 0x0303, 0x0DC, 0x00F0, 0x0DD, 0xF002, 0x0DE,
236cabdff1aSopenharmony_ci    0x10FC, 0x0DF, 0xFC10, 0x0E0, 0xF0FF, 0x0E1, 0xEEEE, 0x0E2, 0xF004, 0x0E3,
237cabdff1aSopenharmony_ci    0xFFF0, 0x0E4, 0xF7F8, 0x0E5, 0xF3F2, 0x0E6, 0xF9FA, 0x0E7, 0x0820, 0x0E8,
238cabdff1aSopenharmony_ci    0x0302, 0x0E9, 0xE0F8, 0x0EA, 0x0505, 0x0EB, 0x2008, 0x0EC, 0xE8E8, 0x0ED,
239cabdff1aSopenharmony_ci    0x0403, 0x0EE, 0xFBFC, 0x0EF, 0xFCFD, 0x0F0, 0xFBFA, 0x0F1, 0x0203, 0x0F2,
240cabdff1aSopenharmony_ci    0xFCFB, 0x0F3, 0x0304, 0x0F4, 0xF810, 0x0F5, 0xFF10, 0x0F6, 0xF008, 0x0F7,
241cabdff1aSopenharmony_ci    0xFEFD, 0x0F8, 0xF7F6, 0x0F9, 0xF2F1, 0x0FA, 0xF3F4, 0x0FB, 0xEDEC, 0x0FC,
242cabdff1aSopenharmony_ci    0xF4F1, 0x0FD, 0xF5F6, 0x0FE, 0xF0F1, 0x0FF, 0xF9F8, 0xC80, 0x10F0, 0xC81,
243cabdff1aSopenharmony_ci    0xF2F3, 0xC82, 0xF7F9, 0xC83, 0xF6F5, 0xC84, 0xF0EF, 0xC85, 0xF4F5, 0xC86,
244cabdff1aSopenharmony_ci    0xF6F7, 0xC87, 0xFAF9, 0xC88, 0x0405, 0xC89, 0xF8F9, 0xC8A, 0xFAFB, 0xC8B,
245cabdff1aSopenharmony_ci    0xF1F0, 0xC8C, 0xF4F3, 0xC8D, 0xF1F2, 0xC8E, 0xF8E0, 0xC8F, 0xF8F7, 0xC90,
246cabdff1aSopenharmony_ci    0xFDFC, 0xC91, 0xF8FA, 0xC92, 0xFAF6, 0xC93, 0xEEEF, 0xC94, 0xF5F7, 0xC95,
247cabdff1aSopenharmony_ci    0xFDFB, 0xC96, 0xF4F6, 0xC97, 0xFCFA, 0xC98, 0xECED, 0xC99, 0xF0F3, 0xC9A,
248cabdff1aSopenharmony_ci    0xF3F1, 0xC9B, 0xECEB, 0xC9C, 0xEDEE, 0xC9D, 0xF9F7, 0xC9E, 0x0420, 0xC9F,
249cabdff1aSopenharmony_ci    0xEBEA, 0xCA0, 0xF0F4, 0xCA1, 0xF3F5, 0xCA2, 0xFAF7, 0xCA3, 0x0301, 0xCA4,
250cabdff1aSopenharmony_ci    0xF3F7, 0xCA5, 0xF7F3, 0xCA6, 0xEFF0, 0xCA7, 0xF9F6, 0xCA8, 0xEFEE, 0xCA9,
251cabdff1aSopenharmony_ci    0xF4F7, 0xCAA, 0x0504, 0xCAB, 0xF5F4, 0xCAC, 0xF1F3, 0xCAD, 0xEBEE, 0xCAE,
252cabdff1aSopenharmony_ci    0xF2F5, 0xCAF, 0xF3EF, 0xCB0, 0xF5F1, 0xCB1, 0xF9F3, 0xCB2, 0xEDF0, 0xCB3,
253cabdff1aSopenharmony_ci    0xEEF1, 0xCB4, 0xF6F9, 0xCB5, 0xF8FB, 0xCB6, 0xF010, 0xCB7, 0xF2F6, 0xCB8,
254cabdff1aSopenharmony_ci    0xF4ED, 0xCB9, 0xF7FB, 0xCBA, 0xF8F3, 0xCBB, 0xEDEB, 0xCBC, 0xF0F2, 0xCBD,
255cabdff1aSopenharmony_ci    0xF2F9, 0xCBE, 0xF8F1, 0xCBF, 0xFAFC, 0xCC0, 0xFBF8, 0xCC1, 0xF6F0, 0xCC2,
256cabdff1aSopenharmony_ci    0xFAF8, 0xCC3, 0x0103, 0xCC4, 0xF3F6, 0xCC5, 0xF4F9, 0xCC6, 0xF7F2, 0xCC7,
257cabdff1aSopenharmony_ci    0x2004, 0xCC8, 0xF2F0, 0xCC9, 0xF4F2, 0xCCA, 0xEEED, 0xCCB, 0xFCE0, 0xCCC,
258cabdff1aSopenharmony_ci    0xEAE9, 0xCCD, 0xEAEB, 0xCCE, 0xF6F4, 0xCCF, 0xFFFD, 0xCD0, 0xE9EA, 0xCD1,
259cabdff1aSopenharmony_ci    0xF1F4, 0xCD2, 0xF6EF, 0xCD3, 0xF6F8, 0xCD4, 0xF8F6, 0xCD5, 0xEFF2, 0xCD6,
260cabdff1aSopenharmony_ci    0xEFF1, 0xCD7, 0xF7F1, 0xCD8, 0xFBFD, 0xCD9, 0xFEF6, 0xCDA, 0xFFF7, 0xCDB,
261cabdff1aSopenharmony_ci    0x0605, 0xCDC, 0xF0F5, 0xCDD, 0xF0FA, 0xCDE, 0xF1F9, 0xCDF, 0xF2FC, 0xCE0,
262cabdff1aSopenharmony_ci    0xF7EE, 0xCE1, 0xF7F5, 0xCE2, 0xF9FC, 0xCE3, 0xFAF5, 0xCE4, 0xFBF1, 0xCE5,
263cabdff1aSopenharmony_ci    0xF1EF, 0xCE6, 0xF1FA, 0xCE7, 0xF4F8, 0xCE8, 0xF7F0, 0xCE9, 0xF7F4, 0xCEA,
264cabdff1aSopenharmony_ci    0xF7FC, 0xCEB, 0xF9FB, 0xCEC, 0xFAF1, 0xCED, 0xFBF9, 0xCEE, 0xFDFF, 0xCEF,
265cabdff1aSopenharmony_ci    0xE0FC, 0xCF0, 0xEBEC, 0xCF1, 0xEDEF, 0xCF2, 0xEFED, 0xCF3, 0xF1F6, 0xCF4,
266cabdff1aSopenharmony_ci    0xF2F7, 0xCF5, 0xF3EE, 0xCF6, 0xF3F8, 0xCF7, 0xF5F2, 0xCF8, 0xF8F2, 0xCF9,
267cabdff1aSopenharmony_ci    0xF9F1, 0xCFA, 0xF9F2, 0xCFB, 0xFBEF, 0xCFC, 0x00FD, 0xCFD, 0xECEE, 0xCFE,
268cabdff1aSopenharmony_ci    0xF2EF, 0xCFF, 0xF2F8, 0xD80, 0xF5F0, 0xD81, 0xF6F2, 0xD82, 0xFCF7, 0xD83,
269cabdff1aSopenharmony_ci    0xFCF9, 0xD84, 0x0506, 0xD85, 0xEEEC, 0xD86, 0xF0F6, 0xD87, 0xF2F4, 0xD88,
270cabdff1aSopenharmony_ci    0xF6F1, 0xD89, 0xF8F5, 0xD8A, 0xF9F4, 0xD8B, 0xFBF7, 0xD8C, 0x0503, 0xD8D,
271cabdff1aSopenharmony_ci    0xEFEC, 0xD8E, 0xF3F0, 0xD8F, 0xF4F0, 0xD90, 0xF5F3, 0xD91, 0xF6F3, 0xD92,
272cabdff1aSopenharmony_ci    0xF7FA, 0xD93, 0x800A, 0xD94, 0x800B, 0xD95, 0x800C, 0xD96, 0x800D, 0xD97,
273cabdff1aSopenharmony_ci    0x800E, 0xD98, 0x800F, 0xD99, 0x8010, 0xD9A, 0x8011, 0xD9B, 0x8012, 0xD9C,
274cabdff1aSopenharmony_ci    0x8013, 0xD9D, 0x8014, 0xD9E, 0x8015, 0xD9F, 0x8016, 0xDA0, 0x8017, 0xDA1,
275cabdff1aSopenharmony_ci    0x8018, 0xDA2, 0x8019, 0xDA3, 0x801A, 0xDA4, 0x801B, 0xDA5, 0x801C, 0xDA6,
276cabdff1aSopenharmony_ci    0x801D, 0xDA7, 0x801E, 0xDA8, 0x801F, 0xDA9, 0x8020, 0xDAA, 0x8021, 0xDAB,
277cabdff1aSopenharmony_ci    0x8022, 0xDAC, 0x8023, 0xDAD, 0x8024, 0xDAE, 0x8025, 0xDAF, 0x8026, 0xDB0,
278cabdff1aSopenharmony_ci    0x8027, 0xDB1, 0x8028, 0xDB2, 0x8029, 0xDB3, 0x802A, 0xDB4, 0x802B, 0xDB5,
279cabdff1aSopenharmony_ci    0x802C, 0xDB6, 0x802D, 0xDB7, 0x802E, 0xDB8, 0x802F, 0xDB9, 0x80FF, 0xDBA,
280cabdff1aSopenharmony_ci};
281cabdff1aSopenharmony_ci
282cabdff1aSopenharmony_cistatic void fill_elements(uint32_t idx, uint32_t shift, uint32_t *e0, uint32_t *e1)
283cabdff1aSopenharmony_ci{
284cabdff1aSopenharmony_ci    uint32_t b, h = idx << (32 - shift);
285cabdff1aSopenharmony_ci
286cabdff1aSopenharmony_ci    for (int j = 0; j < 2; j++) {
287cabdff1aSopenharmony_ci        for (int i = 0; i < 43; i++) {
288cabdff1aSopenharmony_ci            b = 4 * TB(i);
289cabdff1aSopenharmony_ci            if (shift >= b && ((h & (0xFFF00000u << (12 - b))) >> 20) == table[2 * i + 1]) {
290cabdff1aSopenharmony_ci                if (table[2 * i] >> 8 == 0x80u) {
291cabdff1aSopenharmony_ci                    return;
292cabdff1aSopenharmony_ci                } else {
293cabdff1aSopenharmony_ci                    *e0 = (*e0 & 0xFFFFFFu) | (((12 + b - shift)  | (0x40u<<j)) << 22);
294cabdff1aSopenharmony_ci                    if (j == 0) {
295cabdff1aSopenharmony_ci                        *e1 = table[2 * i];
296cabdff1aSopenharmony_ci                        shift -= b;
297cabdff1aSopenharmony_ci                        h <<= b;
298cabdff1aSopenharmony_ci                    } else {
299cabdff1aSopenharmony_ci                        *e1 |= (unsigned)table[2 * i] << 16;
300cabdff1aSopenharmony_ci                    }
301cabdff1aSopenharmony_ci                    break;
302cabdff1aSopenharmony_ci                }
303cabdff1aSopenharmony_ci            }
304cabdff1aSopenharmony_ci        }
305cabdff1aSopenharmony_ci    }
306cabdff1aSopenharmony_ci}
307cabdff1aSopenharmony_ci
308cabdff1aSopenharmony_cistatic void fill_lut(uint32_t *lut)
309cabdff1aSopenharmony_ci{
310cabdff1aSopenharmony_ci    for (int i = 1; i < FF_ARRAY_ELEMS(table); i += 2) {
311cabdff1aSopenharmony_ci        uint32_t a = table[i];
312cabdff1aSopenharmony_ci        uint32_t b = TB(i>>1);
313cabdff1aSopenharmony_ci        uint32_t c, d;
314cabdff1aSopenharmony_ci
315cabdff1aSopenharmony_ci        c = (b << 16) | table[i-1];
316cabdff1aSopenharmony_ci        d = 4 * (3 - b);
317cabdff1aSopenharmony_ci        if (d <= 0) {
318cabdff1aSopenharmony_ci            lut[2 * a] = c;
319cabdff1aSopenharmony_ci            lut[2 * a + 1] = 0;
320cabdff1aSopenharmony_ci        } else {
321cabdff1aSopenharmony_ci            for (int j = 0; j < 1 << d; j++) {
322cabdff1aSopenharmony_ci                uint32_t f = 0xFFFFFFFFu;
323cabdff1aSopenharmony_ci                c &= 0xFFFFFFu;
324cabdff1aSopenharmony_ci                if ((c & 0xFF00u) != 0x8000u)
325cabdff1aSopenharmony_ci                    fill_elements(j, d, &c, &f);
326cabdff1aSopenharmony_ci                lut[2 * a + 2 * j] = c;
327cabdff1aSopenharmony_ci                lut[2 * a + 2 * j + 1] = f;
328cabdff1aSopenharmony_ci            }
329cabdff1aSopenharmony_ci        }
330cabdff1aSopenharmony_ci    }
331cabdff1aSopenharmony_ci
332cabdff1aSopenharmony_ci    for (int i = 0; i < 32; i += 2) {
333cabdff1aSopenharmony_ci        lut[i  ] = 0x68000;
334cabdff1aSopenharmony_ci        lut[i+1] = 0;
335cabdff1aSopenharmony_ci    }
336cabdff1aSopenharmony_ci}
337cabdff1aSopenharmony_ci
338cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
339cabdff1aSopenharmony_ci{
340cabdff1aSopenharmony_ci    ProSumerContext *s = avctx->priv_data;
341cabdff1aSopenharmony_ci
342cabdff1aSopenharmony_ci    s->stride = 3LL * FFALIGN(avctx->width, 8) >> 1;
343cabdff1aSopenharmony_ci    s->size = avctx->height * s->stride;
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_ci    avctx->pix_fmt = AV_PIX_FMT_YUV411P;
346cabdff1aSopenharmony_ci
347cabdff1aSopenharmony_ci    s->initial_line = av_malloc(s->stride);
348cabdff1aSopenharmony_ci    s->decbuffer = av_malloc(s->size);
349cabdff1aSopenharmony_ci    if (!s->initial_line || !s->decbuffer)
350cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
351cabdff1aSopenharmony_ci    memset(s->initial_line, 0x80u, s->stride);
352cabdff1aSopenharmony_ci
353cabdff1aSopenharmony_ci    fill_lut(s->lut);
354cabdff1aSopenharmony_ci
355cabdff1aSopenharmony_ci    return 0;
356cabdff1aSopenharmony_ci}
357cabdff1aSopenharmony_ci
358cabdff1aSopenharmony_cistatic av_cold int decode_close(AVCodecContext *avctx)
359cabdff1aSopenharmony_ci{
360cabdff1aSopenharmony_ci    ProSumerContext *s = avctx->priv_data;
361cabdff1aSopenharmony_ci
362cabdff1aSopenharmony_ci    av_freep(&s->initial_line);
363cabdff1aSopenharmony_ci    av_freep(&s->decbuffer);
364cabdff1aSopenharmony_ci
365cabdff1aSopenharmony_ci    return 0;
366cabdff1aSopenharmony_ci}
367cabdff1aSopenharmony_ci
368cabdff1aSopenharmony_ciconst FFCodec ff_prosumer_decoder = {
369cabdff1aSopenharmony_ci    .p.name         = "prosumer",
370cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("Brooktree ProSumer Video"),
371cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
372cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_PROSUMER,
373cabdff1aSopenharmony_ci    .priv_data_size = sizeof(ProSumerContext),
374cabdff1aSopenharmony_ci    .init           = decode_init,
375cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
376cabdff1aSopenharmony_ci    .close          = decode_close,
377cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1,
378cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
379cabdff1aSopenharmony_ci                      FF_CODEC_CAP_INIT_CLEANUP,
380cabdff1aSopenharmony_ci};
381