Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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