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 "codec_internal.h"
29#include "internal.h"
30
31#define HEADER1_CHUNK    0x03
32#define HEADER2_CHUNK    0x3D
33#define IMAGE_DATA_CHUNK 0x21
34
35/* In 8-bit colour mode, 256 colours are available at any time. Which 256
36 * colours are available is determined by the contents of the hardware palette
37 * (or CLUT). In this case, the palette supplied with BRender (std.pal) has
38 * been loaded into the CLUT.
39 *
40 * The 256 colours in std.pal are divided into seven ranges, or `colour ramps'.
41 * The first 64 colours represent shades of grey ranging from very dark grey
42 * (black) to very light grey (white). The following colours are 32-element
43 * ramps for six colours as shown below.
44 */
45static const uint32_t std_pal_table[256] = {
46    // gray
47    0xFF000000, 0xFF030303, 0xFF060606, 0xFF090909, 0xFF0C0C0C, 0xFF0F0F0F,
48    0xFF121212, 0xFF151515, 0xFF181818, 0xFF1B1B1B, 0xFF1E1E1E, 0xFF212121,
49    0xFF242424, 0xFF272727, 0xFF2A2A2A, 0xFF2D2D2D, 0xFF313131, 0xFF343434,
50    0xFF373737, 0xFF3A3A3A, 0xFF3D3D3D, 0xFF404040, 0xFF434343, 0xFF464646,
51    0xFF494949, 0xFF4C4C4C, 0xFF4F4F4F, 0xFF525252, 0xFF555555, 0xFF585858,
52    0xFF5B5B5B, 0xFF5E5E5E, 0xFF626262, 0xFF656565, 0xFF686868, 0xFF6B6B6B,
53    0xFF6E6E6E, 0xFF717171, 0xFF747474, 0xFF777777, 0xFF7A7A7A, 0xFF7D7D7D,
54    0xFF808080, 0xFF838383, 0xFF868686, 0xFF898989, 0xFF8C8C8C, 0xFF8F8F8F,
55    0xFF939393, 0xFF999999, 0xFFA0A0A0, 0xFFA7A7A7, 0xFFAEAEAE, 0xFFB4B4B4,
56    0xFFBBBBBB, 0xFFC2C2C2, 0xFFC9C9C9, 0xFFCFCFCF, 0xFFD6D6D6, 0xFFDDDDDD,
57    0xFFE4E4E4, 0xFFEAEAEA, 0xFFF1F1F1, 0xFFF8F8F8,
58
59    // blue
60    0xFF000000, 0xFF020209, 0xFF050513, 0xFF07071D, 0xFF0A0A27, 0xFF0C0C31,
61    0xFF0F0F3B, 0xFF111145, 0xFF14144F, 0xFF161659, 0xFF181863, 0xFF1B1B6D,
62    0xFF1E1E77, 0xFF202080, 0xFF22228A, 0xFF252594, 0xFF28289E, 0xFF2A2AA8,
63    0xFF2D2DB2, 0xFF2F2FBC, 0xFF3131C6, 0xFF3434D0, 0xFF3737DA, 0xFF3939E4,
64    0xFF3C3CEE, 0xFF5454F0, 0xFF6C6CF2, 0xFF8585F4, 0xFF9D9DF6, 0xFFB5B5F8,
65    0xFFCECEFA, 0xFFE6E6FC,
66
67    // green
68    0xFF000000, 0xFF020902, 0xFF051305, 0xFF071D07, 0xFF0A270A, 0xFF0C310C,
69    0xFF0F3B0F, 0xFF114511, 0xFF144F14, 0xFF165916, 0xFF186318, 0xFF1B6D1B,
70    0xFF1E771E, 0xFF208020, 0xFF228A22, 0xFF259425, 0xFF289E28, 0xFF2AA82A,
71    0xFF2DB22D, 0xFF2FBC2F, 0xFF31C631, 0xFF34D034, 0xFF37DA37, 0xFF39E439,
72    0xFF3CEE3C, 0xFF54F054, 0xFF6CF26C, 0xFF85F485, 0xFF9DF69D, 0xFFB5F8B5,
73    0xFFCEFACE, 0xFFE6FCE6,
74
75    // cyan
76    0xFF000000, 0xFF020909, 0xFF051313, 0xFF071D1D, 0xFF0A2727, 0xFF0C3131,
77    0xFF0F3B3B, 0xFF114545, 0xFF144F4F, 0xFF165959, 0xFF186363, 0xFF1B6D6D,
78    0xFF1E7777, 0xFF208080, 0xFF228A8A, 0xFF259494, 0xFF289E9E, 0xFF2AA8A8,
79    0xFF2DB2B2, 0xFF2FBCBC, 0xFF31C6C6, 0xFF34D0D0, 0xFF37DADA, 0xFF39E4E4,
80    0xFF3CEEEE, 0xFF54F0F0, 0xFF6CF2F2, 0xFF85F4F4, 0xFF9DF6F6, 0xFFB5F8F8,
81    0xFFCEFAFA, 0xFFE6FCFC,
82
83    // red
84    0xFF000000, 0xFF090202, 0xFF130505, 0xFF1D0707, 0xFF270A0A, 0xFF310C0C,
85    0xFF3B0F0F, 0xFF451111, 0xFF4F1414, 0xFF591616, 0xFF631818, 0xFF6D1B1B,
86    0xFF771E1E, 0xFF802020, 0xFF8A2222, 0xFF942525, 0xFF9E2828, 0xFFA82A2A,
87    0xFFB22D2D, 0xFFBC2F2F, 0xFFC63131, 0xFFD03434, 0xFFDA3737, 0xFFE43939,
88    0xFFEE3C3C, 0xFFF05454, 0xFFF26C6C, 0xFFF48585, 0xFFF69D9D, 0xFFF8B5B5,
89    0xFFFACECE, 0xFFFCE6E6,
90
91    // magenta
92    0xFF000000, 0xFF090209, 0xFF130513, 0xFF1D071D, 0xFF270A27, 0xFF310C31,
93    0xFF3B0F3B, 0xFF451145, 0xFF4F144F, 0xFF591659, 0xFF631863, 0xFF6D1B6D,
94    0xFF771E77, 0xFF802080, 0xFF8A228A, 0xFF942594, 0xFF9E289E, 0xFFA82AA8,
95    0xFFB22DB2, 0xFFBC2FBC, 0xFFC631C6, 0xFFD034D0, 0xFFDA37DA, 0xFFE439E4,
96    0xFFEE3CEE, 0xFFF054F0, 0xFFF26CF2, 0xFFF485F4, 0xFFF69DF6, 0xFFF8B5F8,
97    0xFFFACEFA, 0xFFFCE6FC,
98
99    // yellow
100    0xFF000000, 0xFF090902, 0xFF131305, 0xFF1D1D07, 0xFF27270A, 0xFF31310C,
101    0xFF3B3B0F, 0xFF454511, 0xFF4F4F14, 0xFF595916, 0xFF636318, 0xFF6D6D1B,
102    0xFF77771E, 0xFF808020, 0xFF8A8A22, 0xFF949425, 0xFF9E9E28, 0xFFA8A82A,
103    0xFFB2B22D, 0xFFBCBC2F, 0xFFC6C631, 0xFFD0D034, 0xFFDADA37, 0xFFE4E439,
104    0xFFEEEE3C, 0xFFF0F054, 0xFFF2F26C, 0xFFF4F485, 0xFFF6F69D, 0xFFF8F8B5,
105    0xFFFAFACE, 0xFFFCFCE6,
106};
107
108typedef struct PixHeader {
109    int width;
110    int height;
111    int format;
112} PixHeader;
113
114static int pix_decode_header(PixHeader *out, GetByteContext *pgb)
115{
116    unsigned int header_len = bytestream2_get_be32(pgb);
117
118    out->format = bytestream2_get_byte(pgb);
119    bytestream2_skip(pgb, 2);
120    out->width  = bytestream2_get_be16(pgb);
121    out->height = bytestream2_get_be16(pgb);
122
123    // the header is at least 11 bytes long; we read the first 7
124    if (header_len < 11)
125        return AVERROR_INVALIDDATA;
126
127    // skip the rest of the header
128    bytestream2_skip(pgb, header_len - 7);
129
130    return 0;
131}
132
133static int pix_decode_frame(AVCodecContext *avctx, AVFrame *frame,
134                            int *got_frame, AVPacket *avpkt)
135{
136    int ret, i;
137    GetByteContext gb;
138
139    unsigned int bytes_pp;
140    unsigned int magic[4];
141    unsigned int chunk_type;
142    unsigned int data_len;
143    unsigned int bytes_per_scanline;
144    unsigned int bytes_left;
145    PixHeader hdr;
146
147    bytestream2_init(&gb, avpkt->data, avpkt->size);
148
149    magic[0] = bytestream2_get_be32(&gb);
150    magic[1] = bytestream2_get_be32(&gb);
151    magic[2] = bytestream2_get_be32(&gb);
152    magic[3] = bytestream2_get_be32(&gb);
153
154    if (magic[0] != 0x12 ||
155        magic[1] != 0x08 ||
156        magic[2] != 0x02 ||
157        magic[3] != 0x02) {
158        av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file.\n");
159        return AVERROR_INVALIDDATA;
160    }
161
162    chunk_type = bytestream2_get_be32(&gb);
163    if (chunk_type != HEADER1_CHUNK && chunk_type != HEADER2_CHUNK) {
164        av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d.\n", chunk_type);
165        return AVERROR_INVALIDDATA;
166    }
167
168    ret = pix_decode_header(&hdr, &gb);
169    if (ret < 0) {
170        av_log(avctx, AV_LOG_ERROR, "Invalid header length.\n");
171        return ret;
172    }
173    switch (hdr.format) {
174    case 3:
175        avctx->pix_fmt = AV_PIX_FMT_PAL8;
176        bytes_pp = 1;
177        break;
178    case 4:
179        avctx->pix_fmt = AV_PIX_FMT_RGB555BE;
180        bytes_pp = 2;
181        break;
182    case 5:
183        avctx->pix_fmt = AV_PIX_FMT_RGB565BE;
184        bytes_pp = 2;
185        break;
186    case 6:
187        avctx->pix_fmt = AV_PIX_FMT_RGB24;
188        bytes_pp = 3;
189        break;
190    case 7:
191        avctx->pix_fmt = AV_PIX_FMT_0RGB;
192        bytes_pp = 4;
193        break;
194    case 8: // ARGB
195        avctx->pix_fmt = AV_PIX_FMT_ARGB;
196        bytes_pp = 4;
197        break;
198    case 18:
199        avctx->pix_fmt = AV_PIX_FMT_YA8;
200        bytes_pp = 2;
201        break;
202    default:
203        avpriv_request_sample(avctx, "Format %d", hdr.format);
204        return AVERROR_PATCHWELCOME;
205    }
206    bytes_per_scanline = bytes_pp * hdr.width;
207
208    if (bytestream2_get_bytes_left(&gb) < hdr.height * bytes_per_scanline)
209        return AVERROR_INVALIDDATA;
210
211    if ((ret = ff_set_dimensions(avctx, hdr.width, hdr.height)) < 0)
212        return ret;
213
214    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
215        return ret;
216
217    chunk_type = bytestream2_get_be32(&gb);
218
219    if (avctx->pix_fmt == AV_PIX_FMT_PAL8 &&
220        (chunk_type == HEADER1_CHUNK ||
221         chunk_type == HEADER2_CHUNK)) {
222        /* read palette data from data[1] */
223        PixHeader palhdr;
224        uint32_t *pal_out = (uint32_t *)frame->data[1];
225
226        ret = pix_decode_header(&palhdr, &gb);
227        if (ret < 0) {
228            av_log(avctx, AV_LOG_ERROR, "Invalid palette header length.\n");
229            return ret;
230        }
231        if (palhdr.format != 7)
232            avpriv_request_sample(avctx, "Palette not in RGB format");
233
234        chunk_type = bytestream2_get_be32(&gb);
235        data_len = bytestream2_get_be32(&gb);
236        bytestream2_skip(&gb, 8);
237        if (chunk_type != IMAGE_DATA_CHUNK || data_len != 1032 ||
238            bytestream2_get_bytes_left(&gb) < 1032) {
239            av_log(avctx, AV_LOG_ERROR, "Invalid palette data.\n");
240            return AVERROR_INVALIDDATA;
241        }
242        // palette data is surrounded by 8 null bytes (both top and bottom)
243        // convert 0RGB to machine endian format (ARGB32)
244        for (i = 0; i < 256; ++i)
245            *pal_out++ = (0xFFU << 24) | bytestream2_get_be32u(&gb);
246        bytestream2_skip(&gb, 8);
247
248        frame->palette_has_changed = 1;
249
250        chunk_type = bytestream2_get_be32(&gb);
251    } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
252        /* no palette supplied, use the default one */
253        uint32_t *pal_out = (uint32_t *)frame->data[1];
254
255        // TODO: add an AVOption to load custom palette files
256        av_log(avctx, AV_LOG_WARNING,
257               "Using default palette, colors might be off.\n");
258        memcpy(pal_out, std_pal_table, sizeof(uint32_t) * 256);
259
260        frame->palette_has_changed = 1;
261    }
262
263    data_len = bytestream2_get_be32(&gb);
264    bytestream2_skip(&gb, 8);
265
266    // read the image data to the buffer
267    bytes_left = bytestream2_get_bytes_left(&gb);
268
269    if (chunk_type != IMAGE_DATA_CHUNK || data_len != bytes_left ||
270        bytes_left / bytes_per_scanline < hdr.height) {
271        av_log(avctx, AV_LOG_ERROR, "Invalid image data.\n");
272        return AVERROR_INVALIDDATA;
273    }
274
275    av_image_copy_plane(frame->data[0], frame->linesize[0],
276                        avpkt->data + bytestream2_tell(&gb),
277                        bytes_per_scanline,
278                        bytes_per_scanline, hdr.height);
279
280    frame->pict_type = AV_PICTURE_TYPE_I;
281    frame->key_frame = 1;
282    *got_frame = 1;
283
284    return avpkt->size;
285}
286
287const FFCodec ff_brender_pix_decoder = {
288    .p.name         = "brender_pix",
289    .p.long_name    = NULL_IF_CONFIG_SMALL("BRender PIX image"),
290    .p.type         = AVMEDIA_TYPE_VIDEO,
291    .p.id           = AV_CODEC_ID_BRENDER_PIX,
292    .p.capabilities = AV_CODEC_CAP_DR1,
293    FF_CODEC_DECODE_CB(pix_decode_frame),
294};
295