Statistics
| Branch: | Revision:

ffmpeg / libavcodec / interplayvideo.c @ 80ca19f7

History | View | Annotate | Download (20.6 KB)

1 3ef8be2b Mike Melanson
/*
2
 * Interplay MVE Video Decoder
3
 * Copyright (C) 2003 the ffmpeg project
4
 *
5 b78e7197 Diego Biurrun
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8 3ef8be2b Mike Melanson
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10 b78e7197 Diego Biurrun
 * version 2.1 of the License, or (at your option) any later version.
11 3ef8be2b Mike Melanson
 *
12 b78e7197 Diego Biurrun
 * FFmpeg is distributed in the hope that it will be useful,
13 3ef8be2b Mike Melanson
 * 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 b78e7197 Diego Biurrun
 * License along with FFmpeg; if not, write to the Free Software
19 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 3ef8be2b Mike Melanson
 */
21
22
/**
23 bad5537e Diego Biurrun
 * @file libavcodec/interplayvideo.c
24 186447f8 Mike Melanson
 * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net)
25 3ef8be2b Mike Melanson
 * For more information about the Interplay MVE format, visit:
26 186447f8 Mike Melanson
 *   http://www.pcisys.net/~melanson/codecs/interplay-mve.txt
27
 * This code is written in such a way that the identifiers match up
28
 * with the encoding descriptions in the document.
29
 *
30
 * This decoder presently only supports a PAL8 output colorspace.
31
 *
32
 * An Interplay video frame consists of 2 parts: The decoding map and
33
 * the video data. A demuxer must load these 2 parts together in a single
34
 * buffer before sending it through the stream to this decoder.
35 3ef8be2b Mike Melanson
 */
36
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
41
#include "avcodec.h"
42 2c124cb6 Ramiro Polla
#include "bytestream.h"
43 3ef8be2b Mike Melanson
#include "dsputil.h"
44 6000439c Reimar Döffinger
#define ALT_BITSTREAM_READER_LE
45
#include "get_bits.h"
46 3ef8be2b Mike Melanson
47 186447f8 Mike Melanson
#define PALETTE_COUNT 256
48
49
/* debugging support */
50
#define DEBUG_INTERPLAY 0
51
#if DEBUG_INTERPLAY
52 58aa2b1d Alex Beregszaszi
#define debug_interplay(x,...) av_log(NULL, AV_LOG_DEBUG, x, __VA_ARGS__)
53 186447f8 Mike Melanson
#else
54
static inline void debug_interplay(const char *format, ...) { }
55
#endif
56
57 3ef8be2b Mike Melanson
typedef struct IpvideoContext {
58
59
    AVCodecContext *avctx;
60
    DSPContext dsp;
61 d86e8568 Mike Melanson
    AVFrame second_last_frame;
62 3ef8be2b Mike Melanson
    AVFrame last_frame;
63
    AVFrame current_frame;
64 7993df65 Michael Niedermayer
    const unsigned char *decoding_map;
65 3ef8be2b Mike Melanson
    int decoding_map_size;
66
67 7993df65 Michael Niedermayer
    const unsigned char *buf;
68 3ef8be2b Mike Melanson
    int size;
69
70 8badb23e Kostya Shishkov
    int is_16bpp;
71 7993df65 Michael Niedermayer
    const unsigned char *stream_ptr;
72
    const unsigned char *stream_end;
73 bf649a9d Mike Melanson
    unsigned char *pixel_ptr;
74
    int line_inc;
75
    int stride;
76
    int upper_motion_limit_offset;
77
78 3ef8be2b Mike Melanson
} IpvideoContext;
79
80 80ca19f7 Kostya Shishkov
#define CHECK_STREAM_PTR(stream_ptr, stream_end, n) \
81
    if (stream_end - stream_ptr < n) { \
82 0fb669ae Kostya Shishkov
        av_log(s->avctx, AV_LOG_ERROR, "Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \
83 80ca19f7 Kostya Shishkov
               stream_ptr + n, stream_end); \
84 0fb669ae Kostya Shishkov
        return -1; \
85
    }
