Mercurial > audlegacy-plugins
comparison src/ffmpeg/libavcodec/qtrle.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 * Quicktime Animation (RLE) Video Decoder | |
3 * Copyright (C) 2004 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 /** | |
24 * @file qtrle.c | |
25 * QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net) | |
26 * For more information about the QT RLE format, visit: | |
27 * http://www.pcisys.net/~melanson/codecs/ | |
28 * | |
29 * The QT RLE decoder has seven modes of operation: | |
30 * 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8 | |
31 * the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555 | |
32 * data. 24-bit data is RGB24 and 32-bit data is RGBA32. | |
33 */ | |
34 | |
35 #include <stdio.h> | |
36 #include <stdlib.h> | |
37 #include <string.h> | |
38 #include <unistd.h> | |
39 | |
40 #include "common.h" | |
41 #include "avcodec.h" | |
42 #include "dsputil.h" | |
43 | |
44 typedef struct QtrleContext { | |
45 | |
46 AVCodecContext *avctx; | |
47 DSPContext dsp; | |
48 AVFrame frame; | |
49 | |
50 unsigned char *buf; | |
51 int size; | |
52 | |
53 } QtrleContext; | |
54 | |
55 #define CHECK_STREAM_PTR(n) \ | |
56 if ((stream_ptr + n) > s->size) { \ | |
57 av_log (s->avctx, AV_LOG_INFO, "Problem: stream_ptr out of bounds (%d >= %d)\n", \ | |
58 stream_ptr + n, s->size); \ | |
59 return; \ | |
60 } | |
61 | |
62 #define CHECK_PIXEL_PTR(n) \ | |
63 if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \ | |
64 av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr = %d, pixel_limit = %d\n", \ | |
65 pixel_ptr + n, pixel_limit); \ | |
66 return; \ | |
67 } \ | |
68 | |
69 static void qtrle_decode_1bpp(QtrleContext *s) | |
70 { | |
71 } | |
72 | |
73 static void qtrle_decode_2bpp(QtrleContext *s) | |
74 { | |
75 } | |
76 | |
77 static void qtrle_decode_4bpp(QtrleContext *s) | |
78 { | |
79 int stream_ptr; | |
80 int header; | |
81 int start_line; | |
82 int lines_to_change; | |
83 int rle_code; | |
84 int row_ptr, pixel_ptr; | |
85 int row_inc = s->frame.linesize[0]; | |
86 unsigned char pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8; /* 8 palette indices */ | |
87 unsigned char *rgb = s->frame.data[0]; | |
88 int pixel_limit = s->frame.linesize[0] * s->avctx->height; | |
89 | |
90 /* check if this frame is even supposed to change */ | |
91 if (s->size < 8) | |
92 return; | |
93 | |
94 /* start after the chunk size */ | |
95 stream_ptr = 4; | |
96 | |
97 /* fetch the header */ | |
98 CHECK_STREAM_PTR(2); | |
99 header = BE_16(&s->buf[stream_ptr]); | |
100 stream_ptr += 2; | |
101 | |
102 /* if a header is present, fetch additional decoding parameters */ | |
103 if (header & 0x0008) { | |
104 CHECK_STREAM_PTR(8); | |
105 start_line = BE_16(&s->buf[stream_ptr]); | |
106 stream_ptr += 4; | |
107 lines_to_change = BE_16(&s->buf[stream_ptr]); | |
108 stream_ptr += 4; | |
109 } else { | |
110 start_line = 0; | |
111 lines_to_change = s->avctx->height; | |
112 } | |
113 | |
114 row_ptr = row_inc * start_line; | |
115 while (lines_to_change--) { | |
116 CHECK_STREAM_PTR(2); | |
117 pixel_ptr = row_ptr + (8 * (s->buf[stream_ptr++] - 1)); | |
118 | |
119 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { | |
120 if (rle_code == 0) { | |
121 /* there's another skip code in the stream */ | |
122 CHECK_STREAM_PTR(1); | |
123 pixel_ptr += (8 * (s->buf[stream_ptr++] - 1)); | |
124 CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ | |
125 } else if (rle_code < 0) { | |
126 /* decode the run length code */ | |
127 rle_code = -rle_code; | |
128 /* get the next 4 bytes from the stream, treat them as palette | |
129 * indices, and output them rle_code times */ | |
130 CHECK_STREAM_PTR(4); | |
131 pi1 = ((s->buf[stream_ptr]) >> 4) & 0x0f; | |
132 pi2 = (s->buf[stream_ptr++]) & 0x0f; | |
133 pi3 = ((s->buf[stream_ptr]) >> 4) & 0x0f; | |
134 pi4 = (s->buf[stream_ptr++]) & 0x0f; | |
135 pi5 = ((s->buf[stream_ptr]) >> 4) & 0x0f; | |
136 pi6 = (s->buf[stream_ptr++]) & 0x0f; | |
137 pi7 = ((s->buf[stream_ptr]) >> 4) & 0x0f; | |
138 pi8 = (s->buf[stream_ptr++]) & 0x0f; | |
139 | |
140 CHECK_PIXEL_PTR(rle_code * 8); | |
141 | |
142 while (rle_code--) { | |
143 rgb[pixel_ptr++] = pi1; | |
144 rgb[pixel_ptr++] = pi2; | |
145 rgb[pixel_ptr++] = pi3; | |
146 rgb[pixel_ptr++] = pi4; | |
147 rgb[pixel_ptr++] = pi5; | |
148 rgb[pixel_ptr++] = pi6; | |
149 rgb[pixel_ptr++] = pi7; | |
150 rgb[pixel_ptr++] = pi8; | |
151 } | |
152 } else { | |
153 /* copy the same pixel directly to output 4 times */ | |
154 rle_code *= 4; | |
155 CHECK_STREAM_PTR(rle_code); | |
156 CHECK_PIXEL_PTR(rle_code*2); | |
157 | |
158 while (rle_code--) { | |
159 rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x0f; | |
160 rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x0f; | |
161 } | |
162 } | |
163 } | |
164 row_ptr += row_inc; | |
165 } | |
166 } | |
167 | |
168 static void qtrle_decode_8bpp(QtrleContext *s) | |
169 { | |
170 int stream_ptr; | |
171 int header; | |
172 int start_line; | |
173 int lines_to_change; | |
174 int rle_code; | |
175 int row_ptr, pixel_ptr; | |
176 int row_inc = s->frame.linesize[0]; | |
177 unsigned char pi1, pi2, pi3, pi4; /* 4 palette indices */ | |
178 unsigned char *rgb = s->frame.data[0]; | |
179 int pixel_limit = s->frame.linesize[0] * s->avctx->height; | |
180 | |
181 /* check if this frame is even supposed to change */ | |
182 if (s->size < 8) | |
183 return; | |
184 | |
185 /* start after the chunk size */ | |
186 stream_ptr = 4; | |
187 | |
188 /* fetch the header */ | |
189 CHECK_STREAM_PTR(2); | |
190 header = BE_16(&s->buf[stream_ptr]); | |
191 stream_ptr += 2; | |
192 | |
193 /* if a header is present, fetch additional decoding parameters */ | |
194 if (header & 0x0008) { | |
195 CHECK_STREAM_PTR(8); | |
196 start_line = BE_16(&s->buf[stream_ptr]); | |
197 stream_ptr += 4; | |
198 lines_to_change = BE_16(&s->buf[stream_ptr]); | |
199 stream_ptr += 4; | |
200 } else { | |
201 start_line = 0; | |
202 lines_to_change = s->avctx->height; | |
203 } | |
204 | |
205 row_ptr = row_inc * start_line; | |
206 while (lines_to_change--) { | |
207 CHECK_STREAM_PTR(2); | |
208 pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1)); | |
209 | |
210 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { | |
211 if (rle_code == 0) { | |
212 /* there's another skip code in the stream */ | |
213 CHECK_STREAM_PTR(1); | |
214 pixel_ptr += (4 * (s->buf[stream_ptr++] - 1)); | |
215 CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ | |
216 } else if (rle_code < 0) { | |
217 /* decode the run length code */ | |
218 rle_code = -rle_code; | |
219 /* get the next 4 bytes from the stream, treat them as palette | |
220 * indices, and output them rle_code times */ | |
221 CHECK_STREAM_PTR(4); | |
222 pi1 = s->buf[stream_ptr++]; | |
223 pi2 = s->buf[stream_ptr++]; | |
224 pi3 = s->buf[stream_ptr++]; | |
225 pi4 = s->buf[stream_ptr++]; | |
226 | |
227 CHECK_PIXEL_PTR(rle_code * 4); | |
228 | |
229 while (rle_code--) { | |
230 rgb[pixel_ptr++] = pi1; | |
231 rgb[pixel_ptr++] = pi2; | |
232 rgb[pixel_ptr++] = pi3; | |
233 rgb[pixel_ptr++] = pi4; | |
234 } | |
235 } else { | |
236 /* copy the same pixel directly to output 4 times */ | |
237 rle_code *= 4; | |
238 CHECK_STREAM_PTR(rle_code); | |
239 CHECK_PIXEL_PTR(rle_code); | |
240 | |
241 while (rle_code--) { | |
242 rgb[pixel_ptr++] = s->buf[stream_ptr++]; | |
243 } | |
244 } | |
245 } | |
246 row_ptr += row_inc; | |
247 } | |
248 } | |
249 | |
250 static void qtrle_decode_16bpp(QtrleContext *s) | |
251 { | |
252 int stream_ptr; | |
253 int header; | |
254 int start_line; | |
255 int lines_to_change; | |
256 int rle_code; | |
257 int row_ptr, pixel_ptr; | |
258 int row_inc = s->frame.linesize[0]; | |
259 unsigned short rgb16; | |
260 unsigned char *rgb = s->frame.data[0]; | |
261 int pixel_limit = s->frame.linesize[0] * s->avctx->height; | |
262 | |
263 /* check if this frame is even supposed to change */ | |
264 if (s->size < 8) | |
265 return; | |
266 | |
267 /* start after the chunk size */ | |
268 stream_ptr = 4; | |
269 | |
270 /* fetch the header */ | |
271 CHECK_STREAM_PTR(2); | |
272 header = BE_16(&s->buf[stream_ptr]); | |
273 stream_ptr += 2; | |
274 | |
275 /* if a header is present, fetch additional decoding parameters */ | |
276 if (header & 0x0008) { | |
277 CHECK_STREAM_PTR(8); | |
278 start_line = BE_16(&s->buf[stream_ptr]); | |
279 stream_ptr += 4; | |
280 lines_to_change = BE_16(&s->buf[stream_ptr]); | |
281 stream_ptr += 4; | |
282 } else { | |
283 start_line = 0; | |
284 lines_to_change = s->avctx->height; | |
285 } | |
286 | |
287 row_ptr = row_inc * start_line; | |
288 while (lines_to_change--) { | |
289 CHECK_STREAM_PTR(2); | |
290 pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2; | |
291 | |
292 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { | |
293 if (rle_code == 0) { | |
294 /* there's another skip code in the stream */ | |
295 CHECK_STREAM_PTR(1); | |
296 pixel_ptr += (s->buf[stream_ptr++] - 1) * 2; | |
297 CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ | |
298 } else if (rle_code < 0) { | |
299 /* decode the run length code */ | |
300 rle_code = -rle_code; | |
301 CHECK_STREAM_PTR(2); | |
302 rgb16 = BE_16(&s->buf[stream_ptr]); | |
303 stream_ptr += 2; | |
304 | |
305 CHECK_PIXEL_PTR(rle_code * 2); | |
306 | |
307 while (rle_code--) { | |
308 *(unsigned short *)(&rgb[pixel_ptr]) = rgb16; | |
309 pixel_ptr += 2; | |
310 } | |
311 } else { | |
312 CHECK_STREAM_PTR(rle_code * 2); | |
313 CHECK_PIXEL_PTR(rle_code * 2); | |
314 | |
315 /* copy pixels directly to output */ | |
316 while (rle_code--) { | |
317 rgb16 = BE_16(&s->buf[stream_ptr]); | |
318 stream_ptr += 2; | |
319 *(unsigned short *)(&rgb[pixel_ptr]) = rgb16; | |
320 pixel_ptr += 2; | |
321 } | |
322 } | |
323 } | |
324 row_ptr += row_inc; | |
325 } | |
326 } | |
327 | |
328 static void qtrle_decode_24bpp(QtrleContext *s) | |
329 { | |
330 int stream_ptr; | |
331 int header; | |
332 int start_line; | |
333 int lines_to_change; | |
334 int rle_code; | |
335 int row_ptr, pixel_ptr; | |
336 int row_inc = s->frame.linesize[0]; | |
337 unsigned char r, g, b; | |
338 unsigned char *rgb = s->frame.data[0]; | |
339 int pixel_limit = s->frame.linesize[0] * s->avctx->height; | |
340 | |
341 /* check if this frame is even supposed to change */ | |
342 if (s->size < 8) | |
343 return; | |
344 | |
345 /* start after the chunk size */ | |
346 stream_ptr = 4; | |
347 | |
348 /* fetch the header */ | |
349 CHECK_STREAM_PTR(2); | |
350 header = BE_16(&s->buf[stream_ptr]); | |
351 stream_ptr += 2; | |
352 | |
353 /* if a header is present, fetch additional decoding parameters */ | |
354 if (header & 0x0008) { | |
355 CHECK_STREAM_PTR(8); | |
356 start_line = BE_16(&s->buf[stream_ptr]); | |
357 stream_ptr += 4; | |
358 lines_to_change = BE_16(&s->buf[stream_ptr]); | |
359 stream_ptr += 4; | |
360 } else { | |
361 start_line = 0; | |
362 lines_to_change = s->avctx->height; | |
363 } | |
364 | |
365 row_ptr = row_inc * start_line; | |
366 while (lines_to_change--) { | |
367 CHECK_STREAM_PTR(2); | |
368 pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3; | |
369 | |
370 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { | |
371 if (rle_code == 0) { | |
372 /* there's another skip code in the stream */ | |
373 CHECK_STREAM_PTR(1); | |
374 pixel_ptr += (s->buf[stream_ptr++] - 1) * 3; | |
375 CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ | |
376 } else if (rle_code < 0) { | |
377 /* decode the run length code */ | |
378 rle_code = -rle_code; | |
379 CHECK_STREAM_PTR(3); | |
380 r = s->buf[stream_ptr++]; | |
381 g = s->buf[stream_ptr++]; | |
382 b = s->buf[stream_ptr++]; | |
383 | |
384 CHECK_PIXEL_PTR(rle_code * 3); | |
385 | |
386 while (rle_code--) { | |
387 rgb[pixel_ptr++] = r; | |
388 rgb[pixel_ptr++] = g; | |
389 rgb[pixel_ptr++] = b; | |
390 } | |
391 } else { | |
392 CHECK_STREAM_PTR(rle_code * 3); | |
393 CHECK_PIXEL_PTR(rle_code * 3); | |
394 | |
395 /* copy pixels directly to output */ | |
396 while (rle_code--) { | |
397 rgb[pixel_ptr++] = s->buf[stream_ptr++]; | |
398 rgb[pixel_ptr++] = s->buf[stream_ptr++]; | |
399 rgb[pixel_ptr++] = s->buf[stream_ptr++]; | |
400 } | |
401 } | |
402 } | |
403 row_ptr += row_inc; | |
404 } | |
405 } | |
406 | |
407 static void qtrle_decode_32bpp(QtrleContext *s) | |
408 { | |
409 int stream_ptr; | |
410 int header; | |
411 int start_line; | |
412 int lines_to_change; | |
413 int rle_code; | |
414 int row_ptr, pixel_ptr; | |
415 int row_inc = s->frame.linesize[0]; | |
416 unsigned char a, r, g, b; | |
417 unsigned int argb; | |
418 unsigned char *rgb = s->frame.data[0]; | |
419 int pixel_limit = s->frame.linesize[0] * s->avctx->height; | |
420 | |
421 /* check if this frame is even supposed to change */ | |
422 if (s->size < 8) | |
423 return; | |
424 | |
425 /* start after the chunk size */ | |
426 stream_ptr = 4; | |
427 | |
428 /* fetch the header */ | |
429 CHECK_STREAM_PTR(2); | |
430 header = BE_16(&s->buf[stream_ptr]); | |
431 stream_ptr += 2; | |
432 | |
433 /* if a header is present, fetch additional decoding parameters */ | |
434 if (header & 0x0008) { | |
435 CHECK_STREAM_PTR(8); | |
436 start_line = BE_16(&s->buf[stream_ptr]); | |
437 stream_ptr += 4; | |
438 lines_to_change = BE_16(&s->buf[stream_ptr]); | |
439 stream_ptr += 4; | |
440 } else { | |
441 start_line = 0; | |
442 lines_to_change = s->avctx->height; | |
443 } | |
444 | |
445 row_ptr = row_inc * start_line; | |
446 while (lines_to_change--) { | |
447 CHECK_STREAM_PTR(2); | |
448 pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4; | |
449 | |
450 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { | |
451 if (rle_code == 0) { | |
452 /* there's another skip code in the stream */ | |
453 CHECK_STREAM_PTR(1); | |
454 pixel_ptr += (s->buf[stream_ptr++] - 1) * 4; | |
455 CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ | |
456 } else if (rle_code < 0) { | |
457 /* decode the run length code */ | |
458 rle_code = -rle_code; | |
459 CHECK_STREAM_PTR(4); | |
460 a = s->buf[stream_ptr++]; | |
461 r = s->buf[stream_ptr++]; | |
462 g = s->buf[stream_ptr++]; | |
463 b = s->buf[stream_ptr++]; | |
464 argb = (a << 24) | (r << 16) | (g << 8) | (b << 0); | |
465 | |
466 CHECK_PIXEL_PTR(rle_code * 4); | |
467 | |
468 while (rle_code--) { | |
469 *(unsigned int *)(&rgb[pixel_ptr]) = argb; | |
470 pixel_ptr += 4; | |
471 } | |
472 } else { | |
473 CHECK_STREAM_PTR(rle_code * 4); | |
474 CHECK_PIXEL_PTR(rle_code * 4); | |
475 | |
476 /* copy pixels directly to output */ | |
477 while (rle_code--) { | |
478 a = s->buf[stream_ptr++]; | |
479 r = s->buf[stream_ptr++]; | |
480 g = s->buf[stream_ptr++]; | |
481 b = s->buf[stream_ptr++]; | |
482 argb = (a << 24) | (r << 16) | (g << 8) | (b << 0); | |
483 *(unsigned int *)(&rgb[pixel_ptr]) = argb; | |
484 pixel_ptr += 4; | |
485 } | |
486 } | |
487 } | |
488 row_ptr += row_inc; | |
489 } | |
490 } | |
491 | |
492 static int qtrle_decode_init(AVCodecContext *avctx) | |
493 { | |
494 QtrleContext *s = (QtrleContext *)avctx->priv_data; | |
495 | |
496 s->avctx = avctx; | |
497 switch (avctx->bits_per_sample) { | |
498 case 1: | |
499 case 2: | |
500 case 4: | |
501 case 8: | |
502 case 33: | |
503 case 34: | |
504 case 36: | |
505 case 40: | |
506 avctx->pix_fmt = PIX_FMT_PAL8; | |
507 break; | |
508 | |
509 case 16: | |
510 avctx->pix_fmt = PIX_FMT_RGB555; | |
511 break; | |
512 | |
513 case 24: | |
514 avctx->pix_fmt = PIX_FMT_RGB24; | |
515 break; | |
516 | |
517 case 32: | |
518 avctx->pix_fmt = PIX_FMT_RGBA32; | |
519 break; | |
520 | |
521 default: | |
522 av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n", | |
523 avctx->bits_per_sample); | |
524 break; | |
525 } | |
526 avctx->has_b_frames = 0; | |
527 dsputil_init(&s->dsp, avctx); | |
528 | |
529 s->frame.data[0] = NULL; | |
530 | |
531 return 0; | |
532 } | |
533 | |
534 static int qtrle_decode_frame(AVCodecContext *avctx, | |
535 void *data, int *data_size, | |
536 uint8_t *buf, int buf_size) | |
537 { | |
538 QtrleContext *s = (QtrleContext *)avctx->priv_data; | |
539 | |
540 s->buf = buf; | |
541 s->size = buf_size; | |
542 | |
543 s->frame.reference = 1; | |
544 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | | |
545 FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE; | |
546 if (avctx->reget_buffer(avctx, &s->frame)) { | |
547 av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |
548 return -1; | |
549 } | |
550 | |
551 switch (avctx->bits_per_sample) { | |
552 case 1: | |
553 case 33: | |
554 qtrle_decode_1bpp(s); | |
555 break; | |
556 | |
557 case 2: | |
558 case 34: | |
559 qtrle_decode_2bpp(s); | |
560 break; | |
561 | |
562 case 4: | |
563 case 36: | |
564 qtrle_decode_4bpp(s); | |
565 /* make the palette available on the way out */ | |
566 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); | |
567 if (s->avctx->palctrl->palette_changed) { | |
568 s->frame.palette_has_changed = 1; | |
569 s->avctx->palctrl->palette_changed = 0; | |
570 } | |
571 break; | |
572 | |
573 case 8: | |
574 case 40: | |
575 qtrle_decode_8bpp(s); | |
576 /* make the palette available on the way out */ | |
577 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); | |
578 if (s->avctx->palctrl->palette_changed) { | |
579 s->frame.palette_has_changed = 1; | |
580 s->avctx->palctrl->palette_changed = 0; | |
581 } | |
582 break; | |
583 | |
584 case 16: | |
585 qtrle_decode_16bpp(s); | |
586 break; | |
587 | |
588 case 24: | |
589 qtrle_decode_24bpp(s); | |
590 break; | |
591 | |
592 case 32: | |
593 qtrle_decode_32bpp(s); | |
594 break; | |
595 | |
596 default: | |
597 av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n", | |
598 avctx->bits_per_sample); | |
599 break; | |
600 } | |
601 | |
602 *data_size = sizeof(AVFrame); | |
603 *(AVFrame*)data = s->frame; | |
604 | |
605 /* always report that the buffer was completely consumed */ | |
606 return buf_size; | |
607 } | |
608 | |
609 static int qtrle_decode_end(AVCodecContext *avctx) | |
610 { | |
611 QtrleContext *s = (QtrleContext *)avctx->priv_data; | |
612 | |
613 if (s->frame.data[0]) | |
614 avctx->release_buffer(avctx, &s->frame); | |
615 | |
616 return 0; | |
617 } | |
618 | |
619 AVCodec qtrle_decoder = { | |
620 "qtrle", | |
621 CODEC_TYPE_VIDEO, | |
622 CODEC_ID_QTRLE, | |
623 sizeof(QtrleContext), | |
624 qtrle_decode_init, | |
625 NULL, | |
626 qtrle_decode_end, | |
627 qtrle_decode_frame, | |
628 CODEC_CAP_DR1, | |
629 }; | |
630 |