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
36
37 #include <zlib.h>
38
39 /*
40 * Decoder context
41 */
44
46 #define DECOMP_BUF_PADDING 16
50
51 static const int shift1[6] = { 0, 8, 8, 8, 4, 4 };
52 static const int shift2[6] = { 0, 0, 8, 4, 0, 4 };
53
56 {
58 uint8_t *src_end =
src + srcsize;
60 int type, x, y,
d, d2;
62
65
70
71 for(j = 0; j < avctx->
height; j += 4){
72 for(
i = 0;
i < avctx->
width;
i += 4){
73 if (
data > src_end ||
mv > src_end || msk > src_end)
79 case 4: // motion compensation
80 x = (*mv) >> 4; if(x & 8) x = 8 - x;
81 y = (*
mv++) & 0xF;
if(y & 8) y = 8 - y;
82 if (i < -x || avctx->
width -
i - 4 < x ||
83 j < -y || avctx->
height - j - 4 < y) {
86 }
88 case 0: // skip
89 case 5: // skip in method 12
90 for(y = 0; y < 4; y++){
94 }
95 break;
96 case 1: // masked change
97 case 10: // masked change with only half of pixels changed
98 case 11: // cases 10-15 are for method 12 only
99 case 12:
100 case 13:
101 case 14:
102 case 15:
105 msk += 2;
106 }else{
109 msk++;
110 }
111 for(y = 0; y < 4; y++){
112 for(x = 0; x < 4; x++){
115 }
118 }
119 break;
120 case 2: // fill block
121 for(y = 0; y < 4; y++){
124 }
126 break;
127 case 3: // raw block
128 for(y = 0; y < 4; y++){
132 }
133 break;
134 case 8: // subblocks - method 13 only
136 for(k = 0; k < 4; k++){
137 d = ((k & 1) << 1) + ((k & 2) *
stride);
138 d2 = ((k & 1) << 1) + ((k & 2) *
stride);
141 case 0x80: // motion compensation
142 x = (*mv) >> 4; if(x & 8) x = 8 - x;
143 y = (*
mv++) & 0xF;
if(y & 8) y = 8 - y;
144 if (
i + 2*(k & 1) < -x || avctx->
width -
i - 2*(k & 1) - 2 < x ||
145 j + (k & 2) < -y || avctx->
height - j - (k & 2) - 2 < y) {
148 }
150 case 0x00: // skip
151 tmp[
d + 0 ] = tmp2[0];
152 tmp[
d + 1 ] = tmp2[1];
155 break;
156 case 0x40: // fill
162 break;
163 case 0xC0: // raw
168 break;
169 }
171 }
172 break;
173 case 32: // vector quantization - 2 colors
175 msk += 2;
176 for(y = 0; y < 4; y++){
177 for(x = 0; x < 4; x++){
180 }
183 }
185 break;
186 case 33: // vector quantization - 3 or 4 colors
187 case 34:
189 msk += 4;
190 for(y = 0; y < 4; y++){
191 for(x = 0; x < 4; x++){
194 }
197 }
199 break;
200 default:
203 }
204 }
207 }
208 return 0;
209 }
210
213 {
215 uint8_t *outptr, *srcptr, *tmpptr;
216 unsigned long dsize;
217 int i, j, compr,
ret;
219 int pc = 0;
221
223
224 /* make the palette available on the way out */
225 if (bytestream2_peek_le32(&gb) ==
MKTAG(
'C',
'M',
'A',
'P')) {
227 for(
i = 0;
i < 256;
i++){
228 c->pal[
i] = 0xFF
U << 24 | bytestream2_get_be24(&gb);
229 }
230 pc = 1;
231 }
232
236 frame->palette_has_changed = pc;
237
238 outptr =
frame->data[0];
239 srcptr =
c->decomp_buf;
240 tmpptr =
c->prev->data[0];
242
243 if (bytestream2_get_le32(&gb) ==
MKTAG(
'N',
'U',
'L',
'L'))
244 compr = -1;
245 else
246 compr = bytestream2_get_byte(&gb);
247
249 if (compr != 4 && compr != -1) {
255 }
257 }
258
261
262 switch(compr){
263 case -1:
264 frame->key_frame = 0;
266 if (
c->prev->data[0])
268 else{ // Should happen only when first frame is 'NULL'
270 frame->key_frame = 1;
272 }
273 break;
274 case 2:
275 case 4:
276 frame->key_frame = 1;
278 for (j = 0; j < avctx->
height; j++) {
279 memcpy(outptr, srcptr, avctx->
width);
281 srcptr += avctx->
width;
282 }
283 break;
284 case 3:
285 case 5:
286 if (!tmpptr) {
290 }
291 frame->key_frame = 0;
293 for (j = 0; j < avctx->
height; j++) {
294 if(tmpptr){
296 outptr[
i] = srcptr[
i] ^ tmpptr[
i];
298 }else
299 memcpy(outptr, srcptr, avctx->
width);
301 srcptr += avctx->
width;
302 }
303 break;
304 case 12: // ScummVM coding
305 case 13:
306 frame->key_frame = 0;
308 if (!
c->prev->data[0]) {
311 }
313 break;
314 default:
317 }
318
322
323 *got_frame = 1;
324
325 /* always report that the buffer was completely consumed */
327 }
328
330 {
332
336 }
337
341
343
346 if (!
c->decomp_buf) {
349 }
350
351 return 0;
352 }
353
355 {
357
360
361 return 0;
362 }
363
375 };