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