Browse code

msrle: convert MS RLE decoding function to bytestream2.

Signed-off-by: Justin Ruggles <justin.ruggles@gmail.com>

Ronald Bultje authored on 2012/04/01 02:10:54
Showing 6 changed files
... ...
@@ -34,17 +34,10 @@
34 34
 
35 35
 typedef struct AascContext {
36 36
     AVCodecContext *avctx;
37
+    GetByteContext gb;
37 38
     AVFrame frame;
38 39
 } AascContext;
39 40
 
40
-#define FETCH_NEXT_STREAM_BYTE() \
41
-    if (stream_ptr >= buf_size) \
42
-    { \
43
-      av_log(s->avctx, AV_LOG_ERROR, " AASC: stream ptr just went out of bounds (fetch)\n"); \
44
-      break; \
45
-    } \
46
-    stream_byte = buf[stream_ptr++];
47
-
48 41
 static av_cold int aasc_decode_init(AVCodecContext *avctx)
49 42
 {
50 43
     AascContext *s = avctx->priv_data;
... ...
@@ -84,7 +77,8 @@ static int aasc_decode_frame(AVCodecContext *avctx,
84 84
         }
85 85
         break;
86 86
     case 1:
87
-        ff_msrle_decode(avctx, (AVPicture*)&s->frame, 8, buf - 4, buf_size + 4);
87
+        bytestream2_init(&s->gb, buf - 4, buf_size + 4);
88
+        ff_msrle_decode(avctx, (AVPicture*)&s->frame, 8, &s->gb);
88 89
         break;
89 90
     default:
90 91
         av_log(avctx, AV_LOG_ERROR, "Unknown compression type %d\n", compr);
... ...
@@ -52,6 +52,7 @@ static int bmp_decode_frame(AVCodecContext *avctx,
52 52
     uint8_t *ptr;
53 53
     int dsize;
54 54
     const uint8_t *buf0 = buf;
55
+    GetByteContext gb;
55 56
 
56 57
     if(buf_size < 14){
57 58
         av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size);
... ...
@@ -265,7 +266,8 @@ static int bmp_decode_frame(AVCodecContext *avctx,
265 265
             p->data[0] += p->linesize[0] * (avctx->height - 1);
266 266
             p->linesize[0] = -p->linesize[0];
267 267
         }
268
-        ff_msrle_decode(avctx, (AVPicture*)p, depth, buf, dsize);
268
+        bytestream2_init(&gb, buf, dsize);
269
+        ff_msrle_decode(avctx, (AVPicture*)p, depth, &gb);
269 270
         if(height < 0){
270 271
             p->data[0] += p->linesize[0] * (avctx->height - 1);
271 272
             p->linesize[0] = -p->linesize[0];
... ...
@@ -40,6 +40,7 @@ typedef struct MsrleContext {
40 40
     AVCodecContext *avctx;
41 41
     AVFrame frame;
42 42
 
43
+    GetByteContext gb;
43 44
     const unsigned char *buf;
44 45
     int size;
45 46
 
... ...
@@ -123,7 +124,8 @@ static int msrle_decode_frame(AVCodecContext *avctx,
123 123
             ptr += s->frame.linesize[0];
124 124
         }
125 125
     } else {
126
-        ff_msrle_decode(avctx, (AVPicture*)&s->frame, avctx->bits_per_coded_sample, buf, buf_size);
126
+        bytestream2_init(&s->gb, buf, buf_size);
127
+        ff_msrle_decode(avctx, (AVPicture*)&s->frame, avctx->bits_per_coded_sample, &s->gb);
127 128
     }
128 129
 
129 130
     *data_size = sizeof(AVFrame);
... ...
@@ -30,18 +30,9 @@
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,11 +43,16 @@ static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
52 52
     int i;
53 53
 
54 54
     while (row_ptr >= 0) {
55
-        FETCH_NEXT_STREAM_BYTE();
56
-        rle_code = stream_byte;
55
+        if (bytestream2_get_bytes_left(gb) <= 0) {
56
+            av_log(avctx, AV_LOG_ERROR,
57
+                   "MS RLE: bytestream overrun, %d rows left\n",
58
+                   row_ptr);
59
+            return AVERROR_INVALIDDATA;
60
+        }
61
+        rle_code = stream_byte = bytestream2_get_byteu(gb);
57 62
         if (rle_code == 0) {
58 63
             /* fetch the next byte to see how to handle escape code */
59
-            FETCH_NEXT_STREAM_BYTE();
64
+            stream_byte = bytestream2_get_byte(gb);
60 65
             if (stream_byte == 0) {
61 66
                 /* line is done, goto the next one */
62 67
                 row_ptr -= row_dec;
... ...
@@ -66,24 +62,26 @@ static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
66 66
                 return 0;
67 67
             } else if (stream_byte == 2) {
68 68
                 /* reposition frame decode coordinates */
69
-                FETCH_NEXT_STREAM_BYTE();
69
+                stream_byte = bytestream2_get_byte(gb);
70 70
                 pixel_ptr += stream_byte;
71
-                FETCH_NEXT_STREAM_BYTE();
71
+                stream_byte = bytestream2_get_byte(gb);
72 72
                 row_ptr -= stream_byte * row_dec;
73 73
             } else {
74 74
                 // copy pixels from encoded stream
75 75
                 odd_pixel =  stream_byte & 1;
76 76
                 rle_code = (stream_byte + 1) / 2;
77 77
                 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;
78
+                if (row_ptr + pixel_ptr + stream_byte > frame_size ||
79
+                    bytestream2_get_bytes_left(gb) < rle_code) {
80
+                    av_log(avctx, AV_LOG_ERROR,
81
+                           "MS RLE: frame/stream ptr just went out of bounds (copy)\n");
82
+                    return AVERROR_INVALIDDATA;
81 83
                 }
82 84
 
83 85
                 for (i = 0; i < rle_code; i++) {
84 86
                     if (pixel_ptr >= avctx->width)
85 87
                         break;
86
-                    FETCH_NEXT_STREAM_BYTE();
88
+                    stream_byte = bytestream2_get_byteu(gb);
87 89
                     pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
88 90
                     pixel_ptr++;
89 91
                     if (i + 1 == rle_code && odd_pixel)
... ...
@@ -96,15 +94,16 @@ static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
96 96
 
97 97
                 // if the RLE code is odd, skip a byte in the stream
98 98
                 if (extra_byte)
99
-                    stream_ptr++;
99
+                    bytestream2_skip(gb, 1);
100 100
             }
101 101
         } else {
102 102
             // decode a run of data
103 103
             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;
104
+                av_log(avctx, AV_LOG_ERROR,
105
+                       "MS RLE: frame ptr just went out of bounds (run)\n");
106
+                return AVERROR_INVALIDDATA;
106 107
             }
107
-            FETCH_NEXT_STREAM_BYTE();
108
+            stream_byte = bytestream2_get_byte(gb);
108 109
             for (i = 0; i < rle_code; i++) {
109 110
                 if (pixel_ptr >= avctx->width)
110 111
                     break;
... ...
@@ -118,21 +117,21 @@ static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
118 118
     }
119 119
 
120 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;
121
+    if (bytestream2_get_bytes_left(gb)) {
122
+        av_log(avctx, AV_LOG_ERROR,
123
+               "MS RLE: ended frame decode with %d bytes left over\n",
124
+               bytestream2_get_bytes_left(gb));
125
+        return AVERROR_INVALIDDATA;
125 126
     }
126 127
 
127 128
     return 0;
128 129
 }
129 130
 
130 131
 
131
-static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int depth,
132
-                                    const uint8_t *data, int srcsize)
132
+static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic,
133
+                                   int depth, GetByteContext *gb)
133 134
 {
134 135
     uint8_t *output, *output_end;
135
-    const uint8_t* src = data;
136 136
     int p1, p2, line=avctx->height - 1, pos=0, i;
137 137
     uint16_t pix16;
138 138
     uint32_t pix32;
... ...
@@ -140,23 +139,29 @@ static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int de
140 140
 
141 141
     output     = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
142 142
     output_end = pic->data[0] +  avctx->height      * pic->linesize[0];
143
-    while(src < data + srcsize) {
144
-        p1 = *src++;
143
+    while (bytestream2_get_bytes_left(gb) > 0) {
144
+        p1 = bytestream2_get_byteu(gb);
145 145
         if(p1 == 0) { //Escape code
146
-            p2 = *src++;
146
+            p2 = bytestream2_get_byte(gb);
147 147
             if(p2 == 0) { //End-of-line
148 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;
149
+                if (line < 0) {
150
+                    if (bytestream2_get_be16(gb) == 1) { // end-of-picture
151
+                        return 0;
152
+                    } else {
153
+                        av_log(avctx, AV_LOG_ERROR,
154
+                               "Next line is beyond picture bounds (%d bytes left)\n",
155
+                               bytestream2_get_bytes_left(gb));
156
+                        return AVERROR_INVALIDDATA;
157
+                    }
152 158
                 }
153 159
                 pos = 0;
154 160
                 continue;
155 161
             } else if(p2 == 1) { //End-of-picture
156 162
                 return 0;
157 163
             } else if(p2 == 2) { //Skip
158
-                p1 = *src++;
159
-                p2 = *src++;
164
+                p1 = bytestream2_get_byte(gb);
165
+                p2 = bytestream2_get_byte(gb);
160 166
                 line -= p2;
161 167
                 pos += p1;
162 168
                 if (line < 0 || pos >= width){
... ...
@@ -167,31 +172,31 @@ static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int de
167 167
                 continue;
168 168
             }
169 169
             // 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);
170
+            if ((pic->linesize[0] > 0 && output + p2 * (depth >> 3) > output_end) ||
171
+                (pic->linesize[0] < 0 && output + p2 * (depth >> 3) < output_end)) {
172
+                bytestream2_skip(gb, 2 * (depth >> 3));
173 173
                 continue;
174
+            } else if (bytestream2_get_bytes_left(gb) < p2 * (depth >> 3)) {
175
+                av_log(avctx, AV_LOG_ERROR, "bytestream overrun\n");
176
+                return AVERROR_INVALIDDATA;
174 177
             }
178
+
175 179
             if ((depth == 8) || (depth == 24)) {
176 180
                 for(i = 0; i < p2 * (depth >> 3); i++) {
177
-                    *output++ = *src++;
181
+                    *output++ = bytestream2_get_byteu(gb);
178 182
                 }
179 183
                 // RLE8 copy is actually padded - and runs are not!
180 184
                 if(depth == 8 && (p2 & 1)) {
181
-                    src++;
185
+                    bytestream2_skip(gb, 1);
182 186
                 }
183 187
             } else if (depth == 16) {
184 188
                 for(i = 0; i < p2; i++) {
185
-                    pix16 = AV_RL16(src);
186
-                    src += 2;
187
-                    *(uint16_t*)output = pix16;
189
+                    *(uint16_t*)output = bytestream2_get_le16u(gb);
188 190
                     output += 2;
189 191
                 }
190 192
             } else if (depth == 32) {
191 193
                 for(i = 0; i < p2; i++) {
192
-                    pix32 = AV_RL32(src);
193
-                    src += 4;
194
-                    *(uint32_t*)output = pix32;
194
+                    *(uint32_t*)output = bytestream2_get_le32u(gb);
195 195
                     output += 4;
196 196
                 }
197 197
             }
... ...
@@ -199,21 +204,19 @@ static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int de
199 199
         } else { //run of pixels
200 200
             uint8_t pix[3]; //original pixel
201 201
             switch(depth){
202
-            case  8: pix[0] = *src++;
202
+            case  8: pix[0] = bytestream2_get_byte(gb);
203 203
                      break;
204
-            case 16: pix16 = AV_RL16(src);
205
-                     src += 2;
204
+            case 16: pix16  = bytestream2_get_le16(gb);
206 205
                      break;
207
-            case 24: pix[0] = *src++;
208
-                     pix[1] = *src++;
209
-                     pix[2] = *src++;
206
+            case 24: pix[0] = bytestream2_get_byte(gb);
207
+                     pix[1] = bytestream2_get_byte(gb);
208
+                     pix[2] = bytestream2_get_byte(gb);
210 209
                      break;
211
-            case 32: pix32 = AV_RL32(src);
212
-                     src += 4;
210
+            case 32: pix32  = bytestream2_get_le32(gb);
213 211
                      break;
214 212
             }
215
-            if ((pic->linesize[0] > 0 && output + p1 * (depth >> 3) > output_end)
216
-              ||(pic->linesize[0] < 0 && output + p1 * (depth >> 3) < output_end))
213
+            if ((pic->linesize[0] > 0 && output + p1 * (depth >> 3) > output_end) ||
214
+                (pic->linesize[0] < 0 && output + p1 * (depth >> 3) < output_end))
217 215
                 continue;
218 216
             for(i = 0; i < p1; i++) {
219 217
                 switch(depth){
... ...
@@ -240,17 +243,17 @@ static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int de
240 240
 }
241 241
 
242 242
 
243
-int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, int depth,
244
-                    const uint8_t* data, int data_size)
243
+int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic,
244
+                    int depth, GetByteContext *gb)
245 245
 {
246 246
     switch(depth){
247 247
     case  4:
248
-        return msrle_decode_pal4(avctx, pic, data, data_size);
248
+        return msrle_decode_pal4(avctx, pic, gb);
249 249
     case  8:
250 250
     case 16:
251 251
     case 24:
252 252
     case 32:
253
-        return msrle_decode_8_16_24_32(avctx, pic, depth, data, data_size);
253
+        return msrle_decode_8_16_24_32(avctx, pic, depth, gb);
254 254
     default:
255 255
         av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);
256 256
         return -1;
... ...
@@ -23,6 +23,7 @@
23 23
 #define AVCODEC_MSRLEDEC_H
24 24
 
25 25
 #include "avcodec.h"
26
+#include "bytestream.h"
26 27
 
27 28
 /**
28 29
  * Decode stream in MS RLE format into frame.
... ...
@@ -30,10 +31,9 @@
30 30
  * @param avctx     codec context
31 31
  * @param pic       destination frame
32 32
  * @param depth     bit depth
33
- * @param data      input stream
34
- * @param data_size input size
33
+ * @param gb        input bytestream context
35 34
  */
36
-int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, int depth,
37
-                    const uint8_t* data, int data_size);
35
+int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic,
36
+                    int depth, GetByteContext *gb);
38 37
 
39 38
 #endif /* AVCODEC_MSRLEDEC_H */
... ...
@@ -58,6 +58,7 @@ typedef struct TsccContext {
58 58
     unsigned int decomp_size;
59 59
     // Decompression buffer
60 60
     unsigned char* decomp_buf;
61
+    GetByteContext gb;
61 62
     int height;
62 63
     z_stream zstream;
63 64
 
... ...
@@ -105,8 +106,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
105 105
     }
106 106
 
107 107
 
108
-    if(zret != Z_DATA_ERROR)
109
-        ff_msrle_decode(avctx, (AVPicture*)&c->pic, c->bpp, c->decomp_buf, c->decomp_size - c->zstream.avail_out);
108
+    if (zret != Z_DATA_ERROR) {
109
+        bytestream2_init(&c->gb, c->decomp_buf,
110
+                         c->decomp_size - c->zstream.avail_out);
111
+        ff_msrle_decode(avctx, (AVPicture*)&c->pic, c->bpp, &c->gb);
112
+    }
110 113
 
111 114
     /* make the palette available on the way out */
112 115
     if (c->avctx->pix_fmt == PIX_FMT_PAL8) {