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

Reply via email to