[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