Statistics
| Branch: | Revision:

ffmpeg / libavcodec / interplayvideo.c @ 268a618b

History | View | Annotate | Download (23.1 KB)

1
/*
2
 * Interplay MVE Video Decoder
3
 * Copyright (C) 2003 the ffmpeg project
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/interplayvideo.c
24
 * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net)
25
 * For more information about the Interplay MVE format, visit:
26
 *   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
 */
36

    
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <unistd.h>
41

    
42
#include "avcodec.h"
43
#include "bytestream.h"
44
#include "dsputil.h"
45

    
46
#define PALETTE_COUNT 256
47

    
48
/* debugging support */
49
#define DEBUG_INTERPLAY 0
50
#if DEBUG_INTERPLAY
51
#define debug_interplay(x,...) av_log(NULL, AV_LOG_DEBUG, x, __VA_ARGS__)
52
#else
53
static inline void debug_interplay(const char *format, ...) { }
54
#endif
55

    
56
typedef struct IpvideoContext {
57

    
58
    AVCodecContext *avctx;
59
    DSPContext dsp;
60
    AVFrame second_last_frame;
61
    AVFrame last_frame;
62
    AVFrame current_frame;
63
    const unsigned char *decoding_map;
64
    int decoding_map_size;
65

    
66
    const unsigned char *buf;
67
    int size;
68

    
69
    const unsigned char *stream_ptr;
70
    const unsigned char *stream_end;
71
    unsigned char *pixel_ptr;
72
    int line_inc;
73
    int stride;
74
    int upper_motion_limit_offset;
75

    
76
} IpvideoContext;
77

    
78
#define CHECK_STREAM_PTR(n) \
79
  if (s->stream_end - s->stream_ptr < n) { \
80
    av_log(s->avctx, AV_LOG_ERROR, "Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \
81
      s->stream_ptr + n, s->stream_end); \
82
    return -1; \
83
  }
84

    
85
static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y)
86
{
87
    int current_offset = s->pixel_ptr - s->current_frame.data[0];
88
    int motion_offset = current_offset + delta_y * s->stride + delta_x;
89
    if (motion_offset < 0) {
90
        av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset);
91
        return -1;
92
    } else if (motion_offset > s->upper_motion_limit_offset) {
93
        av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n",
94
            motion_offset, s->upper_motion_limit_offset);
95
        return -1;
96
    }
97
    s->dsp.put_pixels_tab[1][0](s->pixel_ptr, src->data[0] + motion_offset, s->stride, 8);
98
    return 0;
