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