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