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
, AVPacket
*avpkt
)
193 const uint8_t *buf
= avpkt
->data
;
194 int buf_size
= avpkt
->size
;
195 DxaDecContext
* const c
= avctx
->priv_data
;
196 uint8_t *outptr
, *srcptr
, *tmpptr
;
200 int orig_buf_size
= buf_size
;
203 /* make the palette available on the way out */
204 if(buf
[0]=='C' && buf
[1]=='M' && buf
[2]=='A' && buf
[3]=='P'){
208 for(i
= 0; i
< 256; i
++){
212 c
->pal
[i
] = (r
<< 16) | (g
<< 8) | b
;
218 if(avctx
->get_buffer(avctx
, &c
->pic
) < 0){
219 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
222 memcpy(c
->pic
.data
[1], c
->pal
, AVPALETTE_SIZE
);
223 c
->pic
.palette_has_changed
= pc
;
225 outptr
= c
->pic
.data
[0];
226 srcptr
= c
->decomp_buf
;
227 tmpptr
= c
->prev
.data
[0];
228 stride
= c
->pic
.linesize
[0];
230 if(buf
[0]=='N' && buf
[1]=='U' && buf
[2]=='L' && buf
[3]=='L')
236 if((compr
!= 4 && compr
!= -1) && uncompress(c
->decomp_buf
, &dsize
, buf
+ 9, buf_size
- 9) != Z_OK
){
237 av_log(avctx
, AV_LOG_ERROR
, "Uncompress failed!\n");
242 c
->pic
.key_frame
= 0;
243 c
->pic
.pict_type
= FF_P_TYPE
;
245 memcpy(c
->pic
.data
[0], c
->prev
.data
[0], c
->pic
.linesize
[0] * avctx
->height
);
246 else{ // Should happen only when first frame is 'NULL'
247 memset(c
->pic
.data
[0], 0, c
->pic
.linesize
[0] * avctx
->height
);
248 c
->pic
.key_frame
= 1;
249 c
->pic
.pict_type
= FF_I_TYPE
;
256 c
->pic
.key_frame
= !(compr
& 1);
257 c
->pic
.pict_type
= (compr
& 1) ? FF_P_TYPE
: FF_I_TYPE
;
258 for(j
= 0; j
< avctx
->height
; j
++){
260 for(i
= 0; i
< avctx
->width
; i
++)
261 outptr
[i
] = srcptr
[i
] ^ tmpptr
[i
];
264 memcpy(outptr
, srcptr
, avctx
->width
);
266 srcptr
+= avctx
->width
;
269 case 12: // ScummVM coding
271 c
->pic
.key_frame
= 0;
272 c
->pic
.pict_type
= FF_P_TYPE
;
273 decode_13(avctx
, c
, c
->pic
.data
[0], srcptr
, c
->prev
.data
[0]);
276 av_log(avctx
, AV_LOG_ERROR
, "Unknown/unsupported compression type %d\n", buf
[4]);
280 FFSWAP(AVFrame
, c
->pic
, c
->prev
);
282 avctx
->release_buffer(avctx
, &c
->pic
);
284 *data_size
= sizeof(AVFrame
);
285 *(AVFrame
*)data
= c
->prev
;
287 /* always report that the buffer was completely consumed */
288 return orig_buf_size
;
291 static av_cold
int decode_init(AVCodecContext
*avctx
)
293 DxaDecContext
* const c
= avctx
->priv_data
;
296 avctx
->pix_fmt
= PIX_FMT_PAL8
;
298 if (avcodec_check_dimensions(avctx
, avctx
->width
, avctx
->height
) < 0) {
302 c
->dsize
= avctx
->width
* avctx
->height
* 2;
303 if((c
->decomp_buf
= av_malloc(c
->dsize
)) == NULL
) {
304 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate decompression buffer.\n");
311 static av_cold
int decode_end(AVCodecContext
*avctx
)
313 DxaDecContext
* const c
= avctx
->priv_data
;
315 av_freep(&c
->decomp_buf
);
317 avctx
->release_buffer(avctx
, &c
->prev
);
319 avctx
->release_buffer(avctx
, &c
->pic
);
324 AVCodec dxa_decoder
= {
328 sizeof(DxaDecContext
),
334 .long_name
= NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"),