Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Sierra VMD video decoder
  3.  * Copyright (c) 2004 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.  * Sierra VMD video decoder
  25.  * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
  26.  * for more information on the Sierra VMD format, visit:
  27.  *   http://www.pcisys.net/~melanson/codecs/
  28.  *
  29.  * The video decoder outputs PAL8 colorspace data. The decoder expects
  30.  * a 0x330-byte VMD file header to be transmitted via extradata during
  31.  * codec initialization. Each encoded frame that is sent to this decoder
  32.  * is expected to be prepended with the appropriate 16-byte frame
  33.  * information record from the VMD file.
  34.  */
  35.  
  36. #include <string.h>
  37.  
  38. #include "libavutil/common.h"
  39. #include "libavutil/intreadwrite.h"
  40.  
  41. #include "avcodec.h"
  42. #include "internal.h"
  43. #include "bytestream.h"
  44.  
  45. #define VMD_HEADER_SIZE 0x330
  46. #define PALETTE_COUNT 256
  47.  
  48. typedef struct VmdVideoContext {
  49.  
  50.     AVCodecContext *avctx;
  51.     AVFrame *prev_frame;
  52.  
  53.     const unsigned char *buf;
  54.     int size;
  55.  
  56.     unsigned char palette[PALETTE_COUNT * 4];
  57.     unsigned char *unpack_buffer;
  58.     int unpack_buffer_size;
  59.  
  60.     int x_off, y_off;
  61. } VmdVideoContext;
  62.  
  63. #define QUEUE_SIZE 0x1000
  64. #define QUEUE_MASK 0x0FFF
  65.  
  66. static int lz_unpack(const unsigned char *src, int src_len,
  67.                       unsigned char *dest, int dest_len)
  68. {
  69.     unsigned char *d;
  70.     unsigned char *d_end;
  71.     unsigned char queue[QUEUE_SIZE];
  72.     unsigned int qpos;
  73.     unsigned int dataleft;
  74.     unsigned int chainofs;
  75.     unsigned int chainlen;
  76.     unsigned int speclen;
  77.     unsigned char tag;
  78.     unsigned int i, j;
  79.     GetByteContext gb;
  80.  
  81.     bytestream2_init(&gb, src, src_len);
  82.     d = dest;
  83.     d_end = d + dest_len;
  84.     dataleft = bytestream2_get_le32(&gb);
  85.     memset(queue, 0x20, QUEUE_SIZE);
  86.     if (bytestream2_get_bytes_left(&gb) < 4)
  87.         return AVERROR_INVALIDDATA;
  88.     if (bytestream2_peek_le32(&gb) == 0x56781234) {
  89.         bytestream2_skipu(&gb, 4);
  90.         qpos = 0x111;
  91.         speclen = 0xF + 3;
  92.     } else {
  93.         qpos = 0xFEE;
  94.         speclen = 100;  /* no speclen */
  95.     }
  96.  
  97.     while (dataleft > 0 && bytestream2_get_bytes_left(&gb) > 0) {
  98.         tag = bytestream2_get_byteu(&gb);
  99.         if ((tag == 0xFF) && (dataleft > 8)) {
  100.             if (d_end - d < 8 || bytestream2_get_bytes_left(&gb) < 8)
  101.                 return AVERROR_INVALIDDATA;
  102.             for (i = 0; i < 8; i++) {
  103.                 queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
  104.                 qpos &= QUEUE_MASK;
  105.             }
  106.             dataleft -= 8;
  107.         } else {
  108.             for (i = 0; i < 8; i++) {
  109.                 if (dataleft == 0)
  110.                     break;
  111.                 if (tag & 0x01) {
  112.                     if (d_end - d < 1 || bytestream2_get_bytes_left(&gb) < 1)
  113.                         return AVERROR_INVALIDDATA;
  114.                     queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
  115.                     qpos &= QUEUE_MASK;
  116.                     dataleft--;
  117.                 } else {
  118.                     chainofs = bytestream2_get_byte(&gb);
  119.                     chainofs |= ((bytestream2_peek_byte(&gb) & 0xF0) << 4);
  120.                     chainlen = (bytestream2_get_byte(&gb) & 0x0F) + 3;
  121.                     if (chainlen == speclen) {
  122.                         chainlen = bytestream2_get_byte(&gb) + 0xF + 3;
  123.                     }
  124.                     if (d_end - d < chainlen)
  125.                         return AVERROR_INVALIDDATA;
  126.                     for (j = 0; j < chainlen; j++) {
  127.                         *d = queue[chainofs++ & QUEUE_MASK];
  128.                         queue[qpos++] = *d++;
  129.                         qpos &= QUEUE_MASK;
  130.                     }
  131.                     dataleft -= chainlen;
  132.                 }
  133.                 tag >>= 1;
  134.             }
  135.         }
  136.     }
  137.     return d - dest;
  138. }
  139. static int rle_unpack(const unsigned char *src, unsigned char *dest,
  140.                       int src_count, int src_size, int dest_len)
  141. {
  142.     unsigned char *pd;
  143.     int i, l, used = 0;
  144.     unsigned char *dest_end = dest + dest_len;
  145.     GetByteContext gb;
  146.     uint16_t run_val;
  147.  
  148.     bytestream2_init(&gb, src, src_size);
  149.     pd = dest;
  150.     if (src_count & 1) {
  151.         if (bytestream2_get_bytes_left(&gb) < 1)
  152.             return 0;
  153.         *pd++ = bytestream2_get_byteu(&gb);
  154.         used++;
  155.     }
  156.  
  157.     do {
  158.         if (bytestream2_get_bytes_left(&gb) < 1)
  159.             break;
  160.         l = bytestream2_get_byteu(&gb);
  161.         if (l & 0x80) {
  162.             l = (l & 0x7F) * 2;
  163.             if (dest_end - pd < l || bytestream2_get_bytes_left(&gb) < l)
  164.                 return bytestream2_tell(&gb);
  165.             bytestream2_get_bufferu(&gb, pd, l);
  166.             pd += l;
  167.         } else {
  168.             if (dest_end - pd < 2*l || bytestream2_get_bytes_left(&gb) < 2)
  169.                 return bytestream2_tell(&gb);
  170.             run_val = bytestream2_get_ne16(&gb);
  171.             for (i = 0; i < l; i++) {
  172.                 AV_WN16(pd, run_val);
  173.                 pd += 2;
  174.             }
  175.             l *= 2;
  176.         }
  177.         used += l;
  178.     } while (used < src_count);
  179.  
  180.     return bytestream2_tell(&gb);
  181. }
  182.  
  183. static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
  184. {
  185.     int i;
  186.     unsigned int *palette32;
  187.     unsigned char r, g, b;
  188.  
  189.     GetByteContext gb;
  190.  
  191.     unsigned char meth;
  192.     unsigned char *dp;   /* pointer to current frame */
  193.     unsigned char *pp;   /* pointer to previous frame */
  194.     unsigned char len;
  195.     int ofs;
  196.  
  197.     int frame_x, frame_y;
  198.     int frame_width, frame_height;
  199.  
  200.     frame_x = AV_RL16(&s->buf[6]);
  201.     frame_y = AV_RL16(&s->buf[8]);
  202.     frame_width = AV_RL16(&s->buf[10]) - frame_x + 1;
  203.     frame_height = AV_RL16(&s->buf[12]) - frame_y + 1;
  204.  
  205.     if ((frame_width == s->avctx->width && frame_height == s->avctx->height) &&
  206.         (frame_x || frame_y)) {
  207.  
  208.         s->x_off = frame_x;
  209.         s->y_off = frame_y;
  210.     }
  211.     frame_x -= s->x_off;
  212.     frame_y -= s->y_off;
  213.  
  214.     if (frame_x < 0 || frame_width < 0 ||
  215.         frame_x >= s->avctx->width ||
  216.         frame_width > s->avctx->width ||
  217.         frame_x + frame_width > s->avctx->width) {
  218.         av_log(s->avctx, AV_LOG_ERROR,
  219.                "Invalid horizontal range %d-%d\n",
  220.                frame_x, frame_width);
  221.         return AVERROR_INVALIDDATA;
  222.     }
  223.     if (frame_y < 0 || frame_height < 0 ||
  224.         frame_y >= s->avctx->height ||
  225.         frame_height > s->avctx->height ||
  226.         frame_y + frame_height > s->avctx->height) {
  227.         av_log(s->avctx, AV_LOG_ERROR,
  228.                "Invalid vertical range %d-%d\n",
  229.                frame_x, frame_width);
  230.         return AVERROR_INVALIDDATA;
  231.     }
  232.  
  233.     /* if only a certain region will be updated, copy the entire previous
  234.      * frame before the decode */
  235.     if (s->prev_frame->data[0] &&
  236.         (frame_x || frame_y || (frame_width != s->avctx->width) ||
  237.         (frame_height != s->avctx->height))) {
  238.  
  239.         memcpy(frame->data[0], s->prev_frame->data[0],
  240.             s->avctx->height * frame->linesize[0]);
  241.     }
  242.  
  243.     /* check if there is a new palette */
  244.     bytestream2_init(&gb, s->buf + 16, s->size - 16);
  245.     if (s->buf[15] & 0x02) {
  246.         bytestream2_skip(&gb, 2);
  247.         palette32 = (unsigned int *)s->palette;
  248.         if (bytestream2_get_bytes_left(&gb) >= PALETTE_COUNT * 3) {
  249.             for (i = 0; i < PALETTE_COUNT; i++) {
  250.                 r = bytestream2_get_byteu(&gb) * 4;
  251.                 g = bytestream2_get_byteu(&gb) * 4;
  252.                 b = bytestream2_get_byteu(&gb) * 4;
  253.                 palette32[i] = 0xFFU << 24 | (r << 16) | (g << 8) | (b);
  254.                 palette32[i] |= palette32[i] >> 6 & 0x30303;
  255.             }
  256.         } else {
  257.             av_log(s->avctx, AV_LOG_ERROR, "Incomplete palette\n");
  258.             return AVERROR_INVALIDDATA;
  259.         }
  260.     }
  261.  
  262.     if (!s->size)
  263.         return 0;
  264.  
  265.     /* originally UnpackFrame in VAG's code */
  266.     if (bytestream2_get_bytes_left(&gb) < 1)
  267.         return AVERROR_INVALIDDATA;
  268.     meth = bytestream2_get_byteu(&gb);
  269.     if (meth & 0x80) {
  270.         int size;
  271.         if (!s->unpack_buffer_size) {
  272.             av_log(s->avctx, AV_LOG_ERROR,
  273.                    "Trying to unpack LZ-compressed frame with no LZ buffer\n");
  274.             return AVERROR_INVALIDDATA;
  275.         }
  276.         size = lz_unpack(gb.buffer, bytestream2_get_bytes_left(&gb),
  277.                          s->unpack_buffer, s->unpack_buffer_size);
  278.         if (size < 0)
  279.             return size;
  280.         meth &= 0x7F;
  281.         bytestream2_init(&gb, s->unpack_buffer, size);
  282.     }
  283.  
  284.     dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x];
  285.     pp = &s->prev_frame->data[0][frame_y * s->prev_frame->linesize[0] + frame_x];
  286.     switch (meth) {
  287.     case 1:
  288.         for (i = 0; i < frame_height; i++) {
  289.             ofs = 0;
  290.             do {
  291.                 len = bytestream2_get_byte(&gb);
  292.                 if (len & 0x80) {
  293.                     len = (len & 0x7F) + 1;
  294.                     if (ofs + len > frame_width ||
  295.                         bytestream2_get_bytes_left(&gb) < len)
  296.                         return AVERROR_INVALIDDATA;
  297.                     bytestream2_get_bufferu(&gb, &dp[ofs], len);
  298.                     ofs += len;
  299.                 } else {
  300.                     /* interframe pixel copy */
  301.                     if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
  302.                         return AVERROR_INVALIDDATA;
  303.                     memcpy(&dp[ofs], &pp[ofs], len + 1);
  304.                     ofs += len + 1;
  305.                 }
  306.             } while (ofs < frame_width);
  307.             if (ofs > frame_width) {
  308.                 av_log(s->avctx, AV_LOG_ERROR,
  309.                        "offset > width (%d > %d)\n",
  310.                        ofs, frame_width);
  311.                 return AVERROR_INVALIDDATA;
  312.             }
  313.             dp += frame->linesize[0];
  314.             pp += s->prev_frame->linesize[0];
  315.         }
  316.         break;
  317.  
  318.     case 2:
  319.         for (i = 0; i < frame_height; i++) {
  320.             bytestream2_get_buffer(&gb, dp, frame_width);
  321.             dp += frame->linesize[0];
  322.             pp += s->prev_frame->linesize[0];
  323.         }
  324.         break;
  325.  
  326.     case 3:
  327.         for (i = 0; i < frame_height; i++) {
  328.             ofs = 0;
  329.             do {
  330.                 len = bytestream2_get_byte(&gb);
  331.                 if (len & 0x80) {
  332.                     len = (len & 0x7F) + 1;
  333.                     if (bytestream2_peek_byte(&gb) == 0xFF) {
  334.                         int slen = len;
  335.                         bytestream2_get_byte(&gb);
  336.                         len = rle_unpack(gb.buffer, &dp[ofs],
  337.                                          len, bytestream2_get_bytes_left(&gb),
  338.                                          frame_width - ofs);
  339.                         ofs += slen;
  340.                         bytestream2_skip(&gb, len);
  341.                     } else {
  342.                         if (ofs + len > frame_width ||
  343.                             bytestream2_get_bytes_left(&gb) < len)
  344.                             return AVERROR_INVALIDDATA;
  345.                         bytestream2_get_buffer(&gb, &dp[ofs], len);
  346.                         ofs += len;
  347.                     }
  348.                 } else {
  349.                     /* interframe pixel copy */
  350.                     if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
  351.                         return AVERROR_INVALIDDATA;
  352.                     memcpy(&dp[ofs], &pp[ofs], len + 1);
  353.                     ofs += len + 1;
  354.                 }
  355.             } while (ofs < frame_width);
  356.             if (ofs > frame_width) {
  357.                 av_log(s->avctx, AV_LOG_ERROR,
  358.                        "offset > width (%d > %d)\n",
  359.                        ofs, frame_width);
  360.                 return AVERROR_INVALIDDATA;
  361.             }
  362.             dp += frame->linesize[0];
  363.             pp += s->prev_frame->linesize[0];
  364.         }
  365.         break;
  366.     }
  367.     return 0;
  368. }
  369.  
  370. static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
  371. {
  372.     VmdVideoContext *s = avctx->priv_data;
  373.  
  374.     av_frame_free(&s->prev_frame);
  375.     av_freep(&s->unpack_buffer);
  376.     s->unpack_buffer_size = 0;
  377.  
  378.     return 0;
  379. }
  380.  
  381. static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)
  382. {
  383.     VmdVideoContext *s = avctx->priv_data;
  384.     int i;
  385.     unsigned int *palette32;
  386.     int palette_index = 0;
  387.     unsigned char r, g, b;
  388.     unsigned char *vmd_header;
  389.     unsigned char *raw_palette;
  390.  
  391.     s->avctx = avctx;
  392.     avctx->pix_fmt = AV_PIX_FMT_PAL8;
  393.  
  394.     /* make sure the VMD header made it */
  395.     if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
  396.         av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n",
  397.             VMD_HEADER_SIZE);
  398.         return AVERROR_INVALIDDATA;
  399.     }
  400.     vmd_header = (unsigned char *)avctx->extradata;
  401.  
  402.     s->unpack_buffer_size = AV_RL32(&vmd_header[800]);
  403.     if (s->unpack_buffer_size) {
  404.         s->unpack_buffer = av_malloc(s->unpack_buffer_size);
  405.         if (!s->unpack_buffer)
  406.             return AVERROR(ENOMEM);
  407.     }
  408.  
  409.     /* load up the initial palette */
  410.     raw_palette = &vmd_header[28];
  411.     palette32 = (unsigned int *)s->palette;
  412.     for (i = 0; i < PALETTE_COUNT; i++) {
  413.         r = raw_palette[palette_index++] * 4;
  414.         g = raw_palette[palette_index++] * 4;
  415.         b = raw_palette[palette_index++] * 4;
  416.         palette32[i] = 0xFFU << 24 | (r << 16) | (g << 8) | (b);
  417.         palette32[i] |= palette32[i] >> 6 & 0x30303;
  418.     }
  419.  
  420.     s->prev_frame = av_frame_alloc();
  421.     if (!s->prev_frame) {
  422.         vmdvideo_decode_end(avctx);
  423.         return AVERROR(ENOMEM);
  424.     }
  425.  
  426.     return 0;
  427. }
  428.  
  429. static int vmdvideo_decode_frame(AVCodecContext *avctx,
  430.                                  void *data, int *got_frame,
  431.                                  AVPacket *avpkt)
  432. {
  433.     const uint8_t *buf = avpkt->data;
  434.     int buf_size = avpkt->size;
  435.     VmdVideoContext *s = avctx->priv_data;
  436.     AVFrame *frame = data;
  437.     int ret;
  438.  
  439.     s->buf = buf;
  440.     s->size = buf_size;
  441.  
  442.     if (buf_size < 16)
  443.         return AVERROR_INVALIDDATA;
  444.  
  445.     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
  446.         return ret;
  447.  
  448.     if ((ret = vmd_decode(s, frame)) < 0)
  449.         return ret;
  450.  
  451.     /* make the palette available on the way out */
  452.     memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
  453.  
  454.     /* shuffle frames */
  455.     av_frame_unref(s->prev_frame);
  456.     if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
  457.         return ret;
  458.  
  459.     *got_frame      = 1;
  460.  
  461.     /* report that the buffer was completely consumed */
  462.     return buf_size;
  463. }
  464.  
  465. AVCodec ff_vmdvideo_decoder = {
  466.     .name           = "vmdvideo",
  467.     .long_name      = NULL_IF_CONFIG_SMALL("Sierra VMD video"),
  468.     .type           = AVMEDIA_TYPE_VIDEO,
  469.     .id             = AV_CODEC_ID_VMDVIDEO,
  470.     .priv_data_size = sizeof(VmdVideoContext),
  471.     .init           = vmdvideo_decode_init,
  472.     .close          = vmdvideo_decode_end,
  473.     .decode         = vmdvideo_decode_frame,
  474.     .capabilities   = AV_CODEC_CAP_DR1,
  475. };
  476.