86 186447f8 Mike Melanson
87 aadf8811 Reimar Döffinger
static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y)
88 bf649a9d Mike Melanson
{
89
    int current_offset = s->pixel_ptr - s->current_frame.data[0];
90 aadf8811 Reimar Döffinger
    int motion_offset = current_offset + delta_y * s->stride + delta_x;
91
    if (motion_offset < 0) {
92
        av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset);
93
        return -1;
94
    } else if (motion_offset > s->upper_motion_limit_offset) {
95
        av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n",
96
            motion_offset, s->upper_motion_limit_offset);
97
        return -1;
98
    }
99
    s->dsp.put_pixels_tab[1][0](s->pixel_ptr, src->data[0] + motion_offset, s->stride, 8);
100 bf649a9d Mike Melanson
    return 0;
101
}
102
103 aadf8811 Reimar Döffinger
static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
104 bf649a9d Mike Melanson
{
105 aadf8811 Reimar Döffinger
    return copy_from(s, &s->last_frame, 0, 0);
106
}
107 bf649a9d Mike Melanson
108 aadf8811 Reimar Döffinger
static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
109
{
110
    return copy_from(s, &s->second_last_frame, 0, 0);
111 bf649a9d Mike Melanson
}
112
113
static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
114 186447f8 Mike Melanson
{
115
    unsigned char B;
116
    int x, y;
117
118 bf649a9d Mike Melanson
    /* copy block from 2 frames ago using a motion vector; need 1 more byte */
119 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
120 bf649a9d Mike Melanson
    B = *s->stream_ptr++;
121 186447f8 Mike Melanson
122
    if (B < 56) {
123
        x = 8 + (B % 7);
124
        y = B / 7;
125
    } else {
126
        x = -14 + ((B - 56) % 29);
127
        y =   8 + ((B - 56) / 29);
128
    }
129
130
    debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
131 aadf8811 Reimar Döffinger
    return copy_from(s, &s->second_last_frame, x, y);
132 186447f8 Mike Melanson
}
133
134 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
135 186447f8 Mike Melanson
{
136
    unsigned char B;
137
    int x, y;
138
139
    /* copy 8x8 block from current frame from an up/left block */
140
141
    /* need 1 more byte for motion */
142 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
143 bf649a9d Mike Melanson
    B = *s->stream_ptr++;
144 186447f8 Mike Melanson
145
    if (B < 56) {
146
        x = -(8 + (B % 7));
147
        y = -(B / 7);
148
    } else {
149
        x = -(-14 + ((B - 56) % 29));
150
        y = -(  8 + ((B - 56) / 29));
151
    }
152
153
    debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
154 aadf8811 Reimar Döffinger
    return copy_from(s, &s->current_frame, x, y);
155 186447f8 Mike Melanson
}
156
157 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
158 186447f8 Mike Melanson
{
159
    int x, y;
160
    unsigned char B, BL, BH;
161
162
    /* copy a block from the previous frame; need 1 more byte */
163 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
164 186447f8 Mike Melanson
165 bf649a9d Mike Melanson
    B = *s->stream_ptr++;
166 186447f8 Mike Melanson
    BL = B & 0x0F;
167
    BH = (B >> 4) & 0x0F;
168
    x = -8 + BL;
169
    y = -8 + BH;
170
171
    debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
172 aadf8811 Reimar Döffinger
    return copy_from(s, &s->last_frame, x, y);
173 186447f8 Mike Melanson
}
174
175 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
176 186447f8 Mike Melanson
{
177
    signed char x, y;
178
179
    /* copy a block from the previous frame using an expanded range;
180
     * need 2 more bytes */
181 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
182 186447f8 Mike Melanson
183 bf649a9d Mike Melanson
    x = *s->stream_ptr++;
184
    y = *s->stream_ptr++;
185 186447f8 Mike Melanson
186
    debug_interplay ("    motion bytes = %d, %d\n", x, y);
187 aadf8811 Reimar Döffinger
    return copy_from(s, &s->last_frame, x, y);
188 186447f8 Mike Melanson
}
189
190 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
191 186447f8 Mike Melanson
{
192
    /* mystery opcode? skip multiple blocks? */
193 9b879566 Michel Bardiaux
    av_log(s->avctx, AV_LOG_ERROR, "  Interplay video: Help! Mystery opcode 0x6 seen\n");
194 186447f8 Mike Melanson
195
    /* report success */
196
    return 0;
197
}
198
199 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
200 186447f8 Mike Melanson
{
201
    int x, y;
202 9be06a0e Reimar Döffinger
    unsigned char P[2];
203 186447f8 Mike Melanson
    unsigned int flags;
204
205
    /* 2-color encoding */
206 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
207 186447f8 Mike Melanson
208 9be06a0e Reimar Döffinger
    P[0] = *s->stream_ptr++;
209
    P[1] = *s->stream_ptr++;
210 186447f8 Mike Melanson
211 9be06a0e Reimar Döffinger
    if (P[0] <= P[1]) {
212 186447f8 Mike Melanson
213
        /* need 8 more bytes from the stream */
214 80ca19f7 Kostya Shishkov
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
215 186447f8 Mike Melanson
216
        for (y = 0; y < 8; y++) {
217 f02bd7e4 Reimar Döffinger
            flags = *s->stream_ptr++ | 0x100;
218 dd9630e4 Reimar Döffinger
            for (; flags != 1; flags >>= 1)
219 f02bd7e4 Reimar Döffinger
                *s->pixel_ptr++ = P[flags & 1];
220 bf649a9d Mike Melanson
            s->pixel_ptr += s->line_inc;
221 186447f8 Mike Melanson
        }
222
223
    } else {
224
225
        /* need 2 more bytes from the stream */
226 80ca19f7 Kostya Shishkov
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
227 186447f8 Mike Melanson
228 2c124cb6 Ramiro Polla
        flags = bytestream_get_le16(&s->stream_ptr);
229 186447f8 Mike Melanson
        for (y = 0; y < 8; y += 2) {
230 e3114eb1 Reimar Döffinger
            for (x = 0; x < 8; x += 2, flags >>= 1) {
231 51e35028 Reimar Döffinger
                s->pixel_ptr[x                ] =
232
                s->pixel_ptr[x + 1            ] =
233
                s->pixel_ptr[x +     s->stride] =
234
                s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
235 186447f8 Mike Melanson
            }
236 bf649a9d Mike Melanson
            s->pixel_ptr += s->stride * 2;
237 186447f8 Mike Melanson
        }
238
    }
239
240
    /* report success */
241
    return 0;
242
}
243
244 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
245 186447f8 Mike Melanson
{
246
    int x, y;
247 283531a8 Reimar Döffinger
    unsigned char P[2];
248 186447f8 Mike Melanson
    unsigned int flags = 0;
249
250
    /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
251
     * either top and bottom or left and right halves */
252 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
253 186447f8 Mike Melanson
254 bf649a9d Mike Melanson
    P[0] = *s->stream_ptr++;
255
    P[1] = *s->stream_ptr++;
256 186447f8 Mike Melanson
257
    if (P[0] <= P[1]) {
258
259 80ca19f7 Kostya Shishkov
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 14);
260 283531a8 Reimar Döffinger
        s->stream_ptr -= 2;
261 186447f8 Mike Melanson
262 283531a8 Reimar Döffinger
        for (y = 0; y < 16; y++) {
263
            // new values for each 4x4 block
264
            if (!(y & 3)) {
265
                P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
266
                flags = bytestream_get_le16(&s->stream_ptr);
267 186447f8 Mike Melanson
            }
268
269 dd9630e4 Reimar Döffinger
            for (x = 0; x < 4; x++, flags >>= 1)
270 283531a8 Reimar Döffinger
                *s->pixel_ptr++ = P[flags & 1];
271
            s->pixel_ptr += s->stride - 4;
272
            // switch to right half
273
            if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
274 186447f8 Mike Melanson
        }
275
276
    } else {
277
278
        /* need 10 more bytes */
279 80ca19f7 Kostya Shishkov
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 10);
280 186447f8 Mike Melanson
281 3f300d7e Reimar Döffinger
        if (s->stream_ptr[4] <= s->stream_ptr[5]) {
282 186447f8 Mike Melanson
283 283531a8 Reimar Döffinger
            flags = bytestream_get_le32(&s->stream_ptr);
284 0312b77c Reimar Döffinger
285 186447f8 Mike Melanson
            /* vertical split; left & right halves are 2-color encoded */
286
287 283531a8 Reimar Döffinger
            for (y = 0; y < 16; y++) {
288 dd9630e4 Reimar Döffinger
                for (x = 0; x < 4; x++, flags >>= 1)
289 283531a8 Reimar Döffinger
                    *s->pixel_ptr++ = P[flags & 1];
290
                s->pixel_ptr += s->stride - 4;
291
                // switch to right half
292
                if (y == 7) {
293
                    s->pixel_ptr -= 8 * s->stride - 4;
294
                    P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
295
                    flags = bytestream_get_le32(&s->stream_ptr);
296 186447f8 Mike Melanson
                }
297
            }
298
299
        } else {
300
301
            /* horizontal split; top & bottom halves are 2-color encoded */
302
303
            for (y = 0; y < 8; y++) {
304 0312b77c Reimar Döffinger
                if (y == 4) {
305
                    P[0] = *s->stream_ptr++;
306
                    P[1] = *s->stream_ptr++;
307 186447f8 Mike Melanson
                }
308 f02bd7e4 Reimar Döffinger
                flags = *s->stream_ptr++ | 0x100;
309 186447f8 Mike Melanson
310 dd9630e4 Reimar Döffinger
                for (; flags != 1; flags >>= 1)
311 f02bd7e4 Reimar Döffinger
                    *s->pixel_ptr++ = P[flags & 1];
312 bf649a9d Mike Melanson
                s->pixel_ptr += s->line_inc;
313 186447f8 Mike Melanson
            }
314
        }
