Revision 44aa9771

View differences:

libavcodec/Makefile
26 26
OBJS-$(CONFIG_ENCODERS)                += faandct.o jfdctfst.o jfdctint.o
27 27

  
28 28
OBJS-$(CONFIG_AAC_DECODER)             += aac.o aactab.o mdct.o fft.o
29
OBJS-$(CONFIG_AASC_DECODER)            += aasc.o
29
OBJS-$(CONFIG_AASC_DECODER)            += aasc.o msrledec.o
30 30
OBJS-$(CONFIG_AC3_DECODER)             += eac3dec.o ac3dec.o ac3tab.o ac3dec_data.o ac3.o mdct.o fft.o
31 31
OBJS-$(CONFIG_AC3_ENCODER)             += ac3enc.o ac3tab.o ac3.o
32 32
OBJS-$(CONFIG_ALAC_DECODER)            += alac.o
......
136 136
OBJS-$(CONFIG_MSMPEG4V2_ENCODER)       += msmpeg4.o msmpeg4data.o mpegvideo_enc.o motion_est.o ratecontrol.o h263.o mpeg12data.o mpegvideo.o error_resilience.o
137 137
OBJS-$(CONFIG_MSMPEG4V3_DECODER)       += msmpeg4.o msmpeg4data.o h263dec.o h263.o mpeg12data.o mpegvideo.o error_resilience.o
138 138
OBJS-$(CONFIG_MSMPEG4V3_ENCODER)       += msmpeg4.o msmpeg4data.o mpegvideo_enc.o motion_est.o ratecontrol.o h263.o mpeg12data.o mpegvideo.o error_resilience.o
139
OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o
139
OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o msrledec.o
140 140
OBJS-$(CONFIG_MSVIDEO1_DECODER)        += msvideo1.o
141 141
OBJS-$(CONFIG_MSZH_DECODER)            += lcldec.o
142 142
OBJS-$(CONFIG_NELLYMOSER_DECODER)      += nellymoserdec.o nellymoser.o mdct.o fft.o
......
197 197
OBJS-$(CONFIG_TRUEMOTION1_DECODER)     += truemotion1.o
198 198
OBJS-$(CONFIG_TRUEMOTION2_DECODER)     += truemotion2.o
199 199
OBJS-$(CONFIG_TRUESPEECH_DECODER)      += truespeech.o
200
OBJS-$(CONFIG_TSCC_DECODER)            += tscc.o
200
OBJS-$(CONFIG_TSCC_DECODER)            += tscc.o msrledec.o
201 201
OBJS-$(CONFIG_TTA_DECODER)             += tta.o
202 202
OBJS-$(CONFIG_TXD_DECODER)             += txd.o s3tc.o
203 203
OBJS-$(CONFIG_ULTI_DECODER)            += ulti.o
libavcodec/aasc.c
30 30

  
31 31
#include "avcodec.h"
32 32
#include "dsputil.h"
33
#include "msrledec.h"
33 34

  
34 35
typedef struct AascContext {
35 36
    AVCodecContext *avctx;
......
61 62
                              const uint8_t *buf, int buf_size)
62 63
{
63 64
    AascContext *s = avctx->priv_data;
64
    int stream_ptr = 4;
65
    unsigned char rle_code;
66
    unsigned char stream_byte;
67
    int pixel_ptr = 0;
68
    int row_dec, row_ptr;
69
    int frame_size;
70
    int i;
71 65

  
72 66
    s->frame.reference = 1;
73 67
    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
......
76 70
        return -1;
77 71
    }
78 72

  
79
    row_dec = s->frame.linesize[0];
80
    row_ptr = (s->avctx->height - 1) * row_dec;
81
    frame_size = row_dec * s->avctx->height;
