summaryrefslogtreecommitdiff
path: root/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp')
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp216
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)
+ }
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~