315
    }
316
317
    /* report success */
318
    return 0;
319
}
320
321 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
322 186447f8 Mike Melanson
{
323
    int x, y;
324
    unsigned char P[4];
325
326
    /* 4-color encoding */
327 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
328 186447f8 Mike Melanson
329 03b269dd Reimar Döffinger
    memcpy(P, s->stream_ptr, 4);
330
    s->stream_ptr += 4;
331 186447f8 Mike Melanson
332 268a618b Reimar Döffinger
    if (P[0] <= P[1]) {
333
        if (P[2] <= P[3]) {
334 186447f8 Mike Melanson
335 9aaacc24 Reimar Döffinger
            /* 1 of 4 colors for each pixel, need 16 more bytes */
336 80ca19f7 Kostya Shishkov
            CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
337 186447f8 Mike Melanson
338 9aaacc24 Reimar Döffinger
            for (y = 0; y < 8; y++) {
339
                /* get the next set of 8 2-bit flags */
340
                int flags = bytestream_get_le16(&s->stream_ptr);
341 dd9630e4 Reimar Döffinger
                for (x = 0; x < 8; x++, flags >>= 2)
342 9aaacc24 Reimar Döffinger
                    *s->pixel_ptr++ = P[flags & 0x03];
343
                s->pixel_ptr += s->line_inc;
344 186447f8 Mike Melanson
            }
345
346 268a618b Reimar Döffinger
        } else {
347 9aaacc24 Reimar Döffinger
            uint32_t flags;
348 186447f8 Mike Melanson
349 9aaacc24 Reimar Döffinger
            /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
350 80ca19f7 Kostya Shishkov
            CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
351 186447f8 Mike Melanson
352 9aaacc24 Reimar Döffinger
            flags = bytestream_get_le32(&s->stream_ptr);
353 186447f8 Mike Melanson
354 9aaacc24 Reimar Döffinger
            for (y = 0; y < 8; y += 2) {
355
                for (x = 0; x < 8; x += 2, flags >>= 2) {
356
                    s->pixel_ptr[x                ] =
357
                    s->pixel_ptr[x + 1            ] =
358
                    s->pixel_ptr[x +     s->stride] =
359
                    s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
360
                }
361
                s->pixel_ptr += s->stride * 2;
362 186447f8 Mike Melanson
            }
363
364 268a618b Reimar Döffinger
        }
365
    } else {
366 0448b78b Reimar Döffinger
        uint64_t flags;
367 186447f8 Mike Melanson
368 1548839e Reimar Döffinger
        /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */
369 80ca19f7 Kostya Shishkov
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
370 186447f8 Mike Melanson
371 0448b78b Reimar Döffinger
        flags = bytestream_get_le64(&s->stream_ptr);
372 1548839e Reimar Döffinger
        if (P[2] <= P[3]) {
373 9aaacc24 Reimar Döffinger
            for (y = 0; y < 8; y++) {
374
                for (x = 0; x < 8; x += 2, flags >>= 2) {
375
                    s->pixel_ptr[x    ] =
376
                    s->pixel_ptr[x + 1] = P[flags & 0x03];
377
                }
378
                s->pixel_ptr += s->stride;
379 186447f8 Mike Melanson
            }
380 268a618b Reimar Döffinger
        } else {
381 9aaacc24 Reimar Döffinger
            for (y = 0; y < 8; y += 2) {
382
                for (x = 0; x < 8; x++, flags >>= 2) {
383
                    s->pixel_ptr[x            ] =
384
                    s->pixel_ptr[x + s->stride] = P[flags & 0x03];
385
                }
386
                s->pixel_ptr += s->stride * 2;
387 186447f8 Mike Melanson
            }
388 268a618b Reimar Döffinger
        }
389 186447f8 Mike Melanson
    }
390
391
    /* report success */
392
    return 0;
393
}
394
395 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
396 186447f8 Mike Melanson
{
397
    int x, y;
398 49a20ffa Reimar Döffinger
    unsigned char P[4];
399 186447f8 Mike Melanson
    int flags = 0;
400
401
    /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
402
     * either top and bottom or left and right halves */
403 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
404 186447f8 Mike Melanson
405 49a20ffa Reimar Döffinger
    if (s->stream_ptr[0] <= s->stream_ptr[1]) {
406 186447f8 Mike Melanson
407 49a20ffa Reimar Döffinger
        /* 4-color encoding for each quadrant; need 32 bytes */
408 80ca19f7 Kostya Shishkov
        CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
409 186447f8 Mike Melanson
410 5e8b83ac Reimar Döffinger
        for (y = 0; y < 16; y++) {
411
            // new values for each 4x4 block
412
            if (!(y & 3)) {
413
                memcpy(P, s->stream_ptr, 4);
414
                s->stream_ptr += 4;
415
                flags = bytestream_get_le32(&s->stream_ptr);
416
            }
417 186447f8 Mike Melanson
418 dd9630e4 Reimar Döffinger
            for (x = 0; x < 4; x++, flags >>= 2)
419 5e8b83ac Reimar Döffinger
                *s->pixel_ptr++ = P[flags & 0x03];
420 186447f8 Mike Melanson
421 5e8b83ac Reimar Döffinger
            s->pixel_ptr += s->stride - 4;
422
            // switch to right half
423
            if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
424 186447f8 Mike Melanson
        }
425
426
    } else {
427 49a20ffa Reimar Döffinger
        // vertical split?
428
        int vert = s->stream_ptr[12] <= s->stream_ptr[13];
429
        uint64_t flags = 0;
430 186447f8 Mike Melanson
431
        /* 4-color encoding for either left and right or top and bottom
432 49a20ffa Reimar Döffinger
         * halves */
433 186447f8 Mike Melanson
434 49a20ffa Reimar Döffinger
        for (y = 0; y < 16; y++) {
435
            // load values for each half
436
            if (!(y & 7)) {
437
                memcpy(P, s->stream_ptr, 4);
438
                s->stream_ptr += 4;
439
                flags = bytestream_get_le64(&s->stream_ptr);
440 186447f8 Mike Melanson
            }
441
442 49a20ffa Reimar Döffinger
            for (x = 0; x < 4; x++, flags >>= 2)
443
                *s->pixel_ptr++ = P[flags & 0x03];
444 186447f8 Mike Melanson
445 49a20ffa Reimar Döffinger
            if (vert) {
446
                s->pixel_ptr += s->stride - 4;
447
                // switch to right half
448
                if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
449
            } else if (y & 1) s->pixel_ptr += s->line_inc;
450 186447f8 Mike Melanson
        }
451
    }
452
453
    /* report success */
454
    return 0;
455
}
456
457 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
458 186447f8 Mike Melanson
{
459 03b269dd Reimar Döffinger
    int y;
460 186447f8 Mike Melanson
461
    /* 64-color encoding (each pixel in block is a different color) */
462 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 64);
463 186447f8 Mike Melanson
464
    for (y = 0; y < 8; y++) {
465 03b269dd Reimar Döffinger
        memcpy(s->pixel_ptr, s->stream_ptr, 8);
466
        s->stream_ptr += 8;
467
        s->pixel_ptr  += s->stride;
468 186447f8 Mike Melanson
    }
