GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/prosumer.c Lines: 0 158 0.0 %
Date: 2019-11-22 03:34:36 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/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 "internal.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, void *data,
147
                        int *got_frame, AVPacket *avpkt)
148
{
149
    ProSumerContext *s = avctx->priv_data;
150
    AVFrame * const frame = 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))
206
static 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
282
static 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
308
static 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
338
static 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
358
static 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
368
AVCodec ff_prosumer_decoder = {
369
    .name           = "prosumer",
370
    .long_name      = NULL_IF_CONFIG_SMALL("Brooktree ProSumer Video"),
371
    .type           = AVMEDIA_TYPE_VIDEO,
372
    .id             = AV_CODEC_ID_PROSUMER,
373
    .priv_data_size = sizeof(ProSumerContext),
374
    .init           = decode_init,
375
    .decode         = decode_frame,
376
    .close          = decode_close,
377
    .capabilities   = AV_CODEC_CAP_DR1,
378
    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
379
                      FF_CODEC_CAP_INIT_CLEANUP,
380
};