99
}
100

    
101
static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
102
{
103
    return copy_from(s, &s->last_frame, 0, 0);
104
}
105

    
106
static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
107
{
108
    return copy_from(s, &s->second_last_frame, 0, 0);
109
}
110

    
111
static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
112
{
113
    unsigned char B;
114
    int x, y;
115

    
116
    /* copy block from 2 frames ago using a motion vector; need 1 more byte */
117
    CHECK_STREAM_PTR(1);
118
    B = *s->stream_ptr++;
119

    
120
    if (B < 56) {
121
        x = 8 + (B % 7);
122
        y = B / 7;
123
    } else {
124
        x = -14 + ((B - 56) % 29);
125
        y =   8 + ((B - 56) / 29);
126
    }
127

    
128
    debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
129
    return copy_from(s, &s->second_last_frame, x, y);
130
}
131

    
132
static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
133
{
134
    unsigned char B;
135
    int x, y;
136

    
137
    /* copy 8x8 block from current frame from an up/left block */
138

    
139
    /* need 1 more byte for motion */
140
    CHECK_STREAM_PTR(1);
141
    B = *s->stream_ptr++;
142

    
143
    if (B < 56) {
144
        x = -(8 + (B % 7));
145
        y = -(B / 7);
146
    } else {
147
        x = -(-14 + ((B - 56) % 29));
148
        y = -(  8 + ((B - 56) / 29));
149
    }
150

    
151
    debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
152
    return copy_from(s, &s->current_frame, x, y);
153
}
154

    
155
static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
156
{
157
    int x, y;
158
    unsigned char B, BL, BH;
159

    
160
    /* copy a block from the previous frame; need 1 more byte */
161
    CHECK_STREAM_PTR(1);
162

    
163
    B = *s->stream_ptr++;
164
    BL = B & 0x0F;
165
    BH = (B >> 4) & 0x0F;
166
    x = -8 + BL;
167
    y = -8 + BH;
168

    
169
    debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
170
    return copy_from(s, &s->last_frame, x, y);
171
}
172

    
173
static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
174
{
175
    signed char x, y;
176

    
177
    /* copy a block from the previous frame using an expanded range;
178
     * need 2 more bytes */
179
    CHECK_STREAM_PTR(2);
180

    
181
    x = *s->stream_ptr++;
182
    y = *s->stream_ptr++;
183

    
184
    debug_interplay ("    motion bytes = %d, %d\n", x, y);
185
    return copy_from(s, &s->last_frame, x, y);
186
}
187

    
188
static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
189
{
190
    /* mystery opcode? skip multiple blocks? */
191
    av_log(s->avctx, AV_LOG_ERROR, "  Interplay video: Help! Mystery opcode 0x6 seen\n");
192

    
193
    /* report success */
194
    return 0;
195
}
196

    
197
static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
198
{
199
    int x, y;
200
    unsigned char P[2];
201
    unsigned int flags;
202

    
203
    /* 2-color encoding */
204
    CHECK_STREAM_PTR(2);
205

    
206
    P[0] = *s->stream_ptr++;
207
    P[1] = *s->stream_ptr++;
208

    
209
    if (P[0] <= P[1]) {
210

    
211
        /* need 8 more bytes from the stream */
212
        CHECK_STREAM_PTR(8);
213

    
214
        for (y = 0; y < 8; y++) {
215
            flags = *s->stream_ptr++;
216
            for (x = 0x01; x <= 0x80; x <<= 1) {
217
                *s->pixel_ptr++ = P[!!(flags & x)];
218
            }
219
            s->pixel_ptr += s->line_inc;
220
        }
221

    
222
    } else {
223

    
224
        /* need 2 more bytes from the stream */
225
        CHECK_STREAM_PTR(2);
226

    
227
        flags = bytestream_get_le16(&s->stream_ptr);
228
        for (y = 0; y < 8; y += 2) {
229
            for (x = 0; x < 8; x += 2, flags >>= 1) {
230
                s->pixel_ptr[x                ] =
231
                s->pixel_ptr[x + 1            ] =
232
                s->pixel_ptr[x +     s->stride] =
233
                s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
234
            }
235
            s->pixel_ptr += s->stride * 2;
236
        }
237
    }
238

    
239
    /* report success */
240
    return 0;
241
}
242

    
243
static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
244
{
245
    int x, y;
246
    unsigned char P[8];
247
    unsigned char B[8];
248
    unsigned int flags = 0;
249
    unsigned char P0 = 0, P1 = 0;
250
    int lower_half = 0;
251

    
252
    /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
253
     * either top and bottom or left and right halves */
254
    CHECK_STREAM_PTR(2);
255

    
256
    P[0] = *s->stream_ptr++;
257
    P[1] = *s->stream_ptr++;
258

    
259
    if (P[0] <= P[1]) {
260

    
261
        /* need 12 more bytes */
262
        CHECK_STREAM_PTR(12);
263
        B[0] = *s->stream_ptr++;  B[1] = *s->stream_ptr++;
264
        P[2] = *s->stream_ptr++;  P[3] = *s->stream_ptr++;
265
        B[2] = *s->stream_ptr++;  B[3] = *s->stream_ptr++;
266
        P[4] = *s->stream_ptr++;  P[5] = *s->stream_ptr++;
267
        B[4] = *s->stream_ptr++;  B[5] = *s->stream_ptr++;
268
        P[6] = *s->stream_ptr++;  P[7] = *s->stream_ptr++;
269
        B[6] = *s->stream_ptr++;  B[7] = *s->stream_ptr++;
270

    
271
        for (y = 0; y < 8; y++) {
272

    
273
            /* time to reload flags? */
274
            if (y == 0) {
275
                flags =
276
                    ((B[0] & 0xF0) <<  4) | ((B[4] & 0xF0) <<  8) |
277
                    ((B[0] & 0x0F)      ) | ((B[4] & 0x0F) <<  4) |
278
                    ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
279
                    ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
280
                lower_half = 0;  /* still on top half */
281
            } else if (y == 4) {
282
                flags =
283
                    ((B[2] & 0xF0) <<  4) | ((B[6] & 0xF0) <<  8) |
284
                    ((B[2] & 0x0F)      ) | ((B[6] & 0x0F) <<  4) |
285
                    ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
286
                    ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
287
                lower_half = 2;
288
            }
289

    
290
            for (x = 0; x < 8; x++, flags >>= 1) {
291
                /* get the pixel values ready for this quadrant */
292
                if (x == 0) {
293
                    P0 = P[lower_half + 0];
294
                    P1 = P[lower_half + 1];
295
                } else if (x == 4) {
296
                    P0 = P[lower_half + 4];
297
                    P1 = P[lower_half + 5];
298
                }
299

    
300
                *s->pixel_ptr++ = flags & 1 ? P1 : P0;
301
            }
302
            s->pixel_ptr += s->line_inc;
303
        }
304

    
305
    } else {
306

    
307
        /* need 10 more bytes */
308
        CHECK_STREAM_PTR(10);
309

    
310
        if (P[2] <= P[3]) {
311

    
312
            B[0] = *s->stream_ptr++;  B[1] = *s->stream_ptr++;
313
            B[2] = *s->stream_ptr++;  B[3] = *s->stream_ptr++;
314
            P[2] = *s->stream_ptr++;  P[3] = *s->stream_ptr++;
315
            B[4] = *s->stream_ptr++;  B[5] = *s->stream_ptr++;
316
            B[6] = *s->stream_ptr++;  B[7] = *s->stream_ptr++;
317

    
318
            /* vertical split; left & right halves are 2-color encoded */
319

    
320
            for (y = 0; y < 8; y++) {
321

    
322
                /* time to reload flags? */
323
                if (y == 0) {
324
                    flags =
325
                        ((B[0] & 0xF0) <<  4) | ((B[4] & 0xF0) <<  8) |
326
                        ((B[0] & 0x0F)      ) | ((B[4] & 0x0F) <<  4) |
327
                        ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
328
                        ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
329
                } else if (y == 4) {
330
                    flags =
331
                        ((B[2] & 0xF0) <<  4) | ((B[6] & 0xF0) <<  8) |
332
                        ((B[2] & 0x0F)      ) | ((B[6] & 0x0F) <<  4) |
333
                        ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
334
                        ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
335
                }
336

    
337
                for (x = 0; x < 8; x++, flags >>= 1) {
338
                    /* get the pixel values ready for this half */
339
                    if (x == 0) {
340
                        P0 = P[0];
341
                        P1 = P[1];
342
                    } else if (x == 4) {
343
                        P0 = P[2];
344
                        P1 = P[3];
345
                    }
346

    
347
                    *s->pixel_ptr++ = flags & 1 ? P1 : P0;
348
                }
349
                s->pixel_ptr += s->line_inc;
350
            }
351

    
352
        } else {
353

    
354
            /* horizontal split; top & bottom halves are 2-color encoded */
355

    
356
            for (y = 0; y < 8; y++) {
357
                int bitmask;
358

    
359
                if (y == 4) {
360
                    P[0] = *s->stream_ptr++;
361
                    P[1] = *s->stream_ptr++;
362
                }
363
                flags = *s->stream_ptr++;
364

    
365
                for (bitmask = 0x01; bitmask <= 0x80; bitmask <<= 1) {
366

    
367
                    *s->pixel_ptr++ = P[!!(flags & bitmask)];
368
                }
369
                s->pixel_ptr += s->line_inc;
370
            }
371
        }
372
    }
373

    
374
    /* report success */
375
    return 0;
376
}
377

    
378
static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
379
{
380
    int x, y;
381
    unsigned char P[4];
382

    
383
    /* 4-color encoding */
384
    CHECK_STREAM_PTR(4);
385

    
386
    memcpy(P, s->stream_ptr, 4);
387
    s->stream_ptr += 4;
388

    
389
    if (P[0] <= P[1]) {
390
        if (P[2] <= P[3]) {
391

    
392
        /* 1 of 4 colors for each pixel, need 16 more bytes */
393
        CHECK_STREAM_PTR(16);
394

    
395
        for (y = 0; y < 8; y++) {
396
            /* get the next set of 8 2-bit flags */
397
            int flags = bytestream_get_le16(&s->stream_ptr);
398
            for (x = 0; x < 8; x++, flags >>= 2) {
399
                *s->pixel_ptr++ = P[flags & 0x03];
400
            }
401
            s->pixel_ptr += s->line_inc;
402
        }
403

    
404
        } else {
405
        uint32_t flags;
406

    
407
        /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
408
        CHECK_STREAM_PTR(4);
409

    
410
        flags = bytestream_get_le32(&s->stream_ptr);
411

    
412
        for (y = 0; y < 8; y += 2) {
413
            for (x = 0; x < 8; x += 2, flags >>= 2) {
414
                s->pixel_ptr[x                ] =
415
                s->pixel_ptr[x + 1            ] =
416
                s->pixel_ptr[x +     s->stride] =
417
                s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
418
            }
419
            s->pixel_ptr += s->stride * 2;
420
        }
421

    
422
        }
423
    } else {
424
        if (P[2] <= P[3]) {
425
        uint64_t flags;
426

    
427
        /* 1 of 4 colors for each 2x1 block, need 8 more bytes */
428
        CHECK_STREAM_PTR(8);
429

    
430
        flags = bytestream_get_le64(&s->stream_ptr);
431
        for (y = 0; y < 8; y++) {
432
            for (x = 0; x < 8; x += 2, flags >>= 2) {
433
                s->pixel_ptr[x    ] =
434
                s->pixel_ptr[x + 1] = P[flags & 0x03];
435
            }
436
            s->pixel_ptr += s->stride;
437
        }
438
        } else {
439
        uint64_t flags;
440

    
441
        /* 1 of 4 colors for each 1x2 block, need 8 more bytes */
442
        CHECK_STREAM_PTR(8);
443

    
444
        flags = bytestream_get_le64(&s->stream_ptr);
445
        for (y = 0; y < 8; y += 2) {
446
            for (x = 0; x < 8; x++, flags >>= 2) {
447
                s->pixel_ptr[x            ] =
448
                s->pixel_ptr[x + s->stride] = P[flags & 0x03];
449
            }
450
            s->pixel_ptr += s->stride * 2;
451
        }
452
        }
453
    }
454

    
455
    /* report success */
456
    return 0;
457
}
458

    
459
static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
460
{
461
    int x, y;
462
    unsigned char P[16];
463
    unsigned char B[16];
464
    int flags = 0;
465
    int index;
466
    int split;
467
    int lower_half;
468

    
469
    /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
470
     * either top and bottom or left and right halves */
471
    CHECK_STREAM_PTR(4);
472

    
473
    memcpy(P, s->stream_ptr, 4);
474
    s->stream_ptr += 4;
475

    
476
    if (P[0] <= P[1]) {
477

    
478
        /* 4-color encoding for each quadrant; need 28 more bytes */
479
        CHECK_STREAM_PTR(28);
480

    
481
        memcpy(B, s->stream_ptr, 4);
482
        s->stream_ptr += 4;
483
        for (y = 4; y < 16; y += 4) {
484
            memcpy(P + y, s->stream_ptr, 4);
485
            s->stream_ptr += 4;
486
            memcpy(B + y, s->stream_ptr, 4);
487
            s->stream_ptr += 4;
488
        }
489

    
490
        for (y = 0; y < 8; y++) {
491

    
492
            lower_half = (y >= 4) ? 4 : 0;
493
            flags = (B[y + 8] << 8) | B[y];
494

    
495
            for (x = 0; x < 8; x++, flags >>= 2) {
496
                split = (x >= 4) ? 8 : 0;
497
                index = split + lower_half + (flags & 0x03);
498
                *s->pixel_ptr++ = P[index];
499
            }
500

    
501
            s->pixel_ptr += s->line_inc;
502
        }
503

    
504
    } else {
505

    
506
        /* 4-color encoding for either left and right or top and bottom
507
         * halves; need 20 more bytes */
508
        CHECK_STREAM_PTR(20);
509

    
510
        memcpy(B, s->stream_ptr, 8);
511
        s->stream_ptr += 8;
512
        memcpy(P + 4, s->stream_ptr, 4);
513
        s->stream_ptr += 4;
514
        memcpy(B + 8, s->stream_ptr, 8);
515
        s->stream_ptr += 8;
516

    
517
        if (P[4] <= P[5]) {
518

    
519
            /* block is divided into left and right halves */
520
            for (y = 0; y < 8; y++) {
521

    
522
                flags = (B[y + 8] << 8) | B[y];
523
                split = 0;
524

    
525
                for (x = 0; x < 8; x++, flags >>= 2) {
526
                    if (x == 4)
527
                        split = 4;
528
                    *s->pixel_ptr++ = P[split + (flags & 0x03)];
529
                }
530

    
531
                s->pixel_ptr += s->line_inc;
532
            }
533

    
534
        } else {
535

    
536
            /* block is divided into top and bottom halves */
537
            split = 0;
538
            for (y = 0; y < 8; y++) {
539

    
540
                flags = (B[y * 2 + 1] << 8) | B[y * 2];
541
                if (y == 4)
542
                    split = 4;
543

    
544
                for (x = 0; x < 8; x++, flags >>= 2)
545
                    *s->pixel_ptr++ = P[split + (flags & 0x03)];
546

    
547
                s->pixel_ptr += s->line_inc;
548
            }
549
        }
550
    }
551

    
552
    /* report success */
553
    return 0;
554
}
555

    
556
static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
557
{
558
    int y;
559

    
560
    /* 64-color encoding (each pixel in block is a different color) */
561
    CHECK_STREAM_PTR(64);
562

    
563
    for (y = 0; y < 8; y++) {
564
        memcpy(s->pixel_ptr, s->stream_ptr, 8);
565
        s->stream_ptr += 8;
566
        s->pixel_ptr  += s->stride;
567
    }
568

    
569
    /* report success */
570
    return 0;
571
}
572

    
573
static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
574
{
575
    int x, y;
576

    
577
    /* 16-color block encoding: each 2x2 block is a different color */
578
    CHECK_STREAM_PTR(16);
579

    
580
    for (y = 0; y < 8; y += 2) {
581
        for (x = 0; x < 8; x += 2) {
582
            s->pixel_ptr[x                ] =
583
            s->pixel_ptr[x + 1            ] =
584
            s->pixel_ptr[x +     s->stride] =
585
            s->pixel_ptr[x + 1 + s->stride] = *s->stream_ptr++;
586
        }
587
        s->pixel_ptr += s->stride * 2;
588
    }
589

    
590
    /* report success */
591
    return 0;
592
}
593

    
594
static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
595
{
596
    int y;
597
    unsigned char P[4];
598
    unsigned char index = 0;
599

    
600
    /* 4-color block encoding: each 4x4 block is a different color */
601
    CHECK_STREAM_PTR(4);
602

    
603
    memcpy(P, s->stream_ptr, 4);
604
    s->stream_ptr += 4;
605

    
606
    for (y = 0; y < 8; y++) {
607
        if (y < 4)
608
            index = 0;
609
        else
610
            index = 2;
611

    
612
        memset(s->pixel_ptr    , P[index    ], 4);
613
        memset(s->pixel_ptr + 4, P[index + 1], 4);
614
        s->pixel_ptr += s->stride;
615
    }
616

    
617
    /* report success */
618
    return 0;
619
}
620

    
621
static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
622
{
623
    int y;
624
    unsigned char pix;
625

    
626
    /* 1-color encoding: the whole block is 1 solid color */
627
    CHECK_STREAM_PTR(1);
628
    pix = *s->stream_ptr++;
629

    
630
    for (y = 0; y < 8; y++) {
631
        memset(s->pixel_ptr, pix, 8);
632
        s->pixel_ptr += s->stride;
633
    }
634

    
635
    /* report success */
636
    return 0;
637
}
638

    
639
static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
640
{
641
    int x, y;
642
    unsigned char sample[2];
643

    
644
    /* dithered encoding */
645
    CHECK_STREAM_PTR(2);
646
    sample[0] = *s->stream_ptr++;
647
    sample[1] = *s->stream_ptr++;
648

    
649
    for (y = 0; y < 8; y++) {
650
        for (x = 0; x < 8; x += 2) {
651
            *s->pixel_ptr++ = sample[  y & 1 ];
652
            *s->pixel_ptr++ = sample[!(y & 1)];
653
        }
654
        s->pixel_ptr += s->line_inc;
655
    }
656

    
657
    /* report success */
658
    return 0;
659
}
660

    
661
static int (* const ipvideo_decode_block[])(IpvideoContext *s) = {
662
    ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
663
    ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
664
    ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
665
    ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7,
666
    ipvideo_decode_block_opcode_0x8, ipvideo_decode_block_opcode_0x9,
667
    ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB,
668
    ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD,
669
    ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF,
670
};
671

    
672
static void ipvideo_decode_opcodes(IpvideoContext *s)
673
{
674
    int x, y;
675
    int index = 0;
676
    unsigned char opcode;
677
    int ret;
678
    int code_counts[16] = {0};
679
    static int frame = 0;
680

    
681
    debug_interplay("------------------ frame %d\n", frame);
682
    frame++;
683

    
684
    /* this is PAL8, so make the palette available */
685
    memcpy(s->current_frame.data[1], s->avctx->palctrl->palette, PALETTE_COUNT * 4);
686

    
687
    s->stride = s->current_frame.linesize[0];
688
    s->stream_ptr = s->buf + 14;  /* data starts 14 bytes in */
689
    s->stream_end = s->buf + s->size;
690
    s->line_inc = s->stride - 8;
691
    s->upper_motion_limit_offset = (s->avctx->height - 8) * s->stride
692
        + s->avctx->width - 8;
693

    
694
    for (y = 0; y < (s->stride * s->avctx->height); y += s->stride * 8) {
695
        for (x = y; x < y + s->avctx->width; x += 8) {
696
            /* bottom nibble first, then top nibble (which makes it
697
             * hard to use a GetBitcontext) */
698
            if (index & 1)
699
                opcode = s->decoding_map[index >> 1] >> 4;
700
            else
701
                opcode = s->decoding_map[index >> 1] & 0xF;
702
            index++;
703

    
704
            debug_interplay("  block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
705
                x - y, y / s->stride, opcode, s->stream_ptr);
706
            code_counts[opcode]++;
707

    
708
            s->pixel_ptr = s->current_frame.data[0] + x;
709
            ret = ipvideo_decode_block[opcode](s);
710
            if (ret != 0) {
711
                av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
712
                    frame, x - y, y / s->stride);
713
                return;
714
            }
715
        }
716
    }
