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