Read in full packets at a time from smacker files

This commit is contained in:
Chris Robinson 2022-10-01 22:26:29 -07:00 committed by Christoph Oelckers
parent 7401e02a14
commit 19a4eb79aa
4 changed files with 42 additions and 69 deletions

View file

@ -29,8 +29,8 @@ namespace SmackerCommon {
class BitReader class BitReader
{ {
public: public:
BitReader(SmackerCommon::FileStream &file, uint32_t size); BitReader(const uint8_t *data, uint32_t size) : bitData(data), totalSize(size) { }
~BitReader(); ~BitReader() = default;
uint32_t GetBit(); uint32_t GetBit();
uint32_t GetBits(uint32_t n); uint32_t GetBits(uint32_t n);
void SkipBits(uint32_t n); void SkipBits(uint32_t n);
@ -39,15 +39,10 @@ class BitReader
uint32_t GetPosition(); uint32_t GetPosition();
private: private:
uint32_t totalSize; const uint8_t *bitData = nullptr;
uint32_t currentOffset; uint32_t totalSize = 0;
uint32_t bytesRead; uint32_t currentOffset = 0;
uint32_t bytesRead = 0;
SmackerCommon::FileStream *file;
TArray<uint8_t> Cache;
void FillCache();
}; };
} // close namespace SmackerCommon } // close namespace SmackerCommon

View file

@ -135,6 +135,8 @@ class SmackerDecoder
bool isVer4; bool isVer4;
std::vector<uint8_t> packetData;
uint8_t *packetDataPtr = nullptr;
SmackerAudioTrack audioTracks[kMaxAudioTracks]; SmackerAudioTrack audioTracks[kMaxAudioTracks];
uint32_t treeSize; uint32_t treeSize;

View file

