30
30
#include "avcodec.h"
31
31
#include "msrledec.h"
33
#define FETCH_NEXT_STREAM_BYTE() \
34
if (stream_ptr >= data_size) \
36
av_log(avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
39
stream_byte = data[stream_ptr++];
41
33
static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
42
const uint8_t *data, int data_size)
45
36
unsigned char rle_code;
46
37
unsigned char extra_byte, odd_pixel;
47
38
unsigned char stream_byte;
54
45
while (row_ptr >= 0) {
55
FETCH_NEXT_STREAM_BYTE();
56
rle_code = stream_byte;
46
if (bytestream2_get_bytes_left(gb) <= 0) {
47
av_log(avctx, AV_LOG_ERROR,
48
"MS RLE: bytestream overrun, %d rows left\n",
50
return AVERROR_INVALIDDATA;
52
rle_code = stream_byte = bytestream2_get_byteu(gb);
57
53
if (rle_code == 0) {
58
54
/* fetch the next byte to see how to handle escape code */
59
FETCH_NEXT_STREAM_BYTE();
55
stream_byte = bytestream2_get_byte(gb);
60
56
if (stream_byte == 0) {
61
57
/* line is done, goto the next one */
62
58
row_ptr -= row_dec;
67
63
} else if (stream_byte == 2) {
68
64
/* reposition frame decode coordinates */
69
FETCH_NEXT_STREAM_BYTE();
65
stream_byte = bytestream2_get_byte(gb);
70
66
pixel_ptr += stream_byte;
71
FETCH_NEXT_STREAM_BYTE();
67
stream_byte = bytestream2_get_byte(gb);
72
68
row_ptr -= stream_byte * row_dec;
74
70
// copy pixels from encoded stream
75
71
odd_pixel = stream_byte & 1;
76
72
rle_code = (stream_byte + 1) / 2;
77
73
extra_byte = rle_code & 0x01;
78
if (row_ptr + pixel_ptr + stream_byte > frame_size) {
79
av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
74
if (row_ptr + pixel_ptr + stream_byte > frame_size ||
75
bytestream2_get_bytes_left(gb) < rle_code) {
76
av_log(avctx, AV_LOG_ERROR,
77
"MS RLE: frame/stream ptr just went out of bounds (copy)\n");
78
return AVERROR_INVALIDDATA;
83
81
for (i = 0; i < rle_code; i++) {
84
82
if (pixel_ptr >= avctx->width)
86
FETCH_NEXT_STREAM_BYTE();
84
stream_byte = bytestream2_get_byteu(gb);
87
85
pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
89
87
if (i + 1 == rle_code && odd_pixel)
97
95
// if the RLE code is odd, skip a byte in the stream
97
bytestream2_skip(gb, 1);
102
100
// decode a run of data
103
101
if (row_ptr + pixel_ptr + stream_byte > frame_size) {
104
av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
102
av_log(avctx, AV_LOG_ERROR,
103
"MS RLE: frame ptr just went out of bounds (run)\n");
104
return AVERROR_INVALIDDATA;
107
FETCH_NEXT_STREAM_BYTE();
106
stream_byte = bytestream2_get_byte(gb);
108
107
for (i = 0; i < rle_code; i++) {
109
108
if (pixel_ptr >= avctx->width)
120
119
/* one last sanity check on the way out */
121
if (stream_ptr < data_size) {
122
av_log(avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
123
stream_ptr, data_size);
120
if (bytestream2_get_bytes_left(gb)) {
121
av_log(avctx, AV_LOG_ERROR,
122
"MS RLE: ended frame decode with %d bytes left over\n",
123
bytestream2_get_bytes_left(gb));
124
return AVERROR_INVALIDDATA;
131
static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int depth,
132
const uint8_t *data, int srcsize)
131
static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic,
132
int depth, GetByteContext *gb)
134
134
uint8_t *output, *output_end;
135
const uint8_t* src = data;
136
135
int p1, p2, line=avctx->height - 1, pos=0, i;
137
136
uint16_t av_uninit(pix16);
138
137
uint32_t av_uninit(pix32);
141
140
output = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
142
141
output_end = pic->data[0] + avctx->height * pic->linesize[0];
143
while(src < data + srcsize) {
142
while (bytestream2_get_bytes_left(gb) > 0) {
143
p1 = bytestream2_get_byteu(gb);
145
144
if(p1 == 0) { //Escape code
145
p2 = bytestream2_get_byte(gb);
147
146
if(p2 == 0) { //End-of-line
148
output = pic->data[0] + (--line) * pic->linesize[0];
149
if (line < 0 && !(src+1 < data + srcsize && AV_RB16(src) == 1)) {
150
av_log(avctx, AV_LOG_ERROR, "Next line is beyond picture bounds\n");
148
if (bytestream2_get_be16(gb) == 1) { // end-of-picture
151
av_log(avctx, AV_LOG_ERROR,
152
"Next line is beyond picture bounds (%d bytes left)\n",
153
bytestream2_get_bytes_left(gb));
154
return AVERROR_INVALIDDATA;
157
output = pic->data[0] + line * pic->linesize[0];
155
160
} else if(p2 == 1) { //End-of-picture
157
162
} else if(p2 == 2) { //Skip
163
p1 = bytestream2_get_byte(gb);
164
p2 = bytestream2_get_byte(gb);
162
167
if (line < 0 || pos >= width){
170
if ((pic->linesize[0] > 0 && output + p2 * (depth >> 3) > output_end)
171
||(pic->linesize[0] < 0 && output + p2 * (depth >> 3) < output_end)) {
172
src += p2 * (depth >> 3);
175
if ((pic->linesize[0] > 0 && output + p2 * (depth >> 3) > output_end) ||
176
(pic->linesize[0] < 0 && output + p2 * (depth >> 3) < output_end)) {
177
bytestream2_skip(gb, 2 * (depth >> 3));
179
} else if (bytestream2_get_bytes_left(gb) < p2 * (depth >> 3)) {
180
av_log(avctx, AV_LOG_ERROR, "bytestream overrun\n");
181
return AVERROR_INVALIDDATA;
175
184
if ((depth == 8) || (depth == 24)) {
176
185
for(i = 0; i < p2 * (depth >> 3); i++) {
186
*output++ = bytestream2_get_byteu(gb);
179
188
// RLE8 copy is actually padded - and runs are not!
180
189
if(depth == 8 && (p2 & 1)) {
190
bytestream2_skip(gb, 1);
183
192
} else if (depth == 16) {
184
193
for(i = 0; i < p2; i++) {
185
pix16 = AV_RL16(src);
187
*(uint16_t*)output = pix16;
194
*(uint16_t*)output = bytestream2_get_le16u(gb);
190
197
} else if (depth == 32) {
191
198
for(i = 0; i < p2; i++) {
192
pix32 = AV_RL32(src);
194
*(uint32_t*)output = pix32;
199
*(uint32_t*)output = bytestream2_get_le32u(gb);
199
204
} else { //run of pixels
200
205
uint8_t pix[3]; //original pixel
202
case 8: pix[0] = *src++;
204
case 16: pix16 = AV_RL16(src);
207
case 24: pix[0] = *src++;
211
case 32: pix32 = AV_RL32(src);
207
case 8: pix[0] = bytestream2_get_byte(gb);
209
case 16: pix16 = bytestream2_get_le16(gb);
211
case 24: pix[0] = bytestream2_get_byte(gb);
212
pix[1] = bytestream2_get_byte(gb);
213
pix[2] = bytestream2_get_byte(gb);
215
case 32: pix32 = bytestream2_get_le32(gb);
215
if ((pic->linesize[0] > 0 && output + p1 * (depth >> 3) > output_end)
216
||(pic->linesize[0] < 0 && output + p1 * (depth >> 3) < output_end))
218
if ((pic->linesize[0] > 0 && output + p1 * (depth >> 3) > output_end) ||
219
(pic->linesize[0] < 0 && output + p1 * (depth >> 3) < output_end))
218
221
for(i = 0; i < p1; i++) {
243
int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, int depth,
244
const uint8_t* data, int data_size)
246
int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic,
247
int depth, GetByteContext *gb)
248
return msrle_decode_pal4(avctx, pic, data, data_size);
251
return msrle_decode_pal4(avctx, pic, gb);
253
return msrle_decode_8_16_24_32(avctx, pic, depth, data, data_size);
256
return msrle_decode_8_16_24_32(avctx, pic, depth, gb);
255
258
av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);