00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037
00038 #include "libavutil/intreadwrite.h"
00039 #include "avcodec.h"
00040
00041 typedef struct QtrleContext {
00042
00043 AVCodecContext *avctx;
00044 AVFrame frame;
00045
00046 const unsigned char *buf;
00047 int size;
00048
00049 uint32_t pal[256];
00050 } QtrleContext;
00051
00052 #define CHECK_STREAM_PTR(n) \
00053 if ((stream_ptr + n) > s->size) { \
00054 av_log (s->avctx, AV_LOG_INFO, "Problem: stream_ptr out of bounds (%d >= %d)\n", \
00055 stream_ptr + n, s->size); \
00056 return; \
00057 }
00058
00059 #define CHECK_PIXEL_PTR(n) \
00060 if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \
00061 av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr = %d, pixel_limit = %d\n", \
00062 pixel_ptr + n, pixel_limit); \
00063 return; \
00064 } \
00065
00066 static void qtrle_decode_1bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
00067 {
00068 int rle_code;
00069 int pixel_ptr = 0;
00070 int row_inc = s->frame.linesize[0];
00071 unsigned char pi0, pi1;
00072 unsigned char *rgb = s->frame.data[0];
00073 int pixel_limit = s->frame.linesize[0] * s->avctx->height;
00074 int skip;
00075
00076 while (lines_to_change) {
00077 CHECK_STREAM_PTR(2);
00078 skip = s->buf[stream_ptr++];
00079 rle_code = (signed char)s->buf[stream_ptr++];
00080 if (rle_code == 0)
00081 break;
00082 if(skip & 0x80) {
00083 lines_to_change--;
00084 row_ptr += row_inc;
00085 pixel_ptr = row_ptr + 2 * (skip & 0x7f);
00086 } else
00087 pixel_ptr += 2 * skip;
00088 CHECK_PIXEL_PTR(0);
00089
00090 if (rle_code < 0) {
00091
00092 rle_code = -rle_code;
00093
00094
00095 CHECK_STREAM_PTR(2);
00096 pi0 = s->buf[stream_ptr++];
00097 pi1 = s->buf[stream_ptr++];
00098 CHECK_PIXEL_PTR(rle_code * 2);
00099
00100 while (rle_code--) {
00101 rgb[pixel_ptr++] = pi0;
00102 rgb[pixel_ptr++] = pi1;
00103 }
00104 } else {
00105
00106 rle_code *= 2;
00107 CHECK_STREAM_PTR(rle_code);
00108 CHECK_PIXEL_PTR(rle_code);
00109
00110 while (rle_code--)
00111 rgb[pixel_ptr++] = s->buf[stream_ptr++];
00112 }
00113 }
00114 }
00115
00116 static inline void qtrle_decode_2n4bpp(QtrleContext *s, int stream_ptr,
00117 int row_ptr, int lines_to_change, int bpp)
00118 {
00119 int rle_code, i;
00120 int pixel_ptr;
00121 int row_inc = s->frame.linesize[0];
00122 unsigned char pi[16];
00123 unsigned char *rgb = s->frame.data[0];
00124 int pixel_limit = s->frame.linesize[0] * s->avctx->height;
00125 int num_pixels = (bpp == 4) ? 8 : 16;
00126
00127 while (lines_to_change--) {
00128 CHECK_STREAM_PTR(2);
00129 pixel_ptr = row_ptr + (num_pixels * (s->buf[stream_ptr++] - 1));
00130 CHECK_PIXEL_PTR(0);
00131
00132 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
00133 if (rle_code == 0) {
00134
00135 CHECK_STREAM_PTR(1);
00136 pixel_ptr += (num_pixels * (s->buf[stream_ptr++] - 1));
00137 CHECK_PIXEL_PTR(0);
00138 } else if (rle_code < 0) {
00139
00140 rle_code = -rle_code;
00141
00142
00143 CHECK_STREAM_PTR(4);
00144 for (i = num_pixels-1; i >= 0; i--) {
00145 pi[num_pixels-1-i] = (s->buf[stream_ptr] >> ((i*bpp) & 0x07)) & ((1<<bpp)-1);
00146 stream_ptr+= ((i & ((num_pixels>>2)-1)) == 0);
00147 }
00148 CHECK_PIXEL_PTR(rle_code * num_pixels);
00149 while (rle_code--) {
00150 for (i = 0; i < num_pixels; i++)
00151 rgb[pixel_ptr++] = pi[i];
00152 }
00153 } else {
00154
00155 rle_code *= 4;
00156 CHECK_STREAM_PTR(rle_code);
00157 CHECK_PIXEL_PTR(rle_code*(num_pixels>>2));
00158 while (rle_code--) {
00159 if(bpp == 4) {
00160 rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x0f;
00161 rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x0f;
00162 } else {
00163 rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 6) & 0x03;
00164 rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x03;
00165 rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 2) & 0x03;
00166 rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x03;
00167 }
00168 }
00169 }
00170 }
00171 row_ptr += row_inc;
00172 }
00173 }
00174
00175 static void qtrle_decode_8bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
00176 {
00177 int rle_code;
00178 int pixel_ptr;
00179 int row_inc = s->frame.linesize[0];
00180 unsigned char pi1, pi2, pi3, pi4;
00181 unsigned char *rgb = s->frame.data[0];
00182 int pixel_limit = s->frame.linesize[0] * s->avctx->height;
00183
00184 while (lines_to_change--) {
00185 CHECK_STREAM_PTR(2);
00186 pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1));
00187 CHECK_PIXEL_PTR(0);
00188
00189 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
00190 if (rle_code == 0) {
00191
00192 CHECK_STREAM_PTR(1);
00193 pixel_ptr += (4 * (s->buf[stream_ptr++] - 1));
00194 CHECK_PIXEL_PTR(0);
00195 } else if (rle_code < 0) {
00196
00197 rle_code = -rle_code;
00198
00199
00200 CHECK_STREAM_PTR(4);
00201 pi1 = s->buf[stream_ptr++];
00202 pi2 = s->buf[stream_ptr++];
00203 pi3 = s->buf[stream_ptr++];
00204 pi4 = s->buf[stream_ptr++];
00205
00206 CHECK_PIXEL_PTR(rle_code * 4);
00207
00208 while (rle_code--) {
00209 rgb[pixel_ptr++] = pi1;
00210 rgb[pixel_ptr++] = pi2;
00211 rgb[pixel_ptr++] = pi3;
00212 rgb[pixel_ptr++] = pi4;
00213 }
00214 } else {
00215
00216 rle_code *= 4;
00217 CHECK_STREAM_PTR(rle_code);
00218 CHECK_PIXEL_PTR(rle_code);
00219
00220 while (rle_code--) {
00221 rgb[pixel_ptr++] = s->buf[stream_ptr++];
00222 }
00223 }
00224 }
00225 row_ptr += row_inc;
00226 }
00227 }
00228
00229 static void qtrle_decode_16bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
00230 {
00231 int rle_code;
00232 int pixel_ptr;
00233 int row_inc = s->frame.linesize[0];
00234 unsigned short rgb16;
00235 unsigned char *rgb = s->frame.data[0];
00236 int pixel_limit = s->frame.linesize[0] * s->avctx->height;
00237
00238 while (lines_to_change--) {
00239 CHECK_STREAM_PTR(2);
00240 pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2;
00241 CHECK_PIXEL_PTR(0);
00242
00243 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
00244 if (rle_code == 0) {
00245
00246 CHECK_STREAM_PTR(1);
00247 pixel_ptr += (s->buf[stream_ptr++] - 1) * 2;
00248 CHECK_PIXEL_PTR(0);
00249 } else if (rle_code < 0) {
00250
00251 rle_code = -rle_code;
00252 CHECK_STREAM_PTR(2);
00253 rgb16 = AV_RB16(&s->buf[stream_ptr]);
00254 stream_ptr += 2;
00255
00256 CHECK_PIXEL_PTR(rle_code * 2);
00257
00258 while (rle_code--) {
00259 *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
00260 pixel_ptr += 2;
00261 }
00262 } else {
00263 CHECK_STREAM_PTR(rle_code * 2);
00264 CHECK_PIXEL_PTR(rle_code * 2);
00265
00266
00267 while (rle_code--) {
00268 rgb16 = AV_RB16(&s->buf[stream_ptr]);
00269 stream_ptr += 2;
00270 *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
00271 pixel_ptr += 2;
00272 }
00273 }
00274 }
00275 row_ptr += row_inc;
00276 }
00277 }
00278
00279 static void qtrle_decode_24bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
00280 {
00281 int rle_code;
00282 int pixel_ptr;
00283 int row_inc = s->frame.linesize[0];
00284 unsigned char r, g, b;
00285 unsigned char *rgb = s->frame.data[0];
00286 int pixel_limit = s->frame.linesize[0] * s->avctx->height;
00287
00288 while (lines_to_change--) {
00289 CHECK_STREAM_PTR(2);
00290 pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3;
00291 CHECK_PIXEL_PTR(0);
00292
00293 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
00294 if (rle_code == 0) {
00295
00296 CHECK_STREAM_PTR(1);
00297 pixel_ptr += (s->buf[stream_ptr++] - 1) * 3;
00298 CHECK_PIXEL_PTR(0);
00299 } else if (rle_code < 0) {
00300
00301 rle_code = -rle_code;
00302 CHECK_STREAM_PTR(3);
00303 r = s->buf[stream_ptr++];
00304 g = s->buf[stream_ptr++];
00305 b = s->buf[stream_ptr++];
00306
00307 CHECK_PIXEL_PTR(rle_code * 3);
00308
00309 while (rle_code--) {
00310 rgb[pixel_ptr++] = r;
00311 rgb[pixel_ptr++] = g;
00312 rgb[pixel_ptr++] = b;
00313 }
00314 } else {
00315 CHECK_STREAM_PTR(rle_code * 3);
00316 CHECK_PIXEL_PTR(rle_code * 3);
00317
00318
00319 while (rle_code--) {
00320 rgb[pixel_ptr++] = s->buf[stream_ptr++];
00321 rgb[pixel_ptr++] = s->buf[stream_ptr++];
00322 rgb[pixel_ptr++] = s->buf[stream_ptr++];
00323 }
00324 }
00325 }
00326 row_ptr += row_inc;
00327 }
00328 }
00329
00330 static void qtrle_decode_32bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
00331 {
00332 int rle_code;
00333 int pixel_ptr;
00334 int row_inc = s->frame.linesize[0];
00335 unsigned char a, r, g, b;
00336 unsigned int argb;
00337 unsigned char *rgb = s->frame.data[0];
00338 int pixel_limit = s->frame.linesize[0] * s->avctx->height;
00339
00340 while (lines_to_change--) {
00341 CHECK_STREAM_PTR(2);
00342 pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4;
00343 CHECK_PIXEL_PTR(0);
00344
00345 while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
00346 if (rle_code == 0) {
00347
00348 CHECK_STREAM_PTR(1);
00349 pixel_ptr += (s->buf[stream_ptr++] - 1) * 4;
00350 CHECK_PIXEL_PTR(0);
00351 } else if (rle_code < 0) {
00352
00353 rle_code = -rle_code;
00354 CHECK_STREAM_PTR(4);
00355 a = s->buf[stream_ptr++];
00356 r = s->buf[stream_ptr++];
00357 g = s->buf[stream_ptr++];
00358 b = s->buf[stream_ptr++];
00359 argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);
00360
00361 CHECK_PIXEL_PTR(rle_code * 4);
00362
00363 while (rle_code--) {
00364 *(unsigned int *)(&rgb[pixel_ptr]) = argb;
00365 pixel_ptr += 4;
00366 }
00367 } else {
00368 CHECK_STREAM_PTR(rle_code * 4);
00369 CHECK_PIXEL_PTR(rle_code * 4);
00370
00371
00372 while (rle_code--) {
00373 a = s->buf[stream_ptr++];
00374 r = s->buf[stream_ptr++];
00375 g = s->buf[stream_ptr++];
00376 b = s->buf[stream_ptr++];
00377 argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);
00378 *(unsigned int *)(&rgb[pixel_ptr]) = argb;
00379 pixel_ptr += 4;
00380 }
00381 }
00382 }
00383 row_ptr += row_inc;
00384 }
00385 }
00386
00387 static av_cold int qtrle_decode_init(AVCodecContext *avctx)
00388 {
00389 QtrleContext *s = avctx->priv_data;
00390
00391 s->avctx = avctx;
00392 switch (avctx->bits_per_coded_sample) {
00393 case 1:
00394 case 33:
00395 avctx->pix_fmt = PIX_FMT_MONOWHITE;
00396 break;
00397
00398 case 2:
00399 case 4:
00400 case 8:
00401 case 34:
00402 case 36:
00403 case 40:
00404 avctx->pix_fmt = PIX_FMT_PAL8;
00405 break;
00406
00407 case 16:
00408 avctx->pix_fmt = PIX_FMT_RGB555;
00409 break;
00410
00411 case 24:
00412 avctx->pix_fmt = PIX_FMT_RGB24;
00413 break;
00414
00415 case 32:
00416 avctx->pix_fmt = PIX_FMT_RGB32;
00417 break;
00418
00419 default:
00420 av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
00421 avctx->bits_per_coded_sample);
00422 return AVERROR_INVALIDDATA;
00423 }
00424
00425 avcodec_get_frame_defaults(&s->frame);
00426 s->frame.data[0] = NULL;
00427
00428 return 0;
00429 }
00430
00431 static int qtrle_decode_frame(AVCodecContext *avctx,
00432 void *data, int *data_size,
00433 AVPacket *avpkt)
00434 {
00435 const uint8_t *buf = avpkt->data;
00436 int buf_size = avpkt->size;
00437 QtrleContext *s = avctx->priv_data;
00438 int header, start_line;
00439 int stream_ptr, height, row_ptr;
00440 int has_palette = 0;
00441
00442 s->buf = buf;
00443 s->size = buf_size;
00444
00445 s->frame.reference = 1;
00446 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
00447 FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
00448 if (avctx->reget_buffer(avctx, &s->frame)) {
00449 av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00450 return -1;
00451 }
00452
00453
00454 if (s->size < 8)
00455 goto done;
00456
00457
00458 stream_ptr = 4;
00459
00460
00461 header = AV_RB16(&s->buf[stream_ptr]);
00462 stream_ptr += 2;
00463
00464
00465 if (header & 0x0008) {
00466 if(s->size < 14)
00467 goto done;
00468 start_line = AV_RB16(&s->buf[stream_ptr]);
00469 stream_ptr += 4;
00470 height = AV_RB16(&s->buf[stream_ptr]);
00471 stream_ptr += 4;
00472 if (height > s->avctx->height - start_line)
00473 goto done;
00474 } else {
00475 start_line = 0;
00476 height = s->avctx->height;
00477 }
00478 row_ptr = s->frame.linesize[0] * start_line;
00479
00480 switch (avctx->bits_per_coded_sample) {
00481 case 1:
00482 case 33:
00483 qtrle_decode_1bpp(s, stream_ptr, row_ptr, height);
00484 break;
00485
00486 case 2:
00487 case 34:
00488 qtrle_decode_2n4bpp(s, stream_ptr, row_ptr, height, 2);
00489 has_palette = 1;
00490 break;
00491
00492 case 4:
00493 case 36:
00494 qtrle_decode_2n4bpp(s, stream_ptr, row_ptr, height, 4);
00495 has_palette = 1;
00496 break;
00497
00498 case 8:
00499 case 40:
00500 qtrle_decode_8bpp(s, stream_ptr, row_ptr, height);
00501 has_palette = 1;
00502 break;
00503
00504 case 16:
00505 qtrle_decode_16bpp(s, stream_ptr, row_ptr, height);
00506 break;
00507
00508 case 24:
00509 qtrle_decode_24bpp(s, stream_ptr, row_ptr, height);
00510 break;
00511
00512 case 32:
00513 qtrle_decode_32bpp(s, stream_ptr, row_ptr, height);
00514 break;
00515
00516 default:
00517 av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
00518 avctx->bits_per_coded_sample);
00519 break;
00520 }
00521
00522 if(has_palette) {
00523 const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
00524
00525 if (pal) {
00526 s->frame.palette_has_changed = 1;
00527 memcpy(s->pal, pal, AVPALETTE_SIZE);
00528 }
00529
00530
00531 memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
00532 }
00533
00534 done:
00535 *data_size = sizeof(AVFrame);
00536 *(AVFrame*)data = s->frame;
00537
00538
00539 return buf_size;
00540 }
00541
00542 static av_cold int qtrle_decode_end(AVCodecContext *avctx)
00543 {
00544 QtrleContext *s = avctx->priv_data;
00545
00546 if (s->frame.data[0])
00547 avctx->release_buffer(avctx, &s->frame);
00548
00549 return 0;
00550 }
00551
00552 AVCodec ff_qtrle_decoder = {
00553 "qtrle",
00554 AVMEDIA_TYPE_VIDEO,
00555 CODEC_ID_QTRLE,
00556 sizeof(QtrleContext),
00557 qtrle_decode_init,
00558 NULL,
00559 qtrle_decode_end,
00560 qtrle_decode_frame,
00561 CODEC_CAP_DR1,
00562 .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
00563 };
00564