]> git.sesse.net Git - ffmpeg/blob - libavcodec/brenderpix.c
46b7a59aa49562d168d285395d8fe8240f6ba10f
[ffmpeg] / libavcodec / brenderpix.c
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 static int pix_decode_header(PixHeader *out, GetByteContext *pgb)
114 {
115     unsigned int header_len = bytestream2_get_be32(pgb);
116
117     out->format = bytestream2_get_byte(pgb);
118     bytestream2_skip(pgb, 2);
119     out->width  = bytestream2_get_be16(pgb);
120     out->height = bytestream2_get_be16(pgb);
121
122     // the header is at least 11 bytes long; we read the first 7
123     if (header_len < 11)
124         return AVERROR_INVALIDDATA;
125
126     // skip the rest of the header
127     bytestream2_skip(pgb, header_len - 7);
128
129     return 0;
130 }
131
132 static int pix_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
133                             AVPacket *avpkt)
134 {
135     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     bytestream2_init(&gb, avpkt->data, avpkt->size);
149
150     magic[0] = bytestream2_get_be32(&gb);
151     magic[1] = bytestream2_get_be32(&gb);
152     magic[2] = bytestream2_get_be32(&gb);
153     magic[3] = bytestream2_get_be32(&gb);
154
155     if (magic[0] != 0x12 ||
156         magic[1] != 0x08 ||
157         magic[2] != 0x02 ||
158         magic[3] != 0x02) {
159         av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file.\n");
160         return AVERROR_INVALIDDATA;
161     }
162
163     chunk_type = bytestream2_get_be32(&gb);
164     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     ret = pix_decode_header(&hdr, &gb);
170     if (ret < 0) {
171         av_log(avctx, AV_LOG_ERROR, "Invalid header length.\n");
172         return ret;
173     }
174     switch (hdr.format) {
175     case 3:
176         avctx->pix_fmt = AV_PIX_FMT_PAL8;
177         bytes_pp = 1;
178         break;
179     case 4:
180         avctx->pix_fmt = AV_PIX_FMT_RGB555BE;
181         bytes_pp = 2;
182         break;
183     case 5:
184         avctx->pix_fmt = AV_PIX_FMT_RGB565BE;
185         bytes_pp = 2;
186         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     case 18:
200         avctx->pix_fmt = AV_PIX_FMT_YA8;
201         bytes_pp = 2;
202         break;
203     default:
204         avpriv_request_sample(avctx, "Format %d", hdr.format);
205         return AVERROR_PATCHWELCOME;
206     }
207     bytes_per_scanline = bytes_pp * hdr.width;
208
209     if (bytestream2_get_bytes_left(&gb) < hdr.height * bytes_per_scanline)
210         return AVERROR_INVALIDDATA;
211
212     if ((ret = ff_set_dimensions(avctx, hdr.width, hdr.height)) < 0)
213         return ret;
214
215     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
216         return ret;
217
218     chunk_type = bytestream2_get_be32(&gb);
219
220     if (avctx->pix_fmt == AV_PIX_FMT_PAL8 &&
221         (chunk_type == HEADER1_CHUNK ||
222          chunk_type == HEADER2_CHUNK)) {
223         /* read palette data from data[1] */
224         PixHeader palhdr;
225         uint32_t *pal_out = (uint32_t *)frame->data[1];
226
227         ret = pix_decode_header(&palhdr, &gb);
228         if (ret < 0) {
229             av_log(avctx, AV_LOG_ERROR, "Invalid palette header length.\n");
230             return ret;
231         }
232         if (palhdr.format != 7)
233             avpriv_request_sample(avctx, "Palette not in RGB format");
234
235         chunk_type = bytestream2_get_be32(&gb);
236         data_len = bytestream2_get_be32(&gb);
237         bytestream2_skip(&gb, 8);
238         if (chunk_type != IMAGE_DATA_CHUNK || data_len != 1032 ||
239             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         for (i = 0; i < 256; ++i)
246             *pal_out++ = (0xFFU << 24) | bytestream2_get_be32u(&gb);
247         bytestream2_skip(&gb, 8);
248
249         frame->palette_has_changed = 1;
250
251         chunk_type = bytestream2_get_be32(&gb);
252     } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
253         /* no palette supplied, use the default one */
254         uint32_t *pal_out = (uint32_t *)frame->data[1];
255
256         // TODO: add an AVOption to load custom palette files
257         av_log(avctx, AV_LOG_WARNING,
258                "Using default palette, colors might be off.\n");
259         memcpy(pal_out, std_pal_table, sizeof(uint32_t) * 256);
260
261         frame->palette_has_changed = 1;
262     }
263
264     data_len = bytestream2_get_be32(&gb);
265     bytestream2_skip(&gb, 8);
266
267     // read the image data to the buffer
268     bytes_left = bytestream2_get_bytes_left(&gb);
269
270     if (chunk_type != IMAGE_DATA_CHUNK || data_len != bytes_left ||
271         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     av_image_copy_plane(frame->data[0], frame->linesize[0],
277                         avpkt->data + bytestream2_tell(&gb),
278                         bytes_per_scanline,
279                         bytes_per_scanline, hdr.height);
280
281     frame->pict_type = AV_PICTURE_TYPE_I;
282     frame->key_frame = 1;
283     *got_frame = 1;
284
285     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 };