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