diff options
Diffstat (limited to 'libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp')
-rw-r--r-- | libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp new file mode 100644 index 0000000000..ba07580bba --- /dev/null +++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp @@ -0,0 +1,216 @@ +/* + File: CompressedPacketTable.cpp + Abstract: CompressedPacketTable.h + Version: 1.1 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Inc. ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or redistribution of + this Apple software constitutes acceptance of these terms. If you do + not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2014 Apple Inc. All Rights Reserved. + +*/ +#include "CompressedPacketTable.h" +#include "CAAutoDisposer.h" + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const UInt32 CompressedPacketTable::kShift = 5; +const UInt32 CompressedPacketTable::kMask = 31; + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +CompressedPacketTable::~CompressedPacketTable() +{ + size_t size = mBases.size(); + for (size_t i = 0; i < size; ++i) { + free(mBases[i].mDescs); + } +} + +void CompressedPacketTable::push_back(const AudioStreamPacketDescriptionExtended& inDesc) +{ + SInt64 baseIndex = mSize >> kShift; + UInt32 packetIndex = (UInt32)(mSize & kMask); + + if (packetIndex == 0) { + // first packet in a new sequence. create a new PacketBase. + PacketBase newBase; + newBase.mBaseOffset = 0; + newBase.mDescs = CA_malloc((kMask+1) * sizeof(AudioStreamPacketDescriptionExtended)); + newBase.mDescType = kExtendedPacketDescription; + mBases.push_back(newBase); + } + + PacketBase& base = mBases[(size_t)baseIndex]; + AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs; + descs[packetIndex] = inDesc; + + if (packetIndex == kMask) { + // last packet in a sequence. compress the sequence. + Compress(base); + } + + mSize++; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define ACCESS_TYPE(TYPE) \ + case k##TYPE##ContiguousPacketDescription : { \ + TYPE##ContiguousPacketDescription* descs = (TYPE##ContiguousPacketDescription*)base.mDescs; \ + packetOffset = packetIndex ? descs[packetIndex-1].mNextOffset : 0; \ + packetSize = (UInt32)(descs[packetIndex].mNextOffset - packetOffset); \ + } break; \ + case k##TYPE##DiscontiguousPacketDescription : { \ + TYPE##DiscontiguousPacketDescription* descs = (TYPE##DiscontiguousPacketDescription*)base.mDescs; \ + packetOffset = packetIndex ? descs[packetIndex-1].mNextOffset : 0; \ + packetSize = descs[packetIndex].mDataByteSize; \ + } break; + +const AudioStreamPacketDescriptionExtended CompressedPacketTable::operator[](SInt64 inPacketIndex) const +{ + SInt64 baseIndex = inPacketIndex >> kShift; + UInt32 packetIndex = (UInt32)(inPacketIndex & kMask); + + if ((size_t)baseIndex >= mBases.size()) + throw -1; + + const PacketBase& base = mBases[(size_t)baseIndex]; + + SInt64 packetOffset = 0; + UInt32 packetSize = 0; + + switch (base.mDescType) + { + ACCESS_TYPE(Tiny) + ACCESS_TYPE(Small) + ACCESS_TYPE(Big) + case kExtendedPacketDescription : + return ((AudioStreamPacketDescriptionExtended*)base.mDescs)[packetIndex]; + } + + AudioStreamPacketDescriptionExtended outDesc; + outDesc.mStartOffset = base.mBaseOffset + packetOffset; + outDesc.mDataByteSize = packetSize; + outDesc.mVariableFramesInPacket = 0; + outDesc.mFrameOffset = mFramesPerPacket * inPacketIndex; + + //printf("get %d %10qd %10qd %2d %10qd %6d %10qd\n", base.mDescType, inPacketIndex, baseIndex, packetIndex, outDesc.mStartOffset, outDesc.mDataByteSize, outDesc.mFrameOffset); + + return outDesc; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +bool CompressedPacketTable::isContiguous(PacketBase& base) +{ + AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs; + SInt64 expectedOffset = descs[0].mStartOffset + descs[0].mDataByteSize; + for (UInt32 i = 1; i <= kMask; ++i) { + if (expectedOffset != descs[i].mStartOffset) return false; + expectedOffset += descs[i].mDataByteSize; + } + return true; +} + +bool CompressedPacketTable::hasVariableFrames(PacketBase& base) +{ + AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs; + for (UInt32 i = 0; i <= kMask; ++i) { + if (descs[i].mVariableFramesInPacket) return true; + } + return false; +} + +UInt32 CompressedPacketTable::largestPacket(PacketBase& base) +{ + UInt32 maxPacketSize = 0; + AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs; + for (UInt32 i = 0; i <= kMask; ++i) { + UInt32 packetSize = descs[i].mDataByteSize; + if (packetSize > maxPacketSize) maxPacketSize = packetSize; + } + return maxPacketSize; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define COMPRESS_TYPE(TYPE, BITS) \ + if (contiguous) { \ + TYPE##ContiguousPacketDescription* newDescs = (TYPE##ContiguousPacketDescription*)CA_malloc((kMask+1) * sizeof(TYPE##ContiguousPacketDescription)); \ + base.mDescs = newDescs; \ + base.mDescType = k##TYPE##ContiguousPacketDescription; \ + for (UInt32 i = 0; i <= kMask; ++i) { \ + newDescs[i].mNextOffset = (BITS)(descs[i].mStartOffset + descs[i].mDataByteSize - baseOffset); \ + } \ + free(descs); \ + } else { \ + TYPE##DiscontiguousPacketDescription* newDescs = (TYPE##DiscontiguousPacketDescription*)CA_malloc((kMask+1) * sizeof(TYPE##DiscontiguousPacketDescription)); \ + base.mDescs = newDescs; \ + base.mDescType = k##TYPE##DiscontiguousPacketDescription; \ + for (UInt32 i = 0; i <= kMask; ++i) { \ + newDescs[i].mNextOffset = i == kMask ? 0 : (BITS)(descs[i+1].mStartOffset - baseOffset); \ + newDescs[i].mDataByteSize = descs[i].mDataByteSize; \ + } \ + free(descs); \ + } \ + return; + +void CompressedPacketTable::Compress(PacketBase& base) +{ + if (hasVariableFrames(base)) + return; + + bool contiguous = isContiguous(base); + + AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs; + SInt64 delta = descs[kMask].mStartOffset + descs[kMask].mDataByteSize - descs[0].mStartOffset; + + SInt64 baseOffset = descs[0].mStartOffset; + base.mBaseOffset = baseOffset; + + if (delta <= 65535LL) { + COMPRESS_TYPE(Tiny, UInt16) + } else if (delta <= 4294967295LL && largestPacket(base) <= 65535) { + COMPRESS_TYPE(Small, UInt32) + } else { + COMPRESS_TYPE(Big, SInt64) + } +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |