2 * Feeble Files/ScummVM DXA decoder
3 * Copyright (c) 2007 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "libavutil/common.h"
31 #include "libavutil/intreadwrite.h"
40 typedef struct DxaDecContext
{
48 static const int shift1
[6] = { 0, 8, 8, 8, 4, 4 };
49 static const int shift2
[6] = { 0, 0, 8, 4, 0, 4 };
51 static int decode_13(AVCodecContext
*avctx
, DxaDecContext
*c
, uint8_t* dst
,
52 int stride
, uint8_t *src
, uint8_t *ref
)
54 uint8_t *code
, *data
, *mv
, *msk
, *tmp
, *tmp2
;
56 int type
, x
, y
, d
, d2
;
60 data
= code
+ ((avctx
->width
* avctx
->height
) >> 4);
61 mv
= data
+ AV_RB32(src
+ 0);
62 msk
= mv
+ AV_RB32(src
+ 4);
64 for(j
= 0; j
< avctx
->height
; j
+= 4){
65 for(i
= 0; i
< avctx
->width
; i
+= 4){
70 case 4: // motion compensation
71 x
= (*mv
) >> 4; if(x
& 8) x
= 8 - x
;
72 y
= (*mv
++) & 0xF; if(y
& 8) y
= 8 - y
;
75 case 5: // skip in method 12
76 for(y
= 0; y
< 4; y
++){
82 case 1: // masked change
83 case 10: // masked change with only half of pixels changed
84 case 11: // cases 10-15 are for method 12 only
94 mask
= ((msk
[0] & 0xF0) << shift1
[type
]) | ((msk
[0] & 0xF) << shift2
[type
]);
97 for(y
= 0; y
< 4; y
++){
98 for(x
= 0; x
< 4; x
++){
99 tmp
[x
] = (mask
& 0x8000) ? *data
++ : tmp2
[x
];
106 case 2: // fill block
107 for(y
= 0; y
< 4; y
++){
108 memset(tmp
, data
[0], 4);
114 for(y
= 0; y
< 4; y
++){
115 memcpy(tmp
, data
, 4);
120 case 8: // subblocks - method 13 only
122 for(k
= 0; k
< 4; k
++){
123 d
= ((k
& 1) << 1) + ((k
& 2) * stride
);
124 d2
= ((k
& 1) << 1) + ((k
& 2) * stride
);
127 case 0x80: // motion compensation
128 x
= (*mv
) >> 4; if(x
& 8) x
= 8 - x
;
129 y
= (*mv
++) & 0xF; if(y
& 8) y
= 8 - y
;
130 tmp2
+= x
+ y
*stride
;
132 tmp
[d
+ 0 ] = tmp2
[0];
133 tmp
[d
+ 1 ] = tmp2
[1];
134 tmp
[d
+ 0 + stride
] = tmp2
[0 + stride
];
135 tmp
[d
+ 1 + stride
] = tmp2
[1 + stride
];
138 tmp
[d
+ 0 ] = data
[0];
139 tmp
[d
+ 1 ] = data
[0];
140 tmp
[d
+ 0 + stride
] = data
[0];
141 tmp
[d
+ 1 + stride
] = data
[0];
145 tmp
[d
+ 0 ] = *data
++;
146 tmp
[d
+ 1 ] = *data
++;
147 tmp
[d
+ 0 + stride
] = *data
++;
148 tmp
[d
+ 1 + stride
] = *data
++;
154 case 32: // vector quantization - 2 colors
157 for(y
= 0; y
< 4; y
++){
158 for(x
= 0; x
< 4; x
++){
159 tmp
[x
] = data
[mask
& 1];
167 case 33: // vector quantization - 3 or 4 colors
171 for(y
= 0; y
< 4; y
++){
172 for(x
= 0; x
< 4; x
++){
173 tmp
[x
] = data
[mask
& 3];
182 av_log(avctx
, AV_LOG_ERROR
, "Unknown opcode %d\n", type
);
183 return AVERROR_INVALIDDATA
;
192 static int decode_frame(AVCodecContext
*avctx
, void *data
, int *got_frame
, AVPacket
*avpkt
)
194 AVFrame
*frame
= data
;
195 const uint8_t *buf
= avpkt
->data
;
196 int buf_size
= avpkt
->size
;
197 DxaDecContext
* const c
= avctx
->priv_data
;
198 uint8_t *outptr
, *srcptr
, *tmpptr
;
200 int i
, j
, compr
, ret
;
202 int orig_buf_size
= buf_size
;
205 /* make the palette available on the way out */
206 if(buf
[0]=='C' && buf
[1]=='M' && buf
[2]=='A' && buf
[3]=='P'){
210 for(i
= 0; i
< 256; i
++){
214 c
->pal
[i
] = (r
<< 16) | (g
<< 8) | b
;
220 if ((ret
= ff_get_buffer(avctx
, frame
, AV_GET_BUFFER_FLAG_REF
)) < 0) {
221 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
224 memcpy(frame
->data
[1], c
->pal
, AVPALETTE_SIZE
);
225 frame
->palette_has_changed
= pc
;
227 outptr
= frame
->data
[0];
228 srcptr
= c
->decomp_buf
;
229 tmpptr
= c
->prev
->data
[0];
230 stride
= frame
->linesize
[0];
232 if(buf
[0]=='N' && buf
[1]=='U' && buf
[2]=='L' && buf
[3]=='L')
238 if((compr
!= 4 && compr
!= -1) && uncompress(c
->decomp_buf
, &dsize
, buf
+ 9, buf_size
- 9) != Z_OK
){
239 av_log(avctx
, AV_LOG_ERROR
, "Uncompress failed!\n");
240 return AVERROR_UNKNOWN
;
244 frame
->key_frame
= 0;
245 frame
->pict_type
= AV_PICTURE_TYPE_P
;
246 if (c
->prev
->data
[0])
247 memcpy(frame
->data
[0], c
->prev
->data
[0], frame
->linesize
[0] * avctx
->height
);
248 else{ // Should happen only when first frame is 'NULL'
249 memset(frame
->data
[0], 0, frame
->linesize
[0] * avctx
->height
);
250 frame
->key_frame
= 1;
251 frame
->pict_type
= AV_PICTURE_TYPE_I
;
256 frame
->key_frame
= 1;
257 frame
->pict_type
= AV_PICTURE_TYPE_I
;
258 for (j
= 0; j
< avctx
->height
; j
++) {
259 memcpy(outptr
, srcptr
, avctx
->width
);
261 srcptr
+= avctx
->width
;
267 av_log(avctx
, AV_LOG_ERROR
, "Missing reference frame.\n");
268 return AVERROR_INVALIDDATA
;
270 frame
->key_frame
= 0;
271 frame
->pict_type
= AV_PICTURE_TYPE_P
;
272 for (j
= 0; j
< avctx
->height
; j
++) {
273 for (i
= 0; i
< avctx
->width
; i
++)
274 outptr
[i
] = srcptr
[i
] ^ tmpptr
[i
];
277 srcptr
+= avctx
->width
;
280 case 12: // ScummVM coding
282 frame
->key_frame
= 0;
283 frame
->pict_type
= AV_PICTURE_TYPE_P
;
284 decode_13(avctx
, c
, frame
->data
[0], frame
->linesize
[0], srcptr
, c
->prev
->data
[0]);
287 av_log(avctx
, AV_LOG_ERROR
, "Unknown/unsupported compression type %d\n", buf
[4]);
288 return AVERROR_INVALIDDATA
;
291 av_frame_unref(c
->prev
);
292 if ((ret
= av_frame_ref(c
->prev
, frame
)) < 0)
297 /* always report that the buffer was completely consumed */
298 return orig_buf_size
;
301 static av_cold
int decode_init(AVCodecContext
*avctx
)
303 DxaDecContext
* const c
= avctx
->priv_data
;
305 c
->prev
= av_frame_alloc();
307 return AVERROR(ENOMEM
);
309 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
311 c
->dsize
= avctx
->width
* avctx
->height
* 2;
312 if (!(c
->decomp_buf
= av_malloc(c
->dsize
))) {
313 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate decompression buffer.\n");
314 return AVERROR(ENOMEM
);
320 static av_cold
int decode_end(AVCodecContext
*avctx
)
322 DxaDecContext
* const c
= avctx
->priv_data
;
324 av_freep(&c
->decomp_buf
);
325 av_frame_free(&c
->prev
);
330 AVCodec ff_dxa_decoder
= {
332 .long_name
= NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"),
333 .type
= AVMEDIA_TYPE_VIDEO
,
334 .id
= AV_CODEC_ID_DXA
,
335 .priv_data_size
= sizeof(DxaDecContext
),
338 .decode
= decode_frame
,
339 .capabilities
= AV_CODEC_CAP_DR1
,