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