/ source / libsmackerdec / src / SmackerDecoder.cpp
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  }