717
    if (s->stream_end - s->stream_ptr > 1) {
718
        av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %td bytes left over\n",
719
            s->stream_end - s->stream_ptr);
720
    }
721
}
722

    
723
static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
724
{
725
    IpvideoContext *s = avctx->priv_data;
726

    
727
    s->avctx = avctx;
728

    
729
    if (s->avctx->palctrl == NULL) {
730
        av_log(avctx, AV_LOG_ERROR, " Interplay video: palette expected.\n");
731
        return -1;
732
    }
733

    
734
    avctx->pix_fmt = PIX_FMT_PAL8;
735
    dsputil_init(&s->dsp, avctx);
736

    
737
    /* decoding map contains 4 bits of information per 8x8 block */
738
    s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
739

    
740
    s->current_frame.data[0] = s->last_frame.data[0] =
741
    s->second_last_frame.data[0] = NULL;
742

    
743
    return 0;
744
}
745

    
746
static int ipvideo_decode_frame(AVCodecContext *avctx,
747
                                void *data, int *data_size,
748
                                const uint8_t *buf, int buf_size)
749
{
750
    IpvideoContext *s = avctx->priv_data;
751
    AVPaletteControl *palette_control = avctx->palctrl;
752

    
753
    /* compressed buffer needs to be large enough to at least hold an entire
754
     * decoding map */
755
    if (buf_size < s->decoding_map_size)
756
        return buf_size;
757

    
758
    s->decoding_map = buf;
759
    s->buf = buf + s->decoding_map_size;
760
    s->size = buf_size - s->decoding_map_size;
761

    
762
    s->current_frame.reference = 3;
763
    if (avctx->get_buffer(avctx, &s->current_frame)) {
764
        av_log(avctx, AV_LOG_ERROR, "  Interplay Video: get_buffer() failed\n");
765
        return -1;
766
    }
767

    
768
    ipvideo_decode_opcodes(s);
769

    
770
    if (palette_control->palette_changed) {
771
        palette_control->palette_changed = 0;
772
        s->current_frame.palette_has_changed = 1;
773
    }
774

    
775
    *data_size = sizeof(AVFrame);
776
    *(AVFrame*)data = s->current_frame;
777

    
778
    /* shuffle frames */
779
    if (s->second_last_frame.data[0])
780
        avctx->release_buffer(avctx, &s->second_last_frame);
781
    s->second_last_frame = s->last_frame;
782
    s->last_frame = s->current_frame;
783
    s->current_frame.data[0] = NULL;  /* catch any access attempts */
784

    
785
    /* report that the buffer was completely consumed */
786
    return buf_size;
787
}
788

    
789
static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
790
{
791
    IpvideoContext *s = avctx->priv_data;
792

    
793
    /* release the last frame */
794
    if (s->last_frame.data[0])
795
        avctx->release_buffer(avctx, &s->last_frame);
796
    if (s->second_last_frame.data[0])
797
        avctx->release_buffer(avctx, &s->second_last_frame);
798

    
799
    return 0;
800
}
801

    
802
AVCodec interplay_video_decoder = {
803
    "interplayvideo",
804
    CODEC_TYPE_VIDEO,
805
    CODEC_ID_INTERPLAY_VIDEO,
806
    sizeof(IpvideoContext),
807
    ipvideo_decode_init,
808
    NULL,
809
    ipvideo_decode_end,
810
    ipvideo_decode_frame,
811
    CODEC_CAP_DR1,
812
    .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),
813
};