Mercurial > libavcodec.hg
comparison msrle.c @ 7885:f874e1d5cf07 libavcodec
Factorize out code used for MS RLE format decoding in different decoders.
author | kostya |
---|---|
date | Thu, 18 Sep 2008 05:20:54 +0000 |
parents | 4525dcd81357 |
children | e9d9d946f213 |
comparison
equal
deleted
inserted
replaced
7884:4077df298ba2 | 7885:f874e1d5cf07 |
---|---|
36 #include <string.h> | 36 #include <string.h> |
37 #include <unistd.h> | 37 #include <unistd.h> |
38 | 38 |
39 #include "avcodec.h" | 39 #include "avcodec.h" |
40 #include "dsputil.h" | 40 #include "dsputil.h" |
41 #include "msrledec.h" | |
41 | 42 |
42 typedef struct MsrleContext { | 43 typedef struct MsrleContext { |
43 AVCodecContext *avctx; | 44 AVCodecContext *avctx; |
44 AVFrame frame; | 45 AVFrame frame; |
45 | 46 |
46 const unsigned char *buf; | 47 const unsigned char *buf; |
47 int size; | 48 int size; |
48 | 49 |
49 } MsrleContext; | 50 } MsrleContext; |
50 | |
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 | 51 |
239 static av_cold int msrle_decode_init(AVCodecContext *avctx) | 52 static av_cold int msrle_decode_init(AVCodecContext *avctx) |
240 { | 53 { |
241 MsrleContext *s = avctx->priv_data; | 54 MsrleContext *s = avctx->priv_data; |
242 | 55 |
262 if (avctx->reget_buffer(avctx, &s->frame)) { | 75 if (avctx->reget_buffer(avctx, &s->frame)) { |
263 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | 76 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); |
264 return -1; | 77 return -1; |
265 } | 78 } |
266 | 79 |
267 switch (avctx->bits_per_coded_sample) { | 80 /* make the palette available */ |
268 case 8: | 81 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); |
269 msrle_decode_pal8(s); | 82 if (s->avctx->palctrl->palette_changed) { |
270 break; | 83 s->frame.palette_has_changed = 1; |
271 case 4: | 84 s->avctx->palctrl->palette_changed = 0; |
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); | |
277 } | 85 } |
86 | |
87 ff_msrle_decode(avctx, &s->frame, avctx->bits_per_coded_sample, buf, buf_size); | |
278 | 88 |
279 *data_size = sizeof(AVFrame); | 89 *data_size = sizeof(AVFrame); |
280 *(AVFrame*)data = s->frame; | 90 *(AVFrame*)data = s->frame; |
281 | 91 |
282 /* report that the buffer was completely consumed */ | 92 /* report that the buffer was completely consumed */ |