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