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