root/trunk/ACPublic/ACSimpleCodec.cpp

Revision 1, 10.8 kB (checked in by gbooker, 3 years ago)

Initial Import

Line 
1 /*      Copyright:      © Copyright 2004 Apple Computer, Inc. All rights reserved.
2
3         Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
4                         ("Apple") in consideration of your agreement to the following terms, and your
5                         use, installation, modification or redistribution of this Apple software
6                         constitutes acceptance of these terms.  If you do not agree with these terms,
7                         please do not use, install, modify or redistribute this Apple software.
8
9                         In consideration of your agreement to abide by the following terms, and subject
10                         to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
11                         copyrights in this original Apple software (the "Apple Software"), to use,
12                         reproduce, modify and redistribute the Apple Software, with or without
13                         modifications, in source and/or binary forms; provided that if you redistribute
14                         the Apple Software in its entirety and without modifications, you must retain
15                         this notice and the following text and disclaimers in all such redistributions of
16                         the Apple Software.  Neither the name, trademarks, service marks or logos of
17                         Apple Computer, Inc. may be used to endorse or promote products derived from the
18                         Apple Software without specific prior written permission from Apple.  Except as
19                         expressly stated in this notice, no other rights or licenses, express or implied,
20                         are granted by Apple herein, including but not limited to any patent rights that
21                         may be infringed by your derivative works or by other works in which the Apple
22                         Software may be incorporated.
23
24                         The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
25                         WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
26                         WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27                         PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
28                         COMBINATION WITH YOUR PRODUCTS.
29
30                         IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
31                         CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
32                         GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33                         ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
34                         OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
35                         (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
36                         ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38 /*=============================================================================
39         ACSimpleCodec.cpp
40
41 =============================================================================*/
42
43 //=============================================================================
44 //      Includes
45 //=============================================================================
46
47 #include "ACSimpleCodec.h"
48 #include <string.h>
49
50 //=============================================================================
51 //      ACSimpleCodec
52 //=============================================================================
53
54 static const UInt32 kBufferPad = 3840; // this is used to prevent end from passing start.
55
56 ACSimpleCodec::ACSimpleCodec(UInt32 inInputBufferByteSize)
57 :
58         ACBaseCodec(),
59         mInputBuffer(NULL),
60         mInputBufferByteSize(inInputBufferByteSize+kBufferPad),
61         mInputBufferStart(0),
62         mInputBufferEnd(0)
63 {
64 }
65
66 ACSimpleCodec::~ACSimpleCodec()
67 {
68         delete[] mInputBuffer;
69 }
70
71 void    ACSimpleCodec::Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize)
72 {
73         ReallocateInputBuffer(mInputBufferByteSize - kBufferPad);
74        
75         ACBaseCodec::Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
76 }
77
78 void    ACSimpleCodec::Uninitialize()
79 {
80         //      get rid of the buffer
81         delete[] mInputBuffer;
82         mInputBuffer = NULL;
83        
84         //      reset the ring buffer state
85         mInputBufferStart = 0;
86         mInputBufferEnd = 0;
87        
88         ACBaseCodec::Uninitialize();
89 }
90
91 void    ACSimpleCodec::Reset()
92 {
93         //      clear the entire input buffer
94         if (mInputBuffer) { // could be called before allocated.
95                 memset(mInputBuffer, 0, mInputBufferByteSize);
96         }
97        
98         //      reset the ring buffer state
99         mInputBufferStart = 0;
100         mInputBufferEnd = 0;
101        
102         ACBaseCodec::Reset();
103 }
104
105 UInt32  ACSimpleCodec::GetInputBufferByteSize() const
106 {
107         return mInputBufferByteSize - kBufferPad; // minus kBufferPad to prevent end moving past start
108 }
109
110 UInt32  ACSimpleCodec::GetUsedInputBufferByteSize() const
111 {
112         UInt32 theAnswer = 0;
113        
114         //      this object uses a ring buffer
115         if(mInputBufferStart <= mInputBufferEnd)
116         {
117                 //      the active region is contiguous
118                 theAnswer = mInputBufferEnd - mInputBufferStart;
119         }
120         else
121         {
122                 //      the active region wraps around
123                 theAnswer = (mInputBufferByteSize - mInputBufferStart) + mInputBufferEnd;
124         }
125        
126         return theAnswer;
127 }
128
129 void    ACSimpleCodec::AppendInputBuffer(const void* inInputData, UInt32 inOffset, UInt32& ioInputDataByteSize)
130 {
131         //      this buffer handling code doesn't care about such things as the packet descriptions
132         if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
133        
134         //      this is a ring buffer we're dealing with, so we need to set up a few things
135         UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
136         UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
137        
138         const Byte* theInputData = static_cast<const Byte*>(inInputData) + inOffset;
139        
140         if(ioInputDataByteSize > theAvailableByteSize) {
141                 ioInputDataByteSize = theAvailableByteSize;
142         }
143        
144         //      now we have to copy the data taking into account the wrap around and where the start is
145         if(mInputBufferEnd + ioInputDataByteSize < mInputBufferByteSize)
146         {
147                 //      no wrap around here
148                 memcpy(mInputBuffer + mInputBufferEnd, theInputData, ioInputDataByteSize);
149                
150                 //      adjust the end point
151                 mInputBufferEnd += ioInputDataByteSize;
152         }
153         else
154         {
155                 //      the copy will wrap
156                
157                 //      copy the first part
158                 UInt32 theBeforeWrapByteSize = mInputBufferByteSize - mInputBufferEnd;
159                 memcpy(mInputBuffer + mInputBufferEnd, theInputData, theBeforeWrapByteSize);
160                
161                 //      and the rest
162                 UInt32 theAfterWrapByteSize = ioInputDataByteSize - theBeforeWrapByteSize;
163                 memcpy(mInputBuffer, theInputData + theBeforeWrapByteSize, theAfterWrapByteSize);
164                
165                 //      adjust the end point
166                 mInputBufferEnd = theAfterWrapByteSize;
167         }
168 }
169
170 void    ACSimpleCodec::AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription)
171 {
172         //      this buffer handling code doesn't care about such things as the packet descriptions
173         if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
174        
175         //      this is a ring buffer we're dealing with, so we need to set up a few things
176         UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
177         UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
178
179         UInt32 theMaxAvailableInputBytes = ioInputDataByteSize; // we can't consume more than we get
180
181         const Byte* theInputData = static_cast<const Byte*>(inInputData);
182        
183         // >>jamesmcc: added this because ioNumberPackets was not being updated if less was taken than given.
184         // THIS ASSUMES CBR!
185         UInt32 bytesPerPacketOfInput = mInputFormat.mBytesPerPacket;
186         UInt32 theAvailablePacketSize = theAvailableByteSize / bytesPerPacketOfInput;
187        
188         UInt32 minPacketSize = ioNumberPackets < theAvailablePacketSize ? ioNumberPackets : theAvailablePacketSize;
189         UInt32 minByteSize = minPacketSize * bytesPerPacketOfInput;
190        
191         //      we can copy only as much data as there is or up to how much space is availiable
192         ioNumberPackets = minPacketSize;
193         ioInputDataByteSize = minByteSize;
194        
195         // ioInputDataByteSize had better be <= to theMaxAvailableInputBytes or we're screwed
196         if (ioInputDataByteSize > theMaxAvailableInputBytes)
197         {
198                 CODEC_THROW(kAudioCodecStateError);
199         }
200         // <<jamesmcc
201        
202         //      now we have to copy the data taking into account the wrap around and where the start is
203         if(mInputBufferEnd + ioInputDataByteSize < mInputBufferByteSize)
204         {
205                 //      no wrap around here
206                 memcpy(mInputBuffer + mInputBufferEnd, theInputData, ioInputDataByteSize);
207                
208                 //      adjust the end point
209                 mInputBufferEnd += ioInputDataByteSize;
210         }
211         else
212         {
213                 //      the copy will wrap
214                
215                 //      copy the first part
216                 UInt32 theBeforeWrapByteSize = mInputBufferByteSize - mInputBufferEnd;
217                 memcpy(mInputBuffer + mInputBufferEnd, theInputData, theBeforeWrapByteSize);
218                
219                 //      and the rest
220                 UInt32 theAfterWrapByteSize = ioInputDataByteSize - theBeforeWrapByteSize;
221                 memcpy(mInputBuffer, theInputData + theBeforeWrapByteSize, theAfterWrapByteSize);
222                
223                 //      adjust the end point
224                 mInputBufferEnd = theAfterWrapByteSize;
225         }
226        
227 }
228
229 void    ACSimpleCodec::ConsumeInputData(UInt32 inConsumedByteSize)
230 {
231         //      this is a convenience routine to make maintaining the ring buffer state easy
232         UInt32 theContiguousRange = GetInputBufferContiguousByteSize();
233        
234         if(inConsumedByteSize > GetUsedInputBufferByteSize()) CODEC_THROW(kAudioCodecUnspecifiedError);
235        
236         if(inConsumedByteSize <= theContiguousRange)
237         {
238                 //      the region to consume doesn't wrap
239                
240                 //      figure out how much to consume
241                 inConsumedByteSize = (theContiguousRange < inConsumedByteSize) ? theContiguousRange : inConsumedByteSize;
242                
243                 //      clear the consumed bits
244                 memset(mInputBuffer + mInputBufferStart, 0, inConsumedByteSize);
245                
246                 //      adjust the start
247                 mInputBufferStart += inConsumedByteSize;
248         }
249         else
250         {
251                 //      the region to consume will wrap
252                
253                 //      clear the bits to the end of the buffer
254                 memset(mInputBuffer + mInputBufferStart, 0, theContiguousRange);
255                
256                 //      now clear the bits left from the start
257                 memset(mInputBuffer, 0, inConsumedByteSize - theContiguousRange);
258                
259                 //      adjust the start
260                 mInputBufferStart = inConsumedByteSize - theContiguousRange;
261         }
262 }
263
264
265 Byte* ACSimpleCodec::GetBytes(UInt32& ioNumberBytes) const
266 {
267         // if a client's algorithm has to have contiguous data and mInputBuffer wraps, then someone has to make a copy.
268         // I can do it more efficiently than the client.
269        
270         if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError);
271
272         UInt32 theUsedByteSize = GetUsedInputBufferByteSize();
273         //UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize;
274        
275         if (ioNumberBytes > theUsedByteSize) ioNumberBytes = theUsedByteSize;
276                
277         SInt32 leftOver = mInputBufferStart + ioNumberBytes - mInputBufferByteSize;
278        
279         if(leftOver > 0)
280         {
281                 // need to copy beginning of buffer to the end.
282                 // We cleverly over allocated our buffer space to make this possible.
283                 memcpy(mInputBuffer + mInputBufferByteSize, mInputBuffer, leftOver);
284         }
285        
286         return GetInputBufferStart();
287 }
288
289
290 void    ACSimpleCodec::ReallocateInputBuffer(UInt32 inInputBufferByteSize)
291 {
292         mInputBufferByteSize = inInputBufferByteSize + kBufferPad;
293        
294         //      toss the old buffer
295         delete[] mInputBuffer;
296         mInputBuffer = NULL;
297        
298         //      allocate the new one
299         // allocate extra in order to allow making contiguous data.
300         UInt32 allocSize = 2*inInputBufferByteSize + kBufferPad;
301         mInputBuffer = new Byte[allocSize];
302         memset(mInputBuffer, 0, allocSize);
303        
304         //      reset the ring buffer state
305         mInputBufferStart = 0;
306         mInputBufferEnd = 0;
307 }
Note: See TracBrowser for help on using the browser.