~akirad/cinecutie/trunk

« back to all changes in this revision

Viewing changes to quicktime/ffmpeg/libavcodec/dxa.c

  • Committer: Paolo Rampino
  • Date: 2010-02-17 19:46:21 UTC
  • Revision ID: git-v1:c39ff77ffa6ae08441c12e7d7f54e3897ddde7f1
Initial Merge

Show diffs side-by-side

added added

removed removed

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