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