2
* Interplay MVE Video Decoder (16 bit)
3
* Copyright (C) 2003 the ffmpeg project, Mike Melanson
4
* (C) 2006 Jens Granseuer
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
* For more information about the Interplay MVE format, visit:
21
* http://www.pcisys.net/~melanson/codecs/interplay-mve.txt
24
#include "gstmvedemux.h"
27
#define PIXEL(s) GST_READ_UINT16_LE (s)
29
#define CHECK_STREAM(l, n) \
31
if (G_UNLIKELY (*(l) < (n))) { \
32
GST_ERROR ("wanted to read %d bytes from stream, %d available", (n), *(l)); \
38
/* copy an 8x8 block from the stream to the frame buffer */
40
ipvideo_copy_block (const GstMveDemuxStream * s, unsigned short *frame,
41
const unsigned short *src, int offset)
46
frame_offset = frame - (unsigned short *) s->back_buf1 + offset;
48
if (G_UNLIKELY (frame_offset < 0)) {
49
GST_ERROR ("frame offset < 0 (%d)", frame_offset);
51
} else if (G_UNLIKELY (frame_offset > s->max_block_offset)) {
52
GST_ERROR ("frame offset above limit (%d > %u)",
53
frame_offset, s->max_block_offset);
57
for (i = 0; i < 8; ++i) {
58
memcpy (frame, src, 16);
67
ipvideo_decode_0x2 (const GstMveDemuxStream * s, unsigned short *frame,
68
const unsigned char **data, unsigned short *len)
74
/* copy block from 2 frames ago using a motion vector */
75
CHECK_STREAM (len, 1);
82
x = -14 + ((B - 56) % 29);
83
y = 8 + ((B - 56) / 29);
85
offset = y * s->width + x;
87
return ipvideo_copy_block (s, frame, frame + offset, offset);
91
ipvideo_decode_0x3 (const GstMveDemuxStream * s, unsigned short *frame,
92
const unsigned char **data, unsigned short *len)
98
/* copy 8x8 block from current frame from an up/left block */
99
CHECK_STREAM (len, 1);
106
x = -(-14 + ((B - 56) % 29));
107
y = -(8 + ((B - 56) / 29));
109
offset = y * s->width + x;
111
return ipvideo_copy_block (s, frame, frame + offset, offset);
115
ipvideo_decode_0x4 (const GstMveDemuxStream * s, unsigned short *frame,
116
const unsigned char **data, unsigned short *len)
122
/* copy a block from the previous frame */
123
CHECK_STREAM (len, 1);
127
offset = y * s->width + x;
129
return ipvideo_copy_block (s, frame, frame +
130
((unsigned short *) s->back_buf2 - (unsigned short *) s->back_buf1) +
135
ipvideo_decode_0x5 (const GstMveDemuxStream * s, unsigned short *frame,
136
const unsigned char **data, unsigned short *len)
141
/* copy a block from the previous frame using an expanded range */
142
CHECK_STREAM (len, 2);
143
x = (signed char) *(*data)++;
144
y = (signed char) *(*data)++;
145
offset = y * s->width + x;
147
return ipvideo_copy_block (s, frame, frame +
148
((unsigned short *) s->back_buf2 - (unsigned short *) s->back_buf1) +
153
ipvideo_decode_0x7 (const GstMveDemuxStream * s, unsigned short *frame,
154
const unsigned char **data, unsigned short *len)
157
unsigned short P0, P1;
161
/* 2-color encoding */
162
CHECK_STREAM (len, 4 + 2);
168
if (!(P0 & 0x8000)) {
170
/* need 8 more bytes from the stream */
171
CHECK_STREAM (len, 8 - 2);
173
for (y = 0; y < 8; ++y) {
175
for (x = 0x01; x <= 0x80; x <<= 1) {
181
frame += s->width - 8;
187
/* need 2 more bytes from the stream */
189
flags = ((*data)[1] << 8) | (*data)[0];
192
for (y = 0; y < 8; y += 2) {
193
for (x = 0; x < 8; x += 2, bitmask <<= 1) {
194
if (flags & bitmask) {
196
*(frame + x + 1) = P1;
197
*(frame + s->width + x) = P1;
198
*(frame + s->width + x + 1) = P1;
201
*(frame + x + 1) = P0;
202
*(frame + s->width + x) = P0;
203
*(frame + s->width + x + 1) = P0;
206
frame += s->width * 2;
214
ipvideo_decode_0x8 (const GstMveDemuxStream * s, unsigned short *frame,
215
const unsigned char **data, unsigned short *len)
220
unsigned int flags = 0;
221
unsigned int bitmask = 0;
222
unsigned short P0 = 0, P1 = 0;
225
/* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
226
* either top and bottom or left and right halves */
227
CHECK_STREAM (len, 6 + 10);
229
P[0] = PIXEL (*data);
231
P[1] = PIXEL (*data);
236
if (!(P[0] & 0x8000)) {
238
/* need 18 more bytes */
239
CHECK_STREAM (len, 18 - 10);
241
P[2] = PIXEL (*data);
243
P[3] = PIXEL (*data);
247
P[4] = PIXEL (*data);
249
P[5] = PIXEL (*data);
253
P[6] = PIXEL (*data);
255
P[7] = PIXEL (*data);
261
((B[0] & 0xF0) << 4) | ((B[4] & 0xF0) << 8) |
262
((B[0] & 0x0F)) | ((B[4] & 0x0F) << 4) |
263
((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
264
((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
265
bitmask = 0x00000001;
266
lower_half = 0; /* still on top half */
268
for (y = 0; y < 8; ++y) {
270
/* time to reload flags? */
273
((B[2] & 0xF0) << 4) | ((B[6] & 0xF0) << 8) |
274
((B[2] & 0x0F)) | ((B[6] & 0x0F) << 4) |
275
((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
276
((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
277
bitmask = 0x00000001;
281
/* get the pixel values ready for this quadrant */
282
P0 = P[lower_half + 0];
283
P1 = P[lower_half + 1];
285
for (x = 0; x < 8; ++x, bitmask <<= 1) {
287
P0 = P[lower_half + 4];
288
P1 = P[lower_half + 5];
296
frame += s->width - 8;
302
/* need 10 more bytes */
305
P[2] = PIXEL (*data);
307
P[3] = PIXEL (*data);
314
if (!(P[2] & 0x8000)) {
315
/* vertical split; left & right halves are 2-color encoded */
318
((B[0] & 0xF0) << 4) | ((B[4] & 0xF0) << 8) |
319
((B[0] & 0x0F)) | ((B[4] & 0x0F) << 4) |
320
((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
321
((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
322
bitmask = 0x00000001;
324
for (y = 0; y < 8; ++y) {
326
/* time to reload flags? */
329
((B[2] & 0xF0) << 4) | ((B[6] & 0xF0) << 8) |
330
((B[2] & 0x0F)) | ((B[6] & 0x0F) << 4) |
331
((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
332
((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
333
bitmask = 0x00000001;
336
/* get the pixel values ready for this half */
340
for (x = 0; x < 8; ++x, bitmask <<= 1) {
351
frame += s->width - 8;
355
/* horizontal split; top & bottom halves are 2-color encoded */
360
for (y = 0; y < 8; ++y) {
368
for (bitmask = 0x01; bitmask <= 0x80; bitmask <<= 1) {
375
frame += s->width - 8;
384
ipvideo_decode_0x9 (const GstMveDemuxStream * s, unsigned short *frame,
385
const unsigned char **data, unsigned short *len)
390
unsigned int flags = 0;
394
/* 4-color encoding */
395
CHECK_STREAM (len, 8 + 4);
397
P[0] = PIXEL (*data);
399
P[1] = PIXEL (*data);
401
P[2] = PIXEL (*data);
403
P[3] = PIXEL (*data);
406
if (!(P[0] & 0x8000) && !(P[2] & 0x8000)) {
408
/* 1 of 4 colors for each pixel, need 16 more bytes */
409
CHECK_STREAM (len, 16 - 4);
411
for (y = 0; y < 8; ++y) {
412
/* get the next set of 8 2-bit flags */
413
flags = ((*data)[1] << 8) | (*data)[0];
415
for (x = 0, shifter = 0; x < 8; ++x, shifter += 2) {
416
*frame++ = P[(flags >> shifter) & 0x03];
418
frame += s->width - 8;
421
} else if (!(P[0] & 0x8000) && (P[2] & 0x8000)) {
424
/* 1 of 4 colors for each 2x2 block, need 4 more bytes */
430
flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
433
for (y = 0; y < 8; y += 2) {
434
for (x = 0; x < 8; x += 2, shifter += 2) {
435
pix = P[(flags >> shifter) & 0x03];
437
*(frame + x + 1) = pix;
438
*(frame + s->width + x) = pix;
439
*(frame + s->width + x + 1) = pix;
441
frame += s->width * 2;
444
} else if ((P[0] & 0x8000) && !(P[2] & 0x8000)) {
447
/* 1 of 4 colors for each 2x1 block, need 8 more bytes */
449
CHECK_STREAM (len, 8 - 4);
450
for (y = 0; y < 8; ++y) {
451
/* time to reload flags? */
452
if ((y == 0) || (y == 4)) {
457
flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
460
for (x = 0; x < 8; x += 2, shifter += 2) {
461
pix = P[(flags >> shifter) & 0x03];
463
*(frame + x + 1) = pix;
472
/* 1 of 4 colors for each 1x2 block, need 8 more bytes */
473
CHECK_STREAM (len, 8 - 4);
475
for (y = 0; y < 8; y += 2) {
476
/* time to reload flags? */
477
if ((y == 0) || (y == 4)) {
482
flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
485
for (x = 0; x < 8; ++x, shifter += 2) {
486
pix = P[(flags >> shifter) & 0x03];
488
*(frame + s->width + x) = pix;
490
frame += s->width * 2;
498
ipvideo_decode_0xa (const GstMveDemuxStream * s, unsigned short *frame,
499
const unsigned char **data, unsigned short *len)
502
unsigned short P[16];
510
/* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
511
* either top and bottom or left and right halves */
512
CHECK_STREAM (len, 8 + 24);
514
P[0] = PIXEL (*data);
516
P[1] = PIXEL (*data);
518
P[2] = PIXEL (*data);
520
P[3] = PIXEL (*data);
523
if (!(P[0] & 0x8000)) {
525
/* 4-color encoding for each quadrant; need 40 more bytes */
526
CHECK_STREAM (len, 40 - 24);
532
for (y = 4; y < 16; y += 4) {
533
for (x = y; x < y + 4; ++x) {
534
P[x] = PIXEL (*data);
537
for (x = y; x < y + 4; ++x)
541
for (y = 0; y < 8; ++y) {
543
lower_half = (y >= 4) ? 4 : 0;
544
flags = (B[y + 8] << 8) | B[y];
546
for (x = 0, shifter = 0; x < 8; ++x, shifter += 2) {
547
split = (x >= 4) ? 8 : 0;
548
index = split + lower_half + ((flags >> shifter) & 0x03);
552
frame += s->width - 8;
558
/* 4-color encoding for either left and right or top and bottom
559
* halves; need 24 more bytes */
561
memcpy (&B[0], *data, 8);
563
P[4] = PIXEL (*data);
565
P[5] = PIXEL (*data);
567
P[6] = PIXEL (*data);
569
P[7] = PIXEL (*data);
571
memcpy (&B[8], *data, 8);
574
if (!(P[4] & 0x8000)) {
576
/* block is divided into left and right halves */
577
for (y = 0; y < 8; ++y) {
579
flags = (B[y + 8] << 8) | B[y];
582
for (x = 0, shifter = 0; x < 8; ++x, shifter += 2) {
585
*frame++ = P[split + ((flags >> shifter) & 0x03)];
588
frame += s->width - 8;
594
/* block is divided into top and bottom halves */
596
for (y = 0; y < 8; ++y) {
598
flags = (B[y * 2 + 1] << 8) | B[y * 2];
602
for (x = 0, shifter = 0; x < 8; ++x, shifter += 2)
603
*frame++ = P[split + ((flags >> shifter) & 0x03)];
605
frame += s->width - 8;
614
ipvideo_decode_0xb (const GstMveDemuxStream * s, unsigned short *frame,
615
const unsigned char **data, unsigned short *len)
619
/* 64-color encoding (each pixel in block is a different color) */
620
CHECK_STREAM (len, 128);
622
for (y = 0; y < 8; ++y) {
623
for (x = 0; x < 8; ++x) {
624
*frame++ = PIXEL (*data);
627
frame += s->width - 8;
634
ipvideo_decode_0xc (const GstMveDemuxStream * s, unsigned short *frame,
635
const unsigned char **data, unsigned short *len)
640
/* 16-color block encoding: each 2x2 block is a different color */
641
CHECK_STREAM (len, 32);
643
for (y = 0; y < 8; y += 2) {
644
for (x = 0; x < 8; x += 2) {
648
*(frame + x + 1) = pix;
649
*(frame + s->width + x) = pix;
650
*(frame + s->width + x + 1) = pix;
652
frame += s->width * 2;
659
ipvideo_decode_0xd (const GstMveDemuxStream * s, unsigned short *frame,
660
const unsigned char **data, unsigned short *len)
664
unsigned char index = 0;
666
/* 4-color block encoding: each 4x4 block is a different color */
667
CHECK_STREAM (len, 8);
669
P[0] = PIXEL (*data);
671
P[1] = PIXEL (*data);
673
P[2] = PIXEL (*data);
675
P[3] = PIXEL (*data);
678
for (y = 0; y < 8; ++y) {
684
for (x = 0; x < 8; ++x) {
689
frame += s->width - 8;
696
ipvideo_decode_0xe (const GstMveDemuxStream * s, unsigned short *frame,
697
const unsigned char **data, unsigned short *len)
702
/* 1-color encoding: the whole block is 1 solid color */
703
CHECK_STREAM (len, 2);
708
for (y = 0; y < 8; ++y) {
709
for (x = 0; x < 8; ++x) {
712
frame += s->width - 8;
719
ipvideo_decode_0xf (const GstMveDemuxStream * s, unsigned short *frame,
720
const unsigned char **data, unsigned short *len)
725
/* dithered encoding */
726
CHECK_STREAM (len, 4);
728
P[0] = PIXEL (*data);
730
P[1] = PIXEL (*data);
733
for (y = 0; y < 8; ++y) {
734
for (x = 0; x < 4; ++x) {
736
*frame++ = P[(y & 1) ^ 1];
738
frame += s->width - 8;
745
ipvideo_decode_frame16 (const GstMveDemuxStream * s, const unsigned char *data,
751
unsigned short offset;
752
unsigned char opcode;
753
unsigned short *frame;
754
const unsigned char *data2;
757
CHECK_STREAM (&len, 2);
759
offset = (data[1] << 8) | data[0];
760
data2 = data + offset;
761
len2 = len - offset + 2;
764
frame = (unsigned short *) s->back_buf1;
766
/* decoding is done in 8x8 blocks */
770
for (y = 0; y < yy; ++y) {
771
for (x = 0; x < xx; ++x) {
772
/* decoding map contains 4 bits of information per 8x8 block */
773
/* bottom nibble first, then top nibble */
775
opcode = s->code_map[index >> 1] >> 4;
777
opcode = s->code_map[index >> 1] & 0x0F;
780
/* GST_DEBUG ("block @ (%3d, %3d): encoding 0x%X, data ptr @ %p",
781
x, y, opcode, data); */
785
/* copy a block from the previous frame */
786
rc = ipvideo_copy_block (s, frame, frame +
787
((unsigned short *) s->back_buf2 -
788
(unsigned short *) s->back_buf1), 0);
791
/* copy block from 2 frames ago; since we switched the back
792
* buffers we don't actually have to do anything here */
795
rc = ipvideo_decode_0x2 (s, frame, &data2, &len2);
798
rc = ipvideo_decode_0x3 (s, frame, &data2, &len2);
801
rc = ipvideo_decode_0x4 (s, frame, &data2, &len2);
804
rc = ipvideo_decode_0x5 (s, frame, &data, &len);
807
/* mystery opcode? skip multiple blocks? */
808
GST_WARNING ("encountered unsupported opcode 0x6");
812
rc = ipvideo_decode_0x7 (s, frame, &data, &len);
815
rc = ipvideo_decode_0x8 (s, frame, &data, &len);
818
rc = ipvideo_decode_0x9 (s, frame, &data, &len);
821
rc = ipvideo_decode_0xa (s, frame, &data, &len);
824
rc = ipvideo_decode_0xb (s, frame, &data, &len);
827
rc = ipvideo_decode_0xc (s, frame, &data, &len);
830
rc = ipvideo_decode_0xd (s, frame, &data, &len);
833
rc = ipvideo_decode_0xe (s, frame, &data, &len);
836
rc = ipvideo_decode_0xf (s, frame, &data, &len);
845
frame += 7 * s->width;