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