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