00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "avcodec.h"
00023 #include "bytestream.h"
00024 #include "internal.h"
00025 #include "sunrast.h"
00026
00027 typedef struct SUNRASTContext {
00028 AVFrame picture;
00029 PutByteContext p;
00030 int depth;
00031 int length;
00032 int type;
00033 int maptype;
00034 int maplength;
00035 int size;
00036 } SUNRASTContext;
00037
00038 static void sunrast_image_write_header(AVCodecContext *avctx)
00039 {
00040 SUNRASTContext *s = avctx->priv_data;
00041
00042 bytestream2_put_be32u(&s->p, RAS_MAGIC);
00043 bytestream2_put_be32u(&s->p, avctx->width);
00044 bytestream2_put_be32u(&s->p, avctx->height);
00045 bytestream2_put_be32u(&s->p, s->depth);
00046 bytestream2_put_be32u(&s->p, s->length);
00047 bytestream2_put_be32u(&s->p, s->type);
00048 bytestream2_put_be32u(&s->p, s->maptype);
00049 bytestream2_put_be32u(&s->p, s->maplength);
00050 }
00051
00052 static void sunrast_image_write_image(AVCodecContext *avctx,
00053 const uint8_t *pixels,
00054 const uint32_t *palette_data,
00055 int linesize)
00056 {
00057 SUNRASTContext *s = avctx->priv_data;
00058 const uint8_t *ptr;
00059 int len, alen, x, y;
00060
00061 if (s->maplength) {
00062 PutByteContext pb_r, pb_g;
00063 int len = s->maplength / 3;
00064
00065 pb_r = s->p;
00066 bytestream2_skip_p(&s->p, len);
00067 pb_g = s->p;
00068 bytestream2_skip_p(&s->p, len);
00069
00070 for (x = 0; x < len; x++) {
00071 uint32_t pixel = palette_data[x];
00072
00073 bytestream2_put_byteu(&pb_r, (pixel >> 16) & 0xFF);
00074 bytestream2_put_byteu(&pb_g, (pixel >> 8) & 0xFF);
00075 bytestream2_put_byteu(&s->p, pixel & 0xFF);
00076 }
00077 }
00078
00079 len = (s->depth * avctx->width + 7) >> 3;
00080 alen = len + (len & 1);
00081 ptr = pixels;
00082
00083 if (s->type == RT_BYTE_ENCODED) {
00084 uint8_t value, value2;
00085 int run;
00086
00087 ptr = pixels;
00088
00089 #define GET_VALUE y >= avctx->height ? 0 : x >= len ? ptr[len-1] : ptr[x]
00090
00091 x = 0, y = 0;
00092 value2 = GET_VALUE;
00093 while (y < avctx->height) {
00094 run = 1;
00095 value = value2;
00096 x++;
00097 if (x >= alen) {
00098 x = 0;
00099 ptr += linesize, y++;
00100 }
00101
00102 value2 = GET_VALUE;
00103 while (value2 == value && run < 256 && y < avctx->height) {
00104 x++;
00105 run++;
00106 if (x >= alen) {
00107 x = 0;
00108 ptr += linesize, y++;
00109 }
00110 value2 = GET_VALUE;
00111 }
00112
00113 if (run > 2 || value == RLE_TRIGGER) {
00114 bytestream2_put_byteu(&s->p, RLE_TRIGGER);
00115 bytestream2_put_byteu(&s->p, run - 1);
00116 if (run > 1)
00117 bytestream2_put_byteu(&s->p, value);
00118 } else if (run == 1) {
00119 bytestream2_put_byteu(&s->p, value);
00120 } else
00121 bytestream2_put_be16u(&s->p, (value << 8) | value);
00122 }
00123
00124
00125 s->length = bytestream2_tell_p(&s->p) - 32 - s->maplength;
00126 } else {
00127 for (y = 0; y < avctx->height; y++) {
00128 bytestream2_put_buffer(&s->p, ptr, len);
00129 if (len < alen)
00130 bytestream2_put_byteu(&s->p, 0);
00131 ptr += linesize;
00132 }
00133 }
00134 }
00135
00136 static av_cold int sunrast_encode_init(AVCodecContext *avctx)
00137 {
00138 SUNRASTContext *s = avctx->priv_data;
00139
00140 switch (avctx->coder_type) {
00141 case FF_CODER_TYPE_RLE:
00142 s->type = RT_BYTE_ENCODED;
00143 break;
00144 case FF_CODER_TYPE_RAW:
00145 s->type = RT_STANDARD;
00146 break;
00147 default:
00148 av_log(avctx, AV_LOG_ERROR, "invalid coder_type\n");
00149 return AVERROR(EINVAL);
00150 }
00151
00152 avctx->coded_frame = &s->picture;
00153 avctx->coded_frame->key_frame = 1;
00154 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
00155 s->maptype = RMT_NONE;
00156 s->maplength = 0;
00157
00158 switch (avctx->pix_fmt) {
00159 case PIX_FMT_MONOWHITE:
00160 s->depth = 1;
00161 break;
00162 case PIX_FMT_PAL8 :
00163 s->maptype = RMT_EQUAL_RGB;
00164 s->maplength = 3 * 256;
00165 case PIX_FMT_GRAY8:
00166 s->depth = 8;
00167 break;
00168 case PIX_FMT_BGR24:
00169 s->depth = 24;
00170 break;
00171 default:
00172 return AVERROR_BUG;
00173 }
00174 s->length = avctx->height * (FFALIGN(avctx->width * s->depth, 16) >> 3);
00175 s->size = 32 + s->maplength +
00176 s->length * (s->type == RT_BYTE_ENCODED ? 2 : 1);
00177
00178 return 0;
00179 }
00180
00181 static int sunrast_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
00182 const AVFrame *frame, int *got_packet_ptr)
00183 {
00184 SUNRASTContext *s = avctx->priv_data;
00185 int ret;
00186
00187 if ((ret = ff_alloc_packet2(avctx, avpkt, s->size)) < 0)
00188 return ret;
00189
00190 bytestream2_init_writer(&s->p, avpkt->data, avpkt->size);
00191 sunrast_image_write_header(avctx);
00192 sunrast_image_write_image(avctx, frame->data[0],
00193 (const uint32_t *)frame->data[1],
00194 frame->linesize[0]);
00195
00196 if (s->type == RT_BYTE_ENCODED)
00197 AV_WB32(&avpkt->data[16], s->length);
00198
00199 *got_packet_ptr = 1;
00200 avpkt->flags |= AV_PKT_FLAG_KEY;
00201 avpkt->size = bytestream2_tell_p(&s->p);
00202 return 0;
00203 }
00204
00205 static const AVCodecDefault sunrast_defaults[] = {
00206 { "coder", "rle" },
00207 { NULL },
00208 };
00209
00210 AVCodec ff_sunrast_encoder = {
00211 .name = "sunrast",
00212 .type = AVMEDIA_TYPE_VIDEO,
00213 .id = CODEC_ID_SUNRAST,
00214 .priv_data_size = sizeof(SUNRASTContext),
00215 .init = sunrast_encode_init,
00216 .encode2 = sunrast_encode_frame,
00217 .defaults = sunrast_defaults,
00218 .pix_fmts = (const enum PixelFormat[]){ PIX_FMT_BGR24,
00219 PIX_FMT_PAL8,
00220 PIX_FMT_GRAY8,
00221 PIX_FMT_MONOWHITE,
00222 PIX_FMT_NONE },
00223 .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"),
00224 };