2
* Micrsoft RLE Video Decoder
3
* Copyright (C) 2003 the ffmpeg project
5
* This file is part of FFmpeg.
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
* MS RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
25
* For more information about the MS RLE format, visit:
26
* http://www.pcisys.net/~melanson/codecs/
28
* The MS RLE decoder outputs PAL8 colorspace data.
30
* Note that this decoder expects the palette colors from the end of the
31
* BITMAPINFO header passed through palctrl.
42
typedef struct MsrleContext {
43
AVCodecContext *avctx;
51
#define FETCH_NEXT_STREAM_BYTE() \
52
if (stream_ptr >= s->size) \
54
av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
57
stream_byte = s->buf[stream_ptr++];
59
static void msrle_decode_pal4(MsrleContext *s)
62
unsigned char rle_code;
63
unsigned char extra_byte, odd_pixel;
64
unsigned char stream_byte;
66
int row_dec = s->frame.linesize[0];
67
int row_ptr = (s->avctx->height - 1) * row_dec;
68
int frame_size = row_dec * s->avctx->height;
71
/* make the palette available */
72
memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
73
if (s->avctx->palctrl->palette_changed) {
74
s->frame.palette_has_changed = 1;
75
s->avctx->palctrl->palette_changed = 0;
78
while (row_ptr >= 0) {
79
FETCH_NEXT_STREAM_BYTE();
80
rle_code = stream_byte;
82
/* fetch the next byte to see how to handle escape code */
83
FETCH_NEXT_STREAM_BYTE();
84
if (stream_byte == 0) {
85
/* line is done, goto the next one */
88
} else if (stream_byte == 1) {
91
} else if (stream_byte == 2) {
92
/* reposition frame decode coordinates */
93
FETCH_NEXT_STREAM_BYTE();
94
pixel_ptr += stream_byte;
95
FETCH_NEXT_STREAM_BYTE();
96
row_ptr -= stream_byte * row_dec;
98
// copy pixels from encoded stream
99
odd_pixel = stream_byte & 1;
100
rle_code = (stream_byte + 1) / 2;
101
extra_byte = rle_code & 0x01;
102
if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
104
av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
108
for (i = 0; i < rle_code; i++) {
109
if (pixel_ptr >= s->avctx->width)
111
FETCH_NEXT_STREAM_BYTE();
112
s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
114
if (i + 1 == rle_code && odd_pixel)
116
if (pixel_ptr >= s->avctx->width)
118
s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
122
// if the RLE code is odd, skip a byte in the stream
127
// decode a run of data
128
if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
130
av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
133
FETCH_NEXT_STREAM_BYTE();
134
for (i = 0; i < rle_code; i++) {
135
if (pixel_ptr >= s->avctx->width)
138
s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
140
s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
146
/* one last sanity check on the way out */
147
if (stream_ptr < s->size)
148
av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
149
stream_ptr, s->size);
154
static void msrle_decode_pal8(MsrleContext *s)
157
unsigned char rle_code;
158
unsigned char extra_byte;
159
unsigned char stream_byte;
161
int row_dec = s->frame.linesize[0];
162
int row_ptr = (s->avctx->height - 1) * row_dec;
163
int frame_size = row_dec * s->avctx->height;
165
/* make the palette available */
166
memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
167
if (s->avctx->palctrl->palette_changed) {
168
s->frame.palette_has_changed = 1;
169
s->avctx->palctrl->palette_changed = 0;
172
while (row_ptr >= 0) {
173
FETCH_NEXT_STREAM_BYTE();
174
rle_code = stream_byte;
176
/* fetch the next byte to see how to handle escape code */
177
FETCH_NEXT_STREAM_BYTE();
178
if (stream_byte == 0) {
179
/* line is done, goto the next one */
182
} else if (stream_byte == 1) {
185
} else if (stream_byte == 2) {
186
/* reposition frame decode coordinates */
187
FETCH_NEXT_STREAM_BYTE();
188
pixel_ptr += stream_byte;
189
FETCH_NEXT_STREAM_BYTE();
190
row_ptr -= stream_byte * row_dec;
192
/* copy pixels from encoded stream */
193
if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
195
av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
199
rle_code = stream_byte;
200
extra_byte = stream_byte & 0x01;
201
if (stream_ptr + rle_code + extra_byte > s->size) {
202
av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (2)\n");
207
FETCH_NEXT_STREAM_BYTE();
208
s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
212
/* if the RLE code is odd, skip a byte in the stream */
217
/* decode a run of data */
218
if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
220
av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (2)\n");
224
FETCH_NEXT_STREAM_BYTE();
227
s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
233
/* one last sanity check on the way out */
234
if (stream_ptr < s->size)
235
av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
236
stream_ptr, s->size);
239
static int msrle_decode_init(AVCodecContext *avctx)
241
MsrleContext *s = avctx->priv_data;
245
avctx->pix_fmt = PIX_FMT_PAL8;
246
s->frame.data[0] = NULL;
251
static int msrle_decode_frame(AVCodecContext *avctx,
252
void *data, int *data_size,
253
uint8_t *buf, int buf_size)
255
MsrleContext *s = avctx->priv_data;
260
s->frame.reference = 1;
261
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
262
if (avctx->reget_buffer(avctx, &s->frame)) {
263
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
267
switch (avctx->bits_per_sample) {
269
msrle_decode_pal8(s);
272
msrle_decode_pal4(s);
275
av_log(avctx, AV_LOG_ERROR, "Don't know how to decode depth %u.\n",
276
avctx->bits_per_sample);
279
*data_size = sizeof(AVFrame);
280
*(AVFrame*)data = s->frame;
282
/* report that the buffer was completely consumed */
286
static int msrle_decode_end(AVCodecContext *avctx)
288
MsrleContext *s = avctx->priv_data;
290
/* release the last frame */
291
if (s->frame.data[0])
292
avctx->release_buffer(avctx, &s->frame);
297
AVCodec msrle_decoder = {
301
sizeof(MsrleContext),