~rexbron/ffmpeg/debian.libavcore

« back to all changes in this revision

Viewing changes to libavcodec/dxa.c

  • Committer: Andrew Hunter
  • Date: 2010-08-29 06:49:36 UTC
  • Revision ID: andrew@aehunter.net-20100829064936-gyq5l5n2eu0595do
Remove dupe code base

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