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 */ 44static 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 107typedef struct PixHeader { 108 int width; 109 int height; 110 int format; 111} PixHeader; 112 113static 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 132static 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_Y400A; 201 bytes_pp = 2; 202 break; 203 default: 204 avpriv_request_sample(avctx, "Format %d", hdr.format); 205 return AVERROR_PATCHWELCOME; 206 } 207 208 if ((ret = ff_set_dimensions(avctx, hdr.width, hdr.height)) < 0) 209 return ret; 210 211 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 212 return ret; 213 214 chunk_type = bytestream2_get_be32(&gb); 215 216 if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && 217 (chunk_type == HEADER1_CHUNK || 218 chunk_type == HEADER2_CHUNK)) { 219 /* read palette data from data[1] */ 220 PixHeader palhdr; 221 uint32_t *pal_out = (uint32_t *)frame->data[1]; 222 223 ret = pix_decode_header(&palhdr, &gb); 224 if (ret < 0) { 225 av_log(avctx, AV_LOG_ERROR, "Invalid palette header length.\n"); 226 return ret; 227 } 228 if (palhdr.format != 7) 229 avpriv_request_sample(avctx, "Palette not in RGB format"); 230 231 chunk_type = bytestream2_get_be32(&gb); 232 data_len = bytestream2_get_be32(&gb); 233 bytestream2_skip(&gb, 8); 234 if (chunk_type != IMAGE_DATA_CHUNK || data_len != 1032 || 235 bytestream2_get_bytes_left(&gb) < 1032) { 236 av_log(avctx, AV_LOG_ERROR, "Invalid palette data.\n"); 237 return AVERROR_INVALIDDATA; 238 } 239 // palette data is surrounded by 8 null bytes (both top and bottom) 240 // convert 0RGB to machine endian format (ARGB32) 241 for (i = 0; i < 256; ++i) 242 *pal_out++ = (0xFFU << 24) | bytestream2_get_be32u(&gb); 243 bytestream2_skip(&gb, 8); 244 245 frame->palette_has_changed = 1; 246 247 chunk_type = bytestream2_get_be32(&gb); 248 } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { 249 /* no palette supplied, use the default one */ 250 uint32_t *pal_out = (uint32_t *)frame->data[1]; 251 252 // TODO: add an AVOption to load custom palette files 253 av_log(avctx, AV_LOG_WARNING, 254 "Using default palette, colors might be off.\n"); 255 memcpy(pal_out, std_pal_table, sizeof(uint32_t) * 256); 256 257 frame->palette_has_changed = 1; 258 } 259 260 data_len = bytestream2_get_be32(&gb); 261 bytestream2_skip(&gb, 8); 262 263 // read the image data to the buffer 264 bytes_per_scanline = bytes_pp * hdr.width; 265 bytes_left = bytestream2_get_bytes_left(&gb); 266 267 if (chunk_type != IMAGE_DATA_CHUNK || data_len != bytes_left || 268 bytes_left / bytes_per_scanline < hdr.height) { 269 av_log(avctx, AV_LOG_ERROR, "Invalid image data.\n"); 270 return AVERROR_INVALIDDATA; 271 } 272 273 av_image_copy_plane(frame->data[0], frame->linesize[0], 274 avpkt->data + bytestream2_tell(&gb), 275 bytes_per_scanline, 276 bytes_per_scanline, hdr.height); 277 278 frame->pict_type = AV_PICTURE_TYPE_I; 279 frame->key_frame = 1; 280 *got_frame = 1; 281 282 return avpkt->size; 283} 284 285AVCodec ff_brender_pix_decoder = { 286 .name = "brender_pix", 287 .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), 288 .type = AVMEDIA_TYPE_VIDEO, 289 .id = AV_CODEC_ID_BRENDER_PIX, 290 .decode = pix_decode_frame, 291 .capabilities = CODEC_CAP_DR1, 292}; 293