82

  
83
    while (row_ptr >= 0) {
84
        FETCH_NEXT_STREAM_BYTE();
85
        rle_code = stream_byte;
86
        if (rle_code == 0) {
87
            /* fetch the next byte to see how to handle escape code */
88
            FETCH_NEXT_STREAM_BYTE();
89
            if (stream_byte == 0) {
90
                /* line is done, goto the next one */
91
                row_ptr -= row_dec;
92
                pixel_ptr = 0;
93
            } else if (stream_byte == 1) {
94
                /* decode is done */
95
                break;
96
            } else if (stream_byte == 2) {
97
                /* reposition frame decode coordinates */
98
                FETCH_NEXT_STREAM_BYTE();
99
                pixel_ptr += stream_byte;
100
                FETCH_NEXT_STREAM_BYTE();
101
                row_ptr -= stream_byte * row_dec;
102
            } else {
103
                /* copy pixels from encoded stream */
104
                if ((pixel_ptr + stream_byte > avctx->width * 3) ||
105
                    (row_ptr < 0)) {
106
                    av_log(s->avctx, AV_LOG_ERROR, " AASC: frame ptr just went out of bounds (copy1)\n");
107
                    break;
108
                }
109

  
110
                rle_code = stream_byte;
111
                if (stream_ptr + rle_code > buf_size) {
112
                    av_log(s->avctx, AV_LOG_ERROR, " AASC: stream ptr just went out of bounds (copy2)\n");
113
                    break;
114
                }
115

  
116
                for (i = 0; i < rle_code; i++) {
117
                    FETCH_NEXT_STREAM_BYTE();
118
                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
119
                    pixel_ptr++;
120
                }
121
                if (rle_code & 1)
122
                    stream_ptr++;
123
            }
124
        } else {
125
            /* decode a run of data */
126
            if ((pixel_ptr + rle_code > avctx->width * 3) ||
127
                (row_ptr < 0)) {
128
                av_log(s->avctx, AV_LOG_ERROR, " AASC: frame ptr just went out of bounds (run1)\n");
129
                break;
130
            }
131

  
132
            FETCH_NEXT_STREAM_BYTE();
133

  
134
            while(rle_code--) {
135
                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
136
                pixel_ptr++;
137
            }
138
        }
139
    }
140

  
141
    /* one last sanity check on the way out */
142
    if (stream_ptr < buf_size)
143
        av_log(s->avctx, AV_LOG_ERROR, " AASC: ended frame decode with bytes left over (%d < %d)\n",
144
            stream_ptr, buf_size);
73
    ff_msrle_decode(avctx, &s->frame, 8, buf, buf_size);
145 74

  
146 75
    *data_size = sizeof(AVFrame);
147 76
    *(AVFrame*)data = s->frame;
libavcodec/msrle.c
38 38

  
39 39
#include "avcodec.h"
40 40
#include "dsputil.h"
41
#include "msrledec.h"
41 42

  
42 43
typedef struct MsrleContext {
43 44
    AVCodecContext *avctx;
......
48 49

  
49 50
} MsrleContext;
50 51

  
51
#define FETCH_NEXT_STREAM_BYTE() \
52
    if (stream_ptr >= s->size) \
53
    { \
54
      av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
55
      return; \
56
    } \
57
    stream_byte = s->buf[stream_ptr++];
58

  
59
static void msrle_decode_pal4(MsrleContext *s)
60
{
61
    int stream_ptr = 0;
62
    unsigned char rle_code;
63
    unsigned char extra_byte, odd_pixel;
64
    unsigned char stream_byte;
65
    int pixel_ptr = 0;
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;
69
    int i;
70

  
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;
76
    }
77

  
78
    while (row_ptr >= 0) {
79
        FETCH_NEXT_STREAM_BYTE();
80
        rle_code = stream_byte;
81
        if (rle_code == 0) {
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 */
86
                row_ptr -= row_dec;
87
                pixel_ptr = 0;
88
            } else if (stream_byte == 1) {
89
                /* decode is done */
90
                return;
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;
97
        } else {
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) ||
103
                (row_ptr < 0)) {
104
                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
105
                return;
106
            }
107

  
108
            for (i = 0; i < rle_code; i++) {
109
                if (pixel_ptr >= s->avctx->width)
110
                    break;
111
                FETCH_NEXT_STREAM_BYTE();
112
                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
113
                pixel_ptr++;
114
                if (i + 1 == rle_code && odd_pixel)
115
                    break;
116
                if (pixel_ptr >= s->avctx->width)
117
                    break;
118
                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
119
                pixel_ptr++;
120
            }
121

  
122
            // if the RLE code is odd, skip a byte in the stream
