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