Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Silicon Graphics RLE 8-bit video decoder
  3.  * Copyright (c) 2012 Peter Ross
  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.  * Silicon Graphics RLE 8-bit video decoder
  25.  * @note Data is packed in rbg323 with rle, contained in mv or mov.
  26.  * The algorithm and pixfmt are subtly different from SGI images.
  27.  */
  28.  
  29. #include "libavutil/common.h"
  30.  
  31. #include "avcodec.h"
  32. #include "internal.h"
  33.  
  34. typedef struct SGIRLEContext {
  35.     AVFrame *frame;
  36. } SGIRLEContext;
  37.  
  38. static av_cold int sgirle_decode_init(AVCodecContext *avctx)
  39. {
  40.     SGIRLEContext *s = avctx->priv_data;
  41.     avctx->pix_fmt = AV_PIX_FMT_BGR8;
  42.     s->frame = av_frame_alloc();
  43.     if (!s->frame)
  44.         return AVERROR(ENOMEM);
  45.     return 0;
  46. }
  47.  
  48. /**
  49.  * Convert SGI RBG323 pixel into AV_PIX_FMT_BGR8
  50.  * SGI RGB data is packed as 8bpp, (msb)3R 2B 3G(lsb)
  51.  */
  52. #define RBG323_TO_BGR8(x) ((((x) << 3) & 0xC0) |                                \
  53.                            (((x) << 3) & 0x38) |                                \
  54.                            (((x) >> 5) & 7))
  55. static av_always_inline
  56. void rbg323_to_bgr8(uint8_t *dst, const uint8_t *src, int size)
  57. {
  58.     int i;
  59.     for (i = 0; i < size; i++)
  60.         dst[i] = RBG323_TO_BGR8(src[i]);
  61. }
  62.  
  63. /**
  64.  * @param[out] dst Destination buffer
  65.  * @param[in] src  Source buffer
  66.  * @param src_size Source buffer size (bytes)
  67.  * @param width    Width of destination buffer (pixels)
  68.  * @param height   Height of destination buffer (pixels)
  69.  * @param linesize Line size of destination buffer (bytes)
  70.  *
  71.  * @return <0 on error
  72.  */
  73. static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst,
  74.                           const uint8_t *src, int src_size,
  75.                           int width, int height, ptrdiff_t linesize)
  76. {
  77.     const uint8_t *src_end = src + src_size;
  78.     int x = 0, y = 0;
  79.  
  80. #define INC_XY(n)                                                             \
  81.     x += n;                                                                   \
  82.     if (x >= width) {                                                         \
  83.         y++;                                                                  \
  84.         if (y >= height)                                                      \
  85.             return 0;                                                         \
  86.         x = 0;                                                                \
  87.     }
  88.  
  89.     while (src_end - src >= 2) {
  90.         uint8_t v = *src++;
  91.         if (v > 0 && v < 0xC0) {
  92.             do {
  93.                 int length = FFMIN(v, width - x);
  94.                 if (length <= 0)
  95.                     break;
  96.                 memset(dst + y * linesize + x, RBG323_TO_BGR8(*src), length);
  97.                 INC_XY(length);
  98.                 v -= length;
  99.             } while (v > 0);
  100.             src++;
  101.         } else if (v >= 0xC1) {
  102.             v -= 0xC0;
  103.             do {
  104.                 int length = FFMIN3(v, width - x, src_end - src);
  105.                 if (src_end - src < length || length <= 0)
  106.                     break;
  107.                 rbg323_to_bgr8(dst + y * linesize + x, src, length);
  108.                 INC_XY(length);
  109.                 src += length;
  110.                 v   -= length;
  111.             } while (v > 0);
  112.         } else {
  113.             avpriv_request_sample(avctx, "opcode %d", v);
  114.             return AVERROR_PATCHWELCOME;
  115.         }
  116.     }
  117.     return 0;
  118. }
  119.  
  120. static int sgirle_decode_frame(AVCodecContext *avctx, void *data,
  121.                                int *got_frame, AVPacket *avpkt)
  122. {
  123.     SGIRLEContext *s = avctx->priv_data;
  124.     int ret;
  125.  
  126.     if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
  127.         return ret;
  128.  
  129.     ret = decode_sgirle8(avctx, s->frame->data[0], avpkt->data, avpkt->size,
  130.                          avctx->width, avctx->height, s->frame->linesize[0]);
  131.     if (ret < 0)
  132.         return ret;
  133.  
  134.     *got_frame = 1;
  135.     if ((ret = av_frame_ref(data, s->frame)) < 0)
  136.         return ret;
  137.  
  138.     return avpkt->size;
  139. }
  140.  
  141. static av_cold int sgirle_decode_end(AVCodecContext *avctx)
  142. {
  143.     SGIRLEContext *s = avctx->priv_data;
  144.  
  145.     av_frame_free(&s->frame);
  146.  
  147.     return 0;
  148. }
  149.  
  150. AVCodec ff_sgirle_decoder = {
  151.     .name           = "sgirle",
  152.     .long_name      = NULL_IF_CONFIG_SMALL("Silicon Graphics RLE 8-bit video"),
  153.     .type           = AVMEDIA_TYPE_VIDEO,
  154.     .id             = AV_CODEC_ID_SGIRLE,
  155.     .priv_data_size = sizeof(SGIRLEContext),
  156.     .init           = sgirle_decode_init,
  157.     .close          = sgirle_decode_end,
  158.     .decode         = sgirle_decode_frame,
  159.     .capabilities   = AV_CODEC_CAP_DR1,
  160. };
  161.