annotate ffmpeg/libavcodec/sgienc.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * SGI image encoder
yading@10 3 * Todd Kirby <doubleshot@pacbell.net>
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 #include "avcodec.h"
yading@10 23 #include "bytestream.h"
yading@10 24 #include "internal.h"
yading@10 25 #include "sgi.h"
yading@10 26 #include "rle.h"
yading@10 27
yading@10 28 #define SGI_SINGLE_CHAN 2
yading@10 29 #define SGI_MULTI_CHAN 3
yading@10 30
yading@10 31 typedef struct SgiContext {
yading@10 32 AVFrame picture;
yading@10 33 } SgiContext;
yading@10 34
yading@10 35 static av_cold int encode_init(AVCodecContext *avctx)
yading@10 36 {
yading@10 37 SgiContext *s = avctx->priv_data;
yading@10 38
yading@10 39 if (avctx->width > 65535 || avctx->height > 65535) {
yading@10 40 av_log(avctx, AV_LOG_ERROR, "SGI does not support resolutions above 65535x65535\n");
yading@10 41 return -1;
yading@10 42 }
yading@10 43
yading@10 44 avcodec_get_frame_defaults(&s->picture);
yading@10 45 avctx->coded_frame = &s->picture;
yading@10 46
yading@10 47 return 0;
yading@10 48 }
yading@10 49
yading@10 50 static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
yading@10 51 const AVFrame *frame, int *got_packet)
yading@10 52 {
yading@10 53 SgiContext *s = avctx->priv_data;
yading@10 54 AVFrame * const p = &s->picture;
yading@10 55 uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf, *buf;
yading@10 56 int x, y, z, length, tablesize, ret;
yading@10 57 unsigned int width, height, depth, dimension, bytes_per_channel, pixmax, put_be;
yading@10 58 unsigned char *end_buf;
yading@10 59
yading@10 60 *p = *frame;
yading@10 61 p->pict_type = AV_PICTURE_TYPE_I;
yading@10 62 p->key_frame = 1;
yading@10 63
yading@10 64 width = avctx->width;
yading@10 65 height = avctx->height;
yading@10 66 bytes_per_channel = 1;
yading@10 67 pixmax = 0xFF;
yading@10 68 put_be = HAVE_BIGENDIAN;
yading@10 69
yading@10 70 switch (avctx->pix_fmt) {
yading@10 71 case AV_PIX_FMT_GRAY8:
yading@10 72 dimension = SGI_SINGLE_CHAN;
yading@10 73 depth = SGI_GRAYSCALE;
yading@10 74 break;
yading@10 75 case AV_PIX_FMT_RGB24:
yading@10 76 dimension = SGI_MULTI_CHAN;
yading@10 77 depth = SGI_RGB;
yading@10 78 break;
yading@10 79 case AV_PIX_FMT_RGBA:
yading@10 80 dimension = SGI_MULTI_CHAN;
yading@10 81 depth = SGI_RGBA;
yading@10 82 break;
yading@10 83 case AV_PIX_FMT_GRAY16LE:
yading@10 84 put_be = !HAVE_BIGENDIAN;
yading@10 85 case AV_PIX_FMT_GRAY16BE:
yading@10 86 avctx->coder_type = FF_CODER_TYPE_RAW;
yading@10 87 bytes_per_channel = 2;
yading@10 88 pixmax = 0xFFFF;
yading@10 89 dimension = SGI_SINGLE_CHAN;
yading@10 90 depth = SGI_GRAYSCALE;
yading@10 91 break;
yading@10 92 case AV_PIX_FMT_RGB48LE:
yading@10 93 put_be = !HAVE_BIGENDIAN;
yading@10 94 case AV_PIX_FMT_RGB48BE:
yading@10 95 avctx->coder_type = FF_CODER_TYPE_RAW;
yading@10 96 bytes_per_channel = 2;
yading@10 97 pixmax = 0xFFFF;
yading@10 98 dimension = SGI_MULTI_CHAN;
yading@10 99 depth = SGI_RGB;
yading@10 100 break;
yading@10 101 case AV_PIX_FMT_RGBA64LE:
yading@10 102 put_be = !HAVE_BIGENDIAN;
yading@10 103 case AV_PIX_FMT_RGBA64BE:
yading@10 104 avctx->coder_type = FF_CODER_TYPE_RAW;
yading@10 105 bytes_per_channel = 2;
yading@10 106 pixmax = 0xFFFF;
yading@10 107 dimension = SGI_MULTI_CHAN;
yading@10 108 depth = SGI_RGBA;
yading@10 109 break;
yading@10 110 default:
yading@10 111 return AVERROR_INVALIDDATA;
yading@10 112 }
yading@10 113
yading@10 114 tablesize = depth * height * 4;
yading@10 115 length = SGI_HEADER_SIZE;
yading@10 116 if (avctx->coder_type == FF_CODER_TYPE_RAW)
yading@10 117 length += depth * height * width;
yading@10 118 else // assume ff_rl_encode() produces at most 2x size of input
yading@10 119 length += tablesize * 2 + depth * height * (2 * width + 1);
yading@10 120
yading@10 121 if ((ret = ff_alloc_packet2(avctx, pkt, bytes_per_channel * length)) < 0)
yading@10 122 return ret;
yading@10 123 buf = pkt->data;
yading@10 124 end_buf = pkt->data + pkt->size;
yading@10 125
yading@10 126 /* Encode header. */
yading@10 127 bytestream_put_be16(&buf, SGI_MAGIC);
yading@10 128 bytestream_put_byte(&buf, avctx->coder_type != FF_CODER_TYPE_RAW); /* RLE 1 - VERBATIM 0*/
yading@10 129 bytestream_put_byte(&buf, bytes_per_channel);
yading@10 130 bytestream_put_be16(&buf, dimension);
yading@10 131 bytestream_put_be16(&buf, width);
yading@10 132 bytestream_put_be16(&buf, height);
yading@10 133 bytestream_put_be16(&buf, depth);
yading@10 134
yading@10 135 bytestream_put_be32(&buf, 0L); /* pixmin */
yading@10 136 bytestream_put_be32(&buf, pixmax);
yading@10 137 bytestream_put_be32(&buf, 0L); /* dummy */
yading@10 138
yading@10 139 /* name */
yading@10 140 memset(buf, 0, SGI_HEADER_SIZE);
yading@10 141 buf += 80;
yading@10 142
yading@10 143 /* colormap */
yading@10 144 bytestream_put_be32(&buf, 0L);
yading@10 145
yading@10 146 /* The rest of the 512 byte header is unused. */
yading@10 147 buf += 404;
yading@10 148 offsettab = buf;
yading@10 149
yading@10 150 if (avctx->coder_type != FF_CODER_TYPE_RAW) {
yading@10 151 /* Skip RLE offset table. */
yading@10 152 buf += tablesize;
yading@10 153 lengthtab = buf;
yading@10 154
yading@10 155 /* Skip RLE length table. */
yading@10 156 buf += tablesize;
yading@10 157
yading@10 158 /* Make an intermediate consecutive buffer. */
yading@10 159 if (!(encode_buf = av_malloc(width)))
yading@10 160 return -1;
yading@10 161
yading@10 162 for (z = 0; z < depth; z++) {
yading@10 163 in_buf = p->data[0] + p->linesize[0] * (height - 1) + z;
yading@10 164
yading@10 165 for (y = 0; y < height; y++) {
yading@10 166 bytestream_put_be32(&offsettab, buf - pkt->data);
yading@10 167
yading@10 168 for (x = 0; x < width; x++)
yading@10 169 encode_buf[x] = in_buf[depth * x];
yading@10 170
yading@10 171 if ((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) {
yading@10 172 av_free(encode_buf);
yading@10 173 return -1;
yading@10 174 }
yading@10 175
yading@10 176 buf += length;
yading@10 177 bytestream_put_byte(&buf, 0);
yading@10 178 bytestream_put_be32(&lengthtab, length + 1);
yading@10 179 in_buf -= p->linesize[0];
yading@10 180 }
yading@10 181 }
yading@10 182
yading@10 183 av_free(encode_buf);
yading@10 184 } else {
yading@10 185 for (z = 0; z < depth; z++) {
yading@10 186 in_buf = p->data[0] + p->linesize[0] * (height - 1) + z * bytes_per_channel;
yading@10 187
yading@10 188 for (y = 0; y < height; y++) {
yading@10 189 for (x = 0; x < width * depth; x += depth)
yading@10 190 if (bytes_per_channel == 1) {
yading@10 191 bytestream_put_byte(&buf, in_buf[x]);
yading@10 192 } else {
yading@10 193 if (put_be) {
yading@10 194 bytestream_put_be16(&buf, ((uint16_t *)in_buf)[x]);
yading@10 195 } else {
yading@10 196 bytestream_put_le16(&buf, ((uint16_t *)in_buf)[x]);
yading@10 197 }
yading@10 198 }
yading@10 199
yading@10 200 in_buf -= p->linesize[0];
yading@10 201 }
yading@10 202 }
yading@10 203 }
yading@10 204
yading@10 205 /* total length */
yading@10 206 pkt->size = buf - pkt->data;
yading@10 207 pkt->flags |= AV_PKT_FLAG_KEY;
yading@10 208 *got_packet = 1;
yading@10 209
yading@10 210 return 0;
yading@10 211 }
yading@10 212
yading@10 213 AVCodec ff_sgi_encoder = {
yading@10 214 .name = "sgi",
yading@10 215 .type = AVMEDIA_TYPE_VIDEO,
yading@10 216 .id = AV_CODEC_ID_SGI,
yading@10 217 .priv_data_size = sizeof(SgiContext),
yading@10 218 .init = encode_init,
yading@10 219 .encode2 = encode_frame,
yading@10 220 .pix_fmts = (const enum AVPixelFormat[]){
yading@10 221 AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA,
yading@10 222 AV_PIX_FMT_RGB48LE, AV_PIX_FMT_RGB48BE,
yading@10 223 AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_RGBA64BE,
yading@10 224 AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE,
yading@10 225 AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE
yading@10 226 },
yading@10 227 .long_name = NULL_IF_CONFIG_SMALL("SGI image"),
yading@10 228 };