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