00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040
00041 #include "avcodec.h"
00042 #include "bytestream.h"
00043 #include "dsputil.h"
00044 #define ALT_BITSTREAM_READER_LE
00045 #include "get_bits.h"
00046
00047 #define PALETTE_COUNT 256
00048
00049 typedef struct IpvideoContext {
00050
00051 AVCodecContext *avctx;
00052 DSPContext dsp;
00053 AVFrame second_last_frame;
00054 AVFrame last_frame;
00055 AVFrame current_frame;
00056 const unsigned char *decoding_map;
00057 int decoding_map_size;
00058
00059 const unsigned char *buf;
00060 int size;
00061
00062 int is_16bpp;
00063 const unsigned char *stream_ptr;
00064 const unsigned char *stream_end;
00065 const uint8_t *mv_ptr;
00066 const uint8_t *mv_end;
00067 unsigned char *pixel_ptr;
00068 int line_inc;
00069 int stride;
00070 int upper_motion_limit_offset;
00071
00072 uint32_t pal[256];
00073 } IpvideoContext;
00074
00075 #define CHECK_STREAM_PTR(stream_ptr, stream_end, n) \
00076 if (stream_end - stream_ptr < n) { \
00077 av_log(s->avctx, AV_LOG_ERROR, "Interplay video warning: stream_ptr out of bounds (%p >= %p)\n", \
00078 stream_ptr + n, stream_end); \
00079 return -1; \
00080 }
00081
00082 static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y)
00083 {
00084 int current_offset = s->pixel_ptr - s->current_frame.data[0];
00085 int motion_offset = current_offset + delta_y * s->current_frame.linesize[0]
00086 + delta_x * (1 + s->is_16bpp);
00087 if (motion_offset < 0) {
00088 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset);
00089 return -1;
00090 } else if (motion_offset > s->upper_motion_limit_offset) {
00091 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n",
00092 motion_offset, s->upper_motion_limit_offset);
00093 return -1;
00094 }
00095 if (src->data[0] == NULL) {
00096 av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n");
00097 return AVERROR(EINVAL);
00098 }
00099 s->dsp.put_pixels_tab[!s->is_16bpp][0](s->pixel_ptr, src->data[0] + motion_offset,
00100 s->current_frame.linesize[0], 8);
00101 return 0;
00102 }
00103
00104 static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s)
00105 {
00106 return copy_from(s, &s->last_frame, 0, 0);
00107 }
00108
00109 static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s)
00110 {
00111 return copy_from(s, &s->second_last_frame, 0, 0);
00112 }
00113
00114 static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s)
00115 {
00116 unsigned char B;
00117 int x, y;
00118
00119
00120 if (!s->is_16bpp) {
00121 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
00122 B = *s->stream_ptr++;
00123 } else {
00124 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
00125 B = *s->mv_ptr++;
00126 }
00127
00128 if (B < 56) {
00129 x = 8 + (B % 7);
00130 y = B / 7;
00131 } else {
00132 x = -14 + ((B - 56) % 29);
00133 y = 8 + ((B - 56) / 29);
00134 }
00135
00136 av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
00137 return copy_from(s, &s->second_last_frame, x, y);
00138 }
00139
00140 static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
00141 {
00142 unsigned char B;
00143 int x, y;
00144
00145
00146
00147
00148 if (!s->is_16bpp) {
00149 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
00150 B = *s->stream_ptr++;
00151 } else {
00152 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
00153 B = *s->mv_ptr++;
00154 }
00155
00156 if (B < 56) {
00157 x = -(8 + (B % 7));
00158 y = -(B / 7);
00159 } else {
00160 x = -(-14 + ((B - 56) % 29));
00161 y = -( 8 + ((B - 56) / 29));
00162 }
00163
00164 av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
00165 return copy_from(s, &s->current_frame, x, y);
00166 }
00167
00168 static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
00169 {
00170 int x, y;
00171 unsigned char B, BL, BH;
00172
00173
00174 if (!s->is_16bpp) {
00175 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
00176 B = *s->stream_ptr++;
00177 } else {
00178 CHECK_STREAM_PTR(s->mv_ptr, s->mv_end, 1);
00179 B = *s->mv_ptr++;
00180 }
00181
00182 BL = B & 0x0F;
00183 BH = (B >> 4) & 0x0F;
00184 x = -8 + BL;
00185 y = -8 + BH;
00186
00187 av_dlog(NULL, " motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
00188 return copy_from(s, &s->last_frame, x, y);
00189 }
00190
00191 static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
00192 {
00193 signed char x, y;
00194
00195
00196
00197 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
00198
00199 x = *s->stream_ptr++;
00200 y = *s->stream_ptr++;
00201
00202 av_dlog(NULL, " motion bytes = %d, %d\n", x, y);
00203 return copy_from(s, &s->last_frame, x, y);
00204 }
00205
00206 static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
00207 {
00208
00209 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: Help! Mystery opcode 0x6 seen\n");
00210
00211
00212 return 0;
00213 }
00214
00215 static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s)
00216 {
00217 int x, y;
00218 unsigned char P[2];
00219 unsigned int flags;
00220
00221
00222 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
00223
00224 P[0] = *s->stream_ptr++;
00225 P[1] = *s->stream_ptr++;
00226
00227 if (P[0] <= P[1]) {
00228
00229
00230 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
00231
00232 for (y = 0; y < 8; y++) {
00233 flags = *s->stream_ptr++ | 0x100;
00234 for (; flags != 1; flags >>= 1)
00235 *s->pixel_ptr++ = P[flags & 1];
00236 s->pixel_ptr += s->line_inc;
00237 }
00238
00239 } else {
00240
00241
00242 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
00243
00244 flags = bytestream_get_le16(&s->stream_ptr);
00245 for (y = 0; y < 8; y += 2) {
00246 for (x = 0; x < 8; x += 2, flags >>= 1) {
00247 s->pixel_ptr[x ] =
00248 s->pixel_ptr[x + 1 ] =
00249 s->pixel_ptr[x + s->stride] =
00250 s->pixel_ptr[x + 1 + s->stride] = P[flags & 1];
00251 }
00252 s->pixel_ptr += s->stride * 2;
00253 }
00254 }
00255
00256
00257 return 0;
00258 }
00259
00260 static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s)
00261 {
00262 int x, y;
00263 unsigned char P[2];
00264 unsigned int flags = 0;
00265
00266
00267
00268 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
00269
00270 P[0] = *s->stream_ptr++;
00271 P[1] = *s->stream_ptr++;
00272
00273 if (P[0] <= P[1]) {
00274
00275 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 14);
00276 s->stream_ptr -= 2;
00277
00278 for (y = 0; y < 16; y++) {
00279
00280 if (!(y & 3)) {
00281 P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
00282 flags = bytestream_get_le16(&s->stream_ptr);
00283 }
00284
00285 for (x = 0; x < 4; x++, flags >>= 1)
00286 *s->pixel_ptr++ = P[flags & 1];
00287 s->pixel_ptr += s->stride - 4;
00288
00289 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
00290 }
00291
00292 } else {
00293
00294
00295 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 10);
00296
00297 if (s->stream_ptr[4] <= s->stream_ptr[5]) {
00298
00299 flags = bytestream_get_le32(&s->stream_ptr);
00300
00301
00302
00303 for (y = 0; y < 16; y++) {
00304 for (x = 0; x < 4; x++, flags >>= 1)
00305 *s->pixel_ptr++ = P[flags & 1];
00306 s->pixel_ptr += s->stride - 4;
00307
00308 if (y == 7) {
00309 s->pixel_ptr -= 8 * s->stride - 4;
00310 P[0] = *s->stream_ptr++; P[1] = *s->stream_ptr++;
00311 flags = bytestream_get_le32(&s->stream_ptr);
00312 }
00313 }
00314
00315 } else {
00316
00317
00318
00319 for (y = 0; y < 8; y++) {
00320 if (y == 4) {
00321 P[0] = *s->stream_ptr++;
00322 P[1] = *s->stream_ptr++;
00323 }
00324 flags = *s->stream_ptr++ | 0x100;
00325
00326 for (; flags != 1; flags >>= 1)
00327 *s->pixel_ptr++ = P[flags & 1];
00328 s->pixel_ptr += s->line_inc;
00329 }
00330 }
00331 }
00332
00333
00334 return 0;
00335 }
00336
00337 static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s)
00338 {
00339 int x, y;
00340 unsigned char P[4];
00341
00342
00343 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
00344
00345 memcpy(P, s->stream_ptr, 4);
00346 s->stream_ptr += 4;
00347
00348 if (P[0] <= P[1]) {
00349 if (P[2] <= P[3]) {
00350
00351
00352 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
00353
00354 for (y = 0; y < 8; y++) {
00355
00356 int flags = bytestream_get_le16(&s->stream_ptr);
00357 for (x = 0; x < 8; x++, flags >>= 2)
00358 *s->pixel_ptr++ = P[flags & 0x03];
00359 s->pixel_ptr += s->line_inc;
00360 }
00361
00362 } else {
00363 uint32_t flags;
00364
00365
00366 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
00367
00368 flags = bytestream_get_le32(&s->stream_ptr);
00369
00370 for (y = 0; y < 8; y += 2) {
00371 for (x = 0; x < 8; x += 2, flags >>= 2) {
00372 s->pixel_ptr[x ] =
00373 s->pixel_ptr[x + 1 ] =
00374 s->pixel_ptr[x + s->stride] =
00375 s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
00376 }
00377 s->pixel_ptr += s->stride * 2;
00378 }
00379
00380 }
00381 } else {
00382 uint64_t flags;
00383
00384
00385 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
00386
00387 flags = bytestream_get_le64(&s->stream_ptr);
00388 if (P[2] <= P[3]) {
00389 for (y = 0; y < 8; y++) {
00390 for (x = 0; x < 8; x += 2, flags >>= 2) {
00391 s->pixel_ptr[x ] =
00392 s->pixel_ptr[x + 1] = P[flags & 0x03];
00393 }
00394 s->pixel_ptr += s->stride;
00395 }
00396 } else {
00397 for (y = 0; y < 8; y += 2) {
00398 for (x = 0; x < 8; x++, flags >>= 2) {
00399 s->pixel_ptr[x ] =
00400 s->pixel_ptr[x + s->stride] = P[flags & 0x03];
00401 }
00402 s->pixel_ptr += s->stride * 2;
00403 }
00404 }
00405 }
00406
00407
00408 return 0;
00409 }
00410
00411 static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)
00412 {
00413 int x, y;
00414 unsigned char P[4];
00415 int flags = 0;
00416
00417
00418
00419 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
00420
00421 if (s->stream_ptr[0] <= s->stream_ptr[1]) {
00422
00423
00424 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
00425
00426 for (y = 0; y < 16; y++) {
00427
00428 if (!(y & 3)) {
00429 memcpy(P, s->stream_ptr, 4);
00430 s->stream_ptr += 4;
00431 flags = bytestream_get_le32(&s->stream_ptr);
00432 }
00433
00434 for (x = 0; x < 4; x++, flags >>= 2)
00435 *s->pixel_ptr++ = P[flags & 0x03];
00436
00437 s->pixel_ptr += s->stride - 4;
00438
00439 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
00440 }
00441
00442 } else {
00443
00444 int vert = s->stream_ptr[12] <= s->stream_ptr[13];
00445 uint64_t flags = 0;
00446
00447
00448
00449
00450 for (y = 0; y < 16; y++) {
00451
00452 if (!(y & 7)) {
00453 memcpy(P, s->stream_ptr, 4);
00454 s->stream_ptr += 4;
00455 flags = bytestream_get_le64(&s->stream_ptr);
00456 }
00457
00458 for (x = 0; x < 4; x++, flags >>= 2)
00459 *s->pixel_ptr++ = P[flags & 0x03];
00460
00461 if (vert) {
00462 s->pixel_ptr += s->stride - 4;
00463
00464 if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;
00465 } else if (y & 1) s->pixel_ptr += s->line_inc;
00466 }
00467 }
00468
00469
00470 return 0;
00471 }
00472
00473 static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s)
00474 {
00475 int y;
00476
00477
00478 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 64);
00479
00480 for (y = 0; y < 8; y++) {
00481 memcpy(s->pixel_ptr, s->stream_ptr, 8);
00482 s->stream_ptr += 8;
00483 s->pixel_ptr += s->stride;
00484 }
00485
00486
00487 return 0;
00488 }
00489
00490 static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s)
00491 {
00492 int x, y;
00493
00494
00495 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
00496
00497 for (y = 0; y < 8; y += 2) {
00498 for (x = 0; x < 8; x += 2) {
00499 s->pixel_ptr[x ] =
00500 s->pixel_ptr[x + 1 ] =
00501 s->pixel_ptr[x + s->stride] =
00502 s->pixel_ptr[x + 1 + s->stride] = *s->stream_ptr++;
00503 }
00504 s->pixel_ptr += s->stride * 2;
00505 }
00506
00507
00508 return 0;
00509 }
00510
00511 static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s)
00512 {
00513 int y;
00514 unsigned char P[2];
00515
00516
00517 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
00518
00519 for (y = 0; y < 8; y++) {
00520 if (!(y & 3)) {
00521 P[0] = *s->stream_ptr++;
00522 P[1] = *s->stream_ptr++;
00523 }
00524 memset(s->pixel_ptr, P[0], 4);
00525 memset(s->pixel_ptr + 4, P[1], 4);
00526 s->pixel_ptr += s->stride;
00527 }
00528
00529
00530 return 0;
00531 }
00532
00533 static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s)
00534 {
00535 int y;
00536 unsigned char pix;
00537
00538
00539 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 1);
00540 pix = *s->stream_ptr++;
00541
00542 for (y = 0; y < 8; y++) {
00543 memset(s->pixel_ptr, pix, 8);
00544 s->pixel_ptr += s->stride;
00545 }
00546
00547
00548 return 0;
00549 }
00550
00551 static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s)
00552 {
00553 int x, y;
00554 unsigned char sample[2];
00555
00556
00557 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
00558 sample[0] = *s->stream_ptr++;
00559 sample[1] = *s->stream_ptr++;
00560
00561 for (y = 0; y < 8; y++) {
00562 for (x = 0; x < 8; x += 2) {
00563 *s->pixel_ptr++ = sample[ y & 1 ];
00564 *s->pixel_ptr++ = sample[!(y & 1)];
00565 }
00566 s->pixel_ptr += s->line_inc;
00567 }
00568
00569
00570 return 0;
00571 }
00572
00573 static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s)
00574 {
00575 signed char x, y;
00576
00577
00578 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
00579
00580 x = *s->stream_ptr++;
00581 y = *s->stream_ptr++;
00582
00583 av_dlog(NULL, " motion bytes = %d, %d\n", x, y);
00584 return copy_from(s, &s->second_last_frame, x, y);
00585 }
00586
00587 static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s)
00588 {
00589 int x, y;
00590 uint16_t P[2];
00591 unsigned int flags;
00592 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
00593
00594
00595 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
00596
00597 P[0] = bytestream_get_le16(&s->stream_ptr);
00598 P[1] = bytestream_get_le16(&s->stream_ptr);
00599
00600 if (!(P[0] & 0x8000)) {
00601
00602 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
00603
00604 for (y = 0; y < 8; y++) {
00605 flags = *s->stream_ptr++ | 0x100;
00606 for (; flags != 1; flags >>= 1)
00607 *pixel_ptr++ = P[flags & 1];
00608 pixel_ptr += s->line_inc;
00609 }
00610
00611 } else {
00612
00613 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
00614
00615 flags = bytestream_get_le16(&s->stream_ptr);
00616 for (y = 0; y < 8; y += 2) {
00617 for (x = 0; x < 8; x += 2, flags >>= 1) {
00618 pixel_ptr[x ] =
00619 pixel_ptr[x + 1 ] =
00620 pixel_ptr[x + s->stride] =
00621 pixel_ptr[x + 1 + s->stride] = P[flags & 1];
00622 }
00623 pixel_ptr += s->stride * 2;
00624 }
00625 }
00626
00627 return 0;
00628 }
00629
00630 static int ipvideo_decode_block_opcode_0x8_16(IpvideoContext *s)
00631 {
00632 int x, y;
00633 uint16_t P[2];
00634 unsigned int flags = 0;
00635 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
00636
00637
00638
00639 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
00640
00641 P[0] = bytestream_get_le16(&s->stream_ptr);
00642 P[1] = bytestream_get_le16(&s->stream_ptr);
00643
00644 if (!(P[0] & 0x8000)) {
00645
00646 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
00647 s->stream_ptr -= 4;
00648
00649 for (y = 0; y < 16; y++) {
00650
00651 if (!(y & 3)) {
00652 P[0] = bytestream_get_le16(&s->stream_ptr);
00653 P[1] = bytestream_get_le16(&s->stream_ptr);
00654 flags = bytestream_get_le16(&s->stream_ptr);
00655 }
00656
00657 for (x = 0; x < 4; x++, flags >>= 1)
00658 *pixel_ptr++ = P[flags & 1];
00659 pixel_ptr += s->stride - 4;
00660
00661 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
00662 }
00663
00664 } else {
00665
00666 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 12);
00667
00668 if (!(AV_RL16(s->stream_ptr + 4) & 0x8000)) {
00669
00670 flags = bytestream_get_le32(&s->stream_ptr);
00671
00672
00673
00674 for (y = 0; y < 16; y++) {
00675 for (x = 0; x < 4; x++, flags >>= 1)
00676 *pixel_ptr++ = P[flags & 1];
00677 pixel_ptr += s->stride - 4;
00678
00679 if (y == 7) {
00680 pixel_ptr -= 8 * s->stride - 4;
00681 P[0] = bytestream_get_le16(&s->stream_ptr);
00682 P[1] = bytestream_get_le16(&s->stream_ptr);
00683 flags = bytestream_get_le32(&s->stream_ptr);
00684 }
00685 }
00686
00687 } else {
00688
00689
00690
00691 for (y = 0; y < 8; y++) {
00692 if (y == 4) {
00693 P[0] = bytestream_get_le16(&s->stream_ptr);
00694 P[1] = bytestream_get_le16(&s->stream_ptr);
00695 }
00696 flags = *s->stream_ptr++ | 0x100;
00697
00698 for (; flags != 1; flags >>= 1)
00699 *pixel_ptr++ = P[flags & 1];
00700 pixel_ptr += s->line_inc;
00701 }
00702 }
00703 }
00704
00705
00706 return 0;
00707 }
00708
00709 static int ipvideo_decode_block_opcode_0x9_16(IpvideoContext *s)
00710 {
00711 int x, y;
00712 uint16_t P[4];
00713 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
00714
00715
00716 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
00717
00718 for (x = 0; x < 4; x++)
00719 P[x] = bytestream_get_le16(&s->stream_ptr);
00720
00721 if (!(P[0] & 0x8000)) {
00722 if (!(P[2] & 0x8000)) {
00723
00724
00725 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 16);
00726
00727 for (y = 0; y < 8; y++) {
00728
00729 int flags = bytestream_get_le16(&s->stream_ptr);
00730 for (x = 0; x < 8; x++, flags >>= 2)
00731 *pixel_ptr++ = P[flags & 0x03];
00732 pixel_ptr += s->line_inc;
00733 }
00734
00735 } else {
00736 uint32_t flags;
00737
00738
00739 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 4);
00740
00741 flags = bytestream_get_le32(&s->stream_ptr);
00742
00743 for (y = 0; y < 8; y += 2) {
00744 for (x = 0; x < 8; x += 2, flags >>= 2) {
00745 pixel_ptr[x ] =
00746 pixel_ptr[x + 1 ] =
00747 pixel_ptr[x + s->stride] =
00748 pixel_ptr[x + 1 + s->stride] = P[flags & 0x03];
00749 }
00750 pixel_ptr += s->stride * 2;
00751 }
00752
00753 }
00754 } else {
00755 uint64_t flags;
00756
00757
00758 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
00759
00760 flags = bytestream_get_le64(&s->stream_ptr);
00761 if (!(P[2] & 0x8000)) {
00762 for (y = 0; y < 8; y++) {
00763 for (x = 0; x < 8; x += 2, flags >>= 2) {
00764 pixel_ptr[x ] =
00765 pixel_ptr[x + 1] = P[flags & 0x03];
00766 }
00767 pixel_ptr += s->stride;
00768 }
00769 } else {
00770 for (y = 0; y < 8; y += 2) {
00771 for (x = 0; x < 8; x++, flags >>= 2) {
00772 pixel_ptr[x ] =
00773 pixel_ptr[x + s->stride] = P[flags & 0x03];
00774 }
00775 pixel_ptr += s->stride * 2;
00776 }
00777 }
00778 }
00779
00780
00781 return 0;
00782 }
00783
00784 static int ipvideo_decode_block_opcode_0xA_16(IpvideoContext *s)
00785 {
00786 int x, y;
00787 uint16_t P[4];
00788 int flags = 0;
00789 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
00790
00791
00792
00793 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 24);
00794
00795 if (!(AV_RL16(s->stream_ptr) & 0x8000)) {
00796
00797
00798 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 48);
00799
00800 for (y = 0; y < 16; y++) {
00801
00802 if (!(y & 3)) {
00803 for (x = 0; x < 4; x++)
00804 P[x] = bytestream_get_le16(&s->stream_ptr);
00805 flags = bytestream_get_le32(&s->stream_ptr);
00806 }
00807
00808 for (x = 0; x < 4; x++, flags >>= 2)
00809 *pixel_ptr++ = P[flags & 0x03];
00810
00811 pixel_ptr += s->stride - 4;
00812
00813 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
00814 }
00815
00816 } else {
00817
00818 int vert = !(AV_RL16(s->stream_ptr + 16) & 0x8000);
00819 uint64_t flags = 0;
00820
00821
00822
00823
00824 for (y = 0; y < 16; y++) {
00825
00826 if (!(y & 7)) {
00827 for (x = 0; x < 4; x++)
00828 P[x] = bytestream_get_le16(&s->stream_ptr);
00829 flags = bytestream_get_le64(&s->stream_ptr);
00830 }
00831
00832 for (x = 0; x < 4; x++, flags >>= 2)
00833 *pixel_ptr++ = P[flags & 0x03];
00834
00835 if (vert) {
00836 pixel_ptr += s->stride - 4;
00837
00838 if (y == 7) pixel_ptr -= 8 * s->stride - 4;
00839 } else if (y & 1) pixel_ptr += s->line_inc;
00840 }
00841 }
00842
00843
00844 return 0;
00845 }
00846
00847 static int ipvideo_decode_block_opcode_0xB_16(IpvideoContext *s)
00848 {
00849 int x, y;
00850 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
00851
00852
00853 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 128);
00854
00855 for (y = 0; y < 8; y++) {
00856 for (x = 0; x < 8; x++)
00857 pixel_ptr[x] = bytestream_get_le16(&s->stream_ptr);
00858 pixel_ptr += s->stride;
00859 }
00860
00861
00862 return 0;
00863 }
00864
00865 static int ipvideo_decode_block_opcode_0xC_16(IpvideoContext *s)
00866 {
00867 int x, y;
00868 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
00869
00870
00871 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 32);
00872
00873 for (y = 0; y < 8; y += 2) {
00874 for (x = 0; x < 8; x += 2) {
00875 pixel_ptr[x ] =
00876 pixel_ptr[x + 1 ] =
00877 pixel_ptr[x + s->stride] =
00878 pixel_ptr[x + 1 + s->stride] = bytestream_get_le16(&s->stream_ptr);
00879 }
00880 pixel_ptr += s->stride * 2;
00881 }
00882
00883
00884 return 0;
00885 }
00886
00887 static int ipvideo_decode_block_opcode_0xD_16(IpvideoContext *s)
00888 {
00889 int x, y;
00890 uint16_t P[2];
00891 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
00892
00893
00894 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 8);
00895
00896 for (y = 0; y < 8; y++) {
00897 if (!(y & 3)) {
00898 P[0] = bytestream_get_le16(&s->stream_ptr);
00899 P[1] = bytestream_get_le16(&s->stream_ptr);
00900 }
00901 for (x = 0; x < 8; x++)
00902 pixel_ptr[x] = P[x >> 2];
00903 pixel_ptr += s->stride;
00904 }
00905
00906
00907 return 0;
00908 }
00909
00910 static int ipvideo_decode_block_opcode_0xE_16(IpvideoContext *s)
00911 {
00912 int x, y;
00913 uint16_t pix;
00914 uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr;
00915
00916
00917 CHECK_STREAM_PTR(s->stream_ptr, s->stream_end, 2);
00918 pix = bytestream_get_le16(&s->stream_ptr);
00919
00920 for (y = 0; y < 8; y++) {
00921 for (x = 0; x < 8; x++)
00922 pixel_ptr[x] = pix;
00923 pixel_ptr += s->stride;
00924 }
00925
00926
00927 return 0;
00928 }
00929
00930 static int (* const ipvideo_decode_block[])(IpvideoContext *s) = {
00931 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
00932 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
00933 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
00934 ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7,
00935 ipvideo_decode_block_opcode_0x8, ipvideo_decode_block_opcode_0x9,
00936 ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB,
00937 ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD,
00938 ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF,
00939 };
00940
00941 static int (* const ipvideo_decode_block16[])(IpvideoContext *s) = {
00942 ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1,
00943 ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3,
00944 ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5,
00945 ipvideo_decode_block_opcode_0x6_16, ipvideo_decode_block_opcode_0x7_16,
00946 ipvideo_decode_block_opcode_0x8_16, ipvideo_decode_block_opcode_0x9_16,
00947 ipvideo_decode_block_opcode_0xA_16, ipvideo_decode_block_opcode_0xB_16,
00948 ipvideo_decode_block_opcode_0xC_16, ipvideo_decode_block_opcode_0xD_16,
00949 ipvideo_decode_block_opcode_0xE_16, ipvideo_decode_block_opcode_0x1,
00950 };
00951
00952 static void ipvideo_decode_opcodes(IpvideoContext *s)
00953 {
00954 int x, y;
00955 unsigned char opcode;
00956 int ret;
00957 static int frame = 0;
00958 GetBitContext gb;
00959
00960 av_dlog(NULL, "------------------ frame %d\n", frame);
00961 frame++;
00962
00963 if (!s->is_16bpp) {
00964
00965 memcpy(s->current_frame.data[1], s->pal, AVPALETTE_SIZE);
00966
00967 s->stride = s->current_frame.linesize[0];
00968 s->stream_ptr = s->buf + 14;
00969 s->stream_end = s->buf + s->size;
00970 } else {
00971 s->stride = s->current_frame.linesize[0] >> 1;
00972 s->stream_ptr = s->buf + 16;
00973 s->stream_end =
00974 s->mv_ptr = s->buf + 14 + AV_RL16(s->buf+14);
00975 s->mv_end = s->buf + s->size;
00976 }
00977 s->line_inc = s->stride - 8;
00978 s->upper_motion_limit_offset = (s->avctx->height - 8) * s->current_frame.linesize[0]
00979 + (s->avctx->width - 8) * (1 + s->is_16bpp);
00980
00981 init_get_bits(&gb, s->decoding_map, s->decoding_map_size * 8);
00982 for (y = 0; y < s->avctx->height; y += 8) {
00983 for (x = 0; x < s->avctx->width; x += 8) {
00984 opcode = get_bits(&gb, 4);
00985
00986 av_dlog(NULL, " block @ (%3d, %3d): encoding 0x%X, data ptr @ %p\n",
00987 x, y, opcode, s->stream_ptr);
00988
00989 if (!s->is_16bpp) {
00990 s->pixel_ptr = s->current_frame.data[0] + x
00991 + y*s->current_frame.linesize[0];
00992 ret = ipvideo_decode_block[opcode](s);
00993 } else {
00994 s->pixel_ptr = s->current_frame.data[0] + x*2
00995 + y*s->current_frame.linesize[0];
00996 ret = ipvideo_decode_block16[opcode](s);
00997 }
00998 if (ret != 0) {
00999 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
01000 frame, x, y);
01001 return;
01002 }
01003 }
01004 }
01005 if (s->stream_end - s->stream_ptr > 1) {
01006 av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode finished with %td bytes left over\n",
01007 s->stream_end - s->stream_ptr);
01008 }
01009 }
01010
01011 static av_cold int ipvideo_decode_init(AVCodecContext *avctx)
01012 {
01013 IpvideoContext *s = avctx->priv_data;
01014
01015 s->avctx = avctx;
01016
01017 s->is_16bpp = avctx->bits_per_coded_sample == 16;
01018 avctx->pix_fmt = s->is_16bpp ? PIX_FMT_RGB555 : PIX_FMT_PAL8;
01019
01020 dsputil_init(&s->dsp, avctx);
01021
01022
01023 s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
01024
01025 avcodec_get_frame_defaults(&s->second_last_frame);
01026 avcodec_get_frame_defaults(&s->last_frame);
01027 avcodec_get_frame_defaults(&s->current_frame);
01028 s->current_frame.data[0] = s->last_frame.data[0] =
01029 s->second_last_frame.data[0] = NULL;
01030
01031 return 0;
01032 }
01033
01034 static int ipvideo_decode_frame(AVCodecContext *avctx,
01035 void *data, int *data_size,
01036 AVPacket *avpkt)
01037 {
01038 const uint8_t *buf = avpkt->data;
01039 int buf_size = avpkt->size;
01040 IpvideoContext *s = avctx->priv_data;
01041
01042
01043
01044 if (buf_size < s->decoding_map_size)
01045 return buf_size;
01046
01047 s->decoding_map = buf;
01048 s->buf = buf + s->decoding_map_size;
01049 s->size = buf_size - s->decoding_map_size;
01050
01051 s->current_frame.reference = 3;
01052 if (avctx->get_buffer(avctx, &s->current_frame)) {
01053 av_log(avctx, AV_LOG_ERROR, " Interplay Video: get_buffer() failed\n");
01054 return -1;
01055 }
01056
01057 if (!s->is_16bpp) {
01058 const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
01059 if (pal) {
01060 s->current_frame.palette_has_changed = 1;
01061 memcpy(s->pal, pal, AVPALETTE_SIZE);
01062 }
01063 }
01064
01065 ipvideo_decode_opcodes(s);
01066
01067 *data_size = sizeof(AVFrame);
01068 *(AVFrame*)data = s->current_frame;
01069
01070
01071 if (s->second_last_frame.data[0])
01072 avctx->release_buffer(avctx, &s->second_last_frame);
01073 s->second_last_frame = s->last_frame;
01074 s->last_frame = s->current_frame;
01075 s->current_frame.data[0] = NULL;
01076
01077
01078 return buf_size;
01079 }
01080
01081 static av_cold int ipvideo_decode_end(AVCodecContext *avctx)
01082 {
01083 IpvideoContext *s = avctx->priv_data;
01084
01085
01086 if (s->last_frame.data[0])
01087 avctx->release_buffer(avctx, &s->last_frame);
01088 if (s->second_last_frame.data[0])
01089 avctx->release_buffer(avctx, &s->second_last_frame);
01090
01091 return 0;
01092 }
01093
01094 AVCodec ff_interplay_video_decoder = {
01095 "interplayvideo",
01096 AVMEDIA_TYPE_VIDEO,
01097 CODEC_ID_INTERPLAY_VIDEO,
01098 sizeof(IpvideoContext),
01099 ipvideo_decode_init,
01100 NULL,
01101 ipvideo_decode_end,
01102 ipvideo_decode_frame,
01103 CODEC_CAP_DR1,
01104 .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"),
01105 };