2 * Brooktree ProSumer Video decoder
3 * Copyright (c) 2018 Paul B Mahol
5 * This file is part of FFmpeg.
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.
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.
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
26 #include "libavutil/imgutils.h"
27 #include "libavutil/internal.h"
28 #include "libavutil/intreadwrite.h"
29 #include "libavutil/mem.h"
32 #include "bytestream.h"
35 typedef struct ProSumerContext {
41 uint32_t lut[0x10000];
42 uint8_t *initial_line;
46 #define PAIR(high, low) (((uint64_t)(high) << 32) | low)
48 static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const uint32_t *lut)
50 int pos, idx, cnt, fill;
53 bytestream2_skip(gb, 32);
55 a = bytestream2_get_le32(gb);
60 if (bytestream2_get_bytes_left_p(pb) <= 0)
62 if (((b & 0xFF00u) != 0x8000u) || (b & 0xFFu)) {
63 if ((b & 0xFF00u) != 0x8000u) {
64 bytestream2_put_le16(pb, b);
65 } else if (b & 0xFFu) {
67 for (int i = 0; i < (b & 0xFFu); i++)
68 bytestream2_put_le32(pb, 0);
72 c = (((c >> 8) & 0xFFu) | (c & 0xFF00)) & 0xF00F;
73 fill = lut[2 * idx + 1];
74 if ((c & 0xFF00u) == 0x1000) {
75 bytestream2_put_le16(pb, fill);
78 bytestream2_put_le32(pb, fill);
86 if (bytestream2_get_bytes_left(gb) <= 0) {
91 pos = bytestream2_tell(gb) ^ 2;
92 bytestream2_seek(gb, pos, SEEK_SET);
93 AV_WN16(&a, bytestream2_peek_le16(gb));
95 bytestream2_seek(gb, pos, SEEK_SET);
96 bytestream2_skip(gb, 2);
114 if (bytestream2_get_bytes_left(gb) <= 0) {
122 pos = bytestream2_tell(gb) ^ 2;
123 bytestream2_seek(gb, pos, SEEK_SET);
124 AV_WN16(&a, bytestream2_peek_le16(gb));
126 bytestream2_seek(gb, pos, SEEK_SET);
127 bytestream2_skip(gb, 2);
131 b = PAIR(4, a) >> 16;
137 static void vertical_predict(uint32_t *dst, int offset, const uint32_t *src, int stride, int height)
141 for (int i = 0; i < height; i++) {
142 for (int j = 0; j < stride >> 2; j++) {
143 dst[j] = (((src[j] >> 3) + (0x3F3F3F3F & dst[j])) << 3) & 0xFCFCFCFC;
151 static int decode_frame(AVCodecContext *avctx, void *data,
152 int *got_frame, AVPacket *avpkt)
154 ProSumerContext *s = avctx->priv_data;
155 AVFrame * const frame = data;
158 if (avpkt->size <= 32)
159 return AVERROR_INVALIDDATA;
161 memset(s->decbuffer, 0, s->size);
162 bytestream2_init(&s->gb, avpkt->data, avpkt->size);
163 bytestream2_init_writer(&s->pb, s->decbuffer, s->size);
165 decompress(&s->gb, AV_RL32(avpkt->data + 28) >> 1, &s->pb, s->lut);
166 vertical_predict((uint32_t *)s->decbuffer, 0, (uint32_t *)s->initial_line, s->stride, 1);
167 vertical_predict((uint32_t *)s->decbuffer, s->stride, (uint32_t *)s->decbuffer, s->stride, avctx->height - 1);
169 ret = ff_get_buffer(avctx, frame, 0);
173 for (int i = avctx->height - 1; i >= 0 ; i--) {
174 uint8_t *y = &frame->data[0][i * frame->linesize[0]];
175 uint8_t *u = &frame->data[1][i * frame->linesize[1]];
176 uint8_t *v = &frame->data[2][i * frame->linesize[2]];
177 const uint8_t *src = s->decbuffer + (avctx->height - 1 - i) * s->stride;
179 for (int j = 0; j < avctx->width; j += 8) {
197 frame->pict_type = AV_PICTURE_TYPE_I;
198 frame->key_frame = 1;
204 #define TB(i) (1 + ((i) > 10) + ((i) > 49))
205 static const uint16_t table[] = {
206 0x0000, 0x100, 0x0101, 0x200, 0x0202, 0x300, 0xFFFF, 0x400, 0xFEFE, 0x500,
207 0x0001, 0x700, 0x0100, 0x800, 0x00FF, 0x900, 0xFF00, 0xA00, 0x8001, 0x600,
208 0x8002, 0xB00, 0xFCFC, 0x010, 0x0404, 0x030, 0x0002, 0xD30, 0xFEFC, 0x020,
209 0xFCFE, 0x040, 0xFEFF, 0xD20, 0x0808, 0x060, 0xFFFE, 0x050, 0x0402, 0xC00,
210 0x0204, 0xC10, 0xF8F8, 0xC30, 0x0201, 0xC40, 0x0102, 0xC60, 0x0804, 0xF30,
211 0x0408, 0xE00, 0xF8FC, 0xE10, 0xFCF8, 0xC70, 0x00FE, 0xD00, 0xFE00, 0xD40,
212 0xFF01, 0xD50, 0x01FF, 0xD60, 0x0200, 0xD70, 0xFCFF, 0xE20, 0x0104, 0xE30,
213 0xF0F0, 0xE50, 0x0401, 0xE70, 0x02FE, 0xF00, 0xFE02, 0xF10, 0xFE01, 0xF20,
214 0x01FE, 0xF40, 0xFF02, 0xF50, 0x02FF, 0xF60, 0x8003, 0xC20, 0x8004, 0x070,
215 0x8005, 0xD10, 0x8006, 0xC50, 0x8007, 0xE60, 0x8008, 0xE40, 0x8009, 0xF70,
216 0xFC02, 0x080, 0xFE04, 0x081, 0xFC00, 0x082, 0x02FC, 0x083, 0x1010, 0x084,
217 0x00FC, 0x085, 0x0004, 0x086, 0x0400, 0x087, 0xFFFC, 0x088, 0x1008, 0x089,
218 0x0810, 0x08A, 0x0802, 0x08B, 0x0208, 0x08C, 0xFEF8, 0x08D, 0xFC01, 0x08E,
219 0x04FF, 0x08F, 0xF8FE, 0x090, 0xFC04, 0x091, 0x04FC, 0x092, 0xFF04, 0x093,
220 0x01FC, 0x094, 0xF0F8, 0x095, 0xF8F0, 0x096, 0x04FE, 0x097, 0xF0FC, 0x098,
221 0x0008, 0x099, 0x08FE, 0x09A, 0x01F8, 0x09B, 0x0800, 0x09C, 0x08FC, 0x09D,
222 0xFE08, 0x09E, 0xFC08, 0x09F, 0xF800, 0x0A0, 0x0108, 0x0A1, 0xF802, 0x0A2,
223 0x0801, 0x0A3, 0x00F8, 0x0A4, 0xF804, 0x0A5, 0xF8FF, 0x0A6, 0xFFF8, 0x0A7,
224 0x04F8, 0x0A8, 0x02F8, 0x0A9, 0x1004, 0x0AA, 0x08F8, 0x0AB, 0xF808, 0x0AC,
225 0x0410, 0x0AD, 0xFF08, 0x0AE, 0x08FF, 0x0AF, 0xFCF0, 0x0B0, 0xF801, 0x0B1,
226 0xE0F0, 0x0B2, 0xF3F3, 0x0B3, 0xF0E0, 0x0B4, 0xFAFA, 0x0B5, 0xF7F7, 0x0B6,
227 0xFEF0, 0x0B7, 0xF0FE, 0x0B8, 0xE9E9, 0x0B9, 0xF9F9, 0x0BA, 0x2020, 0x0BB,
228 0xE0E0, 0x0BC, 0x02F0, 0x0BD, 0x04F0, 0x0BE, 0x2010, 0x0BF, 0xECEC, 0x0C0,
229 0xEFEF, 0x0C1, 0x1020, 0x0C2, 0xF5F5, 0x0C3, 0xF4F4, 0x0C4, 0xEDED, 0x0C5,
230 0xEAEA, 0x0C6, 0xFBFB, 0x0C7, 0x1002, 0x0C8, 0xF2F2, 0x0C9, 0xF6F6, 0x0CA,
231 0xF1F1, 0x0CB, 0xFDFD, 0x0CC, 0x0210, 0x0CD, 0x10FF, 0x0CE, 0xFDFE, 0x0CF,
232 0x10F8, 0x0D0, 0x1000, 0x0D1, 0xF001, 0x0D2, 0x1001, 0x0D3, 0x0010, 0x0D4,
233 0x10FE, 0x0D5, 0xEBEB, 0x0D6, 0xFE10, 0x0D7, 0x0110, 0x0D8, 0xF000, 0x0D9,
234 0x08F0, 0x0DA, 0x01F0, 0x0DB, 0x0303, 0x0DC, 0x00F0, 0x0DD, 0xF002, 0x0DE,
235 0x10FC, 0x0DF, 0xFC10, 0x0E0, 0xF0FF, 0x0E1, 0xEEEE, 0x0E2, 0xF004, 0x0E3,
236 0xFFF0, 0x0E4, 0xF7F8, 0x0E5, 0xF3F2, 0x0E6, 0xF9FA, 0x0E7, 0x0820, 0x0E8,
237 0x0302, 0x0E9, 0xE0F8, 0x0EA, 0x0505, 0x0EB, 0x2008, 0x0EC, 0xE8E8, 0x0ED,
238 0x0403, 0x0EE, 0xFBFC, 0x0EF, 0xFCFD, 0x0F0, 0xFBFA, 0x0F1, 0x0203, 0x0F2,
239 0xFCFB, 0x0F3, 0x0304, 0x0F4, 0xF810, 0x0F5, 0xFF10, 0x0F6, 0xF008, 0x0F7,
240 0xFEFD, 0x0F8, 0xF7F6, 0x0F9, 0xF2F1, 0x0FA, 0xF3F4, 0x0FB, 0xEDEC, 0x0FC,
241 0xF4F1, 0x0FD, 0xF5F6, 0x0FE, 0xF0F1, 0x0FF, 0xF9F8, 0xC80, 0x10F0, 0xC81,
242 0xF2F3, 0xC82, 0xF7F9, 0xC83, 0xF6F5, 0xC84, 0xF0EF, 0xC85, 0xF4F5, 0xC86,
243 0xF6F7, 0xC87, 0xFAF9, 0xC88, 0x0405, 0xC89, 0xF8F9, 0xC8A, 0xFAFB, 0xC8B,
244 0xF1F0, 0xC8C, 0xF4F3, 0xC8D, 0xF1F2, 0xC8E, 0xF8E0, 0xC8F, 0xF8F7, 0xC90,
245 0xFDFC, 0xC91, 0xF8FA, 0xC92, 0xFAF6, 0xC93, 0xEEEF, 0xC94, 0xF5F7, 0xC95,
246 0xFDFB, 0xC96, 0xF4F6, 0xC97, 0xFCFA, 0xC98, 0xECED, 0xC99, 0xF0F3, 0xC9A,
247 0xF3F1, 0xC9B, 0xECEB, 0xC9C, 0xEDEE, 0xC9D, 0xF9F7, 0xC9E, 0x0420, 0xC9F,
248 0xEBEA, 0xCA0, 0xF0F4, 0xCA1, 0xF3F5, 0xCA2, 0xFAF7, 0xCA3, 0x0301, 0xCA4,
249 0xF3F7, 0xCA5, 0xF7F3, 0xCA6, 0xEFF0, 0xCA7, 0xF9F6, 0xCA8, 0xEFEE, 0xCA9,
250 0xF4F7, 0xCAA, 0x0504, 0xCAB, 0xF5F4, 0xCAC, 0xF1F3, 0xCAD, 0xEBEE, 0xCAE,
251 0xF2F5, 0xCAF, 0xF3EF, 0xCB0, 0xF5F1, 0xCB1, 0xF9F3, 0xCB2, 0xEDF0, 0xCB3,
252 0xEEF1, 0xCB4, 0xF6F9, 0xCB5, 0xF8FB, 0xCB6, 0xF010, 0xCB7, 0xF2F6, 0xCB8,
253 0xF4ED, 0xCB9, 0xF7FB, 0xCBA, 0xF8F3, 0xCBB, 0xEDEB, 0xCBC, 0xF0F2, 0xCBD,
254 0xF2F9, 0xCBE, 0xF8F1, 0xCBF, 0xFAFC, 0xCC0, 0xFBF8, 0xCC1, 0xF6F0, 0xCC2,
255 0xFAF8, 0xCC3, 0x0103, 0xCC4, 0xF3F6, 0xCC5, 0xF4F9, 0xCC6, 0xF7F2, 0xCC7,
256 0x2004, 0xCC8, 0xF2F0, 0xCC9, 0xF4F2, 0xCCA, 0xEEED, 0xCCB, 0xFCE0, 0xCCC,
257 0xEAE9, 0xCCD, 0xEAEB, 0xCCE, 0xF6F4, 0xCCF, 0xFFFD, 0xCD0, 0xE9EA, 0xCD1,
258 0xF1F4, 0xCD2, 0xF6EF, 0xCD3, 0xF6F8, 0xCD4, 0xF8F6, 0xCD5, 0xEFF2, 0xCD6,
259 0xEFF1, 0xCD7, 0xF7F1, 0xCD8, 0xFBFD, 0xCD9, 0xFEF6, 0xCDA, 0xFFF7, 0xCDB,
260 0x0605, 0xCDC, 0xF0F5, 0xCDD, 0xF0FA, 0xCDE, 0xF1F9, 0xCDF, 0xF2FC, 0xCE0,
261 0xF7EE, 0xCE1, 0xF7F5, 0xCE2, 0xF9FC, 0xCE3, 0xFAF5, 0xCE4, 0xFBF1, 0xCE5,
262 0xF1EF, 0xCE6, 0xF1FA, 0xCE7, 0xF4F8, 0xCE8, 0xF7F0, 0xCE9, 0xF7F4, 0xCEA,
263 0xF7FC, 0xCEB, 0xF9FB, 0xCEC, 0xFAF1, 0xCED, 0xFBF9, 0xCEE, 0xFDFF, 0xCEF,
264 0xE0FC, 0xCF0, 0xEBEC, 0xCF1, 0xEDEF, 0xCF2, 0xEFED, 0xCF3, 0xF1F6, 0xCF4,
265 0xF2F7, 0xCF5, 0xF3EE, 0xCF6, 0xF3F8, 0xCF7, 0xF5F2, 0xCF8, 0xF8F2, 0xCF9,
266 0xF9F1, 0xCFA, 0xF9F2, 0xCFB, 0xFBEF, 0xCFC, 0x00FD, 0xCFD, 0xECEE, 0xCFE,
267 0xF2EF, 0xCFF, 0xF2F8, 0xD80, 0xF5F0, 0xD81, 0xF6F2, 0xD82, 0xFCF7, 0xD83,
268 0xFCF9, 0xD84, 0x0506, 0xD85, 0xEEEC, 0xD86, 0xF0F6, 0xD87, 0xF2F4, 0xD88,
269 0xF6F1, 0xD89, 0xF8F5, 0xD8A, 0xF9F4, 0xD8B, 0xFBF7, 0xD8C, 0x0503, 0xD8D,
270 0xEFEC, 0xD8E, 0xF3F0, 0xD8F, 0xF4F0, 0xD90, 0xF5F3, 0xD91, 0xF6F3, 0xD92,
271 0xF7FA, 0xD93, 0x800A, 0xD94, 0x800B, 0xD95, 0x800C, 0xD96, 0x800D, 0xD97,
272 0x800E, 0xD98, 0x800F, 0xD99, 0x8010, 0xD9A, 0x8011, 0xD9B, 0x8012, 0xD9C,
273 0x8013, 0xD9D, 0x8014, 0xD9E, 0x8015, 0xD9F, 0x8016, 0xDA0, 0x8017, 0xDA1,
274 0x8018, 0xDA2, 0x8019, 0xDA3, 0x801A, 0xDA4, 0x801B, 0xDA5, 0x801C, 0xDA6,
275 0x801D, 0xDA7, 0x801E, 0xDA8, 0x801F, 0xDA9, 0x8020, 0xDAA, 0x8021, 0xDAB,
276 0x8022, 0xDAC, 0x8023, 0xDAD, 0x8024, 0xDAE, 0x8025, 0xDAF, 0x8026, 0xDB0,
277 0x8027, 0xDB1, 0x8028, 0xDB2, 0x8029, 0xDB3, 0x802A, 0xDB4, 0x802B, 0xDB5,
278 0x802C, 0xDB6, 0x802D, 0xDB7, 0x802E, 0xDB8, 0x802F, 0xDB9, 0x80FF, 0xDBA,
281 static void fill_elements(uint32_t idx, uint32_t shift, uint32_t *e0, uint32_t *e1)
283 uint32_t b, h = idx << (32 - shift);
285 for (int j = 0; j < 2; j++) {
286 for (int i = 0; i < 43; i++) {
288 if (shift >= b && ((h & (0xFFF00000u << (12 - b))) >> 20) == table[2 * i + 1]) {
289 if (table[2 * i] >> 8 == 0x80u) {
292 *e0 = (*e0 & 0xFFFFFFu) | (((12 + b - shift) | (0x40u<<j)) << 22);
298 *e1 |= (unsigned)table[2 * i] << 16;
307 static void fill_lut(uint32_t *lut)
309 for (int i = 1; i < FF_ARRAY_ELEMS(table); i += 2) {
310 uint32_t a = table[i];
311 uint32_t b = TB(i>>1);
314 c = (b << 16) | table[i-1];
320 for (int j = 0; j < 1 << d; j++) {
321 uint32_t f = 0xFFFFFFFFu;
323 if ((c & 0xFF00u) != 0x8000u)
324 fill_elements(j, d, &c, &f);
325 lut[2 * a + 2 * j] = c;
326 lut[2 * a + 2 * j + 1] = f;
331 for (int i = 0; i < 32; i += 2) {
337 static av_cold int decode_init(AVCodecContext *avctx)
339 ProSumerContext *s = avctx->priv_data;
341 s->stride = 3LL * FFALIGN(avctx->width, 8) >> 1;
342 s->size = avctx->height * s->stride;
344 avctx->pix_fmt = AV_PIX_FMT_YUV411P;
346 s->initial_line = av_malloc(s->stride);
347 s->decbuffer = av_malloc(s->size);
348 if (!s->initial_line || !s->decbuffer)
349 return AVERROR(ENOMEM);
350 memset(s->initial_line, 0x80u, s->stride);
357 static av_cold int decode_close(AVCodecContext *avctx)
359 ProSumerContext *s = avctx->priv_data;
361 av_freep(&s->initial_line);
362 av_freep(&s->decbuffer);
367 AVCodec ff_prosumer_decoder = {
369 .long_name = NULL_IF_CONFIG_SMALL("Brooktree ProSumer Video"),
370 .type = AVMEDIA_TYPE_VIDEO,
371 .id = AV_CODEC_ID_PROSUMER,
372 .priv_data_size = sizeof(ProSumerContext),
374 .decode = decode_frame,
375 .close = decode_close,
376 .capabilities = AV_CODEC_CAP_DR1,
377 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
378 FF_CODEC_CAP_INIT_CLEANUP,