2
* Feeble Files/ScummVM DXA decoder
3
* Copyright (c) 2007 Konstantin Shishkov
5
* This file is part of FFmpeg.
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.
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.
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
23
* @file libavcodec/dxa.c
30
#include "libavutil/intreadwrite.h"
38
typedef struct DxaDecContext {
39
AVCodecContext *avctx;
47
static const int shift1[6] = { 0, 8, 8, 8, 4, 4 };
48
static const int shift2[6] = { 0, 0, 8, 4, 0, 4 };
50
static int decode_13(AVCodecContext *avctx, DxaDecContext *c, uint8_t* dst, uint8_t *src, uint8_t *ref)
52
uint8_t *code, *data, *mv, *msk, *tmp, *tmp2;
54
int type, x, y, d, d2;
55
int stride = c->pic.linesize[0];
59
data = code + ((avctx->width * avctx->height) >> 4);
60
mv = data + AV_RB32(src + 0);
61
msk = mv + AV_RB32(src + 4);
63
for(j = 0; j < avctx->height; j += 4){
64
for(i = 0; i < avctx->width; i += 4){
69
case 4: // motion compensation
70
x = (*mv) >> 4; if(x & 8) x = 8 - x;
71
y = (*mv++) & 0xF; if(y & 8) y = 8 - y;
74
case 5: // skip in method 12
75
for(y = 0; y < 4; y++){
81
case 1: // masked change
82
case 10: // masked change with only half of pixels changed
83
case 11: // cases 10-15 are for method 12 only
93
mask = ((msk[0] & 0xF0) << shift1[type]) | ((msk[0] & 0xF) << shift2[type]);
96
for(y = 0; y < 4; y++){
97
for(x = 0; x < 4; x++){
98
tmp[x] = (mask & 0x8000) ? *data++ : tmp2[x];
105
case 2: // fill block
106
for(y = 0; y < 4; y++){
107
memset(tmp, data[0], 4);
113
for(y = 0; y < 4; y++){
114
memcpy(tmp, data, 4);
119
case 8: // subblocks - method 13 only
121
for(k = 0; k < 4; k++){
122
d = ((k & 1) << 1) + ((k & 2) * stride);
123
d2 = ((k & 1) << 1) + ((k & 2) * stride);
126
case 0x80: // motion compensation
127
x = (*mv) >> 4; if(x & 8) x = 8 - x;
128
y = (*mv++) & 0xF; if(y & 8) y = 8 - y;
129
tmp2 += x + y*stride;
131
tmp[d + 0 ] = tmp2[0];
132
tmp[d + 1 ] = tmp2[1];
133
tmp[d + 0 + stride] = tmp2[0 + stride];
134
tmp[d + 1 + stride] = tmp2[1 + stride];
137
tmp[d + 0 ] = data[0];
138
tmp[d + 1 ] = data[0];
139
tmp[d + 0 + stride] = data[0];
140
tmp[d + 1 + stride] = data[0];
144
tmp[d + 0 ] = *data++;
145
tmp[d + 1 ] = *data++;
146
tmp[d + 0 + stride] = *data++;
147
tmp[d + 1 + stride] = *data++;
153
case 32: // vector quantization - 2 colors
156
for(y = 0; y < 4; y++){
157
for(x = 0; x < 4; x++){
158
tmp[x] = data[mask & 1];
166
case 33: // vector quantization - 3 or 4 colors
170
for(y = 0; y < 4; y++){
171
for(x = 0; x < 4; x++){
172
tmp[x] = data[mask & 3];
181
av_log(avctx, AV_LOG_ERROR, "Unknown opcode %d\n", type);
191
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size)
193
DxaDecContext * const c = avctx->priv_data;
194
uint8_t *outptr, *srcptr, *tmpptr;
198
int orig_buf_size = buf_size;
201
/* make the palette available on the way out */
202
if(buf[0]=='C' && buf[1]=='M' && buf[2]=='A' && buf[3]=='P'){
206
for(i = 0; i < 256; i++){
210
c->pal[i] = (r << 16) | (g << 8) | b;
216
if(avctx->get_buffer(avctx, &c->pic) < 0){
217
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
220
memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE);
221
c->pic.palette_has_changed = pc;
223
outptr = c->pic.data[0];
224
srcptr = c->decomp_buf;
225
tmpptr = c->prev.data[0];
226
stride = c->pic.linesize[0];
228
if(buf[0]=='N' && buf[1]=='U' && buf[2]=='L' && buf[3]=='L')
234
if((compr != 4 && compr != -1) && uncompress(c->decomp_buf, &dsize, buf + 9, buf_size - 9) != Z_OK){
235
av_log(avctx, AV_LOG_ERROR, "Uncompress failed!\n");
240
c->pic.key_frame = 0;
241
c->pic.pict_type = FF_P_TYPE;
243
memcpy(c->pic.data[0], c->prev.data[0], c->pic.linesize[0] * avctx->height);
244
else{ // Should happen only when first frame is 'NULL'
245
memset(c->pic.data[0], 0, c->pic.linesize[0] * avctx->height);
246
c->pic.key_frame = 1;
247
c->pic.pict_type = FF_I_TYPE;
254
c->pic.key_frame = !(compr & 1);
255
c->pic.pict_type = (compr & 1) ? FF_P_TYPE : FF_I_TYPE;
256
for(j = 0; j < avctx->height; j++){
258
for(i = 0; i < avctx->width; i++)
259
outptr[i] = srcptr[i] ^ tmpptr[i];
262
memcpy(outptr, srcptr, avctx->width);
264
srcptr += avctx->width;
267
case 12: // ScummVM coding
269
c->pic.key_frame = 0;
270
c->pic.pict_type = FF_P_TYPE;
271
decode_13(avctx, c, c->pic.data[0], srcptr, c->prev.data[0]);
274
av_log(avctx, AV_LOG_ERROR, "Unknown/unsupported compression type %d\n", buf[4]);
278
FFSWAP(AVFrame, c->pic, c->prev);
280
avctx->release_buffer(avctx, &c->pic);
282
*data_size = sizeof(AVFrame);
283
*(AVFrame*)data = c->prev;
285
/* always report that the buffer was completely consumed */
286
return orig_buf_size;
289
static av_cold int decode_init(AVCodecContext *avctx)
291
DxaDecContext * const c = avctx->priv_data;
294
avctx->pix_fmt = PIX_FMT_PAL8;
296
if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
300
c->dsize = avctx->width * avctx->height * 2;
301
if((c->decomp_buf = av_malloc(c->dsize)) == NULL) {
302
av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
309
static av_cold int decode_end(AVCodecContext *avctx)
311
DxaDecContext * const c = avctx->priv_data;
313
av_freep(&c->decomp_buf);
315
avctx->release_buffer(avctx, &c->prev);
317
avctx->release_buffer(avctx, &c->pic);
322
AVCodec dxa_decoder = {
326
sizeof(DxaDecContext),
331
.long_name = NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"),