00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <unistd.h>
00038
00039 #include "avcodec.h"
00040 #include "dsputil.h"
00041
00042 typedef struct MsrleContext {
00043 AVCodecContext *avctx;
00044 AVFrame frame;
00045
00046 const unsigned char *buf;
00047 int size;
00048
00049 } MsrleContext;
00050
00051 #define FETCH_NEXT_STREAM_BYTE() \
00052 if (stream_ptr >= s->size) \
00053 { \
00054 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
00055 return; \
00056 } \
00057 stream_byte = s->buf[stream_ptr++];
00058
00059 static void msrle_decode_pal4(MsrleContext *s)
00060 {
00061 int stream_ptr = 0;
00062 unsigned char rle_code;
00063 unsigned char extra_byte, odd_pixel;
00064 unsigned char stream_byte;
00065 int pixel_ptr = 0;
00066 int row_dec = s->frame.linesize[0];
00067 int row_ptr = (s->avctx->height - 1) * row_dec;
00068 int frame_size = row_dec * s->avctx->height;
00069 int i;
00070
00071
00072 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
00073 if (s->avctx->palctrl->palette_changed) {
00074 s->frame.palette_has_changed = 1;
00075 s->avctx->palctrl->palette_changed = 0;
00076 }
00077
00078 while (row_ptr >= 0) {
00079 FETCH_NEXT_STREAM_BYTE();
00080 rle_code = stream_byte;
00081 if (rle_code == 0) {
00082
00083 FETCH_NEXT_STREAM_BYTE();
00084 if (stream_byte == 0) {
00085
00086 row_ptr -= row_dec;
00087 pixel_ptr = 0;
00088 } else if (stream_byte == 1) {
00089
00090 return;
00091 } else if (stream_byte == 2) {
00092
00093 FETCH_NEXT_STREAM_BYTE();
00094 pixel_ptr += stream_byte;
00095 FETCH_NEXT_STREAM_BYTE();
00096 row_ptr -= stream_byte * row_dec;
00097 } else {
00098
00099 odd_pixel = stream_byte & 1;
00100 rle_code = (stream_byte + 1) / 2;
00101 extra_byte = rle_code & 0x01;
00102 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
00103 (row_ptr < 0)) {
00104 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
00105 return;
00106 }
00107
00108 for (i = 0; i < rle_code; i++) {
00109 if (pixel_ptr >= s->avctx->width)
00110 break;
00111 FETCH_NEXT_STREAM_BYTE();
00112 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
00113 pixel_ptr++;
00114 if (i + 1 == rle_code && odd_pixel)
00115 break;
00116 if (pixel_ptr >= s->avctx->width)
00117 break;
00118 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
00119 pixel_ptr++;
00120 }
00121
00122
00123 if (extra_byte)
00124 stream_ptr++;
00125 }
00126 } else {
00127
00128 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
00129 (row_ptr < 0)) {
00130 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
00131 return;
00132 }
00133 FETCH_NEXT_STREAM_BYTE();
00134 for (i = 0; i < rle_code; i++) {
00135 if (pixel_ptr >= s->avctx->width)
00136 break;
00137 if ((i & 1) == 0)
00138 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
00139 else
00140 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
00141 pixel_ptr++;
00142 }
00143 }
00144 }
00145
00146
00147 if (stream_ptr < s->size)
00148 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
00149 stream_ptr, s->size);
00150 }
00151
00152
00153
00154 static void msrle_decode_pal8(MsrleContext *s)
00155 {
00156 int stream_ptr = 0;
00157 unsigned char rle_code;
00158 unsigned char extra_byte;
00159 unsigned char stream_byte;
00160 int pixel_ptr = 0;
00161 int row_dec = s->frame.linesize[0];
00162 int row_ptr = (s->avctx->height - 1) * row_dec;
00163 int frame_size = row_dec * s->avctx->height;
00164
00165
00166 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
00167 if (s->avctx->palctrl->palette_changed) {
00168 s->frame.palette_has_changed = 1;
00169 s->avctx->palctrl->palette_changed = 0;
00170 }
00171
00172 while (row_ptr >= 0) {
00173 FETCH_NEXT_STREAM_BYTE();
00174 rle_code = stream_byte;
00175 if (rle_code == 0) {
00176
00177 FETCH_NEXT_STREAM_BYTE();
00178 if (stream_byte == 0) {
00179
00180 row_ptr -= row_dec;
00181 pixel_ptr = 0;
00182 } else if (stream_byte == 1) {
00183
00184 return;
00185 } else if (stream_byte == 2) {
00186
00187 FETCH_NEXT_STREAM_BYTE();
00188 pixel_ptr += stream_byte;
00189 FETCH_NEXT_STREAM_BYTE();
00190 row_ptr -= stream_byte * row_dec;
00191 } else {
00192
00193 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
00194 (row_ptr < 0)) {
00195 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
00196 return;
00197 }
00198
00199 rle_code = stream_byte;
00200 extra_byte = stream_byte & 0x01;
00201 if (stream_ptr + rle_code + extra_byte > s->size) {
00202 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (2)\n");
00203 return;
00204 }
00205
00206 while (rle_code--) {
00207 FETCH_NEXT_STREAM_BYTE();
00208 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
00209 pixel_ptr++;
00210 }
00211
00212
00213 if (extra_byte)
00214 stream_ptr++;
00215 }
00216 } else {
00217
00218 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
00219 (row_ptr < 0)) {
00220 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (2)\n");
00221 return;
00222 }
00223
00224 FETCH_NEXT_STREAM_BYTE();
00225
00226 while(rle_code--) {
00227 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
00228 pixel_ptr++;
00229 }
00230 }
00231 }
00232
00233
00234 if (stream_ptr < s->size)
00235 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
00236 stream_ptr, s->size);
00237 }
00238
00239 static int msrle_decode_init(AVCodecContext *avctx)
00240 {
00241 MsrleContext *s = avctx->priv_data;
00242
00243 s->avctx = avctx;
00244
00245 avctx->pix_fmt = PIX_FMT_PAL8;
00246 s->frame.data[0] = NULL;
00247
00248 return 0;
00249 }
00250
00251 static int msrle_decode_frame(AVCodecContext *avctx,
00252 void *data, int *data_size,
00253 const uint8_t *buf, int buf_size)
00254 {
00255 MsrleContext *s = avctx->priv_data;
00256
00257 s->buf = buf;
00258 s->size = buf_size;
00259
00260 s->frame.reference = 1;
00261 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00262 if (avctx->reget_buffer(avctx, &s->frame)) {
00263 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00264 return -1;
00265 }
00266
00267 switch (avctx->bits_per_sample) {
00268 case 8:
00269 msrle_decode_pal8(s);
00270 break;
00271 case 4:
00272 msrle_decode_pal4(s);
00273 break;
00274 default:
00275 av_log(avctx, AV_LOG_ERROR, "Don't know how to decode depth %u.\n",
00276 avctx->bits_per_sample);
00277 }
00278
00279 *data_size = sizeof(AVFrame);
00280 *(AVFrame*)data = s->frame;
00281
00282
00283 return buf_size;
00284 }
00285
00286 static int msrle_decode_end(AVCodecContext *avctx)
00287 {
00288 MsrleContext *s = avctx->priv_data;
00289
00290
00291 if (s->frame.data[0])
00292 avctx->release_buffer(avctx, &s->frame);
00293
00294 return 0;
00295 }
00296
00297 AVCodec msrle_decoder = {
00298 "msrle",
00299 CODEC_TYPE_VIDEO,
00300 CODEC_ID_MSRLE,
00301 sizeof(MsrleContext),
00302 msrle_decode_init,
00303 NULL,
00304 msrle_decode_end,
00305 msrle_decode_frame,
00306 CODEC_CAP_DR1,
00307 };