source: trunk/CompressAudioCodec.cpp @ 1472

Revision 1472, 8.4 KB checked in by astrange, 3 years ago (diff)

Xcode project cleanup and Lion SDK updates

  • Update ACPublic/PublicUtility to Lion version.

API changed in various ways. Rather than copy the files
I've just included them from the Developer directory,
which may turn out to be a bad idea.
Removed use of ACSimpleCodec along the way.

  • Stop including ffmpeg/, which will improve compilation speed.
  • Some other changes to better use Xcode 4 schemes
Line 
1/*
2 * CompressAudioCodec.cpp
3 * Created by Graham Booker on 8/14/10.
4 * This file is part of Perian.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "CompressAudioCodec.h"
22#include "CodecIDs.h"
23#include "CompressCodecUtils.h"
24
25static const OSType kAllInputFormats[] = 
26{
27        kCompressedAC3,
28        kCompressedMP1,
29        kCompressedMP2,
30        kCompressedMP3,
31        kCompressedDTS,
32        0,
33};
34
35static const UInt32 kIntPCMOutFormatFlag = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked;
36
37CompressAudioCodec::CompressAudioCodec(AudioComponentInstance inInstance) : FFissionCodec(inInstance)
38{
39        for (int i = 0; kAllInputFormats[i] != CODEC_ID_NONE; i++) {
40                CAStreamBasicDescription theInputFormat(kAudioStreamAnyRate, kAllInputFormats[i], 0, 1, 0, 0, 0, 0);
41                AddInputFormat(theInputFormat);
42        }
43       
44        // libavcodec outputs 16-bit native-endian integer pcm, so why do conversions ourselves?
45        CAStreamBasicDescription theOutputFormat(kAudioStreamAnyRate, kAudioFormatLinearPCM, 0, 1, 0, 0, 16, kIntPCMOutFormatFlag);
46        AddOutputFormat(theOutputFormat);
47        strippedHeader = NULL;
48        strippedHeaderSize = 0;
49        innerCookie = NULL;
50        innerCookieSize = 0;
51        actualUnit = NULL;
52}
53
54CompressAudioCodec::~CompressAudioCodec()
55{
56        if(strippedHeader)
57                delete[] strippedHeader;
58        if(innerCookie)
59                delete[] innerCookie;
60        if(actualUnit)
61                CloseComponent(actualUnit);
62}
63
64UInt32 CompressAudioCodec::ParseCookieAtom(const uint8_t* inAtom, UInt32 inAtomMaxSize)
65{
66        if(inAtomMaxSize < 8)
67                //Invalid; atom must be at least 8 bytes.
68                return inAtomMaxSize;
69        const UInt32 *atomElements = reinterpret_cast<const UInt32 *>(inAtom);
70        UInt32 atomSize = EndianU32_BtoN(atomElements[0]);
71        UInt32 atomType = EndianU32_BtoN(atomElements[1]);
72       
73        if(atomSize > inAtomMaxSize)
74                return inAtomMaxSize;
75       
76        switch (atomType) {
77                case 'CpSt': {
78                        //Stripped header
79                        UInt32 headerSize = atomSize - 8;
80                        if(headerSize == 0)
81                                break;
82                        strippedHeaderSize = headerSize;
83                        strippedHeader = new Byte[headerSize];
84                        memcpy(strippedHeader, inAtom+8, headerSize);
85                }
86                        break;
87                case 'CpCk': {
88                        //Real cookie
89                        UInt32 cookieSize = atomSize - 8;
90                        if(cookieSize == 0)
91                                break;
92                        innerCookieSize = cookieSize;
93                        innerCookie = new Byte[cookieSize];
94                        memcpy(innerCookie, inAtom+8, cookieSize);
95                }
96                        break;
97                default:
98                        break;
99        }
100       
101        return atomSize;
102}
103
104void CompressAudioCodec::ParseCookie(const uint8_t* inMagicCookie, UInt32 inMagicCookieByteSize)
105{
106        UInt32 offset = 0;
107        while(offset < inMagicCookieByteSize) {
108                offset += ParseCookieAtom(inMagicCookie + offset, inMagicCookieByteSize - offset);
109        }
110}
111
112void CompressAudioCodec::Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize)
113{
114        FFissionCodec::Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
115        if(inMagicCookie)
116                SetMagicCookie(inMagicCookie, inMagicCookieByteSize);
117        if(mInputFormat.mFormatID != 0 && actualUnit == NULL)
118        {
119                OSType original = originalStreamFourCC(mInputFormat.mFormatID);
120                if(original == 0)
121                        CODEC_THROW(kAudioCodecUnsupportedFormatError);
122               
123                ComponentDescription desc;
124                memset(&desc, 0, sizeof(ComponentDescription));
125                desc.componentType = kAudioDecoderComponentType;
126                desc.componentSubType = original;
127                Component component = NULL;
128                while((component = FindNextComponent(component, &desc)) != NULL)
129                {
130                        ComponentResult err = OpenAComponent(component, &actualUnit);
131                        AudioStreamBasicDescription input = mInputFormat ;
132                        input.mFormatID = original;
133                        err = AudioCodecInitialize(actualUnit, &input, inOutputFormat, innerCookie, innerCookieSize);
134                        if(err == noErr)
135                                break;
136                }
137        }
138        else if(actualUnit != NULL)
139        {
140                OSType original = originalStreamFourCC(mInputFormat.mFormatID);
141                AudioStreamBasicDescription input = mInputFormat ;
142                input.mFormatID = original;
143                AudioCodecInitialize(actualUnit, &input, inOutputFormat, innerCookie, innerCookieSize);
144        }
145}
146
147void CompressAudioCodec::Uninitialize()
148{
149        FFissionCodec::Uninitialize();
150        if(actualUnit)
151                AudioCodecUninitialize(actualUnit);
152}
153
154void CompressAudioCodec::Reset()
155{
156        if(actualUnit)
157                AudioCodecReset(actualUnit);
158}
159
160void CompressAudioCodec::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData)
161{
162        if(actualUnit)
163        {
164                AudioCodecGetProperty(actualUnit, inPropertyID, &ioPropertyDataSize, outPropertyData);
165                switch (inPropertyID) {
166                        case kAudioCodecPropertyCurrentInputFormat:
167                        case kAudioCodecPropertySupportedInputFormats:
168                        case kAudioCodecInputFormatsForOutputFormat:
169                        {
170                                int formatCount = ioPropertyDataSize / sizeof(AudioStreamBasicDescription);
171                                AudioStreamBasicDescription *formats = reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData);
172                                for(int i=0; i<formatCount; i++)
173                                {
174                                        formats[i].mFormatID = mInputFormat.mFormatID;
175                                }
176                        }
177                                break;
178                        default:
179                                break;
180                }
181        }
182        else
183                FFissionCodec::GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData);
184}
185
186void CompressAudioCodec::SetMagicCookie(const void* inMagicCookieData, UInt32 inMagicCookieDataByteSize)
187{
188        ParseCookie(static_cast<const uint8_t *> (inMagicCookieData), inMagicCookieDataByteSize);
189        FFissionCodec::SetMagicCookie(inMagicCookieData, inMagicCookieDataByteSize);
190        if(actualUnit)
191        {
192                OSType original = originalStreamFourCC(mInputFormat.mFormatID);
193                AudioStreamBasicDescription input = mInputFormat;
194                input.mFormatID = original;
195                AudioStreamBasicDescription output = mOutputFormat;
196                AudioCodecInitialize(actualUnit, &input, &output, innerCookie, innerCookieSize);
197        }
198}
199
200void CompressAudioCodec::SetCurrentInputFormat(const AudioStreamBasicDescription& inInputFormat)
201{
202        FFissionCodec::SetCurrentInputFormat(inInputFormat);
203}
204
205void CompressAudioCodec::SetCurrentOutputFormat(const AudioStreamBasicDescription& inOutputFormat)
206{
207        FFissionCodec::SetCurrentOutputFormat(inOutputFormat);
208}
209
210void CompressAudioCodec::AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription)
211{
212        if(inPacketDescription && ioNumberPackets && actualUnit)
213        {
214                UInt32 totalSize = 0;
215                for(int i=0; i<ioNumberPackets; i++)
216                        totalSize += inPacketDescription[i].mDataByteSize;
217               
218                Byte *newInputData = new Byte[totalSize + strippedHeaderSize*ioNumberPackets];
219                AudioStreamPacketDescription *newPackets = new AudioStreamPacketDescription[ioNumberPackets];
220                UInt32 offset = 0;
221                for(int i=0; i<ioNumberPackets; i++)
222                {
223                        memcpy(newInputData + offset, strippedHeader, strippedHeaderSize);
224                        UInt32 packetSize = inPacketDescription[i].mDataByteSize;
225                        memcpy(newInputData + offset + strippedHeaderSize, static_cast<const Byte *>(inInputData) + inPacketDescription[i].mStartOffset, packetSize);
226                        newPackets[i].mDataByteSize = packetSize + strippedHeaderSize;
227                        newPackets[i].mStartOffset = offset;
228                        newPackets[i].mVariableFramesInPacket = inPacketDescription[i].mVariableFramesInPacket;
229                        offset += packetSize + strippedHeaderSize;
230                }
231                AudioCodecAppendInputData(actualUnit, newInputData, &offset, &ioNumberPackets, newPackets);
232                AudioStreamPacketDescription lastPacket = inPacketDescription[ioNumberPackets-1];
233                ioInputDataByteSize = lastPacket.mStartOffset + lastPacket.mDataByteSize;
234                delete[] newInputData;
235                delete[] newPackets;
236        }
237}
238
239UInt32 CompressAudioCodec::ProduceOutputPackets(void* outOutputData, UInt32& ioOutputDataByteSize, UInt32& ioNumberPackets, AudioStreamPacketDescription* outPacketDescription)
240{
241        UInt32 status = noErr;
242        if(actualUnit)
243                AudioCodecProduceOutputPackets(actualUnit, outOutputData, &ioOutputDataByteSize, &ioNumberPackets, outPacketDescription, &status);
244        return status;
245}
246
247#include "ACPlugInDispatch.h"
248
249#define CompressAudioCodecEntry CompressAudioDecoderEntry
250
251AUDIOCOMPONENT_ENTRY(AudioCodecFactory, CompressAudioCodec)
Note: See TracBrowser for help on using the repository browser.