469
470
    /* report success */
471
    return 0;
472
}
473
474 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
475 186447f8 Mike Melanson
{
476
    int x, y;
477
478
    /* 16-color block encoding: each 2x2 block is a different color */
479 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
480 186447f8 Mike Melanson
481
    for (y = 0; y < 8; y += 2) {
482
        for (x = 0; x < 8; x += 2) {
483 32eea24e Reimar Döffinger
            s->pixel_ptr[x                ] =
484
            s->pixel_ptr[x + 1            ] =
485
            s->pixel_ptr[x +     s->stride] =
486 3766b9e0 Reimar Döffinger
            s->pixel_ptr[x + 1 + s->stride] = *s->stream_ptr++;
487 186447f8 Mike Melanson
        }
488 bf649a9d Mike Melanson
        s->pixel_ptr += s->stride * 2;
489 186447f8 Mike Melanson
    }
490
491
    /* report success */
492
    return 0;
493
}
494
495 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
496 186447f8 Mike Melanson
{
497 03b269dd Reimar Döffinger
    int y;
498 8514f842 Reimar Döffinger
    unsigned char P[2];
499 186447f8 Mike Melanson
500
    /* 4-color block encoding: each 4x4 block is a different color */
501 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
502 186447f8 Mike Melanson
503 8514f842 Reimar Döffinger
    for (y = 0; y < 8; y++) {
504
        if (!(y & 3)) {
505
            P[0] = *s->stream_ptr++;
506
            P[1] = *s->stream_ptr++;
507
        }
508
        memset(s->pixel_ptr,     P[0], 4);
509
        memset(s->pixel_ptr + 4, P[1], 4);
510 03b269dd Reimar Döffinger
        s->pixel_ptr += s->stride;
511 186447f8 Mike Melanson
    }
512
513
    /* report success */
514
    return 0;
515
}
516
517 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
518 186447f8 Mike Melanson
{
519 03b269dd Reimar Döffinger
    int y;
520 186447f8 Mike Melanson
    unsigned char pix;
521
522
    /* 1-color encoding: the whole block is 1 solid color */
523 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
524 bf649a9d Mike Melanson
    pix = *s->stream_ptr++;
525 186447f8 Mike Melanson
526
    for (y = 0; y < 8; y++) {
527 03b269dd Reimar Döffinger
        memset(s->pixel_ptr, pix, 8);
528
        s->pixel_ptr += s->stride;
529 186447f8 Mike Melanson
    }
530
531
    /* report success */
532
    return 0;
533
}
534
535 bf649a9d Mike Melanson
static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
536 186447f8 Mike Melanson
{
537
    int x, y;
538 9be06a0e Reimar Döffinger
    unsigned char sample[2];
539 186447f8 Mike Melanson
540
    /* dithered encoding */
541 80ca19f7 Kostya Shishkov
    CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
542 9be06a0e Reimar Döffinger
    sample[0] = *s->stream_ptr++;
543
    sample[1] = *s->stream_ptr++;
544 186447f8 Mike Melanson
545
    for (y = 0; y < 8; y++) {
546
        for (x = 0; x < 8; x += 2) {
547 9be06a0e Reimar Döffinger
            *s->pixel_ptr++ = sample[  y & 1 ];
548
            *s->pixel_ptr++ = sample[!(y & 1)];
549 186447f8 Mike Melanson
        }
550 bf649a9d Mike Melanson
        s->pixel_ptr += s->line_inc;
551 186447f8 Mike Melanson
    }
552
553
    /* report success */
554
    return 0;
555
}
556
557 fff60779 Reimar Döffinger
static int (* const ipvideo_decode_block[])(IpvideoContext *s) = {
558
    ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
559
    ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
560
    ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
561
    ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7,
562
    ipvideo_decode_block_opcode_0x8, ipvideo_decode_block_opcode_0x9,
563
    ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB,
564
    ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD,
565
    ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF,
566
};
567 186447f8 Mike Melanson
568
static void ipvideo_decode_opcodes(IpvideoContext *s)
569
{
570
    int x, y;
571
    unsigned char opcode;
572
    int ret;
573
    static int frame = 0;
574 6000439c Reimar Döffinger
    GetBitContext gb;
575 186447f8 Mike Melanson
576
    debug_interplay("------------------ frame %d\n", frame);
577
    frame++;
578
579
    /* this is PAL8, so make the palette available */
580 2a2bbcb0 Mike Melanson
    memcpy(s->current_frame.data[1], s->avctx->palctrl->palette, PALETTE_COUNT * 4);
581 bf649a9d Mike Melanson
582
    s->stride = s->current_frame.linesize[0];
583
    s->stream_ptr = s->buf + 14;  /* data starts 14 bytes in */
584
    s->stream_end = s->buf + s->size;
585
    s->line_inc = s->stride - 8;
586
    s->upper_motion_limit_offset = (s->avctx->height - 8) * s->stride
587
        + s->avctx->width - 8;
588
589 6000439c Reimar Döffinger
    init_get_bits(&gb, s->decoding_map, s->decoding_map_size * 8);
590 9156a5ad Kostya Shishkov
    for (y = 0; y < s->avctx->height; y += 8) {
591
        for (x = 0; x < s->avctx->width; x += 8) {
592 6000439c Reimar Döffinger
            opcode = get_bits(&gb, 4);
593 bf649a9d Mike Melanson
594
            debug_interplay("  block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
595 9156a5ad Kostya Shishkov
                            x, y, opcode, s->stream_ptr);
596 bf649a9d Mike Melanson
597 9156a5ad Kostya Shishkov
            s->pixel_ptr = s->current_frame.data[0] + x
598
                          + y*s->current_frame.linesize[0];
599 bf649a9d Mike Melanson
            ret = ipvideo_decode_block[opcode](s);
600
            if (ret != 0) {
601 9b879566 Michel Bardiaux
                av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
602 9156a5ad Kostya Shishkov
                       frame, x, y);
603 bf649a9d Mike Melanson
                return;
604 186447f8 Mike Melanson
            }
605
        }
606
    }
