[Ffmpeg-devel] [PATCH] ported SGI decoder to the new API

Michael Niedermayer michaelni
Tue Apr 3 01:13:46 CEST 2007


Hi

On Tue, Apr 03, 2007 at 12:46:36AM +0800, Xiaohui Sun wrote:
> I have updated the patch.

[...]
> Index: libavcodec/rle.c
> ===================================================================
> --- libavcodec/rle.c	(revision 0)
> +++ libavcodec/rle.c	(revision 0)

i think this should be diffed against the old rle code (currently in targaenc.c)

[...]
> +#include "common.h"
> +#include "bytestream.h"
> +#include "rle.h"
> +
> +/**
> + * Count up to 127 consecutive pixels which are either all the same or
> + * all differ from the previous and next pixels with one bpp
> + * @param start pointer to the first pixel
> + * @param len maximum number of pixels
> + * @param same 1 if searching for identical pixel values, 0 for differing
> + * @return number of matching consecutive pixels found
> + */
> +static av_always_inline int count_pixels_1bpp(uint8_t *start, int len, int same)
> +{
> +    uint8_t *pos;
> +    int count = 1;
> +
> +    for (pos = start + 1; count < FFMIN(127, len); pos ++, count ++) {
> +        if (same != !(*(pos - 1) != * pos)) {
> +            if (!same) {
> +                /* if bpp == 1, then 0 1 1 0 is more efficiently encoded as a single
> +                 * raw block of pixels.  for larger bpp, RLE is as good or better */
> +                if (count + 1 < FFMIN(127, len) && *pos != *(pos + 1))
> +                    continue;
> +
> +                /* if RLE can encode the next block better than as a raw block,
> +                 * back up and leave _all_ the identical pixels for RLE */
> +                count --;
> +            }
> +            break;
> +        }
> +    }
> +    return count;
> +}
> +
> +/**
> + * Count up to 127 consecutive pixels which are either all the same or
> + * all differ from the previous and next pixels with more than one bpp
> + * @param start pointer to the first pixel
> + * @param len maximum number of pixels
> + * @param bpp bytes per pixel
> + * @param same 1 if searching for identical pixel values, 0 for differing
> + * @return number of matching consecutive pixels found
> + */
> +static av_always_inline int count_pixels_nbpp(uint8_t *start, int len, int bpp, int same)
> +{
> +    uint8_t *pos;
> +    int count = 1;
> +
> +    for (pos = start + bpp; count < FFMIN(127, len); pos += bpp, count ++) {
> +        if (same != !memcmp(pos - bpp, pos, bpp)) {
> +            if (!same) {
> +                /* if RLE can encode the next block better than as a raw block,
> +                 * back up and leave _all_ the identical pixels for RLE */
> +                count --;
> +            }
> +            break;
> +        }
> +    }
> +    return count;
> +}

code duplication

[...]
> +/**
> + * expand an RLE row into a channel
> + * @param in_buf input buffer
> + * @param out_ptr output buffer
> + * @param end_ptr end of line in output buffer
> + * @param chan_offset offsets into input buffer
> + * @param pixelstride pixel stride of input buffer
> + * @return Size of output in bytes, -1 if buffer overflows
> + */
> +static int expand_rle_row(uint8_t *in_buf, uint8_t* end_buf,
> +            unsigned char *out_ptr, uint8_t* end_ptr,
> +            int chan_offset, int pixelstride)
> +{
> +    unsigned char pixel, count;
> +    unsigned char *orig = out_ptr;
> +
> +    out_ptr += chan_offset;

it would be cleaner if the out_ptr argument would point to the output
array instead of passing the chan_offset into the functin and then changing
the out_ptr


> +
> +    while (1) {

> +        if(in_buf + 1 > end_buf) return -1;

this check isnt really needed as the input array is guranteed to be 8 bytes
larger then end_buf


[...]
> +            start_offset = bytestream_get_be32(&start_table);
> +            if(start_offset > end_buf - in_buf) {
> +                return AVERROR_INVALIDDATA;
> +            }

excelent, finally the check looks good


> +            if (expand_rle_row(in_buf + start_offset, end_buf, dest_row,
> +                dest_row + s->linesize, z, s->depth) != s->width)
> +                return AVERROR_INVALIDDATA;

linesize can be negative



[...]
> +static int decode_frame(AVCodecContext *avctx,
> +                        void *data, int *data_size,
> +                        uint8_t *buf, int buf_size)
> +{
> +    SgiState *s = avctx->priv_data;
> +    AVFrame *picture = data;
> +    AVFrame *p = &s->picture;
> +    uint8_t* orig_buf = buf, *end_buf = buf + buf_size;

the orig_buf variable seems to be unneeded


[...]
> +    s->linesize = p->linesize[0];
> +    p->pict_type = FF_I_TYPE;
> +    p->key_frame = 1;
> +    ptr = p->data[0];
> +
> +    end_ptr = ptr + s->linesize * s->height;

linesize can be negative

also i think ptr / buf are confusing names, out_ptr / in_buf would be
clearer


[...]
> +static av_always_inline int encode_rle_1bpp(int w, uint8_t* in_buf,
> +                        unsigned char* out_buf, uint8_t* end_buf)
> +{
> +    int x, count;
> +    uint8_t* orig_buf = out_buf;
> +
> +    for (x = 0; x < w; x += count) {
> +        /* see if we can encode the next set of pixels with RLE */
> +        if ((count = ff_count_pixels(in_buf, w - x, 1, 1)) > 1) {
> +            if (out_buf + 2 > end_buf) return -1;
> +            bytestream_put_byte(&out_buf, count);
> +            bytestream_put_byte(&out_buf, *in_buf);
> +        } else {
> +            /* fall back on uncompressed */
> +            count = ff_count_pixels(in_buf, w-x, 1, 0);
> +
> +            if (out_buf + count + 1 > end_buf) return -1;
> +            bytestream_put_byte(&out_buf, 0x80 | count);
> +            bytestream_put_buffer(&out_buf, in_buf, count);
> +        }
> +        in_buf += count;
> +    }

> +    *(out_buf++) = 0;

it seems this byte can end outside the array


[...]
> +    /* make an intermediate consecutive buffer */
> +    if ((encode_buf = (char *)av_malloc(width)) == NULL)

unneeded cast


> +        return -1;
> +
> +    for (z = 0; z < depth; z++) {
> +        in_buf = p->data[0] + p->linesize[0] * (height - 1) + z;
> +
> +        for (y = 0; y < height; y++) {
> +            bytestream_put_be32(&offsettab, buf - orig_buf);
> +

> +            for (x = 0; x < width; x++)
> +                *(encode_buf + x) = *(in_buf + depth * x);

i think encode_buf[x] = in_buf[depth*z] is more readable and definitly more
commonly used


> +
> +            if((length = encode_rle_1bpp(width, encode_buf, buf, end_buf)) == -1)
> +                return -1;

memleak


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Observe your enemies, for they first find out your faults. -- Antisthenes
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070403/d36c07d9/attachment.pgp>



More information about the ffmpeg-devel mailing list