00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/intreadwrite.h"
00023 #include "libavutil/imgutils.h"
00024 #include "avcodec.h"
00025
00026 #define RT_OLD 0
00027 #define RT_STANDARD 1
00028 #define RT_BYTE_ENCODED 2
00029 #define RT_FORMAT_RGB 3
00030 #define RT_FORMAT_TIFF 4
00031 #define RT_FORMAT_IFF 5
00032
00033 typedef struct SUNRASTContext {
00034 AVFrame picture;
00035 } SUNRASTContext;
00036
00037 static av_cold int sunrast_init(AVCodecContext *avctx) {
00038 SUNRASTContext *s = avctx->priv_data;
00039
00040 avcodec_get_frame_defaults(&s->picture);
00041 avctx->coded_frame= &s->picture;
00042
00043 return 0;
00044 }
00045
00046 static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
00047 int *data_size, AVPacket *avpkt) {
00048 const uint8_t *buf = avpkt->data;
00049 SUNRASTContext * const s = avctx->priv_data;
00050 AVFrame *picture = data;
00051 AVFrame * const p = &s->picture;
00052 unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen;
00053 uint8_t *ptr;
00054 const uint8_t *bufstart = buf;
00055
00056 if (AV_RB32(buf) != 0x59a66a95) {
00057 av_log(avctx, AV_LOG_ERROR, "this is not sunras encoded data\n");
00058 return -1;
00059 }
00060
00061 w = AV_RB32(buf+4);
00062 h = AV_RB32(buf+8);
00063 depth = AV_RB32(buf+12);
00064 type = AV_RB32(buf+20);
00065 maptype = AV_RB32(buf+24);
00066 maplength = AV_RB32(buf+28);
00067
00068 if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) {
00069 av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n");
00070 return -1;
00071 }
00072 if (type > RT_FORMAT_IFF) {
00073 av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n");
00074 return -1;
00075 }
00076 if (maptype & ~1) {
00077 av_log(avctx, AV_LOG_ERROR, "invalid colormap type\n");
00078 return -1;
00079 }
00080
00081 buf += 32;
00082
00083 switch (depth) {
00084 case 1:
00085 avctx->pix_fmt = PIX_FMT_MONOWHITE;
00086 break;
00087 case 8:
00088 avctx->pix_fmt = PIX_FMT_PAL8;
00089 break;
00090 case 24:
00091 avctx->pix_fmt = (type == RT_FORMAT_RGB) ? PIX_FMT_RGB24 : PIX_FMT_BGR24;
00092 break;
00093 default:
00094 av_log(avctx, AV_LOG_ERROR, "invalid depth\n");
00095 return -1;
00096 }
00097
00098 if (p->data[0])
00099 avctx->release_buffer(avctx, p);
00100
00101 if (av_image_check_size(w, h, 0, avctx))
00102 return -1;
00103 if (w != avctx->width || h != avctx->height)
00104 avcodec_set_dimensions(avctx, w, h);
00105 if (avctx->get_buffer(avctx, p) < 0) {
00106 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00107 return -1;
00108 }
00109
00110 p->pict_type = FF_I_TYPE;
00111
00112 if (depth != 8 && maplength) {
00113 av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n");
00114
00115 } else if (depth == 8) {
00116 unsigned int len = maplength / 3;
00117
00118 if (!maplength) {
00119 av_log(avctx, AV_LOG_ERROR, "colormap expected\n");
00120 return -1;
00121 }
00122 if (maplength % 3 || maplength > 768) {
00123 av_log(avctx, AV_LOG_WARNING, "invalid colormap length\n");
00124 return -1;
00125 }
00126
00127 ptr = p->data[1];
00128 for (x=0; x<len; x++, ptr+=4)
00129 *(uint32_t *)ptr = (buf[x]<<16) + (buf[len+x]<<8) + buf[len+len+x];
00130 }
00131
00132 buf += maplength;
00133
00134 ptr = p->data[0];
00135 stride = p->linesize[0];
00136
00137
00138 len = (depth * w + 7) >> 3;
00139 alen = len + (len&1);
00140
00141 if (type == RT_BYTE_ENCODED) {
00142 int value, run;
00143 uint8_t *end = ptr + h*stride;
00144
00145 x = 0;
00146 while (ptr != end) {
00147 run = 1;
00148 if ((value = *buf++) == 0x80) {
00149 run = *buf++ + 1;
00150 if (run != 1)
00151 value = *buf++;
00152 }
00153 while (run--) {
00154 if (x < len)
00155 ptr[x] = value;
00156 if (++x >= alen) {
00157 x = 0;
00158 ptr += stride;
00159 if (ptr == end)
00160 break;
00161 }
00162 }
00163 }
00164 } else {
00165 for (y=0; y<h; y++) {
00166 memcpy(ptr, buf, len);
00167 ptr += stride;
00168 buf += alen;
00169 }
00170 }
00171
00172 *picture = s->picture;
00173 *data_size = sizeof(AVFrame);
00174
00175 return buf - bufstart;
00176 }
00177
00178 static av_cold int sunrast_end(AVCodecContext *avctx) {
00179 SUNRASTContext *s = avctx->priv_data;
00180
00181 if(s->picture.data[0])
00182 avctx->release_buffer(avctx, &s->picture);
00183
00184 return 0;
00185 }
00186
00187 AVCodec ff_sunrast_decoder = {
00188 "sunrast",
00189 AVMEDIA_TYPE_VIDEO,
00190 CODEC_ID_SUNRAST,
00191 sizeof(SUNRASTContext),
00192 sunrast_init,
00193 NULL,
00194 sunrast_end,
00195 sunrast_decode_frame,
00196 CODEC_CAP_DR1,
00197 NULL,
00198 .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"),
00199 };