SmackerDecoder.cpp
1 /* 2 * libsmackerdec - Smacker video decoder 3 * Copyright (C) 2011 Barry Duncan 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* This code is heavily based on smacker.c from the FFmpeg project which can be obtained from http://www.ffmpeg.org/ 21 * below is the license from smacker.c 22 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 23 24 /* 25 * Smacker decoder 26 * Copyright (c) 2006 Konstantin Shishkov 27 * 28 * This file is part of FFmpeg. 29 * 30 * FFmpeg is free software; you can redistribute it and/or 31 * modify it under the terms of the GNU Lesser General Public 32 * License as published by the Free Software Foundation; either 33 * version 2.1 of the License, or (at your option) any later version. 34 * 35 * FFmpeg is distributed in the hope that it will be useful, 36 * but WITHOUT ANY WARRANTY; without even the implied warranty of 37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 38 * Lesser General Public License for more details. 39 * 40 * You should have received a copy of the GNU Lesser General Public 41 * License along with FFmpeg; if not, write to the Free Software 42 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 43 */ 44 45 #include "SmackerDecoder.h" 46 #include "HuffmanVLC.h" 47 #include "LogError.h" 48 #include <assert.h> 49 #include <algorithm> 50 #include "compat.h" 51 #include "baselayer.h" 52 53 GrowArray<class SmackerDecoder*> classInstances; 54 55 SmackerHandle Smacker_Open(const char* fileName) 56 { 57 SmackerHandle newHandle; 58 newHandle.isValid = false; 59 newHandle.instanceIndex = -1; 60 61 SmackerDecoder *newDecoder = new SmackerDecoder(); 62 if (!newDecoder->Open(fileName)) 63 { 64 delete newDecoder; 65 return newHandle; 66 } 67 68 // add instance to global instance vector 69 classInstances.push_back(newDecoder); 70 71 // get a handle ID 72 newHandle.instanceIndex = classInstances.size() - 1; 73 74 // loaded ok, make handle valid 75 newHandle.isValid = true; 76 77 return newHandle; 78 } 79 80 void Smacker_Close(SmackerHandle &handle) 81 { 82 if (!classInstances.at(handle.instanceIndex)) 83 { 84 // invalid handle 85 return; 86 } 87 88 // close bink decoder 89 delete classInstances[handle.instanceIndex]; 90 classInstances[handle.instanceIndex] = 0; 91 92 handle.instanceIndex = -1; 93 handle.isValid = false; 94 } 95 96 uint32_t Smacker_GetNumAudioTracks(SmackerHandle &handle) 97 { 98 UNREFERENCED_PARAMETER(handle); 99 // TODO: fixme 100 return 1; 101 } 102 103 SmackerAudioInfo Smacker_GetAudioTrackDetails(SmackerHandle &handle, uint32_t trackIndex) 104 { 105 return classInstances[handle.instanceIndex]->GetAudioTrackDetails(trackIndex); 106 } 107 108 /* Get a frame's worth of audio data. 109 * 110 * 'data' needs to be a pointer to allocated memory that this function will fill. 111 * You can find the size (in bytes) to make this buffer by calling Bink_GetAudioTrackDetails() 112 * and checking the 'idealBufferSize' member in the returned AudioInfo struct 113 */ 114 uint32_t Smacker_GetAudioData(SmackerHandle &handle, uint32_t trackIndex, int16_t *data) 115 { 116 return classInstances[handle.instanceIndex]->GetAudioData(trackIndex, data); 117 } 118 119 uint32_t Smacker_GetNumFrames(SmackerHandle &handle) 120 { 121 return classInstances[handle.instanceIndex]->GetNumFrames(); 122 } 123 124 void Smacker_GetFrameSize(SmackerHandle &handle, uint32_t &width, uint32_t &height) 125 { 126 width = classInstances[handle.instanceIndex]->frameWidth; 127 height = classInstances[handle.instanceIndex]->frameHeight; 128 } 129 130 uint32_t Smacker_GetCurrentFrameNum(SmackerHandle &handle) 131 { 132 return classInstances[handle.instanceIndex]->GetCurrentFrameNum(); 133 } 134 135 uint32_t Smacker_GetNextFrame(SmackerHandle &handle) 136 { 137 SmackerDecoder *decoder = classInstances[handle.instanceIndex]; 138 139 uint32_t frameIndex = decoder->GetCurrentFrameNum(); 140 141 decoder->GetNextFrame(); 142 143 return frameIndex; 144 } 145 146 float Smacker_GetFrameRate(SmackerHandle &handle) 147 { 148 return classInstances[handle.instanceIndex]->GetFrameRate(); 149 } 150 151 void Smacker_GetPalette(SmackerHandle &handle, uint8_t *palette) 152 { 153 classInstances[handle.instanceIndex]->GetPalette(palette); 154 } 155 156 void Smacker_GetFrame(SmackerHandle &handle, uint8_t *frame) 157 { 158 classInstances[handle.instanceIndex]->GetFrame(frame); 159 } 160 161 void Smacker_GotoFrame(SmackerHandle &handle, uint32_t frameNum) 162 { 163 classInstances[handle.instanceIndex]->GotoFrame(frameNum); 164 } 165 166 SmackerDecoder::SmackerDecoder() 167 { 168 isVer4 = false; 169 currentFrame = 0; 170 picture = 0; 171 nextPos = 0; 172 173 for (int i = 0; i < kMaxAudioTracks; i++) 174 { 175 audioTracks[i].buffer = 0; 176 } 177 } 178 179 SmackerDecoder::~SmackerDecoder() 180 { 181 for (int i = 0; i < kMaxAudioTracks; i++) 182 { 183 delete[] audioTracks[i].buffer; 184 } 185 186 delete[] picture; 187 } 188 189 // from bswap.h 190 static /*av_always_inline av_const*/ uint16_t av_bswap16(uint16_t x) 191 { 192 x= (x>>8) | (x<<8); 193 return x; 194 } 195 196 /* possible runs of blocks */ 197 static const int block_runs[64] = { 198 1, 2, 3, 4, 5, 6, 7, 8, 199 9, 10, 11, 12, 13, 14, 15, 16, 200 17, 18, 19, 20, 21, 22, 23, 24, 201 25, 26, 27, 28, 29, 30, 31, 32, 202 33, 34, 35, 36, 37, 38, 39, 40, 203 41, 42, 43, 44, 45, 46, 47, 48, 204 49, 50, 51, 52, 53, 54, 55, 56, 205 57, 58, 59, 128, 256, 512, 1024, 2048 }; 206 207 enum SmkBlockTypes { 208 SMK_BLK_MONO = 0, 209 SMK_BLK_FULL = 1, 210 SMK_BLK_SKIP = 2, 211 SMK_BLK_FILL = 3 }; 212 213 /* palette used in Smacker */ 214 static const uint8_t smk_pal[64] = { 215 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, 216 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, 217 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D, 218 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D, 219 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E, 220 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE, 221 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF, 222 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF 223 }; 224 225 enum SAudFlags { 226 SMK_AUD_PACKED = 0x80000000, 227 SMK_AUD_16BITS = 0x20000000, 228 SMK_AUD_STEREO = 0x10000000, 229 SMK_AUD_BINKAUD = 0x08000000, 230 SMK_AUD_USEDCT = 0x04000000 231 }; 232 233 const int kSMKpal = 0x01; 234 const int kFlagRingFrame = 0x01; 235 236 const int kTreeBits = 9; 237 const int kSMKnode = 0x80000000; 238 239 const char *kSMK2iD = "SMK2"; 240 const char *kSMK4iD = "SMK4"; 241 242 243 /** 244 * Context used for code reconstructing 245 */ 246 typedef struct HuffContext { 247 int length; 248 int maxlength; 249 int current; 250 251 GrowArray<uint32_t> bits; 252 GrowArray<int> lengths; 253 GrowArray<int> values; 254 255 } HuffContext; 256 257 /* common parameters used for decode_bigtree */ 258 typedef struct DBCtx { 259 SmackerCommon::VLCtable v1; 260 SmackerCommon::VLCtable v2; 261 GrowArray<int> recode1, recode2; 262 int escapes[3]; 263 int *last; 264 int lcur; 265 } DBCtx; 266 267 268 static void last_reset(GrowArray<int> &recode, int *last) { 269 recode[last[0]] = recode[last[1]] = recode[last[2]] = 0; 270 } 271 272 /* get code and update history */ 273 int SmackerDecoder::GetCode(SmackerCommon::BitReader &bits, GrowArray<int> &recode, int *last) 274 { 275 int *table = &recode[0]; 276 277 int v, b; 278 279 b = bits.GetPosition(); 280 281 while (*table & kSMKnode) 282 { 283 if (bits.GetBit()) 284 table += (*table) & (~kSMKnode); 285 table++; 286 } 287 v = *table; 288 b = bits.GetPosition() - b; 289 290 if (v != recode[last[0]]) { 291 recode[last[2]] = recode[last[1]]; 292 recode[last[1]] = recode[last[0]]; 293 recode[last[0]] = v; 294 } 295 return v; 296 } 297 298 bool SmackerDecoder::Open(const char *fileName) 299 { 300 // open the file (read only) 301 file.Open(fileName); 302 if (!file.Is_Open()) 303 { 304 LOG_F(ERROR, "SmackerDecoder::Open() - Can't open file %s", fileName); 305 return false; 306 } 307 308 // check the file signature 309 file.ReadBytes((uint8_t*)signature, 4); 310 if (memcmp(signature, kSMK2iD, 4) != 0 311 && memcmp(signature, kSMK4iD, 4) != 0) 312 { 313 LOG_F(ERROR, "SmackerDecoder::Open() - Unknown Smacker signature"); 314 return false; 315 } 316 317 if (!memcmp(signature, kSMK4iD, 4)) { 318 isVer4 = true; 319 } 320 321 frameWidth = file.ReadUint32LE(); 322 frameHeight = file.ReadUint32LE(); 323 nFrames = file.ReadUint32LE(); 324 325 picture = new uint8_t[frameWidth * frameHeight]; 326 327 int32_t frameRate = file.ReadUint32LE(); 328 329 if (frameRate > 0) 330 fps = 1000 / frameRate; 331 else if (frameRate < 0) 332 fps = 100000 / (-frameRate); 333 else 334 fps = 10; 335 336 uint32_t flags = file.ReadUint32LE(); 337 338 if (flags & kFlagRingFrame) { 339 nFrames++; 340 } 341 342 for (int i = 0; i < kMaxAudioTracks; i++) { 343 audioTracks[i].sizeInBytes = file.ReadUint32LE(); 344 } 345 346 treeSize = file.ReadUint32LE(); 347 mMapSize = file.ReadUint32LE(); 348 MClrSize = file.ReadUint32LE(); 349 fullSize = file.ReadUint32LE(); 350 typeSize = file.ReadUint32LE(); 351 352 for (int i = 0; i < kMaxAudioTracks; i++) { 353 audioTracks[i].flags = file.ReadUint32LE(); 354 } 355 356 // skip pad 357 file.Skip(4); 358 359 if (nFrames > 0xFFFFFF) 360 { 361 LOG_F(ERROR, "SmackerDecoder::Open() - Too many frames"); 362 return false; 363 } 364 365 frameSizes.resize(nFrames); 366 frameFlags.resize(nFrames); 367 368 // read frame info 369 for (uint32_t i = 0; i < nFrames; i++) { 370 frameSizes[i] = file.ReadUint32LE(); 371 } 372 for (uint32_t i = 0; i < nFrames; i++) { 373 frameFlags[i] = file.ReadByte(); 374 } 375 376 // handle possible audio streams 377 for (int i = 0; i < kMaxAudioTracks; i++) 378 { 379 audioTracks[i].buffer = 0; 380 audioTracks[i].bufferSize = 0; 381 audioTracks[i].bytesReadThisFrame = 0; 382 383 if (audioTracks[i].flags & 0xFFFFFF) 384 { 385 /* 386 if (audioTracks[i].flags & SMK_AUD_BINKAUD) { 387 audioTracks[i].compressionType = SMK_AUD_BINKAUD; 388 } else if (audioTracks[i].flags & SMK_AUD_USEDCT) { 389 audioTracks[i].compressionType = SMK_AUD_USEDCT; 390 } else if (audioTracks[i].flags & SMK_AUD_PACKED){ 391 ast[i]->codec->codec_id = CODEC_ID_SMACKAUDIO; 392 ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A'); 393 } else { 394 ast[i]->codec->codec_id = CODEC_ID_PCM_U8; 395 } 396 */ 397 audioTracks[i].nChannels = (audioTracks[i].flags & SMK_AUD_STEREO) ? 2 : 1; 398 audioTracks[i].sampleRate = audioTracks[i].flags & 0xFFFFFF; 399 audioTracks[i].bitsPerSample = (audioTracks[i].flags & SMK_AUD_16BITS) ? 16 : 8; 400 } 401 } 402 403 memset(palette, 0, 768); 404 405 DecodeHeaderTrees(); 406 407 // set nextPos to where we are now, as next data is frame 1 408 nextPos = file.GetPosition(); 409 firstFrameFilePos = nextPos; 410 411 // determine max buffer sizes for audio tracks 412 // file.Seek(nextPos, SmackerCommon::FileStream::kSeekStart); 413 414 uint32_t UNUSED(frameSize) = frameSizes[0] & (~3); 415 uint8_t frameFlag = frameFlags[0]; 416 417 // skip over palette 418 if (frameFlag & kSMKpal) 419 { 420 uint32_t size = file.ReadByte(); 421 size = size * 4 - 1; 422 file.Skip(size); 423 } 424 425 frameFlag >>= 1; 426 427 for (int i = 0; i < kMaxAudioTracks; i++) 428 { 429 if (frameFlag & 1) 430 { 431 // skip size 432 file.Skip(4); 433 434 uint32_t unpackedSize = file.ReadUint32LE(); 435 436 audioTracks[i].bufferSize = unpackedSize; 437 audioTracks[i].buffer = new uint8_t[unpackedSize]; 438 } 439 frameFlag >>= 1; 440 } 441 442 return true; 443 } 444 445 // static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length) 446 int SmackerDecoder::DecodeTree(SmackerCommon::BitReader &bits, HuffContext *hc, uint32_t prefix, int length) 447 { 448 if (!bits.GetBit()) // Leaf 449 { 450 if (hc->current >= 256){ 451 LOG_F(ERROR, "SmackerDecoder::DecodeTree() - Tree size exceeded"); 452 return -1; 453 } 454 if (length){ 455 hc->bits[hc->current] = prefix; 456 hc->lengths[hc->current] = length; 457 } else { 458 hc->bits[hc->current] = 0; 459 hc->lengths[hc->current] = 0; 460 } 461 hc->values[hc->current] = bits.GetBits(8); 462 463 hc->current++; 464 if (hc->maxlength < length) 465 hc->maxlength = length; 466 return 0; 467 } else { //Node 468 int r; 469 length++; 470 r = DecodeTree(bits, hc, prefix, length); 471 if (r) 472 return r; 473 return DecodeTree(bits, hc, prefix | (1 << (length - 1)), length); 474 } 475 } 476 477 /** 478 * Decode header tree 479 */ 480 int SmackerDecoder::DecodeBigTree(SmackerCommon::BitReader &bits, HuffContext *hc, DBCtx *ctx) 481 { 482 if (!bits.GetBit()) // Leaf 483 { 484 int val, i1, i2, b1, b2; 485 486 i1 = 0; 487 i2 = 0; 488 489 if (hc->current >= hc->length){ 490 LOG_F(ERROR, "SmackerDecoder::DecodeBigTree() - Tree size exceeded"); 491 return -1; 492 } 493 494 b1 = bits.GetPosition(); 495 496 if (VLC_GetSize(ctx->v1)) 497 { 498 i1 = VLC_GetCodeBits(bits, ctx->v1); 499 } 500 501 b1 = bits.GetPosition() - b1; 502 b2 = bits.GetPosition(); 503 504 if (VLC_GetSize(ctx->v2)) 505 { 506 i2 = VLC_GetCodeBits(bits, ctx->v2); 507 } 508 509 b2 = bits.GetPosition() - b2; 510 if (i1 < 0 || i2 < 0) 511 return -1; 512 val = ctx->recode1[i1] | (ctx->recode2[i2] << 8); 513 if (val == ctx->escapes[0]) { 514 ctx->last[0] = hc->current; 515 val = 0; 516 } else if (val == ctx->escapes[1]) { 517 ctx->last[1] = hc->current; 518 val = 0; 519 } else if (val == ctx->escapes[2]) { 520 ctx->last[2] = hc->current; 521 val = 0; 522 } 523 524 hc->values[hc->current++] = val; 525 return 1; 526 } else { //Node 527 int r = 0, t; 528 529 t = hc->current++; 530 r = DecodeBigTree(bits, hc, ctx); 531 if (r < 0) 532 return r; 533 hc->values[t] = kSMKnode | r; 534 r++; 535 r += DecodeBigTree(bits, hc, ctx); 536 return r; 537 } 538 } 539 540 /** 541 * Store large tree as Libav's vlc codes 542 */ 543 int SmackerDecoder::DecodeHeaderTree(SmackerCommon::BitReader &bits, GrowArray<int> &recodes, int *last, int size) 544 { 545 HuffContext huff; 546 HuffContext tmp1, tmp2; 547 int escapes[3]; 548 DBCtx ctx; 549 550 if ((uint32_t)size >= UINT_MAX>>4) 551 { 552 LOG_F(ERROR, "SmackerDecoder::DecodeHeaderTree() - Size too large"); 553 return -1; 554 } 555 556 tmp1.length = 256; 557 tmp1.maxlength = 0; 558 tmp1.current = 0; 559 560 tmp1.bits.resize(256); 561 tmp1.lengths.resize(256); 562 tmp1.values.resize(256); 563 564 tmp2.length = 256; 565 tmp2.maxlength = 0; 566 tmp2.current = 0; 567 568 tmp2.bits.resize(256); 569 tmp2.lengths.resize(256); 570 tmp2.values.resize(256); 571 572 // low byte tree 573 if (bits.GetBit()) // 1: Read Tag 574 { 575 DecodeTree(bits, &tmp1, 0, 0); 576 577 bits.SkipBits(1); 578 579 VLC_InitTable(ctx.v1, tmp1.maxlength, tmp1.current, &tmp1.lengths[0], &tmp1.bits[0]); 580 } 581 else 582 { 583 // Skipping low bytes tree 584 } 585 586 // high byte tree 587 if (bits.GetBit()) 588 { 589 DecodeTree(bits, &tmp2, 0, 0); 590 591 uint32_t UNUSED(end) = bits.GetPosition(); 592 593 bits.SkipBits(1); 594 595 VLC_InitTable(ctx.v2, tmp2.maxlength, tmp2.current, &tmp2.lengths[0], &tmp2.bits[0]); 596 } 597 else 598 { 599 // Skipping high bytes tree 600 } 601 602 escapes[0] = bits.GetBits(8); 603 escapes[0] |= bits.GetBits(8) << 8; 604 escapes[1] = bits.GetBits(8); 605 escapes[1] |= bits.GetBits(8) << 8; 606 escapes[2] = bits.GetBits(8); 607 escapes[2] |= bits.GetBits(8) << 8; 608 609 last[0] = last[1] = last[2] = -1; 610 611 ctx.escapes[0] = escapes[0]; 612 ctx.escapes[1] = escapes[1]; 613 ctx.escapes[2] = escapes[2]; 614 615 ctx.recode1 = tmp1.values; 616 ctx.recode2 = tmp2.values; 617 ctx.last = last; 618 619 huff.length = ((size + 3) >> 2) + 3; 620 huff.maxlength = 0; 621 huff.current = 0; 622 huff.values.resize(huff.length); 623 624 DecodeBigTree(bits, &huff, &ctx); 625 626 bits.SkipBits(1); 627 628 if (ctx.last[0] == -1) ctx.last[0] = huff.current++; 629 if (ctx.last[1] == -1) ctx.last[1] = huff.current++; 630 if (ctx.last[2] == -1) ctx.last[2] = huff.current++; 631 632 recodes = huff.values; 633 634 return 0; 635 } 636 637 // static int decode_header_trees(SmackVContext *smk) { 638 bool SmackerDecoder::DecodeHeaderTrees() 639 { 640 SmackerCommon::BitReader bits(file, treeSize); 641 642 if (!bits.GetBit()) 643 { 644 // Skipping MMAP tree 645 mmap_tbl.resize(2); 646 mmap_tbl[0] = 0; 647 mmap_last[0] = mmap_last[1] = mmap_last[2] = 1; 648 } 649 else 650 { 651 DecodeHeaderTree(bits, mmap_tbl, mmap_last, mMapSize); 652 } 653 654 if (!bits.GetBit()) 655 { 656 // Skipping MCLR tree 657 mclr_tbl.resize(2); 658 mclr_tbl[0] = 0; 659 mclr_last[0] = mclr_last[1] = mclr_last[2] = 1; 660 } 661 else 662 { 663 DecodeHeaderTree(bits, mclr_tbl, mclr_last, MClrSize); 664 } 665 666 if (!bits.GetBit()) 667 { 668 // Skipping FULL tree 669 full_tbl.resize(2); 670 full_tbl[0] = 0; 671 full_last[0] = full_last[1] = full_last[2] = 1; 672 } 673 else 674 { 675 DecodeHeaderTree(bits, full_tbl, full_last, fullSize); 676 } 677 678 if (!bits.GetBit()) 679 { 680 // Skipping TYPE tree 681 type_tbl.resize(2); 682 type_tbl[0] = 0; 683 type_last[0] = type_last[1] = type_last[2] = 1; 684 } 685 else 686 { 687 DecodeHeaderTree(bits, type_tbl, type_last, typeSize); 688 } 689 690 /* FIXME - we don't seems to read/use EVERY bit we 'load' into the bit reader 691 * and as my bitreader reads from the file rather than a buffer read from file 692 * of size 'treeSize', I need to make sure I consume the remaining bits (and thus increment 693 * the file read position to where the code expects it to be when this function returns (ie 694 * 'treeSize' number of bytes must be read 695 */ 696 uint32_t left = bits.GetSize() - bits.GetPosition(); 697 bits.SkipBits(left); 698 699 return true; 700 } 701 702 void SmackerDecoder::GetNextFrame() 703 { 704 ReadPacket(); 705 } 706 707 int SmackerDecoder::ReadPacket() 708 { 709 // test-remove 710 if (currentFrame >= nFrames) 711 return 1; 712 713 // seek to next frame position 714 file.Seek(nextPos, SmackerCommon::FileStream::kSeekStart); 715 716 uint32_t frameSize = frameSizes[currentFrame] & (~3); 717 uint8_t frameFlag = frameFlags[currentFrame]; 718 719 // handle palette change 720 if (frameFlag & kSMKpal) 721 { 722 int size, sz, t, off, j, pos; 723 uint8_t *pal = palette; 724 uint8_t oldpal[768]; 725 726 memcpy(oldpal, pal, 768); 727 size = file.ReadByte(); 728 size = size * 4 - 1; 729 frameSize -= size; 730 frameSize--; 731 sz = 0; 732 pos = file.GetPosition() + size; 733 734 while (sz < 256) 735 { 736 t = file.ReadByte(); 737 if (t & 0x80){ /* skip palette entries */ 738 sz += (t & 0x7F) + 1; 739 pal += ((t & 0x7F) + 1) * 3; 740 } else if (t & 0x40){ /* copy with offset */ 741 off = file.ReadByte() * 3; 742 j = (t & 0x3F) + 1; 743 while (j-- && sz < 256) { 744 *pal++ = oldpal[off + 0]; 745 *pal++ = oldpal[off + 1]; 746 *pal++ = oldpal[off + 2]; 747 sz++; 748 off += 3; 749 } 750 } else { /* new entries */ 751 *pal++ = smk_pal[t]; 752 *pal++ = smk_pal[file.ReadByte() & 0x3F]; 753 *pal++ = smk_pal[file.ReadByte() & 0x3F]; 754 sz++; 755 } 756 } 757 758 file.Seek(pos, SmackerCommon::FileStream::kSeekStart); 759 } 760 761 frameFlag >>= 1; 762 763 // check for and handle audio 764 for (int i = 0; i < kMaxAudioTracks; i++) 765 { 766 audioTracks[i].bytesReadThisFrame = 0; 767 768 if (frameFlag & 1) 769 { 770 uint32_t size = file.ReadUint32LE() - 4; 771 frameSize -= size; 772 frameSize -= 4; 773 774 DecodeAudio(size, audioTracks[i]); 775 } 776 frameFlag >>= 1; 777 } 778 779 if (frameSize == 0) { 780 return -1; 781 } 782 783 DecodeFrame(frameSize); 784 785 currentFrame++; 786 787 nextPos = file.GetPosition(); 788 789 return 0; 790 } 791 792 int SmackerDecoder::DecodeFrame(uint32_t frameSize) 793 { 794 last_reset(mmap_tbl, mmap_last); 795 last_reset(mclr_tbl, mclr_last); 796 last_reset(full_tbl, full_last); 797 last_reset(type_tbl, type_last); 798 799 int blocks, blk, bw, bh; 800 int i; 801 int stride; 802 803 uint8_t *out = picture; // set to output image 804 805 blk = 0; 806 bw = frameWidth >> 2; 807 bh = frameHeight >> 2; 808 blocks = bw * bh; 809 810 stride = frameWidth; 811 812 uint32_t UNUSED(fileStart) = file.GetPosition(); 813 814 SmackerCommon::BitReader bits(file, frameSize); 815 816 while (blk < blocks) 817 { 818 int type, run, mode; 819 uint16_t pix; 820 821 type = GetCode(bits, type_tbl, type_last); 822 run = block_runs[(type >> 2) & 0x3F]; 823 switch (type & 3) 824 { 825 case SMK_BLK_MONO: 826 while (run-- && blk < blocks) 827 { 828 int clr, map; 829 int hi, lo; 830 clr = GetCode(bits, mclr_tbl, mclr_last); 831 map = GetCode(bits, mmap_tbl, mmap_last); 832 833 out = picture + (blk / bw) * (stride * 4) + (blk % bw) * 4; 834 835 hi = clr >> 8; 836 lo = clr & 0xFF; 837 for (i = 0; i < 4; i++) 838 { 839 if (map & 1) out[0] = hi; else out[0] = lo; 840 if (map & 2) out[1] = hi; else out[1] = lo; 841 if (map & 4) out[2] = hi; else out[2] = lo; 842 if (map & 8) out[3] = hi; else out[3] = lo; 843 map >>= 4; 844 out += stride; 845 } 846 blk++; 847 } 848 break; 849 case SMK_BLK_FULL: 850 mode = 0; 851 if (isVer4) // In case of Smacker v4 we have three modes 852 { 853 if (bits.GetBit()) mode = 1; 854 else if (bits.GetBit()) mode = 2; 855 } 856 857 while (run-- && blk < blocks) 858 { 859 out = picture + (blk / bw) * (stride * 4) + (blk % bw) * 4; 860 switch (mode) 861 { 862 case 0: 863 for (i = 0; i < 4; i++) 864 { 865 pix = GetCode(bits, full_tbl, full_last); 866 // FIX AV_WL16(out+2, pix); 867 out[2] = pix & 0xff; 868 out[3] = pix >> 8; 869 870 pix = GetCode(bits, full_tbl, full_last); 871 // FIX AV_WL16(out, pix); 872 out[0] = pix & 0xff; 873 out[1] = pix >> 8; 874 out += stride; 875 } 876 break; 877 case 1: 878 pix = GetCode(bits, full_tbl, full_last); 879 out[0] = out[1] = pix & 0xFF; 880 out[2] = out[3] = pix >> 8; 881 out += stride; 882 out[0] = out[1] = pix & 0xFF; 883 out[2] = out[3] = pix >> 8; 884 out += stride; 885 pix = GetCode(bits, full_tbl, full_last); 886 out[0] = out[1] = pix & 0xFF; 887 out[2] = out[3] = pix >> 8; 888 out += stride; 889 out[0] = out[1] = pix & 0xFF; 890 out[2] = out[3] = pix >> 8; 891 out += stride; 892 break; 893 case 2: 894 for (i = 0; i < 2; i++) 895 { 896 uint16_t pix1, pix2; 897 pix2 = GetCode(bits, full_tbl, full_last); 898 pix1 = GetCode(bits, full_tbl, full_last); 899 900 // FIX AV_WL16(out, pix1); 901 // FIX AV_WL16(out+2, pix2); 902 out[0] = pix1 & 0xff; 903 out[1] = pix1 >> 8; 904 out[2] = pix2 & 0xff; 905 out[3] = pix2 >> 8; 906 907 out += stride; 908 909 // FIX AV_WL16(out, pix1); 910 // FIX AV_WL16(out+2, pix2); 911 out[0] = pix1 & 0xff; 912 out[1] = pix1 >> 8; 913 out[2] = pix2 & 0xff; 914 out[3] = pix2 >> 8; 915 916 out += stride; 917 } 918 break; 919 } 920 blk++; 921 } 922 break; 923 case SMK_BLK_SKIP: 924 while (run-- && blk < blocks) 925 blk++; 926 break; 927 case SMK_BLK_FILL: 928 mode = type >> 8; 929 while (run-- && blk < blocks) 930 { 931 uint32_t col; 932 out = picture + (blk / bw) * (stride * 4) + (blk % bw) * 4; 933 col = mode * 0x01010101; 934 for (i = 0; i < 4; i++) { 935 *((uint32_t*)out) = col; 936 out += stride; 937 } 938 blk++; 939 } 940 break; 941 } 942 } 943 944 /* FIXME - we don't seems to read/use EVERY bit we 'load' into the bit reader 945 * and as my bitreader reads from the file rather than a buffer read from file 946 * of size 'frameSize', I need to make sure I consume the remaining bits (and thus increment 947 * the file read position to where the code expects it to be when this function returns (ie 948 * 'frameSize' number of bytes must be read 949 */ 950 uint32_t left = bits.GetSize() - bits.GetPosition(); 951 bits.SkipBits(left); 952 953 return 0; 954 } 955 956 /** 957 * Decode Smacker audio data 958 */ 959 int SmackerDecoder::DecodeAudio(uint32_t size, SmackerAudioTrack &track) 960 { 961 HuffContext h[4]{}; 962 SmackerCommon::VLCtable vlc[4]; 963 int val; 964 int i, res; 965 int unpackedSize; 966 int sampleBits, stereo; 967 int pred[2] = {0, 0}; 968 969 int16_t *samples = reinterpret_cast<int16_t*>(track.buffer); 970 int8_t *samples8 = reinterpret_cast<int8_t*>(track.buffer); 971 972 int buf_size = track.bufferSize; 973 974 if (buf_size <= 4) { 975 LOG_F(ERROR, "SmackerDecoder::DecodeAudio() - Packet is too small"); 976 return -1; 977 } 978 979 SmackerCommon::BitReader bits(file, size); 980 981 unpackedSize = bits.GetBits(32); 982 983 if (!bits.GetBit()) { 984 // no sound data 985 return 1; 986 } 987 988 stereo = bits.GetBit(); 989 sampleBits = bits.GetBit(); 990 991 if (stereo ^ (track.nChannels != 1)) { 992 LOG_F(ERROR, "SmackerDecoder::DecodeAudio() - Channels mismatch"); 993 return -1; 994 } 995 996 // Initialize 997 for (i = 0; i < (1 << (sampleBits + stereo)); i++) { 998 h[i].length = 256; 999 h[i].maxlength = 0; 1000 h[i].current = 0; 1001 h[i].bits.resize(256); 1002 h[i].lengths.resize(256); 1003 h[i].values.resize(256); 1004 1005 bits.SkipBits(1); 1006 DecodeTree(bits, &h[i], 0, 0); 1007 bits.SkipBits(1); 1008 1009 if (h[i].current > 1) { 1010 VLC_InitTable(vlc[i], h[i].maxlength, h[i].current, &h[i].lengths[0], &h[i].bits[0]); 1011 } 1012 } 1013 if (sampleBits) { //decode 16-bit data 1014 for (i = stereo; i >= 0; i--) 1015 pred[i] = av_bswap16(bits.GetBits(16)); 1016 for (i = 0; i <= stereo; i++) 1017 *samples++ = pred[i]; 1018 for (; i < unpackedSize / 2; i++) { 1019 if (i & stereo) { 1020 if (VLC_GetSize(vlc[2])) 1021 res = VLC_GetCodeBits(bits, vlc[2]); 1022 else 1023 res = 0; 1024 val = h[2].values[res]; 1025 if (VLC_GetSize(vlc[3])) 1026 res = VLC_GetCodeBits(bits, vlc[3]); 1027 else 1028 res = 0; 1029 val |= h[3].values[res] << 8; 1030 pred[1] += (int16_t)val; 1031 *samples++ = pred[1]; 1032 } else { 1033 if (VLC_GetSize(vlc[0])) 1034 res = VLC_GetCodeBits(bits, vlc[0]); 1035 else 1036 res = 0; 1037 val = h[0].values[res]; 1038 if (VLC_GetSize(vlc[1])) 1039 res = VLC_GetCodeBits(bits, vlc[1]); 1040 else 1041 res = 0; 1042 val |= h[1].values[res] << 8; 1043 pred[0] += val; 1044 *samples++ = pred[0]; 1045 } 1046 } 1047 } 1048 else { //8-bit data 1049 for (i = stereo; i >= 0; i--) 1050 pred[i] = bits.GetBits(8); 1051 for (i = 0; i <= stereo; i++) 1052 *samples8++ = pred[i]; 1053 for (; i < unpackedSize; i++) { 1054 if (i & stereo){ 1055 if (VLC_GetSize(vlc[1])) 1056 res = VLC_GetCodeBits(bits, vlc[1]); 1057 else 1058 res = 0; 1059 pred[1] += (int8_t)h[1].values[res]; 1060 *samples8++ = pred[1]; 1061 } else { 1062 if (VLC_GetSize(vlc[0])) 1063 res = VLC_GetCodeBits(bits, vlc[0]); 1064 else 1065 res = 0; 1066 pred[0] += (int8_t)h[0].values[res]; 1067 *samples8++ = pred[0]; 1068 } 1069 } 1070 } 1071 1072 track.bytesReadThisFrame = unpackedSize; 1073 1074 uint32_t left = bits.GetSize() - bits.GetPosition(); 1075 bits.SkipBits(left); 1076 1077 return 0; 1078 } 1079 1080 void SmackerDecoder::GetPalette(uint8_t *palette) 1081 { 1082 memcpy(palette, this->palette, 768); 1083 } 1084 1085 void SmackerDecoder::GetFrame(uint8_t *frame) 1086 { 1087 memcpy(frame, this->picture, frameWidth * frameHeight); 1088 } 1089 1090 void SmackerDecoder::GetFrameSize(uint32_t &width, uint32_t &height) 1091 { 1092 width = this->frameWidth; 1093 height = this->frameHeight; 1094 } 1095 1096 uint32_t SmackerDecoder::GetNumFrames() 1097 { 1098 return nFrames; 1099 } 1100 1101 uint32_t SmackerDecoder::GetCurrentFrameNum() 1102 { 1103 return currentFrame; 1104 } 1105 1106 float SmackerDecoder::GetFrameRate() 1107 { 1108 return (float)fps; 1109 } 1110 1111 void SmackerDecoder::GotoFrame(uint32_t frameNum) 1112 { 1113 if (frameNum > nFrames) { 1114 LOG_F(ERROR, "SmackerDecoder::GotoFrame() - Invalid frame number"); 1115 return; 1116 } 1117 1118 // file.Seek(firstFrameFilePos, SmackerCommon::FileStream::kSeekStart); 1119 1120 currentFrame = 0; 1121 nextPos = firstFrameFilePos; 1122 1123 for (uint32_t i = 0; i < frameNum + 1; i++) 1124 GetNextFrame(); 1125 } 1126 1127 SmackerAudioInfo SmackerDecoder::GetAudioTrackDetails(uint32_t trackIndex) 1128 { 1129 SmackerAudioInfo info; 1130 SmackerAudioTrack *track = &audioTracks[trackIndex]; 1131 1132 info.sampleRate = track->sampleRate; 1133 info.nChannels = track->nChannels; 1134 info.bitsPerSample = track->bitsPerSample; 1135 1136 // audio buffer size in bytes 1137 info.idealBufferSize = track->bufferSize; 1138 1139 return info; 1140 } 1141 1142 uint32_t SmackerDecoder::GetAudioData(uint32_t trackIndex, int16_t *audioBuffer) 1143 { 1144 if (!audioBuffer) { 1145 return 0; 1146 } 1147 1148 SmackerAudioTrack *track = &audioTracks[trackIndex]; 1149 1150 if (track->bytesReadThisFrame) { 1151 memcpy(audioBuffer, track->buffer, std::min(track->bufferSize, track->bytesReadThisFrame)); 1152 } 1153 1154 return track->bytesReadThisFrame; 1155 }