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;