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