~siretart/libav/merge.raring.libav-0.8.6

« back to all changes in this revision

Viewing changes to libavcodec/msrledec.c

  • Committer: Reinhard Tartler
  • Date: 2013-03-27 06:53:14 UTC
  • mfrom: (1.3.32 sid)
  • Revision ID: siretart@tauware.de-20130327065314-fs4shpt6y2h46ekf
first merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
#include "avcodec.h"
31
31
#include "msrledec.h"
32
32
 
33
 
#define FETCH_NEXT_STREAM_BYTE() \
34
 
    if (stream_ptr >= data_size) \
35
 
    { \
36
 
      av_log(avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
37
 
      return -1; \
38
 
    } \
39
 
    stream_byte = data[stream_ptr++];
40
 
 
41
33
static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
42
 
                              const uint8_t *data, int data_size)
 
34
                             GetByteContext *gb)
43
35
{
44
 
    int stream_ptr = 0;
45
36
    unsigned char rle_code;
46
37
    unsigned char extra_byte, odd_pixel;
47
38
    unsigned char stream_byte;
52
43
    int i;
53
44
 
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",
 
49
                   row_ptr);
 
50
            return AVERROR_INVALIDDATA;
 
51
        }
 
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;
66
62
                return 0;
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;
73
69
            } else {
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");
80
 
                    return -1;
 
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;
81
79
                }
82
80
 
83
81
                for (i = 0; i < rle_code; i++) {
84
82
                    if (pixel_ptr >= avctx->width)
85
83
                        break;
86
 
                    FETCH_NEXT_STREAM_BYTE();
 
84
                    stream_byte = bytestream2_get_byteu(gb);
87
85
                    pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
88
86
                    pixel_ptr++;
89
87
                    if (i + 1 == rle_code && odd_pixel)
96
94
 
97
95
                // if the RLE code is odd, skip a byte in the stream
98
96
                if (extra_byte)
99
 
                    stream_ptr++;
 
97
                    bytestream2_skip(gb, 1);
100
98
            }
101
99
        } else {
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");
105
 
                return -1;
 
102
                av_log(avctx, AV_LOG_ERROR,
 
103
                       "MS RLE: frame ptr just went out of bounds (run)\n");
 
104
                return AVERROR_INVALIDDATA;
106
105
            }
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)
110
109
                    break;
118
117
    }
119
118
 
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);
124
 
        return -1;
 
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;
125
125
    }
126
126
 
127
127
    return 0;
128
128
}
129
129
 
130
130
 
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)
133
133
{
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);
140
139
 
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) {
144
 
        p1 = *src++;
 
142
    while (bytestream2_get_bytes_left(gb) > 0) {
 
143
        p1 = bytestream2_get_byteu(gb);
145
144
        if(p1 == 0) { //Escape code
146
 
            p2 = *src++;
 
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");
151
 
                    return -1;
 
147
                if (--line < 0) {
 
148
                    if (bytestream2_get_be16(gb) == 1) { // end-of-picture
 
149
                        return 0;
 
150
                    } else {
 
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;
 
155
                    }
152
156
                }
 
157
                output = pic->data[0] + line * pic->linesize[0];
153
158
                pos = 0;
154
159
                continue;
155
160
            } else if(p2 == 1) { //End-of-picture
156
161
                return 0;
157
162
            } else if(p2 == 2) { //Skip
158
 
                p1 = *src++;
159
 
                p2 = *src++;
 
163
                p1 = bytestream2_get_byte(gb);
 
164
                p2 = bytestream2_get_byte(gb);
160
165
                line -= p2;
161
166
                pos += p1;
162
167
                if (line < 0 || pos >= width){
167
172
                continue;
168
173
            }
169
174
            // Copy data
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));
173
178
                continue;
 
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;
174
182
            }
 
183
 
175
184
            if ((depth == 8) || (depth == 24)) {
176
185
                for(i = 0; i < p2 * (depth >> 3); i++) {
177
 
                    *output++ = *src++;
 
186
                    *output++ = bytestream2_get_byteu(gb);
178
187
                }
179
188
                // RLE8 copy is actually padded - and runs are not!
180
189
                if(depth == 8 && (p2 & 1)) {
181
 
                    src++;
 
190
                    bytestream2_skip(gb, 1);
182
191
                }
183
192
            } else if (depth == 16) {
184
193
                for(i = 0; i < p2; i++) {
185
 
                    pix16 = AV_RL16(src);
186
 
                    src += 2;
187
 
                    *(uint16_t*)output = pix16;
 
194
                    *(uint16_t*)output = bytestream2_get_le16u(gb);
188
195
                    output += 2;
189
196
                }
190
197
            } else if (depth == 32) {
191
198
                for(i = 0; i < p2; i++) {
192
 
                    pix32 = AV_RL32(src);
193
 
                    src += 4;
194
 
                    *(uint32_t*)output = pix32;
 
199
                    *(uint32_t*)output = bytestream2_get_le32u(gb);
195
200
                    output += 4;
196
201
                }
197
202
            }
199
204
        } else { //run of pixels
200
205
            uint8_t pix[3]; //original pixel
201
206
            switch(depth){
202
 
            case  8: pix[0] = *src++;
203
 
                     break;
204
 
            case 16: pix16 = AV_RL16(src);
205
 
                     src += 2;
206
 
                     break;
207
 
            case 24: pix[0] = *src++;
208
 
                     pix[1] = *src++;
209
 
                     pix[2] = *src++;
210
 
                     break;
211
 
            case 32: pix32 = AV_RL32(src);
212
 
                     src += 4;
 
207
            case  8: pix[0] = bytestream2_get_byte(gb);
 
208
                     break;
 
209
            case 16: pix16  = bytestream2_get_le16(gb);
 
210
                     break;
 
211
            case 24: pix[0] = bytestream2_get_byte(gb);
 
212
                     pix[1] = bytestream2_get_byte(gb);
 
213
                     pix[2] = bytestream2_get_byte(gb);
 
214
                     break;
 
215
            case 32: pix32  = bytestream2_get_le32(gb);
213
216
                     break;
214
217
            }
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))
217
220
                continue;
218
221
            for(i = 0; i < p1; i++) {
219
222
                switch(depth){
240
243
}
241
244
 
242
245
 
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)
245
248
{
246
249
    switch(depth){
247
250
    case  4:
248
 
        return msrle_decode_pal4(avctx, pic, data, data_size);
 
251
        return msrle_decode_pal4(avctx, pic, gb);
249
252
    case  8:
250
253
    case 16:
251
254
    case 24:
252
255
    case 32:
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);
254
257
    default:
255
258
        av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);
256
259
        return -1;