@ -22,25 +22,6 @@
namespace SmackerCommon { namespace SmackerCommon {
BitReader::BitReader(SmackerCommon::FileStream &file, uint32_t size)
{
this->file = &file;
this->totalSize = size;
this->currentOffset = 0;
this->bytesRead = 0;
this->Cache.Resize(size);
file.ReadBytes(this->Cache.Data(), size);
}
BitReader::~BitReader()
{
}
void BitReader::FillCache()
{
}
uint32_t BitReader::GetSize() uint32_t BitReader::GetSize()
{ {
return totalSize * 8; return totalSize * 8;
@ -53,7 +34,7 @@ uint32_t BitReader::GetPosition()
uint32_t BitReader::GetBit() uint32_t BitReader::GetBit()
{ {
uint32_t ret = (Cache[currentOffset>>3]>>(currentOffset&7))&1; uint32_t ret = (bitData[currentOffset>>3]>>(currentOffset&7))&1;
currentOffset++; currentOffset++;
return ret; return ret;
} }

View file

@ -49,6 +49,7 @@
#include "limits.h" #include "limits.h"
#include <assert.h> #include <assert.h>
#include <algorithm> #include <algorithm>
#include <memory>
std::vector<class SmackerDecoder*> classInstances; std::vector<class SmackerDecoder*> classInstances;
@ -372,6 +373,10 @@ bool SmackerDecoder::Open(const char *fileName)
frameFlags[i] = file.ReadByte(); frameFlags[i] = file.ReadByte();
} }
auto maxFrameSize = std::max_element(frameSizes.begin(), frameSizes.end());
if (maxFrameSize != frameSizes.end())
packetData.reserve(*maxFrameSize);
// handle possible audio streams // handle possible audio streams
for (int i = 0; i < kMaxAudioTracks; i++) for (int i = 0; i < kMaxAudioTracks; i++)
{ {
@ -633,7 +638,10 @@ int SmackerDecoder::DecodeHeaderTree(SmackerCommon::BitReader &bits, std::vector
// static int decode_header_trees(SmackVContext *smk) { // static int decode_header_trees(SmackVContext *smk) {
bool SmackerDecoder::DecodeHeaderTrees() bool SmackerDecoder::DecodeHeaderTrees()
{ {
SmackerCommon::BitReader bits(file, treeSize); auto treeData = std::make_unique<uint8_t[]>(treeSize);
file.ReadBytes(treeData.get(), treeSize);
SmackerCommon::BitReader bits(treeData.get(), treeSize);
if (!bits.GetBit()) if (!bits.GetBit())
{ {
@ -683,15 +691,6 @@ bool SmackerDecoder::DecodeHeaderTrees()
DecodeHeaderTree(bits, type_tbl, type_last, typeSize); DecodeHeaderTree(bits, type_tbl, type_last, typeSize);
} }
/* FIXME - we don't seems to read/use EVERY bit we 'load' into the bit reader
* and as my bitreader reads from the file rather than a buffer read from file
* of size 'treeSize', I need to make sure I consume the remaining bits (and thus increment
* the file read position to where the code expects it to be when this function returns (ie
* 'treeSize' number of bytes must be read
*/
uint32_t left = bits.GetSize() - bits.GetPosition();
bits.SkipBits(left);
return true; return true;
} }
@ -712,29 +711,34 @@ int SmackerDecoder::ReadPacket()
uint32_t frameSize = frameSizes[currentFrame] & (~3); uint32_t frameSize = frameSizes[currentFrame] & (~3);
uint8_t frameFlag = frameFlags[currentFrame]; uint8_t frameFlag = frameFlags[currentFrame];
packetData.resize(frameSize);
packetDataPtr = packetData.data();
file.ReadBytes(packetDataPtr, frameSize);
// handle palette change // handle palette change
if (frameFlag & kSMKpal) if (frameFlag & kSMKpal)
{ {
int size, sz, t, off, j, pos; int size, sz, t, off, j;
uint8_t *pal = palette; uint8_t *pal = palette;
uint8_t oldpal[768]; uint8_t oldpal[768];
uint8_t *dataEnd;
memcpy(oldpal, pal, 768); memcpy(oldpal, pal, 768);
size = file.ReadByte(); size = *(packetDataPtr++);
size = size * 4 - 1; size = size * 4 - 1;
frameSize -= size; frameSize -= size;
frameSize--; frameSize--;
sz = 0; sz = 0;
pos = file.GetPosition() + size; dataEnd = packetDataPtr + size;
while (sz < 256) while (sz < 256)
{ {
t = file.ReadByte(); t = *(packetDataPtr++);
if (t & 0x80){ /* skip palette entries */ if (t & 0x80){ /* skip palette entries */
sz += (t & 0x7F) + 1; sz += (t & 0x7F) + 1;
pal += ((t & 0x7F) + 1) * 3; pal += ((t & 0x7F) + 1) * 3;
} else if (t & 0x40){ /* copy with offset */ } else if (t & 0x40){ /* copy with offset */
off = file.ReadByte() * 3; off = *(packetDataPtr++) * 3;
j = (t & 0x3F) + 1; j = (t & 0x3F) + 1;
while (j-- && sz < 256) { while (j-- && sz < 256) {
*pal++ = oldpal[off + 0]; *pal++ = oldpal[off + 0];
@ -745,13 +749,13 @@ int SmackerDecoder::ReadPacket()
} }
} else { /* new entries */ } else { /* new entries */
*pal++ = smk_pal[t]; *pal++ = smk_pal[t];
*pal++ = smk_pal[file.ReadByte() & 0x3F]; *pal++ = smk_pal[*(packetDataPtr++) & 0x3F];
*pal++ = smk_pal[file.ReadByte() & 0x3F]; *pal++ = smk_pal[*(packetDataPtr++) & 0x3F];
sz++; sz++;
} }
} }
file.Seek(pos, SmackerCommon::FileStream::kSeekStart); packetDataPtr = dataEnd;
} }
frameFlag >>= 1; frameFlag >>= 1;
@ -763,11 +767,13 @@ int SmackerDecoder::ReadPacket()
if (frameFlag & 1) if (frameFlag & 1)
{ {
uint32_t size = file.ReadUint32LE() - 4; uint32_t size = *(packetDataPtr++);
size |= *(packetDataPtr++) << 8;
size |= *(packetDataPtr++) << 16;
size |= *(packetDataPtr++) << 24;
frameSize -= size; frameSize -= size;
frameSize -= 4;
DecodeAudio(size, audioTracks[i]); DecodeAudio(size-4, audioTracks[i]);
} }
frameFlag >>= 1; frameFlag >>= 1;
} }
@ -805,7 +811,8 @@ int SmackerDecoder::DecodeFrame(uint32_t frameSize)
stride = frameWidth; stride = frameWidth;
SmackerCommon::BitReader bits(file, frameSize); SmackerCommon::BitReader bits(packetDataPtr, frameSize);
packetDataPtr += frameSize;
while (blk < blocks) while (blk < blocks)
{ {
@ -935,15 +942,6 @@ int SmackerDecoder::DecodeFrame(uint32_t frameSize)
} }
} }
/* FIXME - we don't seems to read/use EVERY bit we 'load' into the bit reader
* and as my bitreader reads from the file rather than a buffer read from file
* of size 'frameSize', I need to make sure I consume the remaining bits (and thus increment
* the file read position to where the code expects it to be when this function returns (ie
* 'frameSize' number of bytes must be read
*/
uint32_t left = bits.GetSize() - bits.GetPosition();
bits.SkipBits(left);
return 0; return 0;
} }
@ -952,7 +950,6 @@ int SmackerDecoder::DecodeFrame(uint32_t frameSize)
*/ */
int SmackerDecoder::DecodeAudio(uint32_t size, SmackerAudioTrack &track) int SmackerDecoder::DecodeAudio(uint32_t size, SmackerAudioTrack &track)
{ {
HuffContext h[4];
SmackerCommon::VLCtable vlc[4]; SmackerCommon::VLCtable vlc[4];
int val; int val;
int i, res; int i, res;
@ -970,7 +967,8 @@ int SmackerDecoder::DecodeAudio(uint32_t size, SmackerAudioTrack &track)
return -1; return -1;
} }
SmackerCommon::BitReader bits(file, size); SmackerCommon::BitReader bits(packetDataPtr, size);
packetDataPtr += size;
unpackedSize = bits.GetBits(32); unpackedSize = bits.GetBits(32);
@ -987,7 +985,7 @@ int SmackerDecoder::DecodeAudio(uint32_t size, SmackerAudioTrack &track)
return -1; return -1;
} }
memset(h, 0, sizeof(HuffContext) * 4); HuffContext h[4];
// Initialize // Initialize
for (i = 0; i < (1 << (sampleBits + stereo)); i++) { for (i = 0; i < (1 << (sampleBits + stereo)); i++) {
@ -1067,9 +1065,6 @@ int SmackerDecoder::DecodeAudio(uint32_t size, SmackerAudioTrack &track)
track.bytesReadThisFrame = unpackedSize; track.bytesReadThisFrame = unpackedSize;
uint32_t left = bits.GetSize() - bits.GetPosition();
bits.SkipBits(left);
return 0; return 0;
} }