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