• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/sgienc.c

Go to the documentation of this file.
00001 /*
00002  * SGI image encoder
00003  * Todd Kirby <doubleshot@pacbell.net>
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "avcodec.h"
00023 #include "bytestream.h"
00024 #include "sgi.h"
00025 #include "rle.h"
00026 
00027 #define SGI_SINGLE_CHAN 2
00028 #define SGI_MULTI_CHAN 3
00029 
00030 typedef struct SgiContext {
00031     AVFrame picture;
00032 } SgiContext;
00033 
00034 static av_cold int encode_init(AVCodecContext *avctx)
00035 {
00036     SgiContext *s = avctx->priv_data;
00037 
00038     avcodec_get_frame_defaults(&s->picture);
00039     avctx->coded_frame = &s->picture;
00040 
00041     return 0;
00042 }
00043 
00044 static int encode_frame(AVCodecContext *avctx, unsigned char *buf,
00045                         int buf_size, void *data)
00046 {
00047     SgiContext *s = avctx->priv_data;
00048     AVFrame * const p = &s->picture;
00049     uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf;
00050     int x, y, z, length, tablesize;
00051     unsigned int width, height, depth, dimension, bytes_per_channel, pixmax, put_be;
00052     unsigned char *orig_buf = buf, *end_buf = buf + buf_size;
00053 
00054     *p = *(AVFrame*)data;
00055     p->pict_type = AV_PICTURE_TYPE_I;
00056     p->key_frame = 1;
00057 
00058     width  = avctx->width;
00059     height = avctx->height;
00060     bytes_per_channel = 1;
00061     pixmax = 0xFF;
00062     put_be = HAVE_BIGENDIAN;
00063 
00064     switch (avctx->pix_fmt) {
00065     case PIX_FMT_GRAY8:
00066         dimension = SGI_SINGLE_CHAN;
00067         depth     = SGI_GRAYSCALE;
00068         break;
00069     case PIX_FMT_RGB24:
00070         dimension = SGI_MULTI_CHAN;
00071         depth     = SGI_RGB;
00072         break;
00073     case PIX_FMT_RGBA:
00074         dimension = SGI_MULTI_CHAN;
00075         depth     = SGI_RGBA;
00076         break;
00077     case PIX_FMT_GRAY16LE:
00078         put_be = !HAVE_BIGENDIAN;
00079     case PIX_FMT_GRAY16BE:
00080         avctx->coder_type = FF_CODER_TYPE_RAW;
00081         bytes_per_channel = 2;
00082         pixmax = 0xFFFF;
00083         dimension = SGI_SINGLE_CHAN;
00084         depth     = SGI_GRAYSCALE;
00085         break;
00086     case PIX_FMT_RGB48LE:
00087         put_be = !HAVE_BIGENDIAN;
00088     case PIX_FMT_RGB48BE:
00089         avctx->coder_type = FF_CODER_TYPE_RAW;
00090         bytes_per_channel = 2;
00091         pixmax = 0xFFFF;
00092         dimension = SGI_MULTI_CHAN;
00093         depth     = SGI_RGB;
00094         break;
00095     case PIX_FMT_RGBA64LE:
00096         put_be = !HAVE_BIGENDIAN;
00097     case PIX_FMT_RGBA64BE:
00098         avctx->coder_type = FF_CODER_TYPE_RAW;
00099         bytes_per_channel = 2;
00100         pixmax = 0xFFFF;
00101         dimension = SGI_MULTI_CHAN;
00102         depth     = SGI_RGBA;
00103         break;
00104     default:
00105         return AVERROR_INVALIDDATA;
00106     }
00107 
00108     tablesize = depth * height * 4;
00109     length = tablesize * 2 + SGI_HEADER_SIZE;
00110 
00111     if (buf_size < length) {
00112         av_log(avctx, AV_LOG_ERROR, "buf_size too small(need %d, got %d)\n", length, buf_size);
00113         return -1;
00114     }
00115 
00116     /* Encode header. */
00117     bytestream_put_be16(&buf, SGI_MAGIC);
00118     bytestream_put_byte(&buf, avctx->coder_type != FF_CODER_TYPE_RAW); /* RLE 1 - VERBATIM 0*/
00119     bytestream_put_byte(&buf, bytes_per_channel);
00120     bytestream_put_be16(&buf, dimension);
00121     bytestream_put_be16(&buf, width);
00122     bytestream_put_be16(&buf, height);
00123     bytestream_put_be16(&buf, depth);
00124 
00125     bytestream_put_be32(&buf, 0L); /* pixmin */
00126     bytestream_put_be32(&buf, pixmax);
00127     bytestream_put_be32(&buf, 0L); /* dummy */
00128 
00129     /* name */
00130     memset(buf, 0, SGI_HEADER_SIZE);
00131     buf += 80;
00132 
00133      /* colormap */
00134     bytestream_put_be32(&buf, 0L);
00135 
00136     /* The rest of the 512 byte header is unused. */
00137     buf += 404;
00138     offsettab = buf;
00139 
00140     if (avctx->coder_type  != FF_CODER_TYPE_RAW) {
00141         /* Skip RLE offset table. */
00142         buf += tablesize;
00143         lengthtab = buf;
00144 
00145         /* Skip RLE length table. */
00146         buf += tablesize;
00147 
00148         /* Make an intermediate consecutive buffer. */
00149         if (!(encode_buf = av_malloc(width)))
00150             return -1;
00151 
00152         for (z = 0; z < depth; z++) {
00153             in_buf = p->data[0] + p->linesize[0] * (height - 1) + z;
00154 
00155             for (y = 0; y < height; y++) {
00156                 bytestream_put_be32(&offsettab, buf - orig_buf);
00157 
00158                 for (x = 0; x < width; x++)
00159                     encode_buf[x] = in_buf[depth * x];
00160 
00161                 if ((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) {
00162                     av_free(encode_buf);
00163                     return -1;
00164                 }
00165 
00166                 buf += length;
00167                 bytestream_put_byte(&buf, 0);
00168                 bytestream_put_be32(&lengthtab, length + 1);
00169                 in_buf -= p->linesize[0];
00170             }
00171         }
00172 
00173         av_free(encode_buf);
00174     } else {
00175         for (z = 0; z < depth; z++) {
00176             in_buf = p->data[0] + p->linesize[0] * (height - 1) + z * bytes_per_channel;
00177 
00178             for (y = 0; y < height; y++) {
00179                 for (x = 0; x < width * depth; x += depth)
00180                     if (bytes_per_channel == 1) {
00181                     bytestream_put_byte(&buf, in_buf[x]);
00182                     } else {
00183                         if (put_be) {
00184                             bytestream_put_be16(&buf, ((uint16_t *)in_buf)[x]);
00185                         } else {
00186                             bytestream_put_le16(&buf, ((uint16_t *)in_buf)[x]);
00187                         }
00188                     }
00189 
00190                 in_buf -= p->linesize[0];
00191             }
00192         }
00193     }
00194 
00195     /* total length */
00196     return buf - orig_buf;
00197 }
00198 
00199 AVCodec ff_sgi_encoder = {
00200     .name           = "sgi",
00201     .type           = AVMEDIA_TYPE_VIDEO,
00202     .id             = CODEC_ID_SGI,
00203     .priv_data_size = sizeof(SgiContext),
00204     .init           = encode_init,
00205     .encode         = encode_frame,
00206     .pix_fmts= (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA,
00207                                           PIX_FMT_RGB48LE, PIX_FMT_RGB48BE,
00208                                           PIX_FMT_RGBA64LE, PIX_FMT_RGBA64BE,
00209                                           PIX_FMT_GRAY16LE, PIX_FMT_GRAY16BE,
00210                                           PIX_FMT_GRAY8, PIX_FMT_NONE},
00211     .long_name= NULL_IF_CONFIG_SMALL("SGI image"),
00212 };
Generated on Fri Feb 1 2013 14:34:43 for FFmpeg by doxygen 1.7.1