interplayvideo.c
Go to the documentation of this file.
1 /*
2  * Interplay MVE Video Decoder
3  * Copyright (C) 2003 the ffmpeg project
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #include "avcodec.h"
42 #include "bytestream.h"
43 #include "dsputil.h"
44 #define BITSTREAM_READER_LE
45 #include "get_bits.h"
46 
47 #define PALETTE_COUNT 256
48 
49 typedef struct IpvideoContext {
50 
56  const unsigned char *decoding_map;
58 
59  const unsigned char *buf;
60  int size;
61 
62  int is_16bpp;
63  const unsigned char *stream_ptr;
64  const unsigned char *stream_end;
65  const uint8_t *mv_ptr;
66  const uint8_t *mv_end;
67  unsigned char *pixel_ptr;
68  int line_inc;
69  int stride;
71 
72  uint32_t pal[256];
74 
75 #define CHECK_STREAM_PTR(stream_ptr, stream_end, n) \
76  if (stream_end - stream_ptr < n) { \
77  av_log(s->avctx, AV_LOG_ERROR, "Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \
78  stream_ptr + n, stream_end); \
79  return -1; \
80  }
81 
82 static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y)
83 {
84  int current_offset = s->pixel_ptr - s->current_frame.data[0];
85  int motion_offset = current_offset + delta_y * s->current_frame.linesize[0]
86  + delta_x * (1 + s->is_16bpp);
87  if (motion_offset < 0) {
88  av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset);
89  return -1;
90  } else if (motion_offset > s->upper_motion_limit_offset) {
91  av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n",
92  motion_offset, s->upper_motion_limit_offset);
93  return -1;
94  }
95  if (src->data[0] == NULL) {
96  av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n");
97  return AVERROR(EINVAL);
98  }
99  s->dsp.put_pixels_tab[!s->is_16bpp][0](s->pixel_ptr, src->data[0] + motion_offset,
100  s->current_frame.linesize[0], 8);
101  return 0;
102 }
103 
105 {
106  return copy_from(s, &s->last_frame, 0, 0);
107 }
108 
110 {
111  return copy_from(s, &s->second_last_frame, 0, 0);
112 }
113 
115 {
116  unsigned char B;
117  int x, y;
118 
119  /* copy block from 2 frames ago using a motion vector; need 1 more byte */
120  if (!s->is_16bpp) {
122  B = *s->stream_ptr++;
123  } else {
124  CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
125  B = *s->mv_ptr++;
126  }
127 
128  if (B < 56) {
129  x = 8 + (B % 7);
130  y = B / 7;
131  } else {
132  x = -14 + ((B - 56) % 29);
133  y = 8 + ((B - 56) / 29);
134  }
135 
136  av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
137  return copy_from(s, &s->second_last_frame, x, y);
138 }
139 
141 {
142  unsigned char B;
143  int x, y;
144 
145  /* copy 8x8 block from current frame from an up/left block */
146 
147  /* need 1 more byte for motion */
148  if (!s->is_16bpp) {
150  B = *s->stream_ptr++;
151  } else {
152  CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
153  B = *s->mv_ptr++;
154  }
155 
156  if (B < 56) {
157  x = -(8 + (B % 7));
158  y = -(B / 7);
159  } else {
160  x = -(-14 + ((B - 56) % 29));
161  y = -( 8 + ((B - 56) / 29));
162  }
163 
164  av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
165  return copy_from(s, &s->current_frame, x, y);
166 }
167 
169 {
170  int x, y;
171  unsigned char B, BL, BH;
172 
173  /* copy a block from the previous frame; need 1 more byte */
174  if (!s->is_16bpp) {
176  B = *s->stream_ptr++;
177  } else {
178  CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
179  B = *s->mv_ptr++;
180  }
181 
182  BL = B & 0x0F;
183  BH = (B >> 4) & 0x0F;
184  x = -8 + BL;
185  y = -8 + BH;
186 
187  av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
188  return copy_from(s, &s->last_frame, x, y);
189 }
190 
192 {
193  signed char x, y;
194 
195  /* copy a block from the previous frame using an expanded range;
196  * need 2 more bytes */
198 
199  x = *s->stream_ptr++;
200  y = *s->stream_ptr++;
201 
202  av_dlog(NULL, " motion bytes = %d, %d\n", x, y);
203  return copy_from(s, &s->last_frame, x, y);
204 }
205 
207 {
208  /* mystery opcode? skip multiple blocks? */
209  av_log(s->avctx, AV_LOG_ERROR, " Interplay video: Help! Mystery opcode 0x6 seen\n");
210 
211  /* report success */
212  return 0;
213 }
214 
216 {
217  int x, y;
218  unsigned char P[2];
219  unsigned int flags;
220 
221  /* 2-color encoding */
223 
224  P[0] = *s->stream_ptr++;
225  P[1] = *s->stream_ptr++;
226 
227  if (P[0] <= P[1]) {
228 
229  /* need 8 more bytes from the stream */
231 
232  for (y = 0; y < 8; y++) {
233  flags = *s->stream_ptr++ | 0x100;
234  for (; flags != 1; flags >>= 1)
235  *s->pixel_ptr++ = P[flags & 1];
236  s->pixel_ptr += s->line_inc;
237  }
238 
239  } else {
240 
241  /* need 2 more bytes from the stream */
243 
244  flags = bytestream_get_le16(&s->stream_ptr);
245  for (y = 0; y < 8; y += 2) {
246  for (x = 0; x < 8; x += 2, flags >>= 1) {
247  s->pixel_ptr[x ] =
248  s->pixel_ptr[x + 1 ] =
249  s->pixel_ptr[x + s->stride] =
250  s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
251  }
252  s->pixel_ptr += s->stride * 2;
253  }
254  }
255 
256  /* report success */
257  return 0;
258 }
259 
261 {
262  int x, y;
263  unsigned char P[2];
264  unsigned int flags = 0;
265 
266  /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
267  * either top and bottom or left and right halves */
269 
270  P[0] = *s->stream_ptr++;
271  P[1] = *s->stream_ptr++;
272 
273  if (P[0] <= P[1]) {
274 
276  s->stream_ptr -= 2;
277 
278  for (y = 0; y < 16; y++) {
279  // new values for each 4x4 block
280  if (!(y & 3)) {
281  P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
282  flags = bytestream_get_le16(&s->stream_ptr);
283  }
284 
285  for (x = 0; x < 4; x++, flags >>= 1)
286  *s->pixel_ptr++ = P[flags & 1];
287  s->pixel_ptr += s->stride - 4;
288  // switch to right half
289  if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
290  }
291 
292  } else {
293 
294  /* need 10 more bytes */
296 
297  if (s->stream_ptr[4] <= s->stream_ptr[5]) {
298 
299  flags = bytestream_get_le32(&s->stream_ptr);
300 
301  /* vertical split; left & right halves are 2-color encoded */
302 
303  for (y = 0; y < 16; y++) {
304  for (x = 0; x < 4; x++, flags >>= 1)
305  *s->pixel_ptr++ = P[flags & 1];
306  s->pixel_ptr += s->stride - 4;
307  // switch to right half
308  if (y == 7) {
309  s->pixel_ptr -= 8 * s->stride - 4;
310  P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
311  flags = bytestream_get_le32(&s->stream_ptr);
312  }
313  }
314 
315  } else {
316 
317  /* horizontal split; top & bottom halves are 2-color encoded */
318 
319  for (y = 0; y < 8; y++) {
320  if (y == 4) {
321  P[0] = *s->stream_ptr++;
322  P[1] = *s->stream_ptr++;
323  }
324  flags = *s->stream_ptr++ | 0x100;
325 
326  for (; flags != 1; flags >>= 1)
327  *s->pixel_ptr++ = P[flags & 1];
328  s->pixel_ptr += s->line_inc;
329  }
330  }
331  }
332 
333  /* report success */
334  return 0;
335 }
336 
338 {
339  int x, y;
340  unsigned char P[4];
341 
342  /* 4-color encoding */
344 
345  memcpy(P, s->stream_ptr, 4);
346  s->stream_ptr += 4;
347 
348  if (P[0] <= P[1]) {
349  if (P[2] <= P[3]) {
350 
351  /* 1 of 4 colors for each pixel, need 16 more bytes */
353 
354  for (y = 0; y < 8; y++) {
355  /* get the next set of 8 2-bit flags */
356  int flags = bytestream_get_le16(&s->stream_ptr);
357  for (x = 0; x < 8; x++, flags >>= 2)
358  *s->pixel_ptr++ = P[flags & 0x03];
359  s->pixel_ptr += s->line_inc;
360  }
361 
362  } else {
363  uint32_t flags;
364 
365  /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
367 
368  flags = bytestream_get_le32(&s->stream_ptr);
369 
370  for (y = 0; y < 8; y += 2) {
371  for (x = 0; x < 8; x += 2, flags >>= 2) {
372  s->pixel_ptr[x ] =
373  s->pixel_ptr[x + 1 ] =
374  s->pixel_ptr[x + s->stride] =
375  s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
376  }
377  s->pixel_ptr += s->stride * 2;
378  }
379 
380  }
381  } else {
382  uint64_t flags;
383 
384  /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */
386 
387  flags = bytestream_get_le64(&s->stream_ptr);
388  if (P[2] <= P[3]) {
389  for (y = 0; y < 8; y++) {
390  for (x = 0; x < 8; x += 2, flags >>= 2) {
391  s->pixel_ptr[x ] =
392  s->pixel_ptr[x + 1] = P[flags & 0x03];
393  }
394  s->pixel_ptr += s->stride;
395  }
396  } else {
397  for (y = 0; y < 8; y += 2) {
398  for (x = 0; x < 8; x++, flags >>= 2) {
399  s->pixel_ptr[x ] =
400  s->pixel_ptr[x + s->stride] = P[flags & 0x03];
401  }
402  s->pixel_ptr += s->stride * 2;
403  }
404  }
405  }
406 
407  /* report success */
408  return 0;
409 }
410 
412 {
413  int x, y;
414  unsigned char P[4];
415  int flags = 0;
416 
417  /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
418  * either top and bottom or left and right halves */
420 
421  if (s->stream_ptr[0] <= s->stream_ptr[1]) {
422 
423  /* 4-color encoding for each quadrant; need 32 bytes */
425 
426  for (y = 0; y < 16; y++) {
427  // new values for each 4x4 block
428  if (!(y & 3)) {
429  memcpy(P, s->stream_ptr, 4);
430  s->stream_ptr += 4;
431  flags = bytestream_get_le32(&s->stream_ptr);
432  }
433 
434  for (x = 0; x < 4; x++, flags >>= 2)
435  *s->pixel_ptr++ = P[flags & 0x03];
436 
437  s->pixel_ptr += s->stride - 4;
438  // switch to right half
439  if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
440  }
441 
442  } else {
443  // vertical split?
444  int vert = s->stream_ptr[12] <= s->stream_ptr[13];
445  uint64_t flags = 0;
446 
447  /* 4-color encoding for either left and right or top and bottom
448  * halves */
449 
450  for (y = 0; y < 16; y++) {
451  // load values for each half
452  if (!(y & 7)) {
453  memcpy(P, s->stream_ptr, 4);
454  s->stream_ptr += 4;
455  flags = bytestream_get_le64(&s->stream_ptr);
456  }
457 
458  for (x = 0; x < 4; x++, flags >>= 2)
459  *s->pixel_ptr++ = P[flags & 0x03];
460 
461  if (vert) {
462  s->pixel_ptr += s->stride - 4;
463  // switch to right half
464  if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
465  } else if (y & 1) s->pixel_ptr += s->line_inc;
466  }
467  }
468 
469  /* report success */
470  return 0;
471 }
472 
474 {
475  int y;
476 
477  /* 64-color encoding (each pixel in block is a different color) */
479 
480  for (y = 0; y < 8; y++) {
481  memcpy(s->pixel_ptr, s->stream_ptr, 8);
482  s->stream_ptr += 8;
483  s->pixel_ptr += s->stride;
484  }
485 
486  /* report success */
487  return 0;
488 }
489 
491 {
492  int x, y;
493 
494  /* 16-color block encoding: each 2x2 block is a different color */
496 
497  for (y = 0; y < 8; y += 2) {
498  for (x = 0; x < 8; x += 2) {
499  s->pixel_ptr[x ] =
500  s->pixel_ptr[x + 1 ] =
501  s->pixel_ptr[x + s->stride] =
502  s->pixel_ptr[x + 1 + s->stride] = *s->stream_ptr++;
503  }
504  s->pixel_ptr += s->stride * 2;
505  }
506 
507  /* report success */
508  return 0;
509 }
510 
512 {
513  int y;
514  unsigned char P[2];
515 
516  /* 4-color block encoding: each 4x4 block is a different color */
518 
519  for (y = 0; y < 8; y++) {
520  if (!(y & 3)) {
521  P[0] = *s->stream_ptr++;
522  P[1] = *s->stream_ptr++;
523  }
524  memset(s->pixel_ptr, P[0], 4);
525  memset(s->pixel_ptr + 4, P[1], 4);
526  s->pixel_ptr += s->stride;
527  }
528 
529  /* report success */
530  return 0;
531 }
532 
534 {
535  int y;
536  unsigned char pix;
537 
538  /* 1-color encoding: the whole block is 1 solid color */
540  pix = *s->stream_ptr++;
541 
542  for (y = 0; y < 8; y++) {
543  memset(s->pixel_ptr, pix, 8);
544  s->pixel_ptr += s->stride;
545  }
546 
547  /* report success */
548  return 0;
549 }
550 
552 {
553  int x, y;
554  unsigned char sample[2];
555 
556  /* dithered encoding */
558  sample[0] = *s->stream_ptr++;
559  sample[1] = *s->stream_ptr++;
560 
561  for (y = 0; y < 8; y++) {
562  for (x = 0; x < 8; x += 2) {
563  *s->pixel_ptr++ = sample[ y & 1 ];
564  *s->pixel_ptr++ = sample[!(y & 1)];
565  }
566  s->pixel_ptr += s->line_inc;
567  }
568 
569  /* report success */
570  return 0;
571 }
572 
574 {
575  signed char x, y;
576 
577  /* copy a block from the second last frame using an expanded range */
579 
580  x = *s->stream_ptr++;
581  y = *s->stream_ptr++;
582 
583  av_dlog(NULL, " motion bytes = %d, %d\n", x, y);
584  return copy_from(s, &s->second_last_frame, x, y);
585 }
586 
588 {
589  int x, y;
590  uint16_t P[2];
591  unsigned int flags;
592  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
593 
594  /* 2-color encoding */
596 
597  P[0] = bytestream_get_le16(&s->stream_ptr);
598  P[1] = bytestream_get_le16(&s->stream_ptr);
599 
600  if (!(P[0] & 0x8000)) {
601 
603 
604  for (y = 0; y < 8; y++) {
605  flags = *s->stream_ptr++ | 0x100;
606  for (; flags != 1; flags >>= 1)
607  *pixel_ptr++ = P[flags & 1];
608  pixel_ptr += s->line_inc;
609  }
610 
611  } else {
612 
614 
615  flags = bytestream_get_le16(&s->stream_ptr);
616  for (y = 0; y < 8; y += 2) {
617  for (x = 0; x < 8; x += 2, flags >>= 1) {
618  pixel_ptr[x ] =
619  pixel_ptr[x + 1 ] =
620  pixel_ptr[x + s->stride] =
621  pixel_ptr[x + 1 + s->stride] = P[flags & 1];
622  }
623  pixel_ptr += s->stride * 2;
624  }
625  }
626 
627  return 0;
628 }
629 
631 {
632  int x, y;
633  uint16_t P[2];
634  unsigned int flags = 0;
635  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
636 
637  /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
638  * either top and bottom or left and right halves */
640 
641  P[0] = bytestream_get_le16(&s->stream_ptr);
642  P[1] = bytestream_get_le16(&s->stream_ptr);
643 
644  if (!(P[0] & 0x8000)) {
645 
647  s->stream_ptr -= 4;
648 
649  for (y = 0; y < 16; y++) {
650  // new values for each 4x4 block
651  if (!(y & 3)) {
652  P[0] = bytestream_get_le16(&s->stream_ptr);
653  P[1] = bytestream_get_le16(&s->stream_ptr);
654  flags = bytestream_get_le16(&s->stream_ptr);
655  }
656 
657  for (x = 0; x < 4; x++, flags >>= 1)
658  *pixel_ptr++ = P[flags & 1];
659  pixel_ptr += s->stride - 4;
660  // switch to right half
661  if (y == 7) pixel_ptr -= 8 * s->stride - 4;
662  }
663 
664  } else {
665 
667 
668  if (!(AV_RL16(s->stream_ptr + 4) & 0x8000)) {
669 
670  flags = bytestream_get_le32(&s->stream_ptr);
671 
672  /* vertical split; left & right halves are 2-color encoded */
673 
674  for (y = 0; y < 16; y++) {
675  for (x = 0; x < 4; x++, flags >>= 1)
676  *pixel_ptr++ = P[flags & 1];
677  pixel_ptr += s->stride - 4;
678  // switch to right half
679  if (y == 7) {
680  pixel_ptr -= 8 * s->stride - 4;
681  P[0] = bytestream_get_le16(&s->stream_ptr);
682  P[1] = bytestream_get_le16(&s->stream_ptr);
683  flags = bytestream_get_le32(&s->stream_ptr);
684  }
685  }
686 
687  } else {
688 
689  /* horizontal split; top & bottom halves are 2-color encoded */
690 
691  for (y = 0; y < 8; y++) {
692  if (y == 4) {
693  P[0] = bytestream_get_le16(&s->stream_ptr);
694  P[1] = bytestream_get_le16(&s->stream_ptr);
695  }
696  flags = *s->stream_ptr++ | 0x100;
697 
698  for (; flags != 1; flags >>= 1)
699  *pixel_ptr++ = P[flags & 1];
700  pixel_ptr += s->line_inc;
701  }
702  }
703  }
704 
705  /* report success */
706  return 0;
707 }
708 
710 {
711  int x, y;
712  uint16_t P[4];
713  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
714 
715  /* 4-color encoding */
717 
718  for (x = 0; x < 4; x++)
719  P[x] = bytestream_get_le16(&s->stream_ptr);
720 
721  if (!(P[0] & 0x8000)) {
722  if (!(P[2] & 0x8000)) {
723 
724  /* 1 of 4 colors for each pixel */
726 
727  for (y = 0; y < 8; y++) {
728  /* get the next set of 8 2-bit flags */
729  int flags = bytestream_get_le16(&s->stream_ptr);
730  for (x = 0; x < 8; x++, flags >>= 2)
731  *pixel_ptr++ = P[flags & 0x03];
732  pixel_ptr += s->line_inc;
733  }
734 
735  } else {
736  uint32_t flags;
737 
738  /* 1 of 4 colors for each 2x2 block */
740 
741  flags = bytestream_get_le32(&s->stream_ptr);
742 
743  for (y = 0; y < 8; y += 2) {
744  for (x = 0; x < 8; x += 2, flags >>= 2) {
745  pixel_ptr[x ] =
746  pixel_ptr[x + 1 ] =
747  pixel_ptr[x + s->stride] =
748  pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
749  }
750  pixel_ptr += s->stride * 2;
751  }
752 
753  }
754  } else {
755  uint64_t flags;
756 
757  /* 1 of 4 colors for each 2x1 or 1x2 block */
759 
760  flags = bytestream_get_le64(&s->stream_ptr);
761  if (!(P[2] & 0x8000)) {
762  for (y = 0; y < 8; y++) {
763  for (x = 0; x < 8; x += 2, flags >>= 2) {
764  pixel_ptr[x ] =
765  pixel_ptr[x + 1] = P[flags & 0x03];
766  }
767  pixel_ptr += s->stride;
768  }
769  } else {
770  for (y = 0; y < 8; y += 2) {
771  for (x = 0; x < 8; x++, flags >>= 2) {
772  pixel_ptr[x ] =
773  pixel_ptr[x + s->stride] = P[flags & 0x03];
774  }
775  pixel_ptr += s->stride * 2;
776  }
777  }
778  }
779 
780  /* report success */
781  return 0;
782 }
783 
785 {
786  int x, y;
787  uint16_t P[4];
788  int flags = 0;
789  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
790 
791  /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
792  * either top and bottom or left and right halves */
794 
795  if (!(AV_RL16(s->stream_ptr) & 0x8000)) {
796 
797  /* 4-color encoding for each quadrant */
799 
800  for (y = 0; y < 16; y++) {
801  // new values for each 4x4 block
802  if (!(y & 3)) {
803  for (x = 0; x < 4; x++)
804  P[x] = bytestream_get_le16(&s->stream_ptr);
805  flags = bytestream_get_le32(&s->stream_ptr);
806  }
807 
808  for (x = 0; x < 4; x++, flags >>= 2)
809  *pixel_ptr++ = P[flags & 0x03];
810 
811  pixel_ptr += s->stride - 4;
812  // switch to right half
813  if (y == 7) pixel_ptr -= 8 * s->stride - 4;
814  }
815 
816  } else {
817  // vertical split?
818  int vert = !(AV_RL16(s->stream_ptr + 16) & 0x8000);
819  uint64_t flags = 0;
820 
821  /* 4-color encoding for either left and right or top and bottom
822  * halves */
823 
824  for (y = 0; y < 16; y++) {
825  // load values for each half
826  if (!(y & 7)) {
827  for (x = 0; x < 4; x++)
828  P[x] = bytestream_get_le16(&s->stream_ptr);
829  flags = bytestream_get_le64(&s->stream_ptr);
830  }
831 
832  for (x = 0; x < 4; x++, flags >>= 2)
833  *pixel_ptr++ = P[flags & 0x03];
834 
835  if (vert) {
836  pixel_ptr += s->stride - 4;
837  // switch to right half
838  if (y == 7) pixel_ptr -= 8 * s->stride - 4;
839  } else if (y & 1) pixel_ptr += s->line_inc;
840  }
841  }
842 
843  /* report success */
844  return 0;
845 }
846 
848 {
849  int x, y;
850  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
851 
852  /* 64-color encoding (each pixel in block is a different color) */
854 
855  for (y = 0; y < 8; y++) {
856  for (x = 0; x < 8; x++)
857  pixel_ptr[x] = bytestream_get_le16(&s->stream_ptr);
858  pixel_ptr += s->stride;
859  }
860 
861  /* report success */
862  return 0;
863 }
864 
866 {
867  int x, y;
868  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
869 
870  /* 16-color block encoding: each 2x2 block is a different color */
872 
873  for (y = 0; y < 8; y += 2) {
874  for (x = 0; x < 8; x += 2) {
875  pixel_ptr[x ] =
876  pixel_ptr[x + 1 ] =
877  pixel_ptr[x + s->stride] =
878  pixel_ptr[x + 1 + s->stride] = bytestream_get_le16(&s->stream_ptr);
879  }
880  pixel_ptr += s->stride * 2;
881  }
882 
883  /* report success */
884  return 0;
885 }
886 
888 {
889  int x, y;
890  uint16_t P[2];
891  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
892 
893  /* 4-color block encoding: each 4x4 block is a different color */
895 
896  for (y = 0; y < 8; y++) {
897  if (!(y & 3)) {
898  P[0] = bytestream_get_le16(&s->stream_ptr);
899  P[1] = bytestream_get_le16(&s->stream_ptr);
900  }
901  for (x = 0; x < 8; x++)
902  pixel_ptr[x] = P[x >> 2];
903  pixel_ptr += s->stride;
904  }
905 
906  /* report success */
907  return 0;
908 }
909 
911 {
912  int x, y;
913  uint16_t pix;
914  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
915 
916  /* 1-color encoding: the whole block is 1 solid color */
918  pix = bytestream_get_le16(&s->stream_ptr);
919 
920  for (y = 0; y < 8; y++) {
921  for (x = 0; x < 8; x++)
922  pixel_ptr[x] = pix;
923  pixel_ptr += s->stride;
924  }
925 
926  /* report success */
927  return 0;
928 }
929 
930 static int (* const ipvideo_decode_block[])(IpvideoContext *s) = {
939 };
940 
941 static int (* const ipvideo_decode_block16[])(IpvideoContext *s) = {
950 };
951 
953 {
954  int x, y;
955  unsigned char opcode;
956  int ret;
957  static int frame = 0;
958  GetBitContext gb;
959 
960  av_dlog(NULL, "------------------ frame %d\n", frame);
961  frame++;
962 
963  if (!s->is_16bpp) {
964  /* this is PAL8, so make the palette available */
965  memcpy(s->current_frame.data[1], s->pal, AVPALETTE_SIZE);
966 
967  s->stride = s->current_frame.linesize[0];
968  s->stream_ptr = s->buf + 14; /* data starts 14 bytes in */
969  s->stream_end = s->buf + s->size;
970  } else {
971  s->stride = s->current_frame.linesize[0] >> 1;
972  s->stream_ptr = s->buf + 16;
973  s->stream_end =
974  s->mv_ptr = s->buf + 14 + AV_RL16(s->buf+14);
975  s->mv_end = s->buf + s->size;
976  }
977  s->line_inc = s->stride - 8;
979  + (s->avctx->width - 8) * (1 + s->is_16bpp);
980 
982  for (y = 0; y < s->avctx->height; y += 8) {
983  for (x = 0; x < s->avctx->width; x += 8) {
984  opcode = get_bits(&gb, 4);
985 
986  av_dlog(NULL, " block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
987  x, y, opcode, s->stream_ptr);
988 
989  if (!s->is_16bpp) {
990  s->pixel_ptr = s->current_frame.data[0] + x
991  + y*s->current_frame.linesize[0];
992  ret = ipvideo_decode_block[opcode](s);
993  } else {
994  s->pixel_ptr = s->current_frame.data[0] + x*2
995  + y*s->current_frame.linesize[0];
996  ret = ipvideo_decode_block16[opcode](s);
997  }
998  if (ret != 0) {
999  av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
1000  frame, x, y);
1001  return;
1002  }
1003  }
1004  }
1005  if (s->stream_end - s->stream_ptr > 1) {
1006  av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %td bytes left over\n",
1007  s->stream_end - s->stream_ptr);
1008  }
1009 }
1010 
1012 {
1013  IpvideoContext *s = avctx->priv_data;
1014 
1015  s->avctx = avctx;
1016 
1017  s->is_16bpp = avctx->bits_per_coded_sample == 16;
1018  avctx->pix_fmt = s->is_16bpp ? PIX_FMT_RGB555 : PIX_FMT_PAL8;
1019 
1020  dsputil_init(&s->dsp, avctx);
1021 
1022  s->current_frame.data[0] = s->last_frame.data[0] =
1023  s->second_last_frame.data[0] = NULL;
1024 
1025  return 0;
1026 }
1027 
1029  void *data, int *data_size,
1030  AVPacket *avpkt)
1031 {
1032  const uint8_t *buf = avpkt->data;
1033  int buf_size = avpkt->size;
1034  IpvideoContext *s = avctx->priv_data;
1035 
1036  /* decoding map contains 4 bits of information per 8x8 block */
1037  s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
1038 
1039  /* compressed buffer needs to be large enough to at least hold an entire
1040  * decoding map */
1041  if (buf_size < s->decoding_map_size)
1042  return buf_size;
1043 
1044  s->decoding_map = buf;
1045  s->buf = buf + s->decoding_map_size;
1046  s->size = buf_size - s->decoding_map_size;
1047 
1048  s->current_frame.reference = 3;
1049  if (avctx->get_buffer(avctx, &s->current_frame)) {
1050  av_log(avctx, AV_LOG_ERROR, " Interplay Video: get_buffer() failed\n");
1051  return -1;
1052  }
1053 
1054  if (!s->is_16bpp) {
1055  const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
1056  if (pal) {
1058  memcpy(s->pal, pal, AVPALETTE_SIZE);
1059  }
1060  }
1061 
1063 
1064  *data_size = sizeof(AVFrame);
1065  *(AVFrame*)data = s->current_frame;
1066 
1067  /* shuffle frames */
1068  if (s->second_last_frame.data[0])
1069  avctx->release_buffer(avctx, &s->second_last_frame);
1070  s->second_last_frame = s->last_frame;
1071  s->last_frame = s->current_frame;
1072  s->current_frame.data[0] = NULL; /* catch any access attempts */
1073 
1074  /* report that the buffer was completely consumed */
1075  return buf_size;
1076 }
1077 
1079 {
1080  IpvideoContext *s = avctx->priv_data;
1081 
1082  /* release the last frame */
1083  if (s->last_frame.data[0])
1084  avctx->release_buffer(avctx, &s->last_frame);
1085  if (s->second_last_frame.data[0])
1086  avctx->release_buffer(avctx, &s->second_last_frame);
1087 
1088  return 0;
1089 }
1090 
1092  .name = "interplayvideo",
1093  .type = AVMEDIA_TYPE_VIDEO,
1095  .priv_data_size = sizeof(IpvideoContext),
1099  .capabilities = CODEC_CAP_DR1 | CODEC_CAP_PARAM_CHANGE,
1100  .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),
1101 };