GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/brenderpix.c Lines: 75 111 67.6 %
Date: 2019-11-18 18:00:01 Branches: 32 56 57.1 %

Line Branch Exec Source
1
/*
2
 * BRender PIX (.pix) image decoder
3
 * Copyright (c) 2012 Aleksi Nurmi
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
/* Tested against samples from I-War / Independence War and Defiance. */
23
24
#include "libavutil/imgutils.h"
25
26
#include "avcodec.h"
27
#include "bytestream.h"
28
#include "internal.h"
29
30
#define HEADER1_CHUNK    0x03
31
#define HEADER2_CHUNK    0x3D
32
#define IMAGE_DATA_CHUNK 0x21
33
34
/* In 8-bit colour mode, 256 colours are available at any time. Which 256
35
 * colours are available is determined by the contents of the hardware palette
36
 * (or CLUT). In this case, the palette supplied with BRender (std.pal) has
37
 * been loaded into the CLUT.
38
 *
39
 * The 256 colours in std.pal are divided into seven ranges, or `colour ramps'.
40
 * The first 64 colours represent shades of grey ranging from very dark grey
41
 * (black) to very light grey (white). The following colours are 32-element
42
 * ramps for six colours as shown below.
43
 */
44
static const uint32_t std_pal_table[256] = {
45
    // gray
46
    0xFF000000, 0xFF030303, 0xFF060606, 0xFF090909, 0xFF0C0C0C, 0xFF0F0F0F,
47
    0xFF121212, 0xFF151515, 0xFF181818, 0xFF1B1B1B, 0xFF1E1E1E, 0xFF212121,
48
    0xFF242424, 0xFF272727, 0xFF2A2A2A, 0xFF2D2D2D, 0xFF313131, 0xFF343434,
49
    0xFF373737, 0xFF3A3A3A, 0xFF3D3D3D, 0xFF404040, 0xFF434343, 0xFF464646,
50
    0xFF494949, 0xFF4C4C4C, 0xFF4F4F4F, 0xFF525252, 0xFF555555, 0xFF585858,
51
    0xFF5B5B5B, 0xFF5E5E5E, 0xFF626262, 0xFF656565, 0xFF686868, 0xFF6B6B6B,
52
    0xFF6E6E6E, 0xFF717171, 0xFF747474, 0xFF777777, 0xFF7A7A7A, 0xFF7D7D7D,
53
    0xFF808080, 0xFF838383, 0xFF868686, 0xFF898989, 0xFF8C8C8C, 0xFF8F8F8F,
54
    0xFF939393, 0xFF999999, 0xFFA0A0A0, 0xFFA7A7A7, 0xFFAEAEAE, 0xFFB4B4B4,
55
    0xFFBBBBBB, 0xFFC2C2C2, 0xFFC9C9C9, 0xFFCFCFCF, 0xFFD6D6D6, 0xFFDDDDDD,
56
    0xFFE4E4E4, 0xFFEAEAEA, 0xFFF1F1F1, 0xFFF8F8F8,
57
58
    // blue
59
    0xFF000000, 0xFF020209, 0xFF050513, 0xFF07071D, 0xFF0A0A27, 0xFF0C0C31,
60
    0xFF0F0F3B, 0xFF111145, 0xFF14144F, 0xFF161659, 0xFF181863, 0xFF1B1B6D,
61
    0xFF1E1E77, 0xFF202080, 0xFF22228A, 0xFF252594, 0xFF28289E, 0xFF2A2AA8,
62
    0xFF2D2DB2, 0xFF2F2FBC, 0xFF3131C6, 0xFF3434D0, 0xFF3737DA, 0xFF3939E4,
63
    0xFF3C3CEE, 0xFF5454F0, 0xFF6C6CF2, 0xFF8585F4, 0xFF9D9DF6, 0xFFB5B5F8,
64
    0xFFCECEFA, 0xFFE6E6FC,
65
66
    // green
67
    0xFF000000, 0xFF020902, 0xFF051305, 0xFF071D07, 0xFF0A270A, 0xFF0C310C,
68
    0xFF0F3B0F, 0xFF114511, 0xFF144F14, 0xFF165916, 0xFF186318, 0xFF1B6D1B,
69
    0xFF1E771E, 0xFF208020, 0xFF228A22, 0xFF259425, 0xFF289E28, 0xFF2AA82A,
70
    0xFF2DB22D, 0xFF2FBC2F, 0xFF31C631, 0xFF34D034, 0xFF37DA37, 0xFF39E439,
71
    0xFF3CEE3C, 0xFF54F054, 0xFF6CF26C, 0xFF85F485, 0xFF9DF69D, 0xFFB5F8B5,
72
    0xFFCEFACE, 0xFFE6FCE6,
73
74
    // cyan
75
    0xFF000000, 0xFF020909, 0xFF051313, 0xFF071D1D, 0xFF0A2727, 0xFF0C3131,
76
    0xFF0F3B3B, 0xFF114545, 0xFF144F4F, 0xFF165959, 0xFF186363, 0xFF1B6D6D,
77
    0xFF1E7777, 0xFF208080, 0xFF228A8A, 0xFF259494, 0xFF289E9E, 0xFF2AA8A8,
78
    0xFF2DB2B2, 0xFF2FBCBC, 0xFF31C6C6, 0xFF34D0D0, 0xFF37DADA, 0xFF39E4E4,
79
    0xFF3CEEEE, 0xFF54F0F0, 0xFF6CF2F2, 0xFF85F4F4, 0xFF9DF6F6, 0xFFB5F8F8,
80
    0xFFCEFAFA, 0xFFE6FCFC,
81
82
    // red
83
    0xFF000000, 0xFF090202, 0xFF130505, 0xFF1D0707, 0xFF270A0A, 0xFF310C0C,
84
    0xFF3B0F0F, 0xFF451111, 0xFF4F1414, 0xFF591616, 0xFF631818, 0xFF6D1B1B,
85
    0xFF771E1E, 0xFF802020, 0xFF8A2222, 0xFF942525, 0xFF9E2828, 0xFFA82A2A,
86
    0xFFB22D2D, 0xFFBC2F2F, 0xFFC63131, 0xFFD03434, 0xFFDA3737, 0xFFE43939,
87
    0xFFEE3C3C, 0xFFF05454, 0xFFF26C6C, 0xFFF48585, 0xFFF69D9D, 0xFFF8B5B5,
88
    0xFFFACECE, 0xFFFCE6E6,
89
90
    // magenta
91
    0xFF000000, 0xFF090209, 0xFF130513, 0xFF1D071D, 0xFF270A27, 0xFF310C31,
92
    0xFF3B0F3B, 0xFF451145, 0xFF4F144F, 0xFF591659, 0xFF631863, 0xFF6D1B6D,
93
    0xFF771E77, 0xFF802080, 0xFF8A228A, 0xFF942594, 0xFF9E289E, 0xFFA82AA8,
94
    0xFFB22DB2, 0xFFBC2FBC, 0xFFC631C6, 0xFFD034D0, 0xFFDA37DA, 0xFFE439E4,
95
    0xFFEE3CEE, 0xFFF054F0, 0xFFF26CF2, 0xFFF485F4, 0xFFF69DF6, 0xFFF8B5F8,
96
    0xFFFACEFA, 0xFFFCE6FC,
97
98
    // yellow
99
    0xFF000000, 0xFF090902, 0xFF131305, 0xFF1D1D07, 0xFF27270A, 0xFF31310C,
100
    0xFF3B3B0F, 0xFF454511, 0xFF4F4F14, 0xFF595916, 0xFF636318, 0xFF6D6D1B,
101
    0xFF77771E, 0xFF808020, 0xFF8A8A22, 0xFF949425, 0xFF9E9E28, 0xFFA8A82A,
102
    0xFFB2B22D, 0xFFBCBC2F, 0xFFC6C631, 0xFFD0D034, 0xFFDADA37, 0xFFE4E439,
103
    0xFFEEEE3C, 0xFFF0F054, 0xFFF2F26C, 0xFFF4F485, 0xFFF6F69D, 0xFFF8F8B5,
104
    0xFFFAFACE, 0xFFFCFCE6,
105
};
106
107
typedef struct PixHeader {
108
    int width;
109
    int height;
110
    int format;
111
} PixHeader;
112
113
12
static int pix_decode_header(PixHeader *out, GetByteContext *pgb)
114
{
115
12
    unsigned int header_len = bytestream2_get_be32(pgb);
116
117
12
    out->format = bytestream2_get_byte(pgb);
118
12
    bytestream2_skip(pgb, 2);
119
12
    out->width  = bytestream2_get_be16(pgb);
120
12
    out->height = bytestream2_get_be16(pgb);
121
122
    // the header is at least 11 bytes long; we read the first 7
123
12
    if (header_len < 11)
124
        return AVERROR_INVALIDDATA;
125
126
    // skip the rest of the header
127
12
    bytestream2_skip(pgb, header_len - 7);
128
129
12
    return 0;
130
}
131
132
10
static int pix_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
133
                            AVPacket *avpkt)
