size_t HuffDecompressor::decompress(ZLInputStream &stream, char *targetBuffer, size_t compressedSize, size_t maxUncompressedSize) { if (compressedSize == 0 || myErrorCode == ERROR_CORRUPTED_FILE) { return 0; } if (targetBuffer != 0) { unsigned char *sourceBuffer = new unsigned char[compressedSize]; myTargetBuffer = targetBuffer; myTargetBufferEnd = targetBuffer + maxUncompressedSize; myTargetBufferPtr = targetBuffer; if (stream.read((char*)sourceBuffer, compressedSize) == compressedSize) { const size_t trailSize = sizeOfTrailingEntries(sourceBuffer, compressedSize); if (trailSize < compressedSize) { bitsDecompress(BitReader(sourceBuffer, compressedSize - trailSize)); } else { myErrorCode = ERROR_CORRUPTED_FILE; } } delete[] sourceBuffer; } else { myTargetBuffer = 0; myTargetBufferEnd = 0; myTargetBufferPtr = 0; } return myTargetBufferPtr - myTargetBuffer; }
void HuffDecompressor::bitsDecompress(BitReader bits, size_t depth) { if (depth > 32) { myErrorCode = ERROR_CORRUPTED_FILE; return; } while (bits.left()) { const unsigned long dw = (unsigned long)bits.peek(32); const unsigned long v = myCacheTable[dw >> 24]; unsigned long codelen = v & 0x1F; //if ((codelen == 0) || (codelen > 32)) { // return false; //} unsigned long code = dw >> (32 - codelen); unsigned long r = (v >> 8); if ((v & 0x80) == 0) { while (code < myBaseTable[(codelen - 1) * 2]) { codelen += 1; code = dw >> (32 - codelen); } r = myBaseTable[(codelen - 1) * 2 + 1]; } r -= code; //if (codelen == 0) { // return false; //} if (!bits.eat(codelen)) { return; } const unsigned long dicno = r >> myEntryBits; const unsigned long off1 = 16 + (r - (dicno << myEntryBits)) * 2; const unsigned char* dict = myDicts[dicno]; //TODO need index check const unsigned long off2 = 16 + dict[off1] * 256 + dict[off1 + 1]; //TODO need index check const unsigned long blen = dict[off2] * 256 + dict[off2 + 1]; //TODO need index check const unsigned char* slice = dict + off2 + 2; const unsigned long sliceSize = blen & 0x7fff; if (blen & 0x8000) { if (myTargetBufferPtr + sliceSize < myTargetBufferEnd) { memcpy(myTargetBufferPtr, slice, sliceSize); myTargetBufferPtr += sliceSize; } else { return; } } else { bitsDecompress(BitReader(slice, sliceSize), depth + 1); } } }
bool DtsHeaderParser::parseHeader(const uint8_t *hdr, HeaderInfo *hinfo) { DtsFrameInfo dtsFi; int bsType; bool isBigEndian(true); if ( dtsFi.init(BitReader(hdr, 16, true)) ) bsType = dtsFi.getIs14Bit() ? BITSTREAM_14BE : BITSTREAM_16BE; else if ( dtsFi.init(BitReader(hdr, 16, false)) ) { bsType = dtsFi.getIs14Bit() ? BITSTREAM_14LE : BITSTREAM_16LE; isBigEndian = false; } else return false; ///////////////////////////////////////////////////////// // Constraints if ( dtsFi.getSampleBlocks() < 6 ) // constraint return false; else if ( dtsFi.getChannelLayout() > 0xc ) // we don't work with more than 6 channels return false; else if ( dtsFi.getSampleRate() == 0 ) // constraint return false; else if ( dtsFi.getLfe() == 3 ) // constraint return false; DtsHdFrameInfo dtsHdFrameInfo(BitReader(hdr+dtsFi.getFrameSize(), 16, isBigEndian)); if ( hinfo ) { const int layout2MaskTable[] = { MODE_MONO, MODE_STEREO, MODE_STEREO, MODE_STEREO, MODE_STEREO, MODE_3_0, MODE_2_1, MODE_3_1, MODE_2_2, MODE_3_2 }; const int layout2RelationTable[] = { NO_RELATION, NO_RELATION, NO_RELATION, RELATION_SUMDIFF, RELATION_DOLBY, NO_RELATION, NO_RELATION, NO_RELATION, NO_RELATION, NO_RELATION, }; int mask(layout2MaskTable[dtsFi.getChannelLayout()]); const int relation(layout2RelationTable[dtsFi.getChannelLayout()]); if ( dtsFi.getLfe() ) { mask |= CH_MASK_LFE; } hinfo->setSpeakers(Speakers(FORMAT_DTS, mask, dtsFi.getSampleRate(), 1.0, relation)); hinfo->setFrameSize(dtsFi.getFrameSize() + dtsHdFrameInfo.getHdSize()); hinfo->setDtsHdSize(dtsHdFrameInfo.getHdSize()); hinfo->setScanSize(16384); // always scan up to maximum DTS frame size hinfo->setSampleCount(dtsFi.getSampleCount()); hinfo->setBsType(bsType); switch ( hinfo->getSampleCount() ) { case 512: hinfo->setSpdifType(11); break; case 1024: hinfo->setSpdifType(12); break; case 2048: hinfo->setSpdifType(13); break; default: hinfo->setSpdifType(0); // cannot do SPDIF passthrough break; } } return true; }