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