/*
- * Micrsoft RLE Decoder
+ * Microsoft RLE decoder
* Copyright (C) 2008 Konstantin Shishkov
*
* This file is part of FFmpeg.
*/
/**
- * @file msrledec.c
- * MS RLE Decoder based on decoder by Mike Melanson and my own for TSCC
+ * @file
+ * MS RLE decoder based on decoder by Mike Melanson and my own for TSCC
* For more information about the MS RLE format, visit:
* http://www.multimedia.cx/msrle.txt
*/
+#include "libavutil/intreadwrite.h"
#include "avcodec.h"
+#include "msrledec.h"
#define FETCH_NEXT_STREAM_BYTE() \
if (stream_ptr >= data_size) \
unsigned char rle_code;
unsigned char extra_byte, odd_pixel;
unsigned char stream_byte;
- int pixel_ptr = 0;
+ unsigned int pixel_ptr = 0;
int row_dec = pic->linesize[0];
int row_ptr = (avctx->height - 1) * row_dec;
int frame_size = row_dec * avctx->height;
pixel_ptr += stream_byte;
FETCH_NEXT_STREAM_BYTE();
row_ptr -= stream_byte * row_dec;
- } else {
- // copy pixels from encoded stream
- odd_pixel = stream_byte & 1;
- rle_code = (stream_byte + 1) / 2;
- extra_byte = rle_code & 0x01;
- if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
- (row_ptr < 0)) {
- av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
- return -1;
- }
+ } else {
+ // copy pixels from encoded stream
+ odd_pixel = stream_byte & 1;
+ rle_code = (stream_byte + 1) / 2;
+ extra_byte = rle_code & 0x01;
+ if (row_ptr + pixel_ptr + stream_byte > frame_size) {
+ av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
+ return -1;
+ }
- for (i = 0; i < rle_code; i++) {
- if (pixel_ptr >= avctx->width)
- break;
- FETCH_NEXT_STREAM_BYTE();
- pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
- pixel_ptr++;
- if (i + 1 == rle_code && odd_pixel)
- break;
- if (pixel_ptr >= avctx->width)
- break;
- pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
- pixel_ptr++;
- }
+ for (i = 0; i < rle_code; i++) {
+ if (pixel_ptr >= avctx->width)
+ break;
+ FETCH_NEXT_STREAM_BYTE();
+ pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
+ pixel_ptr++;
+ if (i + 1 == rle_code && odd_pixel)
+ break;
+ if (pixel_ptr >= avctx->width)
+ break;
+ pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
+ pixel_ptr++;
+ }
- // if the RLE code is odd, skip a byte in the stream
- if (extra_byte)
- stream_ptr++;
+ // if the RLE code is odd, skip a byte in the stream
+ if (extra_byte)
+ stream_ptr++;
}
} else {
// decode a run of data
- if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
- (row_ptr < 0)) {
+ if (row_ptr + pixel_ptr + stream_byte > frame_size) {
av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
return -1;
}
{
uint8_t *output, *output_end;
const uint8_t* src = data;
- int p1, p2, line=avctx->height, pos=0, i;
- uint16_t pix16;
- uint32_t pix32;
+ int p1, p2, line=avctx->height - 1, pos=0, i;
+ uint16_t av_uninit(pix16);
+ uint32_t av_uninit(pix32);
+ unsigned int width= FFABS(pic->linesize[0]) / (depth >> 3);
output = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
output_end = pic->data[0] + (avctx->height) * pic->linesize[0];
p2 = *src++;
if(p2 == 0) { //End-of-line
output = pic->data[0] + (--line) * pic->linesize[0];
- if (line < 0)
+ if (line < 0 && !(src+1 < data + srcsize && AV_RB16(src) == 1)) {
+ av_log(avctx, AV_LOG_ERROR, "Next line is beyond picture bounds\n");
return -1;
+ }
pos = 0;
continue;
} else if(p2 == 1) { //End-of-picture
p1 = *src++;
p2 = *src++;
line -= p2;
- if (line < 0)
- return -1;
pos += p1;
+ if (line < 0 || pos >= width){
+ av_log(avctx, AV_LOG_ERROR, "Skip beyond picture bounds\n");
+ return -1;
+ }
output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3);
continue;
}
// Copy data
- if (output + p2 * (depth >> 3) > output_end) {
+ if ((pic->linesize[0] > 0 && output + p2 * (depth >> 3) > output_end)
+ ||(pic->linesize[0] < 0 && output + p2 * (depth >> 3) < output_end)) {
src += p2 * (depth >> 3);
continue;
}
}
}
pos += p2;
- } else { //Run of pixels
- int pix[4]; //original pixel
+ } else { //run of pixels
+ uint8_t pix[3]; //original pixel
switch(depth){
case 8: pix[0] = *src++;
break;
case 16: pix16 = AV_RL16(src);
src += 2;
- *(uint16_t*)pix = pix16;
break;
case 24: pix[0] = *src++;
pix[1] = *src++;
break;
case 32: pix32 = AV_RL32(src);
src += 4;
- *(uint32_t*)pix = pix32;
break;
}
- if (output + p1 * (depth >> 3) > output_end)
+ if ((pic->linesize[0] > 0 && output + p1 * (depth >> 3) > output_end)
+ ||(pic->linesize[0] < 0 && output + p1 * (depth >> 3) < output_end))
continue;
for(i = 0; i < p1; i++) {
switch(depth){
}
}
- av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no End-of-picture code\n");
+ av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no end-of-picture code\n");
return 0;
}