FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/prosumer.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 0 157 0.0%
Functions: 0 7 0.0%
Branches: 0 82 0.0%

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