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