Mercurial > audlegacy-plugins
comparison src/ffmpeg/libavcodec/msrle.c @ 808:e8776388b02a trunk
[svn] - add ffmpeg
author | nenolod |
---|---|
date | Mon, 12 Mar 2007 11:18:54 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
807:0f9c8d4d3ac4 | 808:e8776388b02a |
---|---|
1 /* | |
2 * Micrsoft RLE Video Decoder | |
3 * Copyright (C) 2003 the ffmpeg project | |
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 msrle.c | |
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/ | |
27 * | |
28 * The MS RLE decoder outputs PAL8 colorspace data. | |
29 * | |
30 * Note that this decoder expects the palette colors from the end of the | |
31 * BITMAPINFO header passed through palctrl. | |
32 */ | |
33 | |
34 #include <stdio.h> | |
35 #include <stdlib.h> | |
36 #include <string.h> | |
37 #include <unistd.h> | |
38 | |
39 #include "common.h" | |
40 #include "avcodec.h" | |
41 #include "dsputil.h" | |
42 | |
43 typedef struct MsrleContext { | |
44 AVCodecContext *avctx; | |
45 AVFrame frame; | |
46 | |
47 unsigned char *buf; | |
48 int size; | |
49 | |
50 } MsrleContext; | |
51 | |
52 #define FETCH_NEXT_STREAM_BYTE() \ | |
53 if (stream_ptr >= s->size) \ | |
54 { \ | |
55 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \ | |
56 return; \ | |
57 } \ | |
58 stream_byte = s->buf[stream_ptr++]; | |
59 | |
60 static void msrle_decode_pal4(MsrleContext *s) | |
61 { | |
62 int stream_ptr = 0; | |
63 unsigned char rle_code; | |
64 unsigned char extra_byte, odd_pixel; | |
65 unsigned char stream_byte; | |
66 int pixel_ptr = 0; | |
67 int row_dec = s->frame.linesize[0]; | |
68 int row_ptr = (s->avctx->height - 1) * row_dec; | |
69 int frame_size = row_dec * s->avctx->height; | |
70 int i; | |
71 | |
72 /* make the palette available */ | |
73 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); | |
74 if (s->avctx->palctrl->palette_changed) { | |
75 s->frame.palette_has_changed = 1; | |
76 s->avctx->palctrl->palette_changed = 0; | |
77 } | |
78 | |
79 while (row_ptr >= 0) { | |
80 FETCH_NEXT_STREAM_BYTE(); | |
81 rle_code = stream_byte; | |
82 if (rle_code == 0) { | |
83 /* fetch the next byte to see how to handle escape code */ | |
84 FETCH_NEXT_STREAM_BYTE(); | |
85 if (stream_byte == 0) { | |
86 /* line is done, goto the next one */ | |
87 row_ptr -= row_dec; | |
88 pixel_ptr = 0; | |
89 } else if (stream_byte == 1) { | |
90 /* decode is done */ | |
91 return; | |
92 } else if (stream_byte == 2) { | |
93 /* reposition frame decode coordinates */ | |
94 FETCH_NEXT_STREAM_BYTE(); | |
95 pixel_ptr += stream_byte; | |
96 FETCH_NEXT_STREAM_BYTE(); | |
97 row_ptr -= stream_byte * row_dec; | |
98 } else { | |
99 // copy pixels from encoded stream | |
100 odd_pixel = stream_byte & 1; | |
101 rle_code = (stream_byte + 1) / 2; | |
102 extra_byte = rle_code & 0x01; | |
103 if ((row_ptr + pixel_ptr + stream_byte > frame_size) || | |
104 (row_ptr < 0)) { | |
105 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n"); | |
106 return; | |
107 } | |
108 | |
109 for (i = 0; i < rle_code; i++) { | |
110 if (pixel_ptr >= s->avctx->width) | |
111 break; | |
112 FETCH_NEXT_STREAM_BYTE(); | |
113 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4; | |
114 pixel_ptr++; | |
115 if (i + 1 == rle_code && odd_pixel) | |
116 break; | |
117 if (pixel_ptr >= s->avctx->width) | |
118 break; | |
119 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F; | |
120 pixel_ptr++; | |
121 } | |
122 | |
123 // if the RLE code is odd, skip a byte in the stream | |
124 if (extra_byte) | |
125 stream_ptr++; | |
126 } | |
127 } else { | |
128 // decode a run of data | |
129 if ((row_ptr + pixel_ptr + stream_byte > frame_size) || | |
130 (row_ptr < 0)) { | |
131 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n"); | |
132 return; | |
133 } | |
134 FETCH_NEXT_STREAM_BYTE(); | |
135 for (i = 0; i < rle_code; i++) { | |
136 if (pixel_ptr >= s->avctx->width) | |
137 break; | |
138 if ((i & 1) == 0) | |
139 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4; | |
140 else | |
141 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F; | |
142 pixel_ptr++; | |
143 } | |
144 } | |
145 } | |
146 | |
147 /* one last sanity check on the way out */ | |
148 if (stream_ptr < s->size) | |
149 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n", | |
150 stream_ptr, s->size); | |
151 } | |
152 | |
153 | |
154 | |
155 static void msrle_decode_pal8(MsrleContext *s) | |
156 { | |
157 int stream_ptr = 0; | |
158 unsigned char rle_code; | |
159 unsigned char extra_byte; | |
160 unsigned char stream_byte; | |
161 int pixel_ptr = 0; | |
162 int row_dec = s->frame.linesize[0]; | |
163 int row_ptr = (s->avctx->height - 1) * row_dec; | |
164 int frame_size = row_dec * s->avctx->height; | |
165 | |
166 /* make the palette available */ | |
167 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); | |
168 if (s->avctx->palctrl->palette_changed) { | |
169 s->frame.palette_has_changed = 1; | |
170 s->avctx->palctrl->palette_changed = 0; | |
171 } | |
172 | |
173 while (row_ptr >= 0) { | |
174 FETCH_NEXT_STREAM_BYTE(); | |
175 rle_code = stream_byte; | |
176 if (rle_code == 0) { | |
177 /* fetch the next byte to see how to handle escape code */ | |
178 FETCH_NEXT_STREAM_BYTE(); | |
179 if (stream_byte == 0) { | |
180 /* line is done, goto the next one */ | |
181 row_ptr -= row_dec; | |
182 pixel_ptr = 0; | |
183 } else if (stream_byte == 1) { | |
184 /* decode is done */ | |
185 return; | |
186 } else if (stream_byte == 2) { | |
187 /* reposition frame decode coordinates */ | |
188 FETCH_NEXT_STREAM_BYTE(); | |
189 pixel_ptr += stream_byte; | |
190 FETCH_NEXT_STREAM_BYTE(); | |
191 row_ptr -= stream_byte * row_dec; | |
192 } else { | |
193 /* copy pixels from encoded stream */ | |
194 if ((row_ptr + pixel_ptr + stream_byte > frame_size) || | |
195 (row_ptr < 0)) { | |
196 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n"); | |
197 return; | |
198 } | |
199 | |
200 rle_code = stream_byte; | |
201 extra_byte = stream_byte & 0x01; | |
202 if (stream_ptr + rle_code + extra_byte > s->size) { | |
203 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (2)\n"); | |
204 return; | |
205 } | |
206 | |
207 while (rle_code--) { | |
208 FETCH_NEXT_STREAM_BYTE(); | |
209 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte; | |
210 pixel_ptr++; | |
211 } | |
212 | |
213 /* if the RLE code is odd, skip a byte in the stream */ | |
214 if (extra_byte) | |
215 stream_ptr++; | |
216 } | |
217 } else { | |
218 /* decode a run of data */ | |
219 if ((row_ptr + pixel_ptr + stream_byte > frame_size) || | |
220 (row_ptr < 0)) { | |
221 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (2)\n"); | |
222 return; | |
223 } | |
224 | |
225 FETCH_NEXT_STREAM_BYTE(); | |
226 | |
227 while(rle_code--) { | |
228 s->frame.data[0][row_ptr + pixel_ptr] = stream_byte; | |
229 pixel_ptr++; | |
230 } | |
231 } | |
232 } | |
233 | |
234 /* one last sanity check on the way out */ | |
235 if (stream_ptr < s->size) | |
236 av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n", | |
237 stream_ptr, s->size); | |
238 } | |
239 | |
240 static int msrle_decode_init(AVCodecContext *avctx) | |
241 { | |
242 MsrleContext *s = (MsrleContext *)avctx->priv_data; | |
243 | |
244 s->avctx = avctx; | |
245 | |
246 avctx->pix_fmt = PIX_FMT_PAL8; | |
247 avctx->has_b_frames = 0; | |
248 s->frame.data[0] = NULL; | |
249 | |
250 return 0; | |
251 } | |
252 | |
253 static int msrle_decode_frame(AVCodecContext *avctx, | |
254 void *data, int *data_size, | |
255 uint8_t *buf, int buf_size) | |
256 { | |
257 MsrleContext *s = (MsrleContext *)avctx->priv_data; | |
258 | |
259 s->buf = buf; | |
260 s->size = buf_size; | |
261 | |
262 s->frame.reference = 1; | |
263 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | |
264 if (avctx->reget_buffer(avctx, &s->frame)) { | |
265 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |
266 return -1; | |
267 } | |
268 | |
269 switch (avctx->bits_per_sample) { | |
270 case 8: | |
271 msrle_decode_pal8(s); | |
272 break; | |
273 case 4: | |
274 msrle_decode_pal4(s); | |
275 break; | |
276 default: | |
277 av_log(avctx, AV_LOG_ERROR, "Don't know how to decode depth %u.\n", | |
278 avctx->bits_per_sample); | |
279 } | |
280 | |
281 *data_size = sizeof(AVFrame); | |
282 *(AVFrame*)data = s->frame; | |
283 | |
284 /* report that the buffer was completely consumed */ | |
285 return buf_size; | |
286 } | |
287 | |
288 static int msrle_decode_end(AVCodecContext *avctx) | |
289 { | |
290 MsrleContext *s = (MsrleContext *)avctx->priv_data; | |
291 | |
292 /* release the last frame */ | |
293 if (s->frame.data[0]) | |
294 avctx->release_buffer(avctx, &s->frame); | |
295 | |
296 return 0; | |
297 } | |
298 | |
299 AVCodec msrle_decoder = { | |
300 "msrle", | |
301 CODEC_TYPE_VIDEO, | |
302 CODEC_ID_MSRLE, | |
303 sizeof(MsrleContext), | |
304 msrle_decode_init, | |
305 NULL, | |
306 msrle_decode_end, | |
307 msrle_decode_frame, | |
308 CODEC_CAP_DR1, | |
309 }; |