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