Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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