123
            if (extra_byte)
124
              stream_ptr++;
125
            }
126
        } else {
127
            // decode a run of data
128
            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
129
                (row_ptr < 0)) {
130
                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
131
                return;
132
            }
133
            FETCH_NEXT_STREAM_BYTE();
134
            for (i = 0; i < rle_code; i++) {
135
                if (pixel_ptr >= s->avctx->width)
136
                    break;
137
                if ((i & 1) == 0)
138
                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
139
                else
140
                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
141
                pixel_ptr++;
142
            }
143
        }
144
    }
145

  
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);
150
}
151

  
152

  
153

  
154
static void msrle_decode_pal8(MsrleContext *s)
155
{
156
    int stream_ptr = 0;
157
    unsigned char rle_code;
158
    unsigned char extra_byte;
159
    unsigned char stream_byte;
160
    int pixel_ptr = 0;
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;
164

  
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;
170
    }
171

  
172
    while (row_ptr >= 0) {
173
        FETCH_NEXT_STREAM_BYTE();
174
        rle_code = stream_byte;
175
        if (rle_code == 0) {
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 */
180
                row_ptr -= row_dec;
181
                pixel_ptr = 0;
182
            } else if (stream_byte == 1) {
183
                /* decode is done */
184
                return;
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;
191
            } else {
192
                /* copy pixels from encoded stream */
193
                if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
194
                    (row_ptr < 0)) {
195
                    av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
196
                    return;
197
                }
198

  
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");
203
                    return;
204
                }
205

  
206
                while (rle_code--) {
207
                    FETCH_NEXT_STREAM_BYTE();
208
                    s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
209
                    pixel_ptr++;
210
                }
211

  
212
                /* if the RLE code is odd, skip a byte in the stream */
213
                if (extra_byte)
214
                    stream_ptr++;
215
            }
216
        } else {
217
            /* decode a run of data */
218
            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
219
                (row_ptr < 0)) {
220
                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (2)\n");
221
                return;
222
            }
223

  
224
            FETCH_NEXT_STREAM_BYTE();
225

  
226
            while(rle_code--) {
227
                s->frame.data[0][row_ptr + pixel_ptr] = stream_byte;
228
                pixel_ptr++;
229
            }
230
        }
231
    }
232

  
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);
237
}
238

  
239 52
static av_cold int msrle_decode_init(AVCodecContext *avctx)
240 53
{
241 54
    MsrleContext *s = avctx->priv_data;
......
264 77
        return -1;
265 78
    }
