interplayvideo.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:28k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * Interplay MVE Video Decoder
  3.  * Copyright (C) 2003 the ffmpeg project
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  */
  20. /**
  21.  * @file interplayvideo.c
  22.  * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net)
  23.  * For more information about the Interplay MVE format, visit:
  24.  *   http://www.pcisys.net/~melanson/codecs/interplay-mve.txt
  25.  * This code is written in such a way that the identifiers match up
  26.  * with the encoding descriptions in the document.
  27.  *
  28.  * This decoder presently only supports a PAL8 output colorspace.
  29.  *
  30.  * An Interplay video frame consists of 2 parts: The decoding map and
  31.  * the video data. A demuxer must load these 2 parts together in a single
  32.  * buffer before sending it through the stream to this decoder.
  33.  */
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <unistd.h>
  38. #include "common.h"
  39. #include "avcodec.h"
  40. #include "dsputil.h"
  41. #define PALETTE_COUNT 256
  42. /* debugging support */
  43. #define DEBUG_INTERPLAY 0
  44. #if DEBUG_INTERPLAY
  45. #define debug_interplay(x,...) av_log(NULL, AV_LOG_DEBUG, x, __VA_ARGS__)
  46. #else
  47. static inline void debug_interplay(const char *format, ...) { }
  48. #endif
  49. typedef struct IpvideoContext {
  50.     AVCodecContext *avctx;
  51.     DSPContext dsp;
  52.     AVFrame second_last_frame;
  53.     AVFrame last_frame;
  54.     AVFrame current_frame;
  55.     unsigned char *decoding_map;
  56.     int decoding_map_size;
  57.     unsigned char *buf;
  58.     int size;
  59.     unsigned char *stream_ptr;
  60.     unsigned char *stream_end;
  61.     unsigned char *pixel_ptr;
  62.     int line_inc;
  63.     int stride;
  64.     int upper_motion_limit_offset;
  65. } IpvideoContext;
  66. #define CHECK_STREAM_PTR(n) 
  67.   if ((s->stream_ptr + n) > s->stream_end) { 
  68.     av_log(s->avctx, AV_LOG_ERROR, "Interplay video warning: stream_ptr out of bounds (%p >= %p)n", 
  69.       s->stream_ptr + n, s->stream_end); 
  70.     return -1; 
  71.   }
  72. #define COPY_FROM_CURRENT() 
  73.     motion_offset = current_offset; 
  74.     motion_offset += y * s->stride; 
  75.     motion_offset += x; 
  76.     if (motion_offset < 0) { 
  77.         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)n", motion_offset); 
  78.         return -1; 
  79.     } else if (motion_offset > s->upper_motion_limit_offset) { 
  80.         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)n", 
  81.             motion_offset, s->upper_motion_limit_offset); 
  82.         return -1; 
  83.     } 
  84.     s->dsp.put_pixels_tab[0][0](s->pixel_ptr, 
  85.         s->current_frame.data[0] + motion_offset, s->stride, 8);
  86. #define COPY_FROM_PREVIOUS() 
  87.     motion_offset = current_offset; 
  88.     motion_offset += y * s->stride; 
  89.     motion_offset += x; 
  90.     if (motion_offset < 0) { 
  91.         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)n", motion_offset); 
  92.         return -1; 
  93.     } else if (motion_offset > s->upper_motion_limit_offset) { 
  94.         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)n", 
  95.             motion_offset, s->upper_motion_limit_offset); 
  96.         return -1; 
  97.     } 
  98.     s->dsp.put_pixels_tab[0][0](s->pixel_ptr, 
  99.         s->last_frame.data[0] + motion_offset, s->stride, 8);
  100. #define COPY_FROM_SECOND_LAST() 
  101.     motion_offset = current_offset; 
  102.     motion_offset += y * s->stride; 
  103.     motion_offset += x; 
  104.     if (motion_offset < 0) { 
  105.         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)n", motion_offset); 
  106.         return -1; 
  107.     } else if (motion_offset > s->upper_motion_limit_offset) { 
  108.         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)n", 
  109.             motion_offset, s->upper_motion_limit_offset); 
  110.         return -1; 
  111.     } 
  112.     s->dsp.put_pixels_tab[0][0](s->pixel_ptr, 
  113.         s->second_last_frame.data[0] + motion_offset, s->stride, 8);
  114. static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
  115. {
  116.     int x, y;
  117.     int motion_offset;
  118.     int current_offset = s->pixel_ptr - s->current_frame.data[0];
  119.     /* copy a block from the previous frame */
  120.     x = y = 0;
  121.     COPY_FROM_PREVIOUS();
  122.     /* report success */
  123.     return 0;
  124. }
  125. static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
  126. {
  127.     int x, y;
  128.     int motion_offset;
  129.     int current_offset = s->pixel_ptr - s->current_frame.data[0];
  130.     /* copy block from 2 frames ago */
  131.     x = y = 0;
  132.     COPY_FROM_SECOND_LAST();
  133.     /* report success */
  134.     return 0;
  135. }
  136. static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
  137. {
  138.     unsigned char B;
  139.     int x, y;
  140.     int motion_offset;
  141.     int current_offset = s->pixel_ptr - s->current_frame.data[0];
  142.     /* copy block from 2 frames ago using a motion vector; need 1 more byte */
  143.     CHECK_STREAM_PTR(1);
  144.     B = *s->stream_ptr++;
  145.     if (B < 56) {
  146.         x = 8 + (B % 7);
  147.         y = B / 7;
  148.     } else {
  149.         x = -14 + ((B - 56) % 29);
  150.         y =   8 + ((B - 56) / 29);
  151.     }
  152.     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)n", B, x, y);
  153.     COPY_FROM_SECOND_LAST();
  154.     /* report success */
  155.     return 0;
  156. }
  157. static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
  158. {
  159.     unsigned char B;
  160.     int x, y;
  161.     int motion_offset;
  162.     int current_offset = s->pixel_ptr - s->current_frame.data[0];
  163.     /* copy 8x8 block from current frame from an up/left block */
  164.     /* need 1 more byte for motion */
  165.     CHECK_STREAM_PTR(1);
  166.     B = *s->stream_ptr++;
  167.     if (B < 56) {
  168.         x = -(8 + (B % 7));
  169.         y = -(B / 7);
  170.     } else {
  171.         x = -(-14 + ((B - 56) % 29));
  172.         y = -(  8 + ((B - 56) / 29));
  173.     }
  174.     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)n", B, x, y);
  175.     COPY_FROM_CURRENT();
  176.     /* report success */
  177.     return 0;
  178. }
  179. static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
  180. {
  181.     int x, y;
  182.     unsigned char B, BL, BH;
  183.     int motion_offset;
  184.     int current_offset = s->pixel_ptr - s->current_frame.data[0];
  185.     /* copy a block from the previous frame; need 1 more byte */
  186.     CHECK_STREAM_PTR(1);
  187.     B = *s->stream_ptr++;
  188.     BL = B & 0x0F;
  189.     BH = (B >> 4) & 0x0F;
  190.     x = -8 + BL;
  191.     y = -8 + BH;
  192.     debug_interplay ("    motion byte = %d, (x, y) = (%d, %d)n", B, x, y);
  193.     COPY_FROM_PREVIOUS();
  194.     /* report success */
  195.     return 0;
  196. }
  197. static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
  198. {
  199.     signed char x, y;
  200.     int motion_offset;
  201.     int current_offset = s->pixel_ptr - s->current_frame.data[0];
  202.     /* copy a block from the previous frame using an expanded range;
  203.      * need 2 more bytes */
  204.     CHECK_STREAM_PTR(2);
  205.     x = *s->stream_ptr++;
  206.     y = *s->stream_ptr++;
  207.     debug_interplay ("    motion bytes = %d, %dn", x, y);
  208.     COPY_FROM_PREVIOUS();
  209.     /* report success */
  210.     return 0;
  211. }
  212. static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
  213. {
  214.     /* mystery opcode? skip multiple blocks? */
  215.     av_log(s->avctx, AV_LOG_ERROR, "  Interplay video: Help! Mystery opcode 0x6 seenn");
  216.     /* report success */
  217.     return 0;
  218. }
  219. static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
  220. {
  221.     int x, y;
  222.     unsigned char P0, P1;
  223.     unsigned char B[8];
  224.     unsigned int flags;
  225.     int bitmask;
  226.     /* 2-color encoding */
  227.     CHECK_STREAM_PTR(2);
  228.     P0 = *s->stream_ptr++;
  229.     P1 = *s->stream_ptr++;
  230.     if (P0 <= P1) {
  231.         /* need 8 more bytes from the stream */
  232.         CHECK_STREAM_PTR(8);
  233.         for (y = 0; y < 8; y++)
  234.             B[y] = *s->stream_ptr++;
  235.         for (y = 0; y < 8; y++) {
  236.             flags = B[y];
  237.             for (x = 0x01; x <= 0x80; x <<= 1) {
  238.                 if (flags & x)
  239.                     *s->pixel_ptr++ = P1;
  240.                 else
  241.                     *s->pixel_ptr++ = P0;
  242.             }
  243.             s->pixel_ptr += s->line_inc;
  244.         }
  245.     } else {
  246.         /* need 2 more bytes from the stream */
  247.         CHECK_STREAM_PTR(2);
  248.         B[0] = *s->stream_ptr++;
  249.         B[1] = *s->stream_ptr++;
  250.         flags = (B[1] << 8) | B[0];
  251.         bitmask = 0x0001;
  252.         for (y = 0; y < 8; y += 2) {
  253.             for (x = 0; x < 8; x += 2, bitmask <<= 1) {
  254.                 if (flags & bitmask) {
  255.                     *(s->pixel_ptr + x) = P1;
  256.                     *(s->pixel_ptr + x + 1) = P1;
  257.                     *(s->pixel_ptr + s->stride + x) = P1;
  258.                     *(s->pixel_ptr + s->stride + x + 1) = P1;
  259.                 } else {
  260.                     *(s->pixel_ptr + x) = P0;
  261.                     *(s->pixel_ptr + x + 1) = P0;
  262.                     *(s->pixel_ptr + s->stride + x) = P0;
  263.                     *(s->pixel_ptr + s->stride + x + 1) = P0;
  264.                 }
  265.             }
  266.             s->pixel_ptr += s->stride * 2;
  267.         }
  268.     }
  269.     /* report success */
  270.     return 0;
  271. }
  272. static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
  273. {
  274.     int x, y;
  275.     unsigned char P[8];
  276.     unsigned char B[8];
  277.     unsigned int flags = 0;
  278.     unsigned int bitmask = 0;
  279.     unsigned char P0 = 0, P1 = 0;
  280.     int lower_half = 0;
  281.     /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
  282.      * either top and bottom or left and right halves */
  283.     CHECK_STREAM_PTR(2);
  284.     P[0] = *s->stream_ptr++;
  285.     P[1] = *s->stream_ptr++;
  286.     if (P[0] <= P[1]) {
  287.         /* need 12 more bytes */
  288.         CHECK_STREAM_PTR(12);
  289.         B[0] = *s->stream_ptr++;  B[1] = *s->stream_ptr++;
  290.         P[2] = *s->stream_ptr++;  P[3] = *s->stream_ptr++;
  291.         B[2] = *s->stream_ptr++;  B[3] = *s->stream_ptr++;
  292.         P[4] = *s->stream_ptr++;  P[5] = *s->stream_ptr++;
  293.         B[4] = *s->stream_ptr++;  B[5] = *s->stream_ptr++;
  294.         P[6] = *s->stream_ptr++;  P[7] = *s->stream_ptr++;
  295.         B[6] = *s->stream_ptr++;  B[7] = *s->stream_ptr++;
  296.         for (y = 0; y < 8; y++) {
  297.             /* time to reload flags? */
  298.             if (y == 0) {
  299.                 flags =
  300.                     ((B[0] & 0xF0) <<  4) | ((B[4] & 0xF0) <<  8) |
  301.                     ((B[0] & 0x0F)      ) | ((B[4] & 0x0F) <<  4) |
  302.                     ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
  303.                     ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
  304.                 bitmask = 0x00000001;
  305.                 lower_half = 0;  /* still on top half */
  306.             } else if (y == 4) {
  307.                 flags =
  308.                     ((B[2] & 0xF0) <<  4) | ((B[6] & 0xF0) <<  8) |
  309.                     ((B[2] & 0x0F)      ) | ((B[6] & 0x0F) <<  4) |
  310.                     ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
  311.                     ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
  312.                 bitmask = 0x00000001;
  313.                 lower_half = 2;
  314.             }
  315.             for (x = 0; x < 8; x++, bitmask <<= 1) {
  316.                 /* get the pixel values ready for this quadrant */
  317.                 if (x == 0) {
  318.                     P0 = P[lower_half + 0];
  319.                     P1 = P[lower_half + 1];
  320.                 } else if (x == 4) {
  321.                     P0 = P[lower_half + 4];
  322.                     P1 = P[lower_half + 5];
  323.                 }
  324.                 if (flags & bitmask)
  325.                     *s->pixel_ptr++ = P1;
  326.                 else
  327.                     *s->pixel_ptr++ = P0;
  328.             }
  329.             s->pixel_ptr += s->line_inc;
  330.         }
  331.     } else {
  332.         /* need 10 more bytes */
  333.         CHECK_STREAM_PTR(10);
  334.         B[0] = *s->stream_ptr++;  B[1] = *s->stream_ptr++;
  335.         B[2] = *s->stream_ptr++;  B[3] = *s->stream_ptr++;
  336.         P[2] = *s->stream_ptr++;  P[3] = *s->stream_ptr++;
  337.         B[4] = *s->stream_ptr++;  B[5] = *s->stream_ptr++;
  338.         B[6] = *s->stream_ptr++;  B[7] = *s->stream_ptr++;
  339.         if (P[2] <= P[3]) {
  340.             /* vertical split; left & right halves are 2-color encoded */
  341.             for (y = 0; y < 8; y++) {
  342.                 /* time to reload flags? */
  343.                 if (y == 0) {
  344.                     flags =
  345.                         ((B[0] & 0xF0) <<  4) | ((B[4] & 0xF0) <<  8) |
  346.                         ((B[0] & 0x0F)      ) | ((B[4] & 0x0F) <<  4) |
  347.                         ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
  348.                         ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
  349.                     bitmask = 0x00000001;
  350.                 } else if (y == 4) {
  351.                     flags =
  352.                         ((B[2] & 0xF0) <<  4) | ((B[6] & 0xF0) <<  8) |
  353.                         ((B[2] & 0x0F)      ) | ((B[6] & 0x0F) <<  4) |
  354.                         ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
  355.                         ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
  356.                     bitmask = 0x00000001;
  357.                 }
  358.                 for (x = 0; x < 8; x++, bitmask <<= 1) {
  359.                     /* get the pixel values ready for this half */
  360.                     if (x == 0) {
  361.                         P0 = P[0];
  362.                         P1 = P[1];
  363.                     } else if (x == 4) {
  364.                         P0 = P[2];
  365.                         P1 = P[3];
  366.                     }
  367.                     if (flags & bitmask)
  368.                         *s->pixel_ptr++ = P1;
  369.                     else
  370.                         *s->pixel_ptr++ = P0;
  371.                 }
  372.                 s->pixel_ptr += s->line_inc;
  373.             }
  374.         } else {
  375.             /* horizontal split; top & bottom halves are 2-color encoded */
  376.             for (y = 0; y < 8; y++) {
  377.                 flags = B[y];
  378.                 if (y == 0) {
  379.                     P0 = P[0];
  380.                     P1 = P[1];
  381.                 } else if (y == 4) {
  382.                     P0 = P[2];
  383.                     P1 = P[3];
  384.                 }
  385.                 for (bitmask = 0x01; bitmask <= 0x80; bitmask <<= 1) {
  386.                     if (flags & bitmask)
  387.                         *s->pixel_ptr++ = P1;
  388.                     else
  389.                         *s->pixel_ptr++ = P0;
  390.                 }
  391.                 s->pixel_ptr += s->line_inc;
  392.             }
  393.         }
  394.     }
  395.     /* report success */
  396.     return 0;
  397. }
  398. static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
  399. {
  400.     int x, y;
  401.     unsigned char P[4];
  402.     unsigned char B[4];
  403.     unsigned int flags = 0;
  404.     int shifter = 0;
  405.     unsigned char pix;
  406.     /* 4-color encoding */
  407.     CHECK_STREAM_PTR(4);
  408.     for (y = 0; y < 4; y++)
  409.         P[y] = *s->stream_ptr++;
  410.     if ((P[0] <= P[1]) && (P[2] <= P[3])) {
  411.         /* 1 of 4 colors for each pixel, need 16 more bytes */
  412.         CHECK_STREAM_PTR(16);
  413.         for (y = 0; y < 8; y++) {
  414.             /* get the next set of 8 2-bit flags */
  415.             flags = (s->stream_ptr[1] << 8) | s->stream_ptr[0];
  416.             s->stream_ptr += 2;
  417.             for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
  418.                 *s->pixel_ptr++ = P[(flags >> shifter) & 0x03];
  419.             }
  420.             s->pixel_ptr += s->line_inc;
  421.         }
  422.     } else if ((P[0] <= P[1]) && (P[2] > P[3])) {
  423.         /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
  424.         CHECK_STREAM_PTR(4);
  425.         B[0] = *s->stream_ptr++;
  426.         B[1] = *s->stream_ptr++;
  427.         B[2] = *s->stream_ptr++;
  428.         B[3] = *s->stream_ptr++;
  429.         flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
  430.         shifter = 0;
  431.         for (y = 0; y < 8; y += 2) {
  432.             for (x = 0; x < 8; x += 2, shifter += 2) {
  433.                 pix = P[(flags >> shifter) & 0x03];
  434.                 *(s->pixel_ptr + x) = pix;
  435.                 *(s->pixel_ptr + x + 1) = pix;
  436.                 *(s->pixel_ptr + s->stride + x) = pix;
  437.                 *(s->pixel_ptr + s->stride + x + 1) = pix;
  438.             }
  439.             s->pixel_ptr += s->stride * 2;
  440.         }
  441.     } else if ((P[0] > P[1]) && (P[2] <= P[3])) {
  442.         /* 1 of 4 colors for each 2x1 block, need 8 more bytes */
  443.         CHECK_STREAM_PTR(8);
  444.         for (y = 0; y < 8; y++) {
  445.             /* time to reload flags? */
  446.             if ((y == 0) || (y == 4)) {
  447.                 B[0] = *s->stream_ptr++;
  448.                 B[1] = *s->stream_ptr++;
  449.                 B[2] = *s->stream_ptr++;
  450.                 B[3] = *s->stream_ptr++;
  451.                 flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
  452.                 shifter = 0;
  453.             }
  454.             for (x = 0; x < 8; x += 2, shifter += 2) {
  455.                 pix = P[(flags >> shifter) & 0x03];
  456.                 *(s->pixel_ptr + x) = pix;
  457.                 *(s->pixel_ptr + x + 1) = pix;
  458.             }
  459.             s->pixel_ptr += s->stride;
  460.         }
  461.     } else {
  462.         /* 1 of 4 colors for each 1x2 block, need 8 more bytes */
  463.         CHECK_STREAM_PTR(8);
  464.         for (y = 0; y < 8; y += 2) {
  465.             /* time to reload flags? */
  466.             if ((y == 0) || (y == 4)) {
  467.                 B[0] = *s->stream_ptr++;
  468.                 B[1] = *s->stream_ptr++;
  469.                 B[2] = *s->stream_ptr++;
  470.                 B[3] = *s->stream_ptr++;
  471.                 flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
  472.                 shifter = 0;
  473.             }
  474.             for (x = 0; x < 8; x++, shifter += 2) {
  475.                 pix = P[(flags >> shifter) & 0x03];
  476.                 *(s->pixel_ptr + x) = pix;
  477.                 *(s->pixel_ptr + s->stride + x) = pix;
  478.             }
  479.             s->pixel_ptr += s->stride * 2;
  480.         }
  481.     }
  482.     /* report success */
  483.     return 0;
  484. }
  485. static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
  486. {
  487.     int x, y;
  488.     unsigned char P[16];
  489.     unsigned char B[16];
  490.     int flags = 0;
  491.     int shifter = 0;
  492.     int index;
  493.     int split;
  494.     int lower_half;
  495.     /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
  496.      * either top and bottom or left and right halves */
  497.     CHECK_STREAM_PTR(4);
  498.     for (y = 0; y < 4; y++)
  499.         P[y] = *s->stream_ptr++;
  500.     if (P[0] <= P[1]) {
  501.         /* 4-color encoding for each quadrant; need 28 more bytes */
  502.         CHECK_STREAM_PTR(28);
  503.         for (y = 0; y < 4; y++)
  504.             B[y] = *s->stream_ptr++;
  505.         for (y = 4; y < 16; y += 4) {
  506.             for (x = y; x < y + 4; x++)
  507.                 P[x] = *s->stream_ptr++;
  508.             for (x = y; x < y + 4; x++)
  509.                 B[x] = *s->stream_ptr++;
  510.         }
  511.         for (y = 0; y < 8; y++) {
  512.             lower_half = (y >= 4) ? 4 : 0;
  513.             flags = (B[y + 8] << 8) | B[y];
  514.             for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
  515.                 split = (x >= 4) ? 8 : 0;
  516.                 index = split + lower_half + ((flags >> shifter) & 0x03);
  517.                 *s->pixel_ptr++ = P[index];
  518.             }
  519.             s->pixel_ptr += s->line_inc;
  520.         }
  521.     } else {
  522.         /* 4-color encoding for either left and right or top and bottom
  523.          * halves; need 20 more bytes */
  524.         CHECK_STREAM_PTR(20);
  525.         for (y = 0; y < 8; y++)
  526.             B[y] = *s->stream_ptr++;
  527.         for (y = 4; y < 8; y++)
  528.             P[y] = *s->stream_ptr++;
  529.         for (y = 8; y < 16; y++)
  530.             B[y] = *s->stream_ptr++;
  531.         if (P[4] <= P[5]) {
  532.             /* block is divided into left and right halves */
  533.             for (y = 0; y < 8; y++) {
  534.                 flags = (B[y + 8] << 8) | B[y];
  535.                 split = 0;
  536.                 for (x = 0, shifter = 0; x < 8; x++, shifter += 2) {
  537.                     if (x == 4)
  538.                         split = 4;
  539.                     *s->pixel_ptr++ = P[split + ((flags >> shifter) & 0x03)];
  540.                 }
  541.                 s->pixel_ptr += s->line_inc;
  542.             }
  543.         } else {
  544.             /* block is divided into top and bottom halves */
  545.             split = 0;
  546.             for (y = 0; y < 8; y++) {
  547.                 flags = (B[y * 2 + 1] << 8) | B[y * 2];
  548.                 if (y == 4)
  549.                     split = 4;
  550.                 for (x = 0, shifter = 0; x < 8; x++, shifter += 2)
  551.                     *s->pixel_ptr++ = P[split + ((flags >> shifter) & 0x03)];
  552.                 s->pixel_ptr += s->line_inc;
  553.             }
  554.         }
  555.     }
  556.     /* report success */
  557.     return 0;
  558. }
  559. static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
  560. {
  561.     int x, y;
  562.     /* 64-color encoding (each pixel in block is a different color) */
  563.     CHECK_STREAM_PTR(64);
  564.     for (y = 0; y < 8; y++) {
  565.         for (x = 0; x < 8; x++) {
  566.             *s->pixel_ptr++ = *s->stream_ptr++;
  567.         }
  568.         s->pixel_ptr += s->line_inc;
  569.     }
  570.     /* report success */
  571.     return 0;
  572. }
  573. static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
  574. {
  575.     int x, y;
  576.     unsigned char pix;
  577.     /* 16-color block encoding: each 2x2 block is a different color */
  578.     CHECK_STREAM_PTR(16);
  579.     for (y = 0; y < 8; y += 2) {
  580.         for (x = 0; x < 8; x += 2) {
  581.             pix = *s->stream_ptr++;
  582.             *(s->pixel_ptr + x) = pix;
  583.             *(s->pixel_ptr + x + 1) = pix;
  584.             *(s->pixel_ptr + s->stride + x) = pix;
  585.             *(s->pixel_ptr + s->stride + x + 1) = pix;
  586.         }
  587.         s->pixel_ptr += s->stride * 2;
  588.     }
  589.     /* report success */
  590.     return 0;
  591. }
  592. static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
  593. {
  594.     int x, y;
  595.     unsigned char P[4];
  596.     unsigned char index = 0;
  597.     /* 4-color block encoding: each 4x4 block is a different color */
  598.     CHECK_STREAM_PTR(4);
  599.     for (y = 0; y < 4; y++)
  600.         P[y] = *s->stream_ptr++;
  601.     for (y = 0; y < 8; y++) {
  602.         if (y < 4)
  603.             index = 0;
  604.         else
  605.             index = 2;
  606.         for (x = 0; x < 8; x++) {
  607.             if (x == 4)
  608.                 index++;
  609.             *s->pixel_ptr++ = P[index];
  610.         }
  611.         s->pixel_ptr += s->line_inc;
  612.     }
  613.     /* report success */
  614.     return 0;
  615. }
  616. static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
  617. {
  618.     int x, y;
  619.     unsigned char pix;
  620.     /* 1-color encoding: the whole block is 1 solid color */
  621.     CHECK_STREAM_PTR(1);
  622.     pix = *s->stream_ptr++;
  623.     for (y = 0; y < 8; y++) {
  624.         for (x = 0; x < 8; x++) {
  625.             *s->pixel_ptr++ = pix;
  626.         }
  627.         s->pixel_ptr += s->line_inc;
  628.     }
  629.     /* report success */
  630.     return 0;
  631. }
  632. static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
  633. {
  634.     int x, y;
  635.     unsigned char sample0, sample1;
  636.     /* dithered encoding */
  637.     CHECK_STREAM_PTR(2);
  638.     sample0 = *s->stream_ptr++;
  639.     sample1 = *s->stream_ptr++;
  640.     for (y = 0; y < 8; y++) {
  641.         for (x = 0; x < 8; x += 2) {
  642.             if (y & 1) {
  643.                 *s->pixel_ptr++ = sample1;
  644.                 *s->pixel_ptr++ = sample0;
  645.             } else {
  646.                 *s->pixel_ptr++ = sample0;
  647.                 *s->pixel_ptr++ = sample1;
  648.             }
  649.         }
  650.         s->pixel_ptr += s->line_inc;
  651.     }
  652.     /* report success */
  653.     return 0;
  654. }
  655. static int (*ipvideo_decode_block[16])(IpvideoContext *s);
  656. static void ipvideo_decode_opcodes(IpvideoContext *s)
  657. {
  658.     int x, y;
  659.     int index = 0;
  660.     unsigned char opcode;
  661.     int ret;
  662.     int code_counts[16];
  663.     static int frame = 0;
  664.     debug_interplay("------------------ frame %dn", frame);
  665.     frame++;
  666.     for (x = 0; x < 16; x++)
  667.         code_counts[x] = 0;
  668.     /* this is PAL8, so make the palette available */
  669.     memcpy(s->current_frame.data[1], s->avctx->palctrl->palette, PALETTE_COUNT * 4);
  670.     s->stride = s->current_frame.linesize[0];
  671.     s->stream_ptr = s->buf + 14;  /* data starts 14 bytes in */
  672.     s->stream_end = s->buf + s->size;
  673.     s->line_inc = s->stride - 8;
  674.     s->upper_motion_limit_offset = (s->avctx->height - 8) * s->stride
  675.         + s->avctx->width - 8;
  676.     s->dsp = s->dsp;
  677.     for (y = 0; y < (s->stride * s->avctx->height); y += s->stride * 8) {
  678.         for (x = y; x < y + s->avctx->width; x += 8) {
  679.             /* bottom nibble first, then top nibble (which makes it
  680.              * hard to use a GetBitcontext) */
  681.             if (index & 1)
  682.                 opcode = s->decoding_map[index >> 1] >> 4;
  683.             else
  684.                 opcode = s->decoding_map[index >> 1] & 0xF;
  685.             index++;
  686.             debug_interplay("  block @ (%3d, %3d): encoding 0x%X, data ptr @ %pn",
  687.                 x - y, y / s->stride, opcode, s->stream_ptr);
  688.             code_counts[opcode]++;
  689.             s->pixel_ptr = s->current_frame.data[0] + x;
  690.             ret = ipvideo_decode_block[opcode](s);
  691.             if (ret != 0) {
  692.                 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)n",
  693.                     frame, x - y, y / s->stride);
  694.                 return;
  695.             }
  696.         }
  697.     }
  698.     if ((s->stream_ptr != s->stream_end) &&
  699.         (s->stream_ptr + 1 != s->stream_end)) {
  700.         av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %d bytes left overn",
  701.             s->stream_end - s->stream_ptr);
  702.     }
  703. }
  704. static int ipvideo_decode_init(AVCodecContext *avctx)
  705. {
  706.     IpvideoContext *s = avctx->priv_data;
  707.     s->avctx = avctx;
  708.     if (s->avctx->palctrl == NULL) {
  709.         av_log(avctx, AV_LOG_ERROR, " Interplay video: palette expected.n");
  710.         return -1;
  711.     }
  712.     avctx->pix_fmt = PIX_FMT_PAL8;
  713.     avctx->has_b_frames = 0;
  714.     dsputil_init(&s->dsp, avctx);
  715.     /* decoding map contains 4 bits of information per 8x8 block */
  716.     s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
  717.     /* assign block decode functions */
  718.     ipvideo_decode_block[0x0] = ipvideo_decode_block_opcode_0x0;
  719.     ipvideo_decode_block[0x1] = ipvideo_decode_block_opcode_0x1;
  720.     ipvideo_decode_block[0x2] = ipvideo_decode_block_opcode_0x2;
  721.     ipvideo_decode_block[0x3] = ipvideo_decode_block_opcode_0x3;
  722.     ipvideo_decode_block[0x4] = ipvideo_decode_block_opcode_0x4;
  723.     ipvideo_decode_block[0x5] = ipvideo_decode_block_opcode_0x5;
  724.     ipvideo_decode_block[0x6] = ipvideo_decode_block_opcode_0x6;
  725.     ipvideo_decode_block[0x7] = ipvideo_decode_block_opcode_0x7;
  726.     ipvideo_decode_block[0x8] = ipvideo_decode_block_opcode_0x8;
  727.     ipvideo_decode_block[0x9] = ipvideo_decode_block_opcode_0x9;
  728.     ipvideo_decode_block[0xA] = ipvideo_decode_block_opcode_0xA;
  729.     ipvideo_decode_block[0xB] = ipvideo_decode_block_opcode_0xB;
  730.     ipvideo_decode_block[0xC] = ipvideo_decode_block_opcode_0xC;
  731.     ipvideo_decode_block[0xD] = ipvideo_decode_block_opcode_0xD;
  732.     ipvideo_decode_block[0xE] = ipvideo_decode_block_opcode_0xE;
  733.     ipvideo_decode_block[0xF] = ipvideo_decode_block_opcode_0xF;
  734.     s->current_frame.data[0] = s->last_frame.data[0] =
  735.     s->second_last_frame.data[0] = NULL;
  736.     return 0;
  737. }
  738. static int ipvideo_decode_frame(AVCodecContext *avctx,
  739.                                 void *data, int *data_size,
  740.                                 uint8_t *buf, int buf_size)
  741. {
  742.     IpvideoContext *s = avctx->priv_data;
  743.     AVPaletteControl *palette_control = avctx->palctrl;
  744.     /* compressed buffer needs to be large enough to at least hold an entire
  745.      * decoding map */
  746.     if (buf_size < s->decoding_map_size)
  747.         return buf_size;
  748.     s->decoding_map = buf;
  749.     s->buf = buf + s->decoding_map_size;
  750.     s->size = buf_size - s->decoding_map_size;
  751.     s->current_frame.reference = 3;
  752.     if (avctx->get_buffer(avctx, &s->current_frame)) {
  753.         av_log(avctx, AV_LOG_ERROR, "  Interplay Video: get_buffer() failedn");
  754.         return -1;
  755.     }
  756.     ipvideo_decode_opcodes(s);
  757.     if (palette_control->palette_changed) {
  758.         palette_control->palette_changed = 0;
  759.         s->current_frame.palette_has_changed = 1;
  760.     }
  761.     *data_size = sizeof(AVFrame);
  762.     *(AVFrame*)data = s->current_frame;
  763.     /* shuffle frames */
  764.     if (s->second_last_frame.data[0])
  765.         avctx->release_buffer(avctx, &s->second_last_frame);
  766.     s->second_last_frame = s->last_frame;
  767.     s->last_frame = s->current_frame;
  768.     s->current_frame.data[0] = NULL;  /* catch any access attempts */
  769.     /* report that the buffer was completely consumed */
  770.     return buf_size;
  771. }
  772. static int ipvideo_decode_end(AVCodecContext *avctx)
  773. {
  774.     IpvideoContext *s = avctx->priv_data;
  775.     /* release the last frame */
  776.     if (s->last_frame.data[0])
  777.         avctx->release_buffer(avctx, &s->last_frame);
  778.     if (s->second_last_frame.data[0])
  779.         avctx->release_buffer(avctx, &s->second_last_frame);
  780.     return 0;
  781. }
  782. AVCodec interplay_video_decoder = {
  783.     "interplayvideo",
  784.     CODEC_TYPE_VIDEO,
  785.     CODEC_ID_INTERPLAY_VIDEO,
  786.     sizeof(IpvideoContext),
  787.     ipvideo_decode_init,
  788.     NULL,
  789.     ipvideo_decode_end,
  790.     ipvideo_decode_frame,
  791.     CODEC_CAP_DR1,
  792. };