On Thu, Mar 13, 2014 at 06:57:24PM +0100, Vittorio Giovara wrote:
> From: Peter Ross <[email protected]>
>
> Signed-off-by: Vittorio Giovara <[email protected]>
> ---
> I could find no sample for this decoder but it is needed for the following
> MV patch; if anyone has a sample please share it so I can add it to the tests.
> Vittorio
> Changelog | 1 +
> doc/general.texi | 1 +
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/avcodec.h | 1 +
> libavcodec/codec_desc.c | 7 +++
> libavcodec/sgirledec.c | 156
> ++++++++++++++++++++++++++++++++++++++++++++++++
> libavcodec/version.h | 4 +-
> libavformat/isom.c | 1 +
> 9 files changed, 171 insertions(+), 2 deletions(-)
> create mode 100644 libavcodec/sgirledec.c
>
> diff --git a/libavcodec/sgirledec.c b/libavcodec/sgirledec.c
> new file mode 100644
> index 0000000..acb5390
> --- /dev/null
> +++ b/libavcodec/sgirledec.c
> @@ -0,0 +1,156 @@
> +/*
> + * Silicon Graphics RLE 8-bit video decoder
> + * Copyright (c) 2012 Peter Ross
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
> USA
> + */
> +
> +/**
> + * @file
> + * Silicon Graphics RLE 8-bit video decoder
> + * @note sgirledec decodes rgb332 rle packets in mv or mov.
> + * The algorithm and pixfmt are subtley different from SGI image,
> corresponding
subtly
> + * to the outdated DITHERED mode for COLORMAP.
> + */
> +
> +#include "libavutil/common.h"
> +
> +#include "avcodec.h"
> +#include "internal.h"
> +
> +typedef struct SGIRLEContext {
> + AVFrame *frame;
> +} SGIRLEContext;
> +
> +static av_cold int sgirle_decode_init(AVCodecContext *avctx)
> +{
> + SGIRLEContext *s = avctx->priv_data;
> + avctx->pix_fmt = AV_PIX_FMT_BGR8;
> + s->frame = av_frame_alloc();
> + if (!s->frame)
> + return AVERROR(ENOMEM);
> + return 0;
> +}
> +
> +/**
> + * Convert SGI RGB332 pixel into AV_PIX_FMT_BGR8
> + * SGI RGB332 is packed RGB 3:3:2, 8bpp, (msb)3R 2B 3G(lsb)
> + */
> +#define RGB332_TO_BGR8(x) (((x << 3) & 0xC0) | ((x << 3) & 0x38) | ((x >> 5)
> & 7))
> +
> +static av_always_inline void memcpy_rgb332_to_bgr8(uint8_t *dst, const
> uint8_t *src, int size)
facepalm
shall we rename libswscale to libmemcpy too?
> +{
> + int i;
> + for (i = 0; i < size; i++)
> + dst[i] = RGB332_TO_BGR8(src[i]);
> +}
and we have RGB8 too, why not use it?
> +
> +/**
> + * @param[out] dst Destination buffer
> + * @param[in] src Source buffer
> + * @param src_size Source buffer size (bytes)
> + * @param width Width of destination buffer (pixels)
> + * @param height Height of destination buffer (pixels)
> + * @param linesize Line size of destination buffer (bytes)
> + * @return <0 on error
> + */
> +static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, const uint8_t
> *src, int src_size, int width, int height, int linesize)
the line is not long enough
> +{
> + const uint8_t *src_end = src + src_size;
> + int x = 0, y = 0;
> +
> +#define INC_XY(n) \
> + x += n; \
> + if (x >= width) { \
> + y++; \
> + if (y >= height) \
> + return 0; \
> + x = 0; \
> + }
> +
> + while (src_end - src >= 2) {
> + uint8_t v = *src++;
> + if (v > 0 && v < 0xC0) {
> + do {
> + int length = FFMIN(v, width - x);
> + if (length <= 0)
> + break;
> + memset(dst + y*linesize + x, RGB332_TO_BGR8(*src), length);
> + INC_XY(length);
> + v -= length;
> + } while (v > 0);
> + src++;
> + } else if (v >= 0xC1) {
> + v -= 0xC0;
> + do {
> + int length = FFMIN3(v, width - x, src_end - src);
> + if (src_end - src < length || length <= 0)
> + break;
> + memcpy_rgb332_to_bgr8(dst + y*linesize + x, src, length);
> + INC_XY(length);
> + src += length;
> + v -= length;
> + } while (v > 0);
> + } else {
that happens only for v=0, probably it's better to error out in this case
> + avpriv_request_sample(avctx, "opcode %d", v);
> + return AVERROR_PATCHWELCOME;
> + }
> + }
> + return 0;
> +}
> +
> +static int sgirle_decode_frame(AVCodecContext *avctx,
> + void *data, int *got_frame,
> + AVPacket *avpkt)
> +{
> + SGIRLEContext *s = avctx->priv_data;
> + int ret;
> +
> + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
> + return ret;
> +
> + ret = decode_sgirle8(avctx, s->frame->data[0], avpkt->data, avpkt->size,
> avctx->width, avctx->height, s->frame->linesize[0]);
this line should be longer
> + if (ret < 0)
> + return ret;
> +
> + *got_frame = 1;
> + if ((ret = av_frame_ref(data, s->frame)) < 0)
> + return ret;
> +
> + return avpkt->size;
> +}
> +
> +static av_cold int sgirle_decode_end(AVCodecContext *avctx)
> +{
> + SGIRLEContext *s = avctx->priv_data;
> +
> + av_frame_free(&s->frame);
> +
> + return 0;
> +}
> +
> +AVCodec ff_sgirle_decoder = {
> + .name = "sgirle",
> + .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics RLE 8-bit
> video"),
> + .type = AVMEDIA_TYPE_VIDEO,
> + .id = AV_CODEC_ID_SGIRLE,
> + .priv_data_size = sizeof(SGIRLEContext),
> + .init = sgirle_decode_init,
> + .close = sgirle_decode_end,
> + .decode = sgirle_decode_frame,
> + .capabilities = CODEC_CAP_DR1,
> +};
[the rest is trivial]
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel