00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <unistd.h>
00036
00037 #include "common.h"
00038 #include "avcodec.h"
00039 #include "dsputil.h"
00040
00041 typedef struct MsrleContext {
00042 AVCodecContext *avctx;
00043 AVFrame frame;
00044
00045 unsigned char *buf;
00046 int size;
00047
00048 } MsrleContext;
00049
00050 #define FETCH_NEXT_STREAM_BYTE() \
00051 if (stream_ptr >= s->size) \
00052 { \
00053 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
00054 return; \
00055 } \
00056 stream_byte = s->buf[stream_ptr++];
00057
00058 static void msrle_decode_pal4(MsrleContext *s)
00059 {
00060 int stream_ptr = 0;
00061 unsigned char rle_code;
00062 unsigned char extra_byte, odd_pixel;
00063 unsigned char stream_byte;
00064 int pixel_ptr = 0;
00065 int row_dec = s->frame.linesize[0];
00066 int row_ptr = (s->avctx->height - 1) * row_dec;
00067 int frame_size = row_dec * s->avctx->height;
00068 int i;
00069
00070
00071 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
00072 if (s->avctx->palctrl->palette_changed) {
00073 s->frame.palette_has_changed = 1;
00074 s->avctx->palctrl->palette_changed = 0;
00075 }
00076
00077 while (row_ptr >= 0) {
00078 FETCH_NEXT_STREAM_BYTE();
00079 rle_code = stream_byte;
00080 if (rle_code == 0) {
00081
00082 FETCH_NEXT_STREAM_BYTE();
00083 if (stream_byte == 0) {
00084
00085 row_ptr -= row_dec;
00086 pixel_ptr = 0;
00087 } else if (stream_byte == 1) {
00088
00089 return;
00090 } else if (stream_byte == 2) {
00091
00092 FETCH_NEXT_STREAM_BYTE();
00093 pixel_ptr += stream_byte;
00094 FETCH_NEXT_STREAM_BYTE();
00095 row_ptr -= stream_byte * row_dec;
00096 } else {
00097
00098 odd_pixel = stream_byte & 1;
00099 rle_code = (stream_byte + 1) / 2;
00100 extra_byte = rle_code & 0x01;
00101 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
00102 (row_ptr < 0)) {
00103 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
00104 return;
00105 }
00106
00107 for (i = 0; i < rle_code; i++) {
00108 if (pixel_ptr >= s->avctx->width)
00109 break;
00110 FETCH_NEXT_STREAM_BYTE();
00111 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
00112 pixel_ptr++;
00113 if (i + 1 == rle_code && odd_pixel)
00114 break;
00115 if (pixel_ptr >= s->avctx->width)
00116 break;
00117 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
00118 pixel_ptr++;
00119 }
00120
00121
00122 if (extra_byte)
00123 stream_ptr++;
00124 }
00125 } else {
00126
00127 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
00128 (row_ptr < 0)) {
00129 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
00130 return;
00131 }
00132 FETCH_NEXT_STREAM_BYTE();
00133 for (i = 0; i < rle_code; i++) {
00134 if (pixel_ptr >= s->avctx->width)
00135 break;
00136 if ((i & 1) == 0)
00137 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
00138 else
00139 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
00140 pixel_ptr++;
00141 }
00142 }
00143 }
00144
00145
00146 if (stream_ptr < s->size)
00147 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
00148 stream_ptr, s->size);
00149 }
00150
00151
00152
00153 static void msrle_decode_pal8(MsrleContext *s)
00154 {
00155 int stream_ptr = 0;
00156 unsigned char rle_code;
00157 unsigned char extra_byte;
00158 unsigned char stream_byte;
00159 int pixel_ptr = 0;
00160 int row_dec = s->frame.linesize[0];
00161 int row_ptr = (s->avctx->height - 1) * row_dec;
00162 int frame_size = row_dec * s->avctx->height;
00163
00164
00165 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
00166 if (s->avctx->palctrl->palette_changed) {
00167 s->frame.palette_has_changed = 1;
00168 s->avctx->palctrl->palette_changed = 0;
00169 }
00170
00171 while (row_ptr >= 0) {
00172 FETCH_NEXT_STREAM_BYTE();
00173 rle_code = stream_byte;
00174 if (rle_code == 0) {
00175
00176 FETCH_NEXT_STREAM_BYTE();
00177 if (stream_byte == 0) {
00178
00179 row_ptr -= row_dec;
00180 pixel_ptr = 0;
00181 } else if (stream_byte == 1) {
00182
00183 return;
00184 } else if (stream_byte == 2) {
00185
00186 FETCH_NEXT_STREAM_BYTE();
00187 pixel_ptr += stream_byte;
00188 FETCH_NEXT_STREAM_BYTE();
00189 row_ptr -= stream_byte * row_dec;
00190 } else {
00191
00192 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
00193 (row_ptr < 0)) {
00194 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
00195 return;
00196 }
00197
00198 rle_code = stream_byte;
00199 extra_byte = stream_byte & 0x01;
00200 if (stream_ptr + rle_code + extra_byte > s->size) {
00201 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (2)\n");
00202 return;
00203 }
00204
00205 while (rle_code--) {
00206 FETCH_NEXT_STREAM_BYTE();
00207 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
00208 pixel_ptr++;
00209 }
00210
00211
00212 if (extra_byte)
00213 stream_ptr++;
00214 }
00215 } else {
00216
00217 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
00218 (row_ptr < 0)) {
00219 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (2)\n");
00220 return;
00221 }
00222
00223 FETCH_NEXT_STREAM_BYTE();
00224
00225 while(rle_code--) {
00226 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
00227 pixel_ptr++;
00228 }
00229 }
00230 }
00231
00232
00233 if (stream_ptr < s->size)
00234 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
00235 stream_ptr, s->size);
00236 }
00237
00238 static int msrle_decode_init(AVCodecContext *avctx)
00239 {
00240 MsrleContext *s = (MsrleContext *)avctx->priv_data;
00241
00242 s->avctx = avctx;
00243
00244 avctx->pix_fmt = PIX_FMT_PAL8;
00245 avctx->has_b_frames = 0;
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 uint8_t *buf, int buf_size)
00254 {
00255 MsrleContext *s = (MsrleContext *)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 = (MsrleContext *)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 };