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