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 #include <unistd.h>
00038
00039 #include "libavutil/intreadwrite.h"
00040 #include "avcodec.h"
00041
00042 typedef struct QtrleContext {
00043
00044 AVCodecContext *avctx;
00045 AVFrame frame;
00046
00047 const unsigned char *buf;
00048 int size;
00049
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 break;
00423 }
00424
00425 s->frame.data[0] = NULL;
00426
00427 return 0;
00428 }
00429
00430 static int qtrle_decode_frame(AVCodecContext *avctx,
00431 void *data, int *data_size,
00432 const uint8_t *buf, int buf_size)
00433 {
00434 QtrleContext *s = avctx->priv_data;
00435 int header, start_line;
00436 int stream_ptr, height, row_ptr;
00437 int has_palette = 0;
00438
00439 s->buf = buf;
00440 s->size = buf_size;
00441
00442 s->frame.reference = 1;
00443 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
00444 FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
00445 if (avctx->reget_buffer(avctx, &s->frame)) {
00446 av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00447 return -1;
00448 }
00449
00450
00451 if (s->size < 8)
00452 goto done;
00453
00454
00455 stream_ptr = 4;
00456
00457
00458 header = AV_RB16(&s->buf[stream_ptr]);
00459 stream_ptr += 2;
00460
00461
00462 if (header & 0x0008) {
00463 if(s->size < 14)
00464 goto done;
00465 start_line = AV_RB16(&s->buf[stream_ptr]);
00466 stream_ptr += 4;
00467 height = AV_RB16(&s->buf[stream_ptr]);
00468 stream_ptr += 4;
00469 if (height > s->avctx->height - start_line)
00470 goto done;
00471 } else {
00472 start_line = 0;
00473 height = s->avctx->height;
00474 }
00475 row_ptr = s->frame.linesize[0] * start_line;
00476
00477 switch (avctx->bits_per_coded_sample) {
00478 case 1:
00479 case 33:
00480 qtrle_decode_1bpp(s, stream_ptr, row_ptr, height);
00481 break;
00482
00483 case 2:
00484 case 34:
00485 qtrle_decode_2n4bpp(s, stream_ptr, row_ptr, height, 2);
00486 has_palette = 1;
00487 break;
00488
00489 case 4:
00490 case 36:
00491 qtrle_decode_2n4bpp(s, stream_ptr, row_ptr, height, 4);
00492 has_palette = 1;
00493 break;
00494
00495 case 8:
00496 case 40:
00497 qtrle_decode_8bpp(s, stream_ptr, row_ptr, height);
00498 has_palette = 1;
00499 break;
00500
00501 case 16:
00502 qtrle_decode_16bpp(s, stream_ptr, row_ptr, height);
00503 break;
00504
00505 case 24:
00506 qtrle_decode_24bpp(s, stream_ptr, row_ptr, height);
00507 break;
00508
00509 case 32:
00510 qtrle_decode_32bpp(s, stream_ptr, row_ptr, height);
00511 break;
00512
00513 default:
00514 av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
00515 avctx->bits_per_coded_sample);
00516 break;
00517 }
00518
00519 if(has_palette) {
00520
00521 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
00522 if (s->avctx->palctrl->palette_changed) {
00523 s->frame.palette_has_changed = 1;
00524 s->avctx->palctrl->palette_changed = 0;
00525 }
00526 }
00527
00528 done:
00529 *data_size = sizeof(AVFrame);
00530 *(AVFrame*)data = s->frame;
00531
00532
00533 return buf_size;
00534 }
00535
00536 static av_cold int qtrle_decode_end(AVCodecContext *avctx)
00537 {
00538 QtrleContext *s = avctx->priv_data;
00539
00540 if (s->frame.data[0])
00541 avctx->release_buffer(avctx, &s->frame);
00542
00543 return 0;
00544 }
00545
00546 AVCodec qtrle_decoder = {
00547 "qtrle",
00548 CODEC_TYPE_VIDEO,
00549 CODEC_ID_QTRLE,
00550 sizeof(QtrleContext),
00551 qtrle_decode_init,
00552 NULL,
00553 qtrle_decode_end,
00554 qtrle_decode_frame,
00555 CODEC_CAP_DR1,
00556 .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
00557 };
00558