1/* 2 * Feeble Files/ScummVM DXA decoder 3 * Copyright (c) 2007 Konstantin Shishkov 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/** 23 * @file 24 * DXA Video decoder 25 */ 26 27#include <stdio.h> 28#include <stdlib.h> 29 30#include "libavutil/common.h" 31#include "libavutil/intreadwrite.h" 32#include "bytestream.h" 33#include "avcodec.h" 34#include "internal.h" 35 36#include <zlib.h> 37 38/* 39 * Decoder context 40 */ 41typedef struct DxaDecContext { 42 AVFrame *prev; 43 44 int dsize; 45#define DECOMP_BUF_PADDING 16 46 uint8_t *decomp_buf; 47 uint32_t pal[256]; 48} DxaDecContext; 49 50static const int shift1[6] = { 0, 8, 8, 8, 4, 4 }; 51static const int shift2[6] = { 0, 0, 8, 4, 0, 4 }; 52 53static int decode_13(AVCodecContext *avctx, DxaDecContext *c, uint8_t* dst, 54 int stride, uint8_t *src, int srcsize, uint8_t *ref) 55{ 56 uint8_t *code, *data, *mv, *msk, *tmp, *tmp2; 57 uint8_t *src_end = src + srcsize; 58 int i, j, k; 59 int type, x, y, d, d2; 60 uint32_t mask; 61 62 if (12ULL + ((avctx->width * avctx->height) >> 4) + AV_RB32(src + 0) + AV_RB32(src + 4) > srcsize) 63 return AVERROR_INVALIDDATA; 64 65 code = src + 12; 66 data = code + ((avctx->width * avctx->height) >> 4); 67 mv = data + AV_RB32(src + 0); 68 msk = mv + AV_RB32(src + 4); 69 70 for(j = 0; j < avctx->height; j += 4){ 71 for(i = 0; i < avctx->width; i += 4){ 72 if (data > src_end || mv > src_end || msk > src_end) 73 return AVERROR_INVALIDDATA; 74 tmp = dst + i; 75 tmp2 = ref + i; 76 type = *code++; 77 switch(type){ 78 case 4: // motion compensation 79 x = (*mv) >> 4; if(x & 8) x = 8 - x; 80 y = (*mv++) & 0xF; if(y & 8) y = 8 - y; 81 if (i < -x || avctx->width - i - 4 < x || 82 j < -y || avctx->height - j - 4 < y) { 83 av_log(avctx, AV_LOG_ERROR, "MV %d %d out of bounds\n", x,y); 84 return AVERROR_INVALIDDATA; 85 } 86 tmp2 += x + y*stride; 87 case 0: // skip 88 case 5: // skip in method 12 89 for(y = 0; y < 4; y++){ 90 memcpy(tmp, tmp2, 4); 91 tmp += stride; 92 tmp2 += stride; 93 } 94 break; 95 case 1: // masked change 96 case 10: // masked change with only half of pixels changed 97 case 11: // cases 10-15 are for method 12 only 98 case 12: 99 case 13: 100 case 14: 101 case 15: 102 if(type == 1){ 103 mask = AV_RB16(msk); 104 msk += 2; 105 }else{ 106 type -= 10; 107 mask = ((msk[0] & 0xF0) << shift1[type]) | ((msk[0] & 0xF) << shift2[type]); 108 msk++; 109 } 110 for(y = 0; y < 4; y++){ 111 for(x = 0; x < 4; x++){ 112 tmp[x] = (mask & 0x8000) ? *data++ : tmp2[x]; 113 mask <<= 1; 114 } 115 tmp += stride; 116 tmp2 += stride; 117 } 118 break; 119 case 2: // fill block 120 for(y = 0; y < 4; y++){ 121 memset(tmp, data[0], 4); 122 tmp += stride; 123 } 124 data++; 125 break; 126 case 3: // raw block 127 for(y = 0; y < 4; y++){ 128 memcpy(tmp, data, 4); 129 data += 4; 130 tmp += stride; 131 } 132 break; 133 case 8: // subblocks - method 13 only 134 mask = *msk++; 135 for(k = 0; k < 4; k++){ 136 d = ((k & 1) << 1) + ((k & 2) * stride); 137 d2 = ((k & 1) << 1) + ((k & 2) * stride); 138 tmp2 = ref + i + d2; 139 switch(mask & 0xC0){ 140 case 0x80: // motion compensation 141 x = (*mv) >> 4; if(x & 8) x = 8 - x; 142 y = (*mv++) & 0xF; if(y & 8) y = 8 - y; 143 if (i + 2*(k & 1) < -x || avctx->width - i - 2*(k & 1) - 2 < x || 144 j + (k & 2) < -y || avctx->height - j - (k & 2) - 2 < y) { 145 av_log(avctx, AV_LOG_ERROR, "MV %d %d out of bounds\n", x,y); 146 return AVERROR_INVALIDDATA; 147 } 148 tmp2 += x + y*stride; 149 case 0x00: // skip 150 tmp[d + 0 ] = tmp2[0]; 151 tmp[d + 1 ] = tmp2[1]; 152 tmp[d + 0 + stride] = tmp2[0 + stride]; 153 tmp[d + 1 + stride] = tmp2[1 + stride]; 154 break; 155 case 0x40: // fill 156 tmp[d + 0 ] = data[0]; 157 tmp[d + 1 ] = data[0]; 158 tmp[d + 0 + stride] = data[0]; 159 tmp[d + 1 + stride] = data[0]; 160 data++; 161 break; 162 case 0xC0: // raw 163 tmp[d + 0 ] = *data++; 164 tmp[d + 1 ] = *data++; 165 tmp[d + 0 + stride] = *data++; 166 tmp[d + 1 + stride] = *data++; 167 break; 168 } 169 mask <<= 2; 170 } 171 break; 172 case 32: // vector quantization - 2 colors 173 mask = AV_RB16(msk); 174 msk += 2; 175 for(y = 0; y < 4; y++){ 176 for(x = 0; x < 4; x++){ 177 tmp[x] = data[mask & 1]; 178 mask >>= 1; 179 } 180 tmp += stride; 181 tmp2 += stride; 182 } 183 data += 2; 184 break; 185 case 33: // vector quantization - 3 or 4 colors 186 case 34: 187 mask = AV_RB32(msk); 188 msk += 4; 189 for(y = 0; y < 4; y++){ 190 for(x = 0; x < 4; x++){ 191 tmp[x] = data[mask & 3]; 192 mask >>= 2; 193 } 194 tmp += stride; 195 tmp2 += stride; 196 } 197 data += type - 30; 198 break; 199 default: 200 av_log(avctx, AV_LOG_ERROR, "Unknown opcode %d\n", type); 201 return AVERROR_INVALIDDATA; 202 } 203 } 204 dst += stride * 4; 205 ref += stride * 4; 206 } 207 return 0; 208} 209 210static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) 211{ 212 AVFrame *frame = data; 213 DxaDecContext * const c = avctx->priv_data; 214 uint8_t *outptr, *srcptr, *tmpptr; 215 unsigned long dsize; 216 int i, j, compr, ret; 217 int stride; 218 int pc = 0; 219 GetByteContext gb; 220 221 bytestream2_init(&gb, avpkt->data, avpkt->size); 222 223 /* make the palette available on the way out */ 224 if (bytestream2_peek_le32(&gb) == MKTAG('C','M','A','P')) { 225 bytestream2_skip(&gb, 4); 226 for(i = 0; i < 256; i++){ 227 c->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&gb); 228 } 229 pc = 1; 230 } 231 232 if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) 233 return ret; 234 memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); 235 frame->palette_has_changed = pc; 236 237 outptr = frame->data[0]; 238 srcptr = c->decomp_buf; 239 tmpptr = c->prev->data[0]; 240 stride = frame->linesize[0]; 241 242 if (bytestream2_get_le32(&gb) == MKTAG('N','U','L','L')) 243 compr = -1; 244 else 245 compr = bytestream2_get_byte(&gb); 246 247 dsize = c->dsize; 248 if (compr != 4 && compr != -1) { 249 bytestream2_skip(&gb, 4); 250 if (uncompress(c->decomp_buf, &dsize, avpkt->data + bytestream2_tell(&gb), 251 bytestream2_get_bytes_left(&gb)) != Z_OK) { 252 av_log(avctx, AV_LOG_ERROR, "Uncompress failed!\n"); 253 return AVERROR_UNKNOWN; 254 } 255 memset(c->decomp_buf + dsize, 0, DECOMP_BUF_PADDING); 256 } 257 258 if (avctx->debug & FF_DEBUG_PICT_INFO) 259 av_log(avctx, AV_LOG_DEBUG, "compr:%2d, dsize:%d\n", compr, (int)dsize); 260 261 switch(compr){ 262 case -1: 263 frame->key_frame = 0; 264 frame->pict_type = AV_PICTURE_TYPE_P; 265 if (c->prev->data[0]) 266 memcpy(frame->data[0], c->prev->data[0], frame->linesize[0] * avctx->height); 267 else{ // Should happen only when first frame is 'NULL' 268 memset(frame->data[0], 0, frame->linesize[0] * avctx->height); 269 frame->key_frame = 1; 270 frame->pict_type = AV_PICTURE_TYPE_I; 271 } 272 break; 273 case 2: 274 case 4: 275 frame->key_frame = 1; 276 frame->pict_type = AV_PICTURE_TYPE_I; 277 for (j = 0; j < avctx->height; j++) { 278 memcpy(outptr, srcptr, avctx->width); 279 outptr += stride; 280 srcptr += avctx->width; 281 } 282 break; 283 case 3: 284 case 5: 285 if (!tmpptr) { 286 av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); 287 if (!(avctx->flags2 & CODEC_FLAG2_SHOW_ALL)) 288 return AVERROR_INVALIDDATA; 289 } 290 frame->key_frame = 0; 291 frame->pict_type = AV_PICTURE_TYPE_P; 292 for (j = 0; j < avctx->height; j++) { 293 if(tmpptr){ 294 for(i = 0; i < avctx->width; i++) 295 outptr[i] = srcptr[i] ^ tmpptr[i]; 296 tmpptr += stride; 297 }else 298 memcpy(outptr, srcptr, avctx->width); 299 outptr += stride; 300 srcptr += avctx->width; 301 } 302 break; 303 case 12: // ScummVM coding 304 case 13: 305 frame->key_frame = 0; 306 frame->pict_type = AV_PICTURE_TYPE_P; 307 if (!c->prev->data[0]) { 308 av_log(avctx, AV_LOG_ERROR, "Missing reference frame\n"); 309 return AVERROR_INVALIDDATA; 310 } 311 decode_13(avctx, c, frame->data[0], frame->linesize[0], srcptr, dsize, c->prev->data[0]); 312 break; 313 default: 314 av_log(avctx, AV_LOG_ERROR, "Unknown/unsupported compression type %d\n", compr); 315 return AVERROR_INVALIDDATA; 316 } 317 318 av_frame_unref(c->prev); 319 if ((ret = av_frame_ref(c->prev, frame)) < 0) 320 return ret; 321 322 *got_frame = 1; 323 324 /* always report that the buffer was completely consumed */ 325 return avpkt->size; 326} 327 328static av_cold int decode_init(AVCodecContext *avctx) 329{ 330 DxaDecContext * const c = avctx->priv_data; 331 332 c->prev = av_frame_alloc(); 333 if (!c->prev) 334 return AVERROR(ENOMEM); 335 336 avctx->pix_fmt = AV_PIX_FMT_PAL8; 337 338 c->dsize = avctx->width * avctx->height * 2; 339 c->decomp_buf = av_malloc(c->dsize + DECOMP_BUF_PADDING); 340 if (!c->decomp_buf) { 341 av_frame_free(&c->prev); 342 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); 343 return AVERROR(ENOMEM); 344 } 345 346 return 0; 347} 348 349static av_cold int decode_end(AVCodecContext *avctx) 350{ 351 DxaDecContext * const c = avctx->priv_data; 352 353 av_freep(&c->decomp_buf); 354 av_frame_free(&c->prev); 355 356 return 0; 357} 358 359AVCodec ff_dxa_decoder = { 360 .name = "dxa", 361 .long_name = NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"), 362 .type = AVMEDIA_TYPE_VIDEO, 363 .id = AV_CODEC_ID_DXA, 364 .priv_data_size = sizeof(DxaDecContext), 365 .init = decode_init, 366 .close = decode_end, 367 .decode = decode_frame, 368 .capabilities = CODEC_CAP_DR1, 369}; 370