00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/common.h"
00023 #include "libavutil/intreadwrite.h"
00024 #include "libavutil/imgutils.h"
00025 #include "avcodec.h"
00026 #include "sunrast.h"
00027
00028 typedef struct SUNRASTContext {
00029 AVFrame picture;
00030 } SUNRASTContext;
00031
00032 static av_cold int sunrast_init(AVCodecContext *avctx) {
00033 SUNRASTContext *s = avctx->priv_data;
00034
00035 avcodec_get_frame_defaults(&s->picture);
00036 avctx->coded_frame = &s->picture;
00037
00038 return 0;
00039 }
00040
00041 static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
00042 int *data_size, AVPacket *avpkt) {
00043 const uint8_t *buf = avpkt->data;
00044 const uint8_t *buf_end = avpkt->data + avpkt->size;
00045 SUNRASTContext * const s = avctx->priv_data;
00046 AVFrame *picture = data;
00047 AVFrame * const p = &s->picture;
00048 unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen;
00049 uint8_t *ptr, *ptr2 = NULL;
00050 const uint8_t *bufstart = buf;
00051 int ret;
00052
00053 if (avpkt->size < 32)
00054 return AVERROR_INVALIDDATA;
00055
00056 if (AV_RB32(buf) != RAS_MAGIC) {
00057 av_log(avctx, AV_LOG_ERROR, "this is not sunras encoded data\n");
00058 return AVERROR_INVALIDDATA;
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 buf += 32;
00068
00069 if (type == RT_EXPERIMENTAL) {
00070 av_log_ask_for_sample(avctx, "unsupported (compression) type\n");
00071 return AVERROR_PATCHWELCOME;
00072 }
00073 if (type > RT_FORMAT_IFF) {
00074 av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n");
00075 return AVERROR_INVALIDDATA;
00076 }
00077 if (av_image_check_size(w, h, 0, avctx)) {
00078 av_log(avctx, AV_LOG_ERROR, "invalid image size\n");
00079 return AVERROR_INVALIDDATA;
00080 }
00081 if (maptype == RMT_RAW) {
00082 av_log_ask_for_sample(avctx, "unsupported colormap type\n");
00083 return AVERROR_PATCHWELCOME;
00084 }
00085 if (maptype > RMT_RAW) {
00086 av_log(avctx, AV_LOG_ERROR, "invalid colormap type\n");
00087 return AVERROR_INVALIDDATA;
00088 }
00089
00090 if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) {
00091 av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n");
00092 return -1;
00093 }
00094
00095 switch (depth) {
00096 case 1:
00097 avctx->pix_fmt = maplength ? PIX_FMT_PAL8 : PIX_FMT_MONOWHITE;
00098 break;
00099 case 4:
00100 avctx->pix_fmt = maplength ? PIX_FMT_PAL8 : PIX_FMT_NONE;
00101 break;
00102 case 8:
00103 avctx->pix_fmt = maplength ? PIX_FMT_PAL8 : PIX_FMT_GRAY8;
00104 break;
00105 case 24:
00106 avctx->pix_fmt = (type == RT_FORMAT_RGB) ? PIX_FMT_RGB24 : PIX_FMT_BGR24;
00107 break;
00108 case 32:
00109 avctx->pix_fmt = (type == RT_FORMAT_RGB) ? PIX_FMT_0RGB : PIX_FMT_0BGR;
00110 break;
00111 default:
00112 av_log(avctx, AV_LOG_ERROR, "invalid depth\n");
00113 return AVERROR_INVALIDDATA;
00114 }
00115
00116 if (p->data[0])
00117 avctx->release_buffer(avctx, p);
00118
00119 if (w != avctx->width || h != avctx->height)
00120 avcodec_set_dimensions(avctx, w, h);
00121 if ((ret = avctx->get_buffer(avctx, p)) < 0) {
00122 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00123 return ret;
00124 }
00125
00126 p->pict_type = AV_PICTURE_TYPE_I;
00127
00128 if (buf_end - buf < maplength)
00129 return AVERROR_INVALIDDATA;
00130
00131 if (depth > 8 && maplength) {
00132 av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n");
00133
00134 } else if (maplength) {
00135 unsigned int len = maplength / 3;
00136
00137 if (maplength % 3 || maplength > 768) {
00138 av_log(avctx, AV_LOG_WARNING, "invalid colormap length\n");
00139 return AVERROR_INVALIDDATA;
00140 }
00141
00142 ptr = p->data[1];
00143 for (x = 0; x < len; x++, ptr += 4)
00144 *(uint32_t *)ptr = (0xFF<<24) + (buf[x]<<16) + (buf[len+x]<<8) + buf[len+len+x];
00145 }
00146
00147 buf += maplength;
00148
00149 if (maplength && depth < 8) {
00150 ptr = ptr2 = av_malloc((w + 15) * h);
00151 if (!ptr)
00152 return AVERROR(ENOMEM);
00153 stride = (w + 15 >> 3) * depth;
00154 } else {
00155 ptr = p->data[0];
00156 stride = p->linesize[0];
00157 }
00158
00159
00160 len = (depth * w + 7) >> 3;
00161 alen = len + (len & 1);
00162
00163 if (type == RT_BYTE_ENCODED) {
00164 int value, run;
00165 uint8_t *end = ptr + h * stride;
00166
00167 x = 0;
00168 while (ptr != end && buf < buf_end) {
00169 run = 1;
00170 if (buf_end - buf < 1)
00171 return AVERROR_INVALIDDATA;
00172
00173 if ((value = *buf++) == RLE_TRIGGER) {
00174 run = *buf++ + 1;
00175 if (run != 1)
00176 value = *buf++;
00177 }
00178 while (run--) {
00179 if (x < len)
00180 ptr[x] = value;
00181 if (++x >= alen) {
00182 x = 0;
00183 ptr += stride;
00184 if (ptr == end)
00185 break;
00186 }
00187 }
00188 }
00189 } else {
00190 for (y = 0; y < h; y++) {
00191 if (buf_end - buf < len)
00192 break;
00193 memcpy(ptr, buf, len);
00194 ptr += stride;
00195 buf += alen;
00196 }
00197 }
00198 if (avctx->pix_fmt == PIX_FMT_PAL8 && depth < 8) {
00199 uint8_t *ptr_free = ptr2;
00200 ptr = p->data[0];
00201 for (y=0; y<h; y++) {
00202 for (x = 0; x < (w + 7 >> 3) * depth; x++) {
00203 if (depth == 1) {
00204 ptr[8*x] = ptr2[x] >> 7;
00205 ptr[8*x+1] = ptr2[x] >> 6 & 1;
00206 ptr[8*x+2] = ptr2[x] >> 5 & 1;
00207 ptr[8*x+3] = ptr2[x] >> 4 & 1;
00208 ptr[8*x+4] = ptr2[x] >> 3 & 1;
00209 ptr[8*x+5] = ptr2[x] >> 2 & 1;
00210 ptr[8*x+6] = ptr2[x] >> 1 & 1;
00211 ptr[8*x+7] = ptr2[x] & 1;
00212 } else {
00213 ptr[2*x] = ptr2[x] >> 4;
00214 ptr[2*x+1] = ptr2[x] & 0xF;
00215 }
00216 }
00217 ptr += p->linesize[0];
00218 ptr2 += (w + 15 >> 3) * depth;
00219 }
00220 av_freep(&ptr_free);
00221 }
00222
00223 *picture = s->picture;
00224 *data_size = sizeof(AVFrame);
00225
00226 return buf - bufstart;
00227 }
00228
00229 static av_cold int sunrast_end(AVCodecContext *avctx) {
00230 SUNRASTContext *s = avctx->priv_data;
00231
00232 if(s->picture.data[0])
00233 avctx->release_buffer(avctx, &s->picture);
00234
00235 return 0;
00236 }
00237
00238 AVCodec ff_sunrast_decoder = {
00239 .name = "sunrast",
00240 .type = AVMEDIA_TYPE_VIDEO,
00241 .id = AV_CODEC_ID_SUNRAST,
00242 .priv_data_size = sizeof(SUNRASTContext),
00243 .init = sunrast_init,
00244 .close = sunrast_end,
00245 .decode = sunrast_decode_frame,
00246 .capabilities = CODEC_CAP_DR1,
00247 .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"),
00248 };