266 79

  
267
    switch (avctx->bits_per_coded_sample) {
268
        case 8:
269
            msrle_decode_pal8(s);
270
            break;
271
        case 4:
272
            msrle_decode_pal4(s);
273
            break;
274
        default:
275
            av_log(avctx, AV_LOG_ERROR, "Don't know how to decode depth %u.\n",
276
                   avctx->bits_per_coded_sample);
80
    /* make the palette available */
81
    memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
82
    if (s->avctx->palctrl->palette_changed) {
83
        s->frame.palette_has_changed = 1;
84
        s->avctx->palctrl->palette_changed = 0;
277 85
    }
278 86

  
87
    ff_msrle_decode(avctx, &s->frame, avctx->bits_per_coded_sample, buf, buf_size);
88

  
279 89
    *data_size = sizeof(AVFrame);
280 90
    *(AVFrame*)data = s->frame;
281 91

  
libavcodec/msrledec.c
1
/*
2
 * Micrsoft RLE Decoder
3
 * Copyright (C) 2008 Konstantin Shishkov
4
 *
5
 * This file is part of FFmpeg.
6
 *
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.
11
 *
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.
16
 *
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
20
 */
21

  
22
/**
23
 * @file msrledec.c
24
 * MS RLE Decoder based on decoder by Mike Melanson and my own for TSCC
25
 * For more information about the MS RLE format, visit:
26
 *   http://www.multimedia.cx/msrle.txt
27
 */
28

  
29
#include "avcodec.h"
30

  
31
#define FETCH_NEXT_STREAM_BYTE() \
32
    if (stream_ptr >= data_size) \
33
    { \
34
      av_log(avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
35
      return -1; \
36
    } \
37
    stream_byte = data[stream_ptr++];
38

  
39
static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
40
                              const uint8_t *data, int data_size)
41
{
42
    int stream_ptr = 0;
43
    unsigned char rle_code;
44
    unsigned char extra_byte, odd_pixel;
45
    unsigned char stream_byte;
46
    int pixel_ptr = 0;
47
    int row_dec = pic->linesize[0];
48
    int row_ptr = (avctx->height - 1) * row_dec;
49
    int frame_size = row_dec * avctx->height;
50
    int i;
51

  
52
    while (row_ptr >= 0) {
53
        FETCH_NEXT_STREAM_BYTE();
54
        rle_code = stream_byte;
55
        if (rle_code == 0) {
56
            /* fetch the next byte to see how to handle escape code */
57
            FETCH_NEXT_STREAM_BYTE();
58
            if (stream_byte == 0) {
59
                /* line is done, goto the next one */
60
                row_ptr -= row_dec;
61
                pixel_ptr = 0;
62
            } else if (stream_byte == 1) {
63
                /* decode is done */
64
                return 0;
65
            } else if (stream_byte == 2) {
66
                /* reposition frame decode coordinates */
67
                FETCH_NEXT_STREAM_BYTE();
68
                pixel_ptr += stream_byte;
69
                FETCH_NEXT_STREAM_BYTE();
70
                row_ptr -= stream_byte * row_dec;
71
        } else {
72
            // copy pixels from encoded stream
73
            odd_pixel =  stream_byte & 1;
74
            rle_code = (stream_byte + 1) / 2;
75
            extra_byte = rle_code & 0x01;
76
            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
77
                (row_ptr < 0)) {
78
                av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
79
                return -1;
80
            }
81

  
82
            for (i = 0; i < rle_code; i++) {
83
                if (pixel_ptr >= avctx->width)
84
                    break;
85
                FETCH_NEXT_STREAM_BYTE();
86
                pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
87
                pixel_ptr++;
88
                if (i + 1 == rle_code && odd_pixel)
89
                    break;
90
                if (pixel_ptr >= avctx->width)
91
                    break;
92
                pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
93
                pixel_ptr++;
94
            }
95

  
96
            // if the RLE code is odd, skip a byte in the stream
97
            if (extra_byte)
98
              stream_ptr++;
99
            }
100
        } else {
101
            // decode a run of data
102
            if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
103
                (row_ptr < 0)) {
104
                av_log(avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
105
                return -1;
106
            }
107
            FETCH_NEXT_STREAM_BYTE();
108
            for (i = 0; i < rle_code; i++) {
109
                if (pixel_ptr >= avctx->width)
110
                    break;
111
                if ((i & 1) == 0)
112
                    pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
113
                else
114
                    pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
115
                pixel_ptr++;
116
            }
117
        }
118
    }
119

  
120
    /* 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);
124
        return -1;
125
    }
126

  
127
    return 0;
128
}
129

  
130

  
131
static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int depth,
132
                                    const uint8_t *data, int srcsize)
133
{
134
    uint8_t *output, *output_end;
135
    const uint8_t* src = data;
136
    int p1, p2, line=avctx->height, pos=0, i;
137
    uint16_t pix16;
138
    uint32_t pix32;
139

  
140
    output = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
141
    output_end = pic->data[0] + (avctx->height) * pic->linesize[0];
142
    while(src < data + srcsize) {
143
        p1 = *src++;
144
        if(p1 == 0) { //Escape code
145
            p2 = *src++;
146
            if(p2 == 0) { //End-of-line
147
                output = pic->data[0] + (--line) * pic->linesize[0];
148
                if (line < 0)
149
                    return -1;
150
                pos = 0;
151
                continue;
152
            } else if(p2 == 1) { //End-of-picture
153
                return 0;
154
            } else if(p2 == 2) { //Skip
155
                p1 = *src++;
156
                p2 = *src++;
157
                line -= p2;
158
                if (line < 0)
159
                    return -1;
160
                pos += p1;
161
                output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3);
162
                continue;
163
            }
164
            // Copy data
165
            if (output + p2 * (depth >> 3) > output_end) {
166
                src += p2 * (depth >> 3);
167
                continue;
168
            }
169
            if ((depth == 8) || (depth == 24)) {
170
                for(i = 0; i < p2 * (depth >> 3); i++) {
171
                    *output++ = *src++;
172
                }
173
                // RLE8 copy is actually padded - and runs are not!
174
                if(depth == 8 && (p2 & 1)) {
175
                    src++;
176
                }
177
            } else if (depth == 16) {
178
                for(i = 0; i < p2; i++) {
179
                    pix16 = AV_RL16(src);
180
                    src += 2;
181
                    *(uint16_t*)output = pix16;
182
                    output += 2;
183
                }
184
            } else if (depth == 32) {
185
                for(i = 0; i < p2; i++) {
186
                    pix32 = AV_RL32(src);
187
                    src += 4;
188
                    *(uint32_t*)output = pix32;
189
                    output += 4;
190
                }
191
            }
192
            pos += p2;
193
        } else { //Run of pixels
194
            int pix[4]; //original pixel
195
            switch(depth){
196
            case  8: pix[0] = *src++;
197
                     break;
198
            case 16: pix16 = AV_RL16(src);
199
                     src += 2;
200
                     *(uint16_t*)pix = pix16;
201
                     break;
202
            case 24: pix[0] = *src++;
203
                     pix[1] = *src++;
204
                     pix[2] = *src++;
205
                     break;
206
            case 32: pix32 = AV_RL32(src);
207
                     src += 4;
208
                     *(uint32_t*)pix = pix32;
209
                     break;
210
            }
211
            if (output + p1 * (depth >> 3) > output_end)
212
                continue;
213
            for(i = 0; i < p1; i++) {
214
                switch(depth){
215
                case  8: *output++ = pix[0];
216
                         break;
217
                case 16: *(uint16_t*)output = pix16;
218
                         output += 2;
219
                         break;
220
                case 24: *output++ = pix[0];
221
                         *output++ = pix[1];
222
                         *output++ = pix[2];
223
                         break;
224
                case 32: *(uint32_t*)output = pix32;
225
                         output += 4;
226
                         break;
227
                }
228
            }
229
            pos += p1;
230
        }
231
    }
232

  
233
    av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no End-of-picture code\n");
234
    return 0;
235
}
236

  
237

  
238
int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, int depth,
239
                    const uint8_t* data, int data_size)
240
{
241
    switch(depth){
242
    case  4:
243
        return msrle_decode_pal4(avctx, pic, data, data_size);
244
    case  8:
245
    case 16:
246
    case 24:
247
    case 32:
248
        return msrle_decode_8_16_24_32(avctx, pic, depth, data, data_size);
249
    default:
250
        av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);
251
        return -1;
252
    }
253
}
254

  
libavcodec/msrledec.h
1
/*
2
 * Micrsoft RLE Decoder
3
 * Copyright (C) 2008 Konstantin Shishkov
4
 *
5
 * This file is part of FFmpeg.
6
 *
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.
11
 *
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.
16
 *
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
20
 */
21

  
22
#ifndef AVCODEC_MSRLEDEC_H
23
#define AVCODEC_MSRLEDEC_H
24

  
25
#include "avcodec.h"
26

  
27
/**
28
 * decode stream in MS RLE format into frame
29
 *
30
 * @param avctx     codec context
31
 * @param pic       destination frame
32
 * @param depth     bit depth
33
 * @param data      input stream
34
 * @param data_size input size
35
 */
36
int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, int depth,
37
                    const uint8_t* data, int data_size);
