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