FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 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
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 
41 #include "avcodec.h"
42 #include "bytestream.h"
43 #include "hpeldsp.h"
44 #define BITSTREAM_READER_LE
45 #include "get_bits.h"
46 #include "internal.h"
47 
48 #define PALETTE_COUNT 256
49 
50 typedef struct IpvideoContext {
51 
56  const unsigned char *decoding_map;
58 
59  int is_16bpp;
61  unsigned char *pixel_ptr;
62  int line_inc;
63  int stride;
65 
66  uint32_t pal[256];
68 
69 static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int delta_y)
70 {
71  int current_offset = s->pixel_ptr - dst->data[0];
72  int motion_offset = current_offset + delta_y * dst->linesize[0]
73  + delta_x * (1 + s->is_16bpp);
74  if (motion_offset < 0) {
75  av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset);
76  return AVERROR_INVALIDDATA;
77  } else if (motion_offset > s->upper_motion_limit_offset) {
78  av_log(s->avctx, AV_LOG_ERROR, "motion offset above limit (%d >= %d)\n",
79  motion_offset, s->upper_motion_limit_offset);
80  return AVERROR_INVALIDDATA;
81  }
82  if (src->data[0] == NULL) {
83  av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n");
84  return AVERROR(EINVAL);
85  }
86  s->hdsp.put_pixels_tab[!s->is_16bpp][0](s->pixel_ptr, src->data[0] + motion_offset,
87  dst->linesize[0], 8);
88  return 0;
89 }
90 
92 {
93  return copy_from(s, s->last_frame, frame, 0, 0);
94 }
95 
97 {
98  return copy_from(s, s->second_last_frame, frame, 0, 0);
99 }
100 
102 {
103  unsigned char B;
104  int x, y;
105 
106  /* copy block from 2 frames ago using a motion vector; need 1 more byte */
107  if (!s->is_16bpp) {
108  B = bytestream2_get_byte(&s->stream_ptr);
109  } else {
110  B = bytestream2_get_byte(&s->mv_ptr);
111  }
112 
113  if (B < 56) {
114  x = 8 + (B % 7);
115  y = B / 7;
116  } else {
117  x = -14 + ((B - 56) % 29);
118  y = 8 + ((B - 56) / 29);
119  }
120 
121  av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
122  return copy_from(s, s->second_last_frame, frame, x, y);
123 }
124 
126 {
127  unsigned char B;
128  int x, y;
129 
130  /* copy 8x8 block from current frame from an up/left block */
131 
132  /* need 1 more byte for motion */
133  if (!s->is_16bpp) {
134  B = bytestream2_get_byte(&s->stream_ptr);
135  } else {
136  B = bytestream2_get_byte(&s->mv_ptr);
137  }
138 
139  if (B < 56) {
140  x = -(8 + (B % 7));
141  y = -(B / 7);
142  } else {
143  x = -(-14 + ((B - 56) % 29));
144  y = -( 8 + ((B - 56) / 29));
145  }
146 
147  av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
148  return copy_from(s, frame, frame, x, y);
149 }
150 
152 {
153  int x, y;
154  unsigned char B, BL, BH;
155 
156  /* copy a block from the previous frame; need 1 more byte */
157  if (!s->is_16bpp) {
158  B = bytestream2_get_byte(&s->stream_ptr);
159  } else {
160  B = bytestream2_get_byte(&s->mv_ptr);
161  }
162 
163  BL = B & 0x0F;
164  BH = (B >> 4) & 0x0F;
165  x = -8 + BL;
166  y = -8 + BH;
167 
168  av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
169  return copy_from(s, s->last_frame, frame, x, y);
170 }
171 
173 {
174  signed char x, y;
175 
176  /* copy a block from the previous frame using an expanded range;
177  * need 2 more bytes */
178  x = bytestream2_get_byte(&s->stream_ptr);
179  y = bytestream2_get_byte(&s->stream_ptr);
180 
181  av_dlog(s->avctx, "motion bytes = %d, %d\n", x, y);
182  return copy_from(s, s->last_frame, frame, x, y);
183 }
184 
186 {
187  /* mystery opcode? skip multiple blocks? */
188  av_log(s->avctx, AV_LOG_ERROR, "Help! Mystery opcode 0x6 seen\n");
189 
190  /* report success */
191  return 0;
192 }
193 
195 {
196  int x, y;
197  unsigned char P[2];
198  unsigned int flags;
199 
200  /* 2-color encoding */
201  P[0] = bytestream2_get_byte(&s->stream_ptr);
202  P[1] = bytestream2_get_byte(&s->stream_ptr);
203 
204  if (P[0] <= P[1]) {
205 
206  /* need 8 more bytes from the stream */
207  for (y = 0; y < 8; y++) {
208  flags = bytestream2_get_byte(&s->stream_ptr) | 0x100;
209  for (; flags != 1; flags >>= 1)
210  *s->pixel_ptr++ = P[flags & 1];
211  s->pixel_ptr += s->line_inc;
212  }
213 
214  } else {
215 
216  /* need 2 more bytes from the stream */
217  flags = bytestream2_get_le16(&s->stream_ptr);
218  for (y = 0; y < 8; y += 2) {
219  for (x = 0; x < 8; x += 2, flags >>= 1) {
220  s->pixel_ptr[x ] =
221  s->pixel_ptr[x + 1 ] =
222  s->pixel_ptr[x + s->stride] =
223  s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
224  }
225  s->pixel_ptr += s->stride * 2;
226  }
227  }
228 
229  /* report success */
230  return 0;
231 }
232 
234 {
235  int x, y;
236  unsigned char P[4];
237  unsigned int flags = 0;
238 
239  /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
240  * either top and bottom or left and right halves */
241  P[0] = bytestream2_get_byte(&s->stream_ptr);
242  P[1] = bytestream2_get_byte(&s->stream_ptr);
243 
244  if (P[0] <= P[1]) {
245  for (y = 0; y < 16; y++) {
246  // new values for each 4x4 block
247  if (!(y & 3)) {
248  if (y) {
249  P[0] = bytestream2_get_byte(&s->stream_ptr);
250  P[1] = bytestream2_get_byte(&s->stream_ptr);
251  }
252  flags = bytestream2_get_le16(&s->stream_ptr);
253  }
254 
255  for (x = 0; x < 4; x++, flags >>= 1)
256  *s->pixel_ptr++ = P[flags & 1];
257  s->pixel_ptr += s->stride - 4;
258  // switch to right half
259  if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
260  }
261 
262  } else {
263  flags = bytestream2_get_le32(&s->stream_ptr);
264  P[2] = bytestream2_get_byte(&s->stream_ptr);
265  P[3] = bytestream2_get_byte(&s->stream_ptr);
266 
267  if (P[2] <= P[3]) {
268 
269  /* vertical split; left & right halves are 2-color encoded */
270 
271  for (y = 0; y < 16; y++) {
272  for (x = 0; x < 4; x++, flags >>= 1)
273  *s->pixel_ptr++ = P[flags & 1];
274  s->pixel_ptr += s->stride - 4;
275  // switch to right half
276  if (y == 7) {
277  s->pixel_ptr -= 8 * s->stride - 4;
278  P[0] = P[2];
279  P[1] = P[3];
280  flags = bytestream2_get_le32(&s->stream_ptr);
281  }
282  }
283 
284  } else {
285 
286  /* horizontal split; top & bottom halves are 2-color encoded */
287 
288  for (y = 0; y < 8; y++) {
289  if (y == 4) {
290  P[0] = P[2];
291  P[1] = P[3];
292  flags = bytestream2_get_le32(&s->stream_ptr);
293  }
294 
295  for (x = 0; x < 8; x++, flags >>= 1)
296  *s->pixel_ptr++ = P[flags & 1];
297  s->pixel_ptr += s->line_inc;
298  }
299  }
300  }
301 
302  /* report success */
303  return 0;
304 }
305 
307 {
308  int x, y;
309  unsigned char P[4];
310 
311  /* 4-color encoding */
313 
314  if (P[0] <= P[1]) {
315  if (P[2] <= P[3]) {
316 
317  /* 1 of 4 colors for each pixel, need 16 more bytes */
318  for (y = 0; y < 8; y++) {
319  /* get the next set of 8 2-bit flags */
320  int flags = bytestream2_get_le16(&s->stream_ptr);
321  for (x = 0; x < 8; x++, flags >>= 2)
322  *s->pixel_ptr++ = P[flags & 0x03];
323  s->pixel_ptr += s->line_inc;
324  }
325 
326  } else {
327  uint32_t flags;
328 
329  /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
330  flags = bytestream2_get_le32(&s->stream_ptr);
331 
332  for (y = 0; y < 8; y += 2) {
333  for (x = 0; x < 8; x += 2, flags >>= 2) {
334  s->pixel_ptr[x ] =
335  s->pixel_ptr[x + 1 ] =
336  s->pixel_ptr[x + s->stride] =
337  s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
338  }
339  s->pixel_ptr += s->stride * 2;
340  }
341 
342  }
343  } else {
344  uint64_t flags;
345 
346  /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */
347  flags = bytestream2_get_le64(&s->stream_ptr);
348  if (P[2] <= P[3]) {
349  for (y = 0; y < 8; y++) {
350  for (x = 0; x < 8; x += 2, flags >>= 2) {
351  s->pixel_ptr[x ] =
352  s->pixel_ptr[x + 1] = P[flags & 0x03];
353  }
354  s->pixel_ptr += s->stride;
355  }
356  } else {
357  for (y = 0; y < 8; y += 2) {
358  for (x = 0; x < 8; x++, flags >>= 2) {
359  s->pixel_ptr[x ] =
360  s->pixel_ptr[x + s->stride] = P[flags & 0x03];
361  }
362  s->pixel_ptr += s->stride * 2;
363  }
364  }
365  }
366 
367  /* report success */
368  return 0;
369 }
370 
372 {
373  int x, y;
374  unsigned char P[8];
375  int flags = 0;
376 
378 
379  /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
380  * either top and bottom or left and right halves */
381  if (P[0] <= P[1]) {
382 
383  /* 4-color encoding for each quadrant; need 32 bytes */
384  for (y = 0; y < 16; y++) {
385  // new values for each 4x4 block
386  if (!(y & 3)) {
387  if (y) bytestream2_get_buffer(&s->stream_ptr, P, 4);
388  flags = bytestream2_get_le32(&s->stream_ptr);
389  }
390 
391  for (x = 0; x < 4; x++, flags >>= 2)
392  *s->pixel_ptr++ = P[flags & 0x03];
393 
394  s->pixel_ptr += s->stride - 4;
395  // switch to right half
396  if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
397  }
398 
399  } else {
400  // vertical split?
401  int vert;
402  uint64_t flags = bytestream2_get_le64(&s->stream_ptr);
403 
404  bytestream2_get_buffer(&s->stream_ptr, P + 4, 4);
405  vert = P[4] <= P[5];
406 
407  /* 4-color encoding for either left and right or top and bottom
408  * halves */
409 
410  for (y = 0; y < 16; y++) {
411  for (x = 0; x < 4; x++, flags >>= 2)
412  *s->pixel_ptr++ = P[flags & 0x03];
413 
414  if (vert) {
415  s->pixel_ptr += s->stride - 4;
416  // switch to right half
417  if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
418  } else if (y & 1) s->pixel_ptr += s->line_inc;
419 
420  // load values for second half
421  if (y == 7) {
422  memcpy(P, P + 4, 4);
423  flags = bytestream2_get_le64(&s->stream_ptr);
424  }
425  }
426  }
427 
428  /* report success */
429  return 0;
430 }
431 
433 {
434  int y;
435 
436  /* 64-color encoding (each pixel in block is a different color) */
437  for (y = 0; y < 8; y++) {
439  s->pixel_ptr += s->stride;
440  }
441 
442  /* report success */
443  return 0;
444 }
445 
447 {
448  int x, y;
449 
450  /* 16-color block encoding: each 2x2 block is a different color */
451  for (y = 0; y < 8; y += 2) {
452  for (x = 0; x < 8; x += 2) {
453  s->pixel_ptr[x ] =
454  s->pixel_ptr[x + 1 ] =
455  s->pixel_ptr[x + s->stride] =
456  s->pixel_ptr[x + 1 + s->stride] = bytestream2_get_byte(&s->stream_ptr);
457  }
458  s->pixel_ptr += s->stride * 2;
459  }
460 
461  /* report success */
462  return 0;
463 }
464 
466 {
467  int y;
468  unsigned char P[2];
469 
470  /* 4-color block encoding: each 4x4 block is a different color */
471  for (y = 0; y < 8; y++) {
472  if (!(y & 3)) {
473  P[0] = bytestream2_get_byte(&s->stream_ptr);
474  P[1] = bytestream2_get_byte(&s->stream_ptr);
475  }
476  memset(s->pixel_ptr, P[0], 4);
477  memset(s->pixel_ptr + 4, P[1], 4);
478  s->pixel_ptr += s->stride;
479  }
480 
481  /* report success */
482  return 0;
483 }
484 
486 {
487  int y;
488  unsigned char pix;
489 
490  /* 1-color encoding: the whole block is 1 solid color */
491  pix = bytestream2_get_byte(&s->stream_ptr);
492 
493  for (y = 0; y < 8; y++) {
494  memset(s->pixel_ptr, pix, 8);
495  s->pixel_ptr += s->stride;
496  }
497 
498  /* report success */
499  return 0;
500 }
501 
503 {
504  int x, y;
505  unsigned char sample[2];
506 
507  /* dithered encoding */
508  sample[0] = bytestream2_get_byte(&s->stream_ptr);
509  sample[1] = bytestream2_get_byte(&s->stream_ptr);
510 
511  for (y = 0; y < 8; y++) {
512  for (x = 0; x < 8; x += 2) {
513  *s->pixel_ptr++ = sample[ y & 1 ];
514  *s->pixel_ptr++ = sample[!(y & 1)];
515  }
516  s->pixel_ptr += s->line_inc;
517  }
518 
519  /* report success */
520  return 0;
521 }
522 
524 {
525  signed char x, y;
526 
527  /* copy a block from the second last frame using an expanded range */
528  x = bytestream2_get_byte(&s->stream_ptr);
529  y = bytestream2_get_byte(&s->stream_ptr);
530 
531  av_dlog(s->avctx, "motion bytes = %d, %d\n", x, y);
532  return copy_from(s, s->second_last_frame, frame, x, y);
533 }
534 
536 {
537  int x, y;
538  uint16_t P[2];
539  unsigned int flags;
540  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
541 
542  /* 2-color encoding */
543  P[0] = bytestream2_get_le16(&s->stream_ptr);
544  P[1] = bytestream2_get_le16(&s->stream_ptr);
545 
546  if (!(P[0] & 0x8000)) {
547 
548  for (y = 0; y < 8; y++) {
549  flags = bytestream2_get_byte(&s->stream_ptr) | 0x100;
550  for (; flags != 1; flags >>= 1)
551  *pixel_ptr++ = P[flags & 1];
552  pixel_ptr += s->line_inc;
553  }
554 
555  } else {
556 
557  flags = bytestream2_get_le16(&s->stream_ptr);
558  for (y = 0; y < 8; y += 2) {
559  for (x = 0; x < 8; x += 2, flags >>= 1) {
560  pixel_ptr[x ] =
561  pixel_ptr[x + 1 ] =
562  pixel_ptr[x + s->stride] =
563  pixel_ptr[x + 1 + s->stride] = P[flags & 1];
564  }
565  pixel_ptr += s->stride * 2;
566  }
567  }
568 
569  return 0;
570 }
571 
573 {
574  int x, y;
575  uint16_t P[4];
576  unsigned int flags = 0;
577  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
578 
579  /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
580  * either top and bottom or left and right halves */
581  P[0] = bytestream2_get_le16(&s->stream_ptr);
582  P[1] = bytestream2_get_le16(&s->stream_ptr);
583 
584  if (!(P[0] & 0x8000)) {
585 
586  for (y = 0; y < 16; y++) {
587  // new values for each 4x4 block
588  if (!(y & 3)) {
589  if (y) {
590  P[0] = bytestream2_get_le16(&s->stream_ptr);
591  P[1] = bytestream2_get_le16(&s->stream_ptr);
592  }
593  flags = bytestream2_get_le16(&s->stream_ptr);
594  }
595 
596  for (x = 0; x < 4; x++, flags >>= 1)
597  *pixel_ptr++ = P[flags & 1];
598  pixel_ptr += s->stride - 4;
599  // switch to right half
600  if (y == 7) pixel_ptr -= 8 * s->stride - 4;
601  }
602 
603  } else {
604 
605  flags = bytestream2_get_le32(&s->stream_ptr);
606  P[2] = bytestream2_get_le16(&s->stream_ptr);
607  P[3] = bytestream2_get_le16(&s->stream_ptr);
608 
609  if (!(P[2] & 0x8000)) {
610 
611  /* vertical split; left & right halves are 2-color encoded */
612 
613  for (y = 0; y < 16; y++) {
614  for (x = 0; x < 4; x++, flags >>= 1)
615  *pixel_ptr++ = P[flags & 1];
616  pixel_ptr += s->stride - 4;
617  // switch to right half
618  if (y == 7) {
619  pixel_ptr -= 8 * s->stride - 4;
620  P[0] = P[2];
621  P[1] = P[3];
622  flags = bytestream2_get_le32(&s->stream_ptr);
623  }
624  }
625 
626  } else {
627 
628  /* horizontal split; top & bottom halves are 2-color encoded */
629 
630  for (y = 0; y < 8; y++) {
631  if (y == 4) {
632  P[0] = P[2];
633  P[1] = P[3];
634  flags = bytestream2_get_le32(&s->stream_ptr);
635  }
636 
637  for (x = 0; x < 8; x++, flags >>= 1)
638  *pixel_ptr++ = P[flags & 1];
639  pixel_ptr += s->line_inc;
640  }
641  }
642  }
643 
644  /* report success */
645  return 0;
646 }
647 
649 {
650  int x, y;
651  uint16_t P[4];
652  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
653 
654  /* 4-color encoding */
655  for (x = 0; x < 4; x++)
656  P[x] = bytestream2_get_le16(&s->stream_ptr);
657 
658  if (!(P[0] & 0x8000)) {
659  if (!(P[2] & 0x8000)) {
660 
661  /* 1 of 4 colors for each pixel */
662  for (y = 0; y < 8; y++) {
663  /* get the next set of 8 2-bit flags */
664  int flags = bytestream2_get_le16(&s->stream_ptr);
665  for (x = 0; x < 8; x++, flags >>= 2)
666  *pixel_ptr++ = P[flags & 0x03];
667  pixel_ptr += s->line_inc;
668  }
669 
670  } else {
671  uint32_t flags;
672 
673  /* 1 of 4 colors for each 2x2 block */
674  flags = bytestream2_get_le32(&s->stream_ptr);
675 
676  for (y = 0; y < 8; y += 2) {
677  for (x = 0; x < 8; x += 2, flags >>= 2) {
678  pixel_ptr[x ] =
679  pixel_ptr[x + 1 ] =
680  pixel_ptr[x + s->stride] =
681  pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
682  }
683  pixel_ptr += s->stride * 2;
684  }
685 
686  }
687  } else {
688  uint64_t flags;
689 
690  /* 1 of 4 colors for each 2x1 or 1x2 block */
691  flags = bytestream2_get_le64(&s->stream_ptr);
692  if (!(P[2] & 0x8000)) {
693  for (y = 0; y < 8; y++) {
694  for (x = 0; x < 8; x += 2, flags >>= 2) {
695  pixel_ptr[x ] =
696  pixel_ptr[x + 1] = P[flags & 0x03];
697  }
698  pixel_ptr += s->stride;
699  }
700  } else {
701  for (y = 0; y < 8; y += 2) {
702  for (x = 0; x < 8; x++, flags >>= 2) {
703  pixel_ptr[x ] =
704  pixel_ptr[x + s->stride] = P[flags & 0x03];
705  }
706  pixel_ptr += s->stride * 2;
707  }
708  }
709  }
710 
711  /* report success */
712  return 0;
713 }
714 
716 {
717  int x, y;
718  uint16_t P[8];
719  int flags = 0;
720  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
721 
722  for (x = 0; x < 4; x++)
723  P[x] = bytestream2_get_le16(&s->stream_ptr);
724 
725  /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
726  * either top and bottom or left and right halves */
727  if (!(P[0] & 0x8000)) {
728 
729  /* 4-color encoding for each quadrant */
730  for (y = 0; y < 16; y++) {
731  // new values for each 4x4 block
732  if (!(y & 3)) {
733  if (y)
734  for (x = 0; x < 4; x++)
735  P[x] = bytestream2_get_le16(&s->stream_ptr);
736  flags = bytestream2_get_le32(&s->stream_ptr);
737  }
738 
739  for (x = 0; x < 4; x++, flags >>= 2)
740  *pixel_ptr++ = P[flags & 0x03];
741 
742  pixel_ptr += s->stride - 4;
743  // switch to right half
744  if (y == 7) pixel_ptr -= 8 * s->stride - 4;
745  }
746 
747  } else {
748  // vertical split?
749  int vert;
750  uint64_t flags = bytestream2_get_le64(&s->stream_ptr);
751 
752  for (x = 4; x < 8; x++)
753  P[x] = bytestream2_get_le16(&s->stream_ptr);
754  vert = !(P[4] & 0x8000);
755 
756  /* 4-color encoding for either left and right or top and bottom
757  * halves */
758 
759  for (y = 0; y < 16; y++) {
760  for (x = 0; x < 4; x++, flags >>= 2)
761  *pixel_ptr++ = P[flags & 0x03];
762 
763  if (vert) {
764  pixel_ptr += s->stride - 4;
765  // switch to right half
766  if (y == 7) pixel_ptr -= 8 * s->stride - 4;
767  } else if (y & 1) pixel_ptr += s->line_inc;
768 
769  // load values for second half
770  if (y == 7) {
771  memcpy(P, P + 4, 8);
772  flags = bytestream2_get_le64(&s->stream_ptr);
773  }
774  }
775  }
776 
777  /* report success */
778  return 0;
779 }
780 
782 {
783  int x, y;
784  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
785 
786  /* 64-color encoding (each pixel in block is a different color) */
787  for (y = 0; y < 8; y++) {
788  for (x = 0; x < 8; x++)
789  pixel_ptr[x] = bytestream2_get_le16(&s->stream_ptr);
790  pixel_ptr += s->stride;
791  }
792 
793  /* report success */
794  return 0;
795 }
796 
798 {
799  int x, y;
800  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
801 
802  /* 16-color block encoding: each 2x2 block is a different color */
803  for (y = 0; y < 8; y += 2) {
804  for (x = 0; x < 8; x += 2) {
805  pixel_ptr[x ] =
806  pixel_ptr[x + 1 ] =
807  pixel_ptr[x + s->stride] =
808  pixel_ptr[x + 1 + s->stride] = bytestream2_get_le16(&s->stream_ptr);
809  }
810  pixel_ptr += s->stride * 2;
811  }
812 
813  /* report success */
814  return 0;
815 }
816 
818 {
819  int x, y;
820  uint16_t P[2];
821  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
822 
823  /* 4-color block encoding: each 4x4 block is a different color */
824  for (y = 0; y < 8; y++) {
825  if (!(y & 3)) {
826  P[0] = bytestream2_get_le16(&s->stream_ptr);
827  P[1] = bytestream2_get_le16(&s->stream_ptr);
828  }
829  for (x = 0; x < 8; x++)
830  pixel_ptr[x] = P[x >> 2];
831  pixel_ptr += s->stride;
832  }
833 
834  /* report success */
835  return 0;
836 }
837 
839 {
840  int x, y;
841  uint16_t pix;
842  uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
843 
844  /* 1-color encoding: the whole block is 1 solid color */
845  pix = bytestream2_get_le16(&s->stream_ptr);
846 
847  for (y = 0; y < 8; y++) {
848  for (x = 0; x < 8; x++)
849  pixel_ptr[x] = pix;
850  pixel_ptr += s->stride;
851  }
852 
853  /* report success */
854  return 0;
855 }
856 
857 static int (* const ipvideo_decode_block[])(IpvideoContext *s, AVFrame *frame) = {
866 };
867 
868 static int (* const ipvideo_decode_block16[])(IpvideoContext *s, AVFrame *frame) = {
877 };
878 
880 {
881  int x, y;
882  unsigned char opcode;
883  int ret;
884  GetBitContext gb;
885 
886  bytestream2_skip(&s->stream_ptr, 14); /* data starts 14 bytes in */
887  if (!s->is_16bpp) {
888  /* this is PAL8, so make the palette available */
889  memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
890 
891  s->stride = frame->linesize[0];
892  } else {
893  s->stride = frame->linesize[0] >> 1;
894  s->mv_ptr = s->stream_ptr;
895  bytestream2_skip(&s->mv_ptr, bytestream2_get_le16(&s->stream_ptr));
896  }
897  s->line_inc = s->stride - 8;
898  s->upper_motion_limit_offset = (s->avctx->height - 8) * frame->linesize[0]
899  + (s->avctx->width - 8) * (1 + s->is_16bpp);
900 
902  for (y = 0; y < s->avctx->height; y += 8) {
903  for (x = 0; x < s->avctx->width; x += 8) {
904  opcode = get_bits(&gb, 4);
905 
906  av_dlog(s->avctx,
907  " block @ (%3d, %3d): encoding 0x%X, data ptr offset %d\n",
908  x, y, opcode, bytestream2_tell(&s->stream_ptr));
909 
910  if (!s->is_16bpp) {
911  s->pixel_ptr = frame->data[0] + x
912  + y*frame->linesize[0];
913  ret = ipvideo_decode_block[opcode](s, frame);
914  } else {
915  s->pixel_ptr = frame->data[0] + x*2
916  + y*frame->linesize[0];
917  ret = ipvideo_decode_block16[opcode](s, frame);
918  }
919  if (ret != 0) {
920  av_log(s->avctx, AV_LOG_ERROR, "decode problem on frame %d, @ block (%d, %d)\n",
921  s->avctx->frame_number, x, y);
922  return;
923  }
924  }
925  }
926  if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) {
928  "decode finished with %d bytes left over\n",
930  }
931 }
932 
934 {
935  IpvideoContext *s = avctx->priv_data;
936 
937  s->avctx = avctx;
938 
939  s->is_16bpp = avctx->bits_per_coded_sample == 16;
941 
942  ff_hpeldsp_init(&s->hdsp, avctx->flags);
943 
944  s->last_frame = av_frame_alloc();
946  if (!s->last_frame || !s->second_last_frame) {
949  return AVERROR(ENOMEM);
950  }
951 
952  return 0;
953 }
954 
956  void *data, int *got_frame,
957  AVPacket *avpkt)
958 {
959  const uint8_t *buf = avpkt->data;
960  int buf_size = avpkt->size;
961  IpvideoContext *s = avctx->priv_data;
962  AVFrame *frame = data;
963  int ret;
964 
965  /* decoding map contains 4 bits of information per 8x8 block */
966  s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
967 
968  /* compressed buffer needs to be large enough to at least hold an entire
969  * decoding map */
970  if (buf_size < s->decoding_map_size)
971  return buf_size;
972 
976  }
977 
978  s->decoding_map = buf;
980  buf_size - s->decoding_map_size);
981 
982  if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
983  return ret;
984 
985  if (!s->is_16bpp) {
986  const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
987  if (pal) {
988  frame->palette_has_changed = 1;
989  memcpy(s->pal, pal, AVPALETTE_SIZE);
990  }
991  }
992 
993  ipvideo_decode_opcodes(s, frame);
994 
995  *got_frame = 1;
996 
997  /* shuffle frames */
1000  if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
1001  return ret;
1002 
1003  /* report that the buffer was completely consumed */
1004  return buf_size;
1005 }
1006 
1008 {
1009  IpvideoContext *s = avctx->priv_data;
1010 
1013 
1014  return 0;
1015 }
1016 
1018  .name = "interplayvideo",
1019  .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),
1020  .type = AVMEDIA_TYPE_VIDEO,
1022  .priv_data_size = sizeof(IpvideoContext),
1026  .capabilities = CODEC_CAP_DR1 | CODEC_CAP_PARAM_CHANGE,
1027 };