134
{
135
10
    AVFrame *frame = data;
136
137
    int ret, i;
138
    GetByteContext gb;
139
140
    unsigned int bytes_pp;
141
    unsigned int magic[4];
142
    unsigned int chunk_type;
143
    unsigned int data_len;
144
    unsigned int bytes_per_scanline;
145
    unsigned int bytes_left;
146
    PixHeader hdr;
147
148
10
    bytestream2_init(&gb, avpkt->data, avpkt->size);
149
150
10
    magic[0] = bytestream2_get_be32(&gb);
151
10
    magic[1] = bytestream2_get_be32(&gb);
152
10
    magic[2] = bytestream2_get_be32(&gb);
153
10
    magic[3] = bytestream2_get_be32(&gb);
154
155
10
    if (magic[0] != 0x12 ||
156
10
        magic[1] != 0x08 ||
157
10
        magic[2] != 0x02 ||
158
10
        magic[3] != 0x02) {
159
        av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file.\n");
160
        return AVERROR_INVALIDDATA;
161
    }
162
163
10
    chunk_type = bytestream2_get_be32(&gb);
164

10
    if (chunk_type != HEADER1_CHUNK && chunk_type != HEADER2_CHUNK) {
165
        av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d.\n", chunk_type);
166
        return AVERROR_INVALIDDATA;
167
    }
168
169
10
    ret = pix_decode_header(&hdr, &gb);
170
10
    if (ret < 0) {
171
        av_log(avctx, AV_LOG_ERROR, "Invalid header length.\n");
172
        return ret;
173
    }
174


10
    switch (hdr.format) {
175
4
    case 3:
176
4
        avctx->pix_fmt = AV_PIX_FMT_PAL8;
177
4
        bytes_pp = 1;
178
4
        break;
179
    case 4:
180
        avctx->pix_fmt = AV_PIX_FMT_RGB555BE;
181
        bytes_pp = 2;
182
        break;
183
4
    case 5:
184
4
        avctx->pix_fmt = AV_PIX_FMT_RGB565BE;
185
4
        bytes_pp = 2;
186
4
        break;
187
    case 6:
188
        avctx->pix_fmt = AV_PIX_FMT_RGB24;
189
        bytes_pp = 3;
190
        break;
191
    case 7:
192
        avctx->pix_fmt = AV_PIX_FMT_0RGB;
193
        bytes_pp = 4;
194
        break;
195
    case 8: // ARGB
196
        avctx->pix_fmt = AV_PIX_FMT_ARGB;
197
        bytes_pp = 4;
198
        break;
199
2
    case 18:
200
2
        avctx->pix_fmt = AV_PIX_FMT_YA8;
201
2
        bytes_pp = 2;
202
2
        break;
203
    default:
204
        avpriv_request_sample(avctx, "Format %d", hdr.format);
205
        return AVERROR_PATCHWELCOME;
206
    }
207
10
    bytes_per_scanline = bytes_pp * hdr.width;
208
209
10
    if (bytestream2_get_bytes_left(&gb) < hdr.height * bytes_per_scanline)
210
        return AVERROR_INVALIDDATA;
211
212
10
    if ((ret = ff_set_dimensions(avctx, hdr.width, hdr.height)) < 0)
213
        return ret;
214
215
10
    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
216
        return ret;
217
218
10
    chunk_type = bytestream2_get_be32(&gb);
219
220

10
    if (avctx->pix_fmt == AV_PIX_FMT_PAL8 &&
221
2
        (chunk_type == HEADER1_CHUNK ||
222
2
         chunk_type == HEADER2_CHUNK)) {
223
        /* read palette data from data[1] */
224
        PixHeader palhdr;
225
2
        uint32_t *pal_out = (uint32_t *)frame->data[1];
226
227
2
        ret = pix_decode_header(&palhdr, &gb);
228
2
        if (ret < 0) {
229
            av_log(avctx, AV_LOG_ERROR, "Invalid palette header length.\n");
230
            return ret;
231
        }
232
2
        if (palhdr.format != 7)
233
            avpriv_request_sample(avctx, "Palette not in RGB format");
234
235
2
        chunk_type = bytestream2_get_be32(&gb);
236
2
        data_len = bytestream2_get_be32(&gb);
237
2
        bytestream2_skip(&gb, 8);
238

4
        if (chunk_type != IMAGE_DATA_CHUNK || data_len != 1032 ||
239
2
            bytestream2_get_bytes_left(&gb) < 1032) {
240
            av_log(avctx, AV_LOG_ERROR, "Invalid palette data.\n");
241
            return AVERROR_INVALIDDATA;
242
        }
243
        // palette data is surrounded by 8 null bytes (both top and bottom)
244
        // convert 0RGB to machine endian format (ARGB32)
245
514
        for (i = 0; i < 256; ++i)
246
512
            *pal_out++ = (0xFFU << 24) | bytestream2_get_be32u(&gb);
247
2
        bytestream2_skip(&gb, 8);
248
249
2
        frame->palette_has_changed = 1;
250
251
2
        chunk_type = bytestream2_get_be32(&gb);
252
8
    } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
253
        /* no palette supplied, use the default one */
254
2
        uint32_t *pal_out = (uint32_t *)frame->data[1];
255
256
        // TODO: add an AVOption to load custom palette files
257
2
        av_log(avctx, AV_LOG_WARNING,
258
               "Using default palette, colors might be off.\n");
259
2
        memcpy(pal_out, std_pal_table, sizeof(uint32_t) * 256);
260
261
2
        frame->palette_has_changed = 1;
262
    }