38

  
39
#endif /* AVCODEC_MSRLEDEC_H */
40

  
libavcodec/tscc.c
39 39
#include <stdlib.h>
40 40

  
41 41
#include "avcodec.h"
42
#include "msrledec.h"
42 43

  
43 44
#ifdef CONFIG_ZLIB
44 45
#include <zlib.h>
......
67 68

  
68 69
/*
69 70
 *
70
 * Decode RLE - almost identical to Windows BMP RLE8
71
 *              and enhanced to bigger color depths
72
 *
73
 */
74

  
75
static int decode_rle(CamtasiaContext *c, unsigned int srcsize)
76
{
77
    unsigned char *src = c->decomp_buf;
78
    unsigned char *output, *output_end;
79
    int p1, p2, line=c->height, pos=0, i;
80
    uint16_t pix16;
81
    uint32_t pix32;
82

  
83
    output = c->pic.data[0] + (c->height - 1) * c->pic.linesize[0];
84
    output_end = c->pic.data[0] + (c->height) * c->pic.linesize[0];
85
    while(src < c->decomp_buf + srcsize) {
86
        p1 = *src++;
87
        if(p1 == 0) { //Escape code
88
            p2 = *src++;
89
            if(p2 == 0) { //End-of-line
90
                output = c->pic.data[0] + (--line) * c->pic.linesize[0];
91
                if (line < 0)
92
                    return -1;
93
                pos = 0;
94
                continue;
95
            } else if(p2 == 1) { //End-of-picture
96
                return 0;
97
            } else if(p2 == 2) { //Skip
98
                p1 = *src++;
99
                p2 = *src++;
100
                line -= p2;
101
                if (line < 0)
102
                    return -1;
103
                pos += p1;
104
                output = c->pic.data[0] + line * c->pic.linesize[0] + pos * (c->bpp / 8);
105
                continue;
106
            }
107
            // Copy data
108
            if (output + p2 * (c->bpp / 8) > output_end) {
109
                src += p2 * (c->bpp / 8);
110
                continue;
111
            }
112
            if ((c->bpp == 8) || (c->bpp == 24)) {
113
                for(i = 0; i < p2 * (c->bpp / 8); i++) {
114
                    *output++ = *src++;
115
                }
116
                // RLE8 copy is actually padded - and runs are not!
117
                if(c->bpp == 8 && (p2 & 1)) {
118
                    src++;
119
                }
120
            } else if (c->bpp == 16) {
121
                for(i = 0; i < p2; i++) {
122
                    pix16 = AV_RL16(src);
123
                    src += 2;
124
                    *(uint16_t*)output = pix16;
125
                    output += 2;
126
                }
127
            } else if (c->bpp == 32) {
128
                for(i = 0; i < p2; i++) {
129
                    pix32 = AV_RL32(src);
130
                    src += 4;
131
                    *(uint32_t*)output = pix32;
132
                    output += 4;
133
                }
134
            }
135
            pos += p2;
136
        } else { //Run of pixels
137
            int pix[4]; //original pixel
138
            switch(c->bpp){
139
            case  8: pix[0] = *src++;
140
                     break;
141
            case 16: pix16 = AV_RL16(src);
142
                     src += 2;
143
                     *(uint16_t*)pix = pix16;
144
                     break;
145
            case 24: pix[0] = *src++;
146
                     pix[1] = *src++;
147
                     pix[2] = *src++;
148
                     break;
149
            case 32: pix32 = AV_RL32(src);
150
                     src += 4;
151
                     *(uint32_t*)pix = pix32;
152
                     break;
153
            }
154
            if (output + p1 * (c->bpp / 8) > output_end)
155
                continue;
156
            for(i = 0; i < p1; i++) {
157
                switch(c->bpp){
158
                case  8: *output++ = pix[0];
159
                         break;
160
                case 16: *(uint16_t*)output = pix16;
161
                         output += 2;
162
                         break;
163
                case 24: *output++ = pix[0];
164
                         *output++ = pix[1];
165
                         *output++ = pix[2];
166
                         break;
167
                case 32: *(uint32_t*)output = pix32;
168
                         output += 4;
169
                         break;
170
                }
171
            }
172
            pos += p1;
173
        }
174
    }
175

  
176
    av_log(c->avctx, AV_LOG_ERROR, "Camtasia warning: no End-of-picture code\n");
177
    return 1;
178
}
179

  
180
/*
181
 *
182 71
 * Decode a frame
183 72
 *
184 73
 */
......
223 112

  
224 113

  
225 114
    if(zret != Z_DATA_ERROR)
226
        decode_rle(c, c->zstream.avail_out);
115
        ff_msrle_decode(avctx, &c->pic, c->bpp, c->decomp_buf, c->zstream.avail_out);
227 116

  
228 117
    /* make the palette available on the way out */
229 118
    if (c->avctx->pix_fmt == PIX_FMT_PAL8) {

Also available in: Unified diff