1 /*
2      File: CompressedPacketTable.h
3  Abstract: Part of CoreAudio Utility Classes
4   Version: 1.1
5 
6  Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
7  Inc. ("Apple") in consideration of your agreement to the following
8  terms, and your use, installation, modification or redistribution of
9  this Apple software constitutes acceptance of these terms.  If you do
10  not agree with these terms, please do not use, install, modify or
11  redistribute this Apple software.
12 
13  In consideration of your agreement to abide by the following terms, and
14  subject to these terms, Apple grants you a personal, non-exclusive
15  license, under Apple's copyrights in this original Apple software (the
16  "Apple Software"), to use, reproduce, modify and redistribute the Apple
17  Software, with or without modifications, in source and/or binary forms;
18  provided that if you redistribute the Apple Software in its entirety and
19  without modifications, you must retain this notice and the following
20  text and disclaimers in all such redistributions of the Apple Software.
21  Neither the name, trademarks, service marks or logos of Apple Inc. may
22  be used to endorse or promote products derived from the Apple Software
23  without specific prior written permission from Apple.  Except as
24  expressly stated in this notice, no other rights or licenses, express or
25  implied, are granted by Apple herein, including but not limited to any
26  patent rights that may be infringed by your derivative works or by other
27  works in which the Apple Software may be incorporated.
28 
29  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
30  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 
35  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42  POSSIBILITY OF SUCH DAMAGE.
43 
44  Copyright (C) 2014 Apple Inc. All Rights Reserved.
45 
46 */
47 #include <iterator>
48 #include <vector>
49 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
50 	#include <CoreAudio/CoreAudioTypes.h>
51 #else
52 	#include "CoreAudioTypes.h"
53 #endif
54 
55 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56 
57 struct  AudioStreamPacketDescriptionExtended : AudioStreamPacketDescription
58 {
59     SInt64  mFrameOffset; // this is the sum of the mVariableFramesInPacket up to this point so we can binary search.
60 };
61 typedef struct AudioStreamPacketDescriptionExtended AudioStreamPacketDescriptionExtended;
62 
63 inline bool operator < (const AudioStreamPacketDescriptionExtended& a, const AudioStreamPacketDescriptionExtended& b)
64 {
65 	return a.mFrameOffset < b.mFrameOffset;
66 }
67 
68 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 
70 class CompressedPacketTable
71 {
72 public:
CompressedPacketTable(UInt32 inFramesPerPacket)73 	CompressedPacketTable(UInt32 inFramesPerPacket) : mSize(0), mFramesPerPacket(inFramesPerPacket) {}
74 	~CompressedPacketTable();
75 
size()76 	SInt64 size() const { return mSize; }
77 	void push_back(const AudioStreamPacketDescriptionExtended& inDesc);
78 
79 	const AudioStreamPacketDescriptionExtended operator[](SInt64 inPacketIndex) const;
front()80 	const AudioStreamPacketDescriptionExtended front() const { return (*this)[0]; }
back()81 	const AudioStreamPacketDescriptionExtended back() const { return (*this)[mSize-1]; }
82 
83 	//SInt64 PacketForByte(SInt64 inByteOffset) const;
ByteForPacket(SInt64 inPacketIndex)84 	SInt64 ByteForPacket(SInt64 inPacketIndex) const { return (*this)[inPacketIndex].mStartOffset; }
85 
86 	class iterator {
87 		public:
88 			typedef std::input_iterator_tag iterator_category;
89 			typedef iterator pointer;
90 			typedef SInt64 difference_type;
91 			typedef AudioStreamPacketDescriptionExtended value_type;
92 			typedef value_type& reference;
93 
iterator()94 			iterator() : mTable(NULL), mIndex(0) {}
iterator(const CompressedPacketTable * table,SInt64 index)95 			iterator(const CompressedPacketTable* table, SInt64 index) : mTable(table), mIndex(index) {}
iterator(const iterator & that)96 			iterator(const iterator& that) : mTable(that.mTable), mIndex(that.mIndex) {}
97 
98 			iterator& operator=(const iterator& that) { mTable = that.mTable; mIndex = that.mIndex; return *this; }
99 
100 			const AudioStreamPacketDescriptionExtended operator*() const { return (*mTable)[mIndex]; }
101 			const AudioStreamPacketDescriptionExtended* const operator->() { mValue = (*mTable)[mIndex]; return &mValue; }
102 			iterator& operator++() { ++mIndex; return *this; }
103 			iterator& operator--() { --mIndex; return *this; }
104 
105 			SInt64 operator-(const iterator& that) { return mIndex - that.mIndex; }
106 			const iterator operator-(SInt64 index) { return iterator(mTable, mIndex - index); }
107 			const iterator operator+(SInt64 index) { return iterator(mTable, mIndex + index); }
108 			bool operator==(const iterator& that) { return mIndex == that.mIndex; }
109 			bool operator!=(const iterator& that) { return mIndex != that.mIndex; }
110 			bool operator>(const iterator& that) { return mIndex > that.mIndex; }
111 			bool operator<(const iterator& that) { return mIndex < that.mIndex; }
112 		private:
113 			const CompressedPacketTable* mTable;
114 			SInt64 mIndex;
115 			AudioStreamPacketDescriptionExtended mValue; // in order to support operator-> .
116 	};
117 
begin()118 	iterator begin() const { return iterator(this, 0); }
end()119 	iterator end() const { return iterator(this, mSize); }
120 
121 private:
122 	struct TinyContiguousPacketDescription
123 	{
124 		UInt16 mNextOffset;
125 	};
126 
127 	struct TinyDiscontiguousPacketDescription : TinyContiguousPacketDescription
128 	{
129 		UInt16 mDataByteSize;
130 	};
131 
132 	// There could be a 24 bit packet description. But ALAC is who usually needs SmallContiguousPacketDescription and
133 	// it already uses 8x fewer packet descriptions than AAC due to the mFramesPerPacket being 8x greater.
134 	// So there isn't as great a need for saving space. 4 bytes per packet is OK for ALAC.
135 
136 	struct SmallContiguousPacketDescription
137 	{
138 		UInt32 mNextOffset;
139 	};
140 
141 	struct SmallDiscontiguousPacketDescription : SmallContiguousPacketDescription
142 	{
143 		UInt16 mDataByteSize;
144 	};
145 
146 	struct BigContiguousPacketDescription
147 	{
148 		UInt64 mNextOffset;
149 	};
150 
151 	struct BigDiscontiguousPacketDescription : BigContiguousPacketDescription
152 	{
153 		UInt32 mDataByteSize;
154 	};
155 
156 	struct PacketBase
157 	{
158 		SInt64 mBaseOffset;
159 		UInt8 mDescType;
160 		void* mDescs;
161 	};
162 
163 	enum {
164 		kTinyContiguousPacketDescription,
165 		kTinyDiscontiguousPacketDescription,
166 		kSmallContiguousPacketDescription,
167 		kSmallDiscontiguousPacketDescription,
168 		kBigContiguousPacketDescription,
169 		kBigDiscontiguousPacketDescription,
170 		kExtendedPacketDescription
171 	};
172 	static const UInt32 kShift;
173 	static const UInt32 kMask;
174 
175 	bool isContiguous(PacketBase& base);
176 	bool hasVariableFrames(PacketBase& base);
177 	UInt32 largestPacket(PacketBase& base);
178 
179 	void Compress(PacketBase& base);
180 
181 private:
182 	std::vector<PacketBase> mBases;
183 	UInt64 mSize;
184 	UInt32 mFramesPerPacket;
185 };
186 
187