263
264
10
    data_len = bytestream2_get_be32(&gb);
265
10
    bytestream2_skip(&gb, 8);
266
267
    // read the image data to the buffer
268
10
    bytes_left = bytestream2_get_bytes_left(&gb);
269
270

10
    if (chunk_type != IMAGE_DATA_CHUNK || data_len != bytes_left ||
271
10
        bytes_left / bytes_per_scanline < hdr.height) {
272
        av_log(avctx, AV_LOG_ERROR, "Invalid image data.\n");
273
        return AVERROR_INVALIDDATA;
274
    }
275
276
20
    av_image_copy_plane(frame->data[0], frame->linesize[0],
277
10
                        avpkt->data + bytestream2_tell(&gb),
278
                        bytes_per_scanline,
279
                        bytes_per_scanline, hdr.height);
280
281
10
    frame->pict_type = AV_PICTURE_TYPE_I;
282
10
    frame->key_frame = 1;
283
10
    *got_frame = 1;
284
285
10
    return avpkt->size;
286
}
287
288
AVCodec ff_brender_pix_decoder = {
289
    .name         = "brender_pix",
290
    .long_name    = NULL_IF_CONFIG_SMALL("BRender PIX image"),
291
    .type         = AVMEDIA_TYPE_VIDEO,
292
    .id           = AV_CODEC_ID_BRENDER_PIX,
293
    .decode       = pix_decode_frame,
294
    .capabilities = AV_CODEC_CAP_DR1,
295
};