607 3017d8e9 Reimar Döffinger
    if (s->stream_end - s->stream_ptr > 1) {
608 4733abcb Måns Rullgård
        av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %td bytes left over\n",
609 0fb669ae Kostya Shishkov
               s->stream_end - s->stream_ptr);
610 bf649a9d Mike Melanson
    }
611 186447f8 Mike Melanson
}
612
613 98a6fff9 Zuxy Meng
static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
614 3ef8be2b Mike Melanson
{
615
    IpvideoContext *s = avctx->priv_data;
616
617
    s->avctx = avctx;
618 186447f8 Mike Melanson
619 2a2bbcb0 Mike Melanson
    if (s->avctx->palctrl == NULL) {
620 9b879566 Michel Bardiaux
        av_log(avctx, AV_LOG_ERROR, " Interplay video: palette expected.\n");
621 186447f8 Mike Melanson
        return -1;
622
    }
623
624 8badb23e Kostya Shishkov
    s->is_16bpp = avctx->bits_per_coded_sample == 16;
625
    avctx->pix_fmt = s->is_16bpp ? PIX_FMT_RGB555 : PIX_FMT_PAL8;
626
    if (s->is_16bpp) {
627
        av_log(avctx, AV_LOG_ERROR, "16-bit Interplay video is not supported yet.\n");
628
        return -1;
629
    }
630 3ef8be2b Mike Melanson
    dsputil_init(&s->dsp, avctx);
631
632
    /* decoding map contains 4 bits of information per 8x8 block */
633
    s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
634 186447f8 Mike Melanson
635 d86e8568 Mike Melanson
    s->current_frame.data[0] = s->last_frame.data[0] =
636
    s->second_last_frame.data[0] = NULL;
637
638 3ef8be2b Mike Melanson
    return 0;
639
}
640
641
static int ipvideo_decode_frame(AVCodecContext *avctx,
642
                                void *data, int *data_size,
643 7a00bbad Thilo Borgmann
                                AVPacket *avpkt)
