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

Xiaohui Sun sunxiaohui
Fri Apr 6 18:03:37 CEST 2007


patch updated.

Diego Biurrun wrote:
> On Fri, Apr 06, 2007 at 12:34:05AM +0800, Xiaohui Sun wrote:
>   
>> patch updated.
>>
>> --- libavcodec/sgidec.c	(revision 0)
>> +++ libavcodec/sgidec.c	(revision 0)
>> @@ -0,0 +1,267 @@
>> +
>> +#include "sgi.h"
>>     
>
> Where is sgi.h ???
>
>   

Sorry , I forgot attach it, try this new patch.

> I was about to commit your patch and made some spelling fixes to
> sgienc.c and sgidec.c.  Please use the attached files when you
> send a patch with sgi.h.
>
>   

ok

> Diego
>   
> ------------------------------------------------------------------------
>
> /*
>  * SGI image decoder
>  * Todd Kirby <doubleshot at pacbell.net>
>  *
>  * This file is part of FFmpeg.
>  *
>  * FFmpeg 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.
>  *
>  * FFmpeg 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 FFmpeg; if not, write to the Free Software
>  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>  */
>
> #include "avcodec.h"
> #include "bytestream.h"
> #include "sgi.h"
>
> typedef struct SgiState {
>     AVFrame picture;
>     unsigned int width;
>     unsigned int height;
>     unsigned int depth;
>     int linesize;
> } SgiState;
>
> /**
>  * Expand an RLE row into a channel.
>  * @param in_buf input buffer
>  * @param in_end end of input buffer
>  * @param out_buf Points to one line after the output buffer.
>  * @param out_end end of line in output 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* in_end,
>             unsigned char *out_buf, uint8_t* out_end, int pixelstride)
> {
>     unsigned char pixel, count;
>     unsigned char *orig = out_buf;
>
>     while (1) {
>         if(in_buf + 1 > in_end) return -1;
>         pixel = bytestream_get_byte(&in_buf);
>         if (!(count = (pixel & 0x7f))) {
>             return (out_buf - orig) / pixelstride;
>         }
>
>         /* Check for buffer overflow. */
>         if(out_buf + pixelstride * count >= out_end) return -1;
>
>         if (pixel & 0x80) {
>             while (count--) {
>                 *out_buf = bytestream_get_byte(&in_buf);
>                 out_buf += pixelstride;
>             }
>         } else {
>             pixel = bytestream_get_byte(&in_buf);
>
>             while (count--) {
>                 *out_buf = pixel;
>                 out_buf += pixelstride;
>             }
>         }
>     }
> }
>
> /**
>  * Read a run length encoded SGI image.
>  * @param out_buf output buffer
>  * @param in_buf input buffer
>  * @param in_end end of input buffer
>  * @param s the current image state
>  * @return 0 if no error, else return error number.
>  */
> static int read_rle_sgi(unsigned char* out_buf, uint8_t *in_buf,
>                         uint8_t *in_end, SgiState* s)
> {
>     uint8_t *dest_row;
>     unsigned int len = s->height * s->depth * 4;
>     uint8_t *start_table = in_buf;
>     unsigned int y, z;
>     unsigned int start_offset;
>
>     /* size of  RLE offset and length tables */
>     if(len * 2  > in_end - in_buf) {
>         return AVERROR_INVALIDDATA;
>     }
>
>     in_buf -= SGI_HEADER_SIZE;
>     for (z = 0; z < s->depth; z++) {
>         dest_row = out_buf;
>         for (y = 0; y < s->height; y++) {
>             dest_row -= s->linesize;
>             start_offset = bytestream_get_be32(&start_table);
>             if(start_offset > in_end - in_buf) {
>                 return AVERROR_INVALIDDATA;
>             }
>             if (expand_rle_row(in_buf + start_offset, in_end, dest_row + z,
>                 dest_row + FFABS(s->linesize), s->depth) != s->width)
>                 return AVERROR_INVALIDDATA;
>         }
>     }
>     return 0;
> }
>
> /**
>  * Read an uncompressed SGI image.
>  * @param out_buf output buffer
>  * @param out_end end ofoutput buffer
>  * @param in_buf input buffer
>  * @param in_end end of input buffer
>  * @param s the current image state
>  * @return 0 if read success, otherwise return -1.
>  */
> static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end,
>                 uint8_t *in_buf, uint8_t *in_end, SgiState* s)
> {
>     int x, y, z;
>     uint8_t *ptr;
>     unsigned int offset = s->height * s->width;
>
>     /* Test buffer size. */
>     if (offset * s->depth > in_end - in_buf) {
>        return -1;
>     }
>
>     for (y = s->height - 1; y >= 0; y--) {
>         out_end = out_buf + (y * s->linesize);
>         for (x = s->width; x > 0; x--) {
>             ptr = in_buf++;
>             for(z = 0; z < s->depth; z ++) {
>                 bytestream_put_byte(&out_end, *ptr);
>                 ptr += offset;
>             }
>         }
>     }
>     return 0;
> }
>
> static int decode_frame(AVCodecContext *avctx,
>                         void *data, int *data_size,
>                         uint8_t *in_buf, int buf_size)
> {
>     SgiState *s = avctx->priv_data;
>     AVFrame *picture = data;
>     AVFrame *p = &s->picture;
>     uint8_t *in_end = in_buf + buf_size;
>     unsigned int dimension, bytes_per_channel, rle;
>     int ret = 0;
>     uint8_t *out_buf, *out_end;
>
>     if (buf_size < SGI_HEADER_SIZE){
>         av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", buf_size);
>         return -1;
>     }
>
>     /* Test for SGI magic. */
>     if (bytestream_get_be16(&in_buf) != SGI_MAGIC) {
>         av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
>         return -1;
>     }
>
>     rle = bytestream_get_byte(&in_buf);
>     bytes_per_channel = bytestream_get_byte(&in_buf);
>     dimension = bytestream_get_be16(&in_buf);
>     s->width  = bytestream_get_be16(&in_buf);
>     s->height = bytestream_get_be16(&in_buf);
>     s->depth  = bytestream_get_be16(&in_buf);
>
>     if (bytes_per_channel != 1) {
>         av_log(avctx, AV_LOG_ERROR, "wrong channel number\n");
>         return -1;
>     }
>
>     /* Check for supported image dimensions. */
>     if (dimension != 2 && dimension != 3) {
>         av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n");
>         return -1;
>     }
>
>     if (s->depth == SGI_GRAYSCALE) {
>         avctx->pix_fmt = PIX_FMT_GRAY8;
>     } else if (s->depth == SGI_RGB) {
>         avctx->pix_fmt = PIX_FMT_RGB24;
>     } else if (s->depth == SGI_RGBA) {
>         avctx->pix_fmt = PIX_FMT_RGBA;
>     } else {
>         av_log(avctx, AV_LOG_ERROR, "wrong picture format\n");
>         return -1;
>     }
>
>     if (avcodec_check_dimensions(avctx, s->width, s->height))
>         return -1;
>     avcodec_set_dimensions(avctx, s->width, s->height);
>
>     if (p->data[0])
>         avctx->release_buffer(avctx, p);
>
>     p->reference = 0;
>     if (avctx->get_buffer(avctx, p) < 0) {
>         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n");
>         return -1;
>     }
>
>     p->pict_type = FF_I_TYPE;
>     p->key_frame = 1;
>     out_buf = p->data[0];
>
>     out_end = out_buf + p->linesize[0] * s->height;
>
>     s->linesize = p->linesize[0];
>
>     /* Skip header. */
>     in_buf += SGI_HEADER_SIZE - 12;
>     if (rle) {
>         ret = read_rle_sgi(out_end, in_buf, in_end, s);
>     } else {
>         ret = read_uncompressed_sgi(out_buf, out_end, in_buf, in_end, s);
>     }
>
>     if (ret == 0) {
>         *picture   = s->picture;
>         *data_size = sizeof(AVPicture);
>         return buf_size;
>     } else {
>         return -1;
>     }
> }
>
> static int sgi_init(AVCodecContext *avctx){
>     SgiState *s = avctx->priv_data;
>
>     avcodec_get_frame_defaults(&s->picture);
>     avctx->coded_frame = &s->picture;
>
>     return 0;
> }
>
> static int sgi_end(AVCodecContext *avctx)
> {
>     SgiState * const s = avctx->priv_data;
>
>     if (s->picture.data[0])
>         avctx->release_buffer(avctx, &s->picture);
>
>     return 0;
> }
>
> AVCodec sgi_decoder = {
>     "sgi",
>     CODEC_TYPE_VIDEO,
>     CODEC_ID_SGI,
>     sizeof(SgiState),
>     sgi_init,
>     NULL,
>     sgi_end,
>     decode_frame,
> };
>
>   
> ------------------------------------------------------------------------
>
> /*
>  * SGI image encoder
>  * Todd Kirby <doubleshot at pacbell.net>
>  *
>  * This file is part of FFmpeg.
>  *
>  * FFmpeg 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.
>  *
>  * FFmpeg 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 FFmpeg; if not, write to the Free Software
>  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>  */
>
> #include "avcodec.h"
> #include "bytestream.h"
> #include "sgi.h"
> #include "rle.h"
>
> #define SGI_SINGLE_CHAN 2
> #define SGI_MULTI_CHAN 3
>
> typedef struct SgiContext {
>     AVFrame picture;
> } SgiContext;
>
> static int encode_init(AVCodecContext *avctx){
>     SgiContext *s = avctx->priv_data;
>
>     avcodec_get_frame_defaults(&s->picture);
>     avctx->coded_frame = &s->picture;
>
>     return 0;
> }
>
> static int encode_frame(AVCodecContext *avctx, unsigned char *buf,
>                         int buf_size, void *data) {
>     SgiContext *s = avctx->priv_data;
>     AVFrame * const p = &s->picture;
>     uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf;
>     int x, y, z, length, tablesize;
>     unsigned int width, height, depth, dimension;
>     unsigned char *orig_buf = buf, *end_buf = buf + buf_size;
>
>     *p = *(AVFrame*)data;
>     p->pict_type = FF_I_TYPE;
>     p->key_frame = 1;
>
>     width = avctx->width;
>     height = avctx->height;
>
>     switch (avctx->pix_fmt) {
>         case PIX_FMT_GRAY8:
>             dimension = SGI_SINGLE_CHAN;
>             depth = SGI_GRAYSCALE;
>             break;
>         case PIX_FMT_RGB24:
>             dimension = SGI_MULTI_CHAN;
>             depth = SGI_RGB;
>             break;
>         case PIX_FMT_RGBA:
>             dimension = SGI_MULTI_CHAN;
>             depth = SGI_RGBA;
>             break;
>         default:
>             return AVERROR_INVALIDDATA;
>     }
>
>     tablesize = depth * height * 4;
>     length = tablesize * 2 + SGI_HEADER_SIZE;
>
>     if (buf_size < length) {
>         av_log(avctx, AV_LOG_ERROR, "buf_size too small(need %d, got %d)\n", length, buf_size);
>         return -1;
>     }
>
>     /* Encode header. */
>     bytestream_put_be16(&buf, SGI_MAGIC);
>     bytestream_put_byte(&buf, 1); /* RLE */
>     bytestream_put_byte(&buf, 1); /* bytes_per_channel */
>     bytestream_put_be16(&buf, dimension);
>     bytestream_put_be16(&buf, width);
>     bytestream_put_be16(&buf, height);
>     bytestream_put_be16(&buf, depth);
>
>     /* The rest are constant in this implementation. */
>     bytestream_put_be32(&buf, 0L); /* pixmin */
>     bytestream_put_be32(&buf, 255L); /* pixmax */
>     bytestream_put_be32(&buf, 0L); /* dummy */
>
>     /* name */
>     memset(buf, 0, SGI_HEADER_SIZE);
>     buf += 80;
>
>      /* colormap */
>     bytestream_put_be32(&buf, 0L);
>
>     /* The rest of the 512 byte header is unused. */
>     buf += 404;
>     offsettab = buf;
>
>     /* Skip RLE offset table. */
>     buf += tablesize;
>     lengthtab = buf;
>
>     /* Skip RLE length table. */
>     buf += tablesize;
>
>     /* Make an intermediate consecutive buffer. */
>     if ((encode_buf = av_malloc(width)) == NULL)
>         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];
>
>             if((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) {
>                 av_free(encode_buf);
>                 return -1;
>             }
>
>             buf += length;
>             bytestream_put_byte(&buf, 0);
>             bytestream_put_be32(&lengthtab, length + 1);
>             in_buf -= p->linesize[0];
>         }
>     }
>
>     av_free(encode_buf);
>     /* total length */
>     return buf - orig_buf;
> }
>
> AVCodec sgi_encoder = {
>     "sgi",
>     CODEC_TYPE_VIDEO,
>     CODEC_ID_SGI,
>     sizeof(SgiContext),
>     encode_init,
>     encode_frame,
>     NULL,
>     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA, PIX_FMT_PAL8, PIX_FMT_GRAY8, -1},
> };
>
>   
> ------------------------------------------------------------------------
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at mplayerhq.hu
> http://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-devel

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: sgi_port.patch
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070407/e0f7d467/attachment.txt>



More information about the ffmpeg-devel mailing list