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