644 3ef8be2b Mike Melanson
{
645 7a00bbad Thilo Borgmann
    const uint8_t *buf = avpkt->data;
646
    int buf_size = avpkt->size;
647 3ef8be2b Mike Melanson
    IpvideoContext *s = avctx->priv_data;
648 2a2bbcb0 Mike Melanson
    AVPaletteControl *palette_control = avctx->palctrl;
649 3ef8be2b Mike Melanson
650 18a508c5 Mike Melanson
    /* compressed buffer needs to be large enough to at least hold an entire
651
     * decoding map */
652
    if (buf_size < s->decoding_map_size)
653
        return buf_size;
654
655 186447f8 Mike Melanson
    s->decoding_map = buf;
656
    s->buf = buf + s->decoding_map_size;
657
    s->size = buf_size - s->decoding_map_size;
658 3ef8be2b Mike Melanson
659 d86e8568 Mike Melanson
    s->current_frame.reference = 3;
660 186447f8 Mike Melanson
    if (avctx->get_buffer(avctx, &s->current_frame)) {
661 9b879566 Michel Bardiaux
        av_log(avctx, AV_LOG_ERROR, "  Interplay Video: get_buffer() failed\n");
662 186447f8 Mike Melanson
        return -1;
663
    }
664 3ef8be2b Mike Melanson
665 186447f8 Mike Melanson
    ipvideo_decode_opcodes(s);
666 3ef8be2b Mike Melanson
667 2a2bbcb0 Mike Melanson
    if (palette_control->palette_changed) {
668
        palette_control->palette_changed = 0;
669
        s->current_frame.palette_has_changed = 1;
670
    }
671
672 d86e8568 Mike Melanson
    *data_size = sizeof(AVFrame);
673
    *(AVFrame*)data = s->current_frame;
674 3ef8be2b Mike Melanson
675 186447f8 Mike Melanson
    /* shuffle frames */
676 d86e8568 Mike Melanson
    if (s->second_last_frame.data[0])
677
        avctx->release_buffer(avctx, &s->second_last_frame);
678
    s->second_last_frame = s->last_frame;
679 186447f8 Mike Melanson
    s->last_frame = s->current_frame;
680 d86e8568 Mike Melanson
    s->current_frame.data[0] = NULL;  /* catch any access attempts */
681 3ef8be2b Mike Melanson
682 186447f8 Mike Melanson
    /* report that the buffer was completely consumed */
683 3ef8be2b Mike Melanson
    return buf_size;
684
}
685
686 98a6fff9 Zuxy Meng
static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
687 3ef8be2b Mike Melanson
{
688
    IpvideoContext *s = avctx->priv_data;
689
690
    /* release the last frame */
691 d86e8568 Mike Melanson
    if (s->last_frame.data[0])
692
        avctx->release_buffer(avctx, &s->last_frame);
693
    if (s->second_last_frame.data[0])
694
        avctx->release_buffer(avctx, &s->second_last_frame);
695 3ef8be2b Mike Melanson
696
    return 0;
697
}
698
699
AVCodec interplay_video_decoder = {
700
    "interplayvideo",
701
    CODEC_TYPE_VIDEO,
702
    CODEC_ID_INTERPLAY_VIDEO,
703
    sizeof(IpvideoContext),
704
    ipvideo_decode_init,
705
    NULL,
706
    ipvideo_decode_end,
707
    ipvideo_decode_frame,
708
    CODEC_CAP_DR1,
709 0ffbc258 Diego Biurrun
    .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),
710 3ef8be2b Mike Melanson
};