source: trunk/FFissionCodec/FFissionDecoder.cpp @ 1108

Revision 1108, 19.1 KB checked in by gbooker, 5 years ago (diff)

New system for defining resources. Hopefully this makes more sense

Line 
1/*
2 * FFissionDecoder.cpp
3 * Copyright (c) 2006 David Conrad
4 *
5 * This file is part of Perian.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22
23#include "FFissionDecoder.h"
24#include "ACCodecDispatch.h"
25#include "PerianResourceIDs.h"
26#include "Codecprintf.h"
27#include "CodecIDs.h"
28#include "dca.h"
29
30#define MY_APP_DOMAIN CFSTR("org.perian.Perian")
31#define PASSTHROUGH_KEY CFSTR("attemptDTSPassthrough")
32
33typedef struct CookieAtomHeader {
34    long           size;
35    long           type;
36    unsigned char  data[1];
37} CookieAtomHeader;
38
39struct CodecPair {
40        OSType mFormatID;
41        CodecID codecID;
42};
43
44static const CodecPair kAllInputFormats[] = 
45{
46        { kAudioFormatWMA1MS, CODEC_ID_WMAV1 },
47        { kAudioFormatWMA2MS, CODEC_ID_WMAV2 },
48        { kAudioFormatFlashADPCM, CODEC_ID_ADPCM_SWF },
49        { kAudioFormatXiphVorbis, CODEC_ID_VORBIS },
50        { kAudioFormatMPEGLayer2, CODEC_ID_MP2 },
51        { kAudioFormatMPEGLayer1, CODEC_ID_MP2 },
52        { 0x6d730050, CODEC_ID_MP2 },
53        { kAudioFormatTTA, CODEC_ID_TTA },
54        { kAudioFormatDTS, CODEC_ID_DTS },
55        { kAudioFormatNellymoser, CODEC_ID_NELLYMOSER },
56        { 0, CODEC_ID_NONE }
57};
58
59static CodecID GetCodecID(OSType formatID)
60{
61        for (int i = 0; kAllInputFormats[i].codecID != CODEC_ID_NONE; i++) {
62                if (kAllInputFormats[i].mFormatID == formatID)
63                        return kAllInputFormats[i].codecID;
64        }
65        return CODEC_ID_NONE;
66}
67
68
69FFissionDecoder::FFissionDecoder(UInt32 inInputBufferByteSize) : FFissionCodec(0)
70{
71        kIntPCMOutFormatFlag = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked;
72        magicCookie = NULL;
73        magicCookieSize = 0;
74       
75        for (int i = 0; kAllInputFormats[i].codecID != CODEC_ID_NONE; i++) {
76                CAStreamBasicDescription theInputFormat(kAudioStreamAnyRate, kAllInputFormats[i].mFormatID, 0, 1, 0, 0, 0, 0);
77                AddInputFormat(theInputFormat);
78        }
79       
80        // libavcodec outputs 16-bit native-endian integer pcm, so why do conversions ourselves?
81        CAStreamBasicDescription theOutputFormat(kAudioStreamAnyRate, kAudioFormatLinearPCM, 0, 1, 0, 0, 16, kIntPCMOutFormatFlag);
82        AddOutputFormat(theOutputFormat);
83       
84        inputBuffer.Initialize(inInputBufferByteSize);
85        outBufUsed = 0;
86        outBufSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
87        outputBuffer = new Byte[outBufSize];
88       
89        CFStringRef myApp = MY_APP_DOMAIN;
90        CFPreferencesAppSynchronize(myApp);
91        CFTypeRef pass = CFPreferencesCopyAppValue(PASSTHROUGH_KEY, myApp);
92        if(pass != NULL)
93        {
94                CFTypeID type = CFGetTypeID(pass);
95                if(type == CFStringGetTypeID())
96                        dtsPassthrough = CFStringGetIntValue((CFStringRef)pass);
97                else if(type == CFNumberGetTypeID())
98                        CFNumberGetValue((CFNumberRef)pass, kCFNumberIntType, &dtsPassthrough);
99                else
100                        dtsPassthrough = 0;
101                CFRelease(pass);
102        }
103        else
104                dtsPassthrough = 0;
105       
106        int initialMap[6] = {0, 1, 2, 3, 4, 5};
107        memcpy(fullChannelMap, initialMap, sizeof(initialMap));
108}
109
110FFissionDecoder::~FFissionDecoder()
111{
112        if (magicCookie)
113                delete[] magicCookie;
114       
115        delete[] outputBuffer;
116}
117
118void FFissionDecoder::Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize)
119{
120        if (inMagicCookieByteSize > 0)
121                SetMagicCookie(inMagicCookie, inMagicCookieByteSize);
122       
123        FFissionCodec::Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize);
124}
125
126void FFissionDecoder::Uninitialize()
127{
128        outBufUsed = 0;
129        inputBuffer.Zap(inputBuffer.GetDataAvailable());
130       
131        FFissionCodec::Uninitialize();
132}
133
134void FFissionDecoder::Reset()
135{
136        outBufUsed = 0;
137        inputBuffer.Zap(inputBuffer.GetDataAvailable());
138       
139        FFissionCodec::Reset();
140}
141
142void FFissionDecoder::SetMagicCookie(const void* inMagicCookieData, UInt32 inMagicCookieDataByteSize)
143{
144        if (magicCookie)
145                delete[] magicCookie;
146       
147        magicCookieSize = inMagicCookieDataByteSize;
148       
149        if (magicCookieSize > 0) {
150                magicCookie = new Byte[magicCookieSize + FF_INPUT_BUFFER_PADDING_SIZE];
151                memcpy(magicCookie, inMagicCookieData, magicCookieSize);
152        } else
153                magicCookie = NULL;
154       
155        FFissionCodec::SetMagicCookie(inMagicCookieData, inMagicCookieDataByteSize);
156}
157
158void FFissionDecoder::SetupExtradata(OSType formatID)
159{
160        if (!magicCookie) return;
161       
162        switch (formatID) {
163                case kAudioFormatWMA1MS:
164                case kAudioFormatWMA2MS:
165                case kAudioFormatTTA:
166                        if (magicCookieSize < 12 + 18 + 8 + 8)
167                                return;
168                       
169                        avContext->extradata = magicCookie + 12 + 18 + 8;
170                        avContext->extradata_size = magicCookieSize - 12 - 18 - 8 - 8;
171                        break;
172                       
173                case kAudioFormatXiphVorbis:
174                        avContext->extradata_size = ConvertXiphVorbisCookie();
175                        avContext->extradata = magicCookie;
176                        break;
177                       
178                default:
179                        return;
180        }
181       
182        // this is safe because we always allocate this amount of additional memory for our copy of the magic cookie
183        memset(avContext->extradata + avContext->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
184}
185
186int FFissionDecoder::ConvertXiphVorbisCookie()
187{
188        Byte *ptr = magicCookie;
189        Byte *cend = magicCookie + magicCookieSize;
190        Byte *headerData[3] = {NULL};
191        int headerSize[3] = {0};
192       
193        while (ptr < cend) {
194                CookieAtomHeader *aheader = reinterpret_cast<CookieAtomHeader *>(ptr);
195                int size = EndianU32_BtoN(aheader->size);
196                ptr += size;
197                if (ptr > cend || size <= 0)
198                        break;
199               
200                switch(EndianS32_BtoN(aheader->type)) {
201                        case kCookieTypeVorbisHeader:
202                                headerData[0] = aheader->data;
203                                headerSize[0] = size - 8;
204                                break;
205                               
206                        case kCookieTypeVorbisComments:
207                                headerData[1] = aheader->data;
208                                headerSize[1] = size - 8;
209                                break;
210                               
211                        case kCookieTypeVorbisCodebooks:
212                                headerData[2] = aheader->data;
213                                headerSize[2] = size - 8;
214                                break;
215                }
216        }
217       
218    if (headerSize[0] <= 0 || headerSize[1] <= 0 || headerSize[2] <= 0) {
219                Codecprintf(NULL, "Invalid Vorbis extradata\n");
220                return 0;
221        }
222       
223        int len = headerSize[0] + headerSize[1] + headerSize[2];
224        Byte *newCookie = new Byte[len + len/255 + 64];
225        ptr = newCookie;
226       
227        ptr[0] = 2;             // number of packets minus 1
228        int offset = 1;
229        offset += av_xiphlacing(&ptr[offset], headerSize[0]);
230        offset += av_xiphlacing(&ptr[offset], headerSize[1]);
231        for (int i = 0; i < 3; i++) {
232                memcpy(&ptr[offset], headerData[i], headerSize[i]);
233                offset += headerSize[i];
234        }
235       
236        delete[] magicCookie;
237        magicCookie = newCookie;
238        magicCookieSize = offset;
239       
240        return offset;
241}
242
243void FFissionDecoder::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData) {
244        switch (inPropertyID) {
245                case kAudioCodecPropertyNameCFString:
246                        if (ioPropertyDataSize != sizeof(CFStringRef))
247                                CODEC_THROW(kAudioCodecBadPropertySizeError);
248                        break;
249                       
250                case kAudioCodecPropertyInputBufferSize:
251                case kAudioCodecPropertyUsedInputBufferSize:
252                        if (ioPropertyDataSize != sizeof(UInt32))
253                                CODEC_THROW(kAudioCodecBadPropertySizeError);
254                        break;
255        }
256       
257        switch (inPropertyID) {
258                case kAudioCodecPropertyNameCFString:
259                        *(CFStringRef*)outPropertyData = CFCopyLocalizedStringFromTableInBundle(CFSTR("Perian FFmpeg audio decoder"), CFSTR("CodecNames"), GetCodecBundle(), CFSTR(""));
260                        break; 
261                       
262                case kAudioCodecPropertyInputBufferSize:
263                        *reinterpret_cast<UInt32*>(outPropertyData) = inputBuffer.GetBufferByteSize();
264                        break;
265                       
266                case kAudioCodecPropertyUsedInputBufferSize:
267                        *reinterpret_cast<UInt32*>(outPropertyData) = inputBuffer.GetDataAvailable();
268                        break;
269                       
270                default:
271                        FFissionCodec::GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData);
272        }
273}
274
275void FFissionDecoder::SetCurrentInputFormat(const AudioStreamBasicDescription& inInputFormat)
276{
277        if(mIsInitialized) {
278                CODEC_THROW(kAudioCodecStateError);
279        }
280       
281        if (avCodec) {
282                avcodec_close(avContext);
283                avCodec = NULL;
284        }
285       
286        CodecID codecID = GetCodecID(inInputFormat.mFormatID);
287       
288        // check to make sure the input format is legal
289        if (avcodec_find_decoder(codecID) == NULL) {
290                Codecprintf(NULL, "Unsupported input format id %4.4s\n", &inInputFormat.mFormatID);
291                CODEC_THROW(kAudioCodecUnsupportedFormatError);
292        }
293       
294        // tell our base class about the new format
295        FFissionCodec::SetCurrentInputFormat(inInputFormat);
296}
297       
298void FFissionDecoder::OpenAVCodec()
299{
300        if (!mIsInitialized)
301                CODEC_THROW(kAudioCodecStateError);
302       
303        CodecID codecID = GetCodecID(mInputFormat.mFormatID);
304       
305        avCodec = avcodec_find_decoder(codecID);
306       
307        avcodec_get_context_defaults(avContext);
308       
309        avContext->sample_rate = mInputFormat.mSampleRate;
310        avContext->channels = mInputFormat.mChannelsPerFrame;
311        avContext->block_align = mInputFormat.mBytesPerPacket;
312        avContext->frame_size = mInputFormat.mFramesPerPacket;
313        avContext->bits_per_coded_sample = mInputFormat.mBitsPerChannel;
314       
315        if (avContext->sample_rate == 0) {
316                Codecprintf(NULL, "Invalid sample rate %d\n", avContext->sample_rate);
317                avCodec = NULL;
318                return;
319        }
320       
321        if (magicCookie) {
322                SetupExtradata(mInputFormat.mFormatID);
323        }
324       
325        if (avcodec_open(avContext, avCodec)) {
326                Codecprintf(NULL, "error opening audio avcodec\n");
327                avCodec = NULL;
328                CODEC_THROW(kAudioCodecUnsupportedFormatError);
329        }
330        if(mInputFormat.mFormatID != kAudioFormatDTS)
331                dtsPassthrough = 0;
332        else
333        {
334                switch (mInputFormat.mChannelsPerFrame) {
335                        case 3:
336                        case 6:
337                        {
338                                int chanMap[6] = {1, 2, 0, 5, 3, 4};//L R C -> C L R  and  L R C LFE Ls Rs -> C L R Ls Rs LFE
339                                memcpy(fullChannelMap, chanMap, sizeof(chanMap));
340                                break;
341                        }
342                        case 4:
343                        case 5:
344                        {
345                                int chanMap[6] = {1, 2, 0, 3, 4, 5};//L R C Cs -> C L R Cs  and  L R C Ls Rs -> C L R Ls Rs
346                                memcpy(fullChannelMap, chanMap, sizeof(chanMap));
347                                break;
348                        }
349                        default:
350                                break;
351                }
352        }
353}
354
355void FFissionDecoder::SetCurrentOutputFormat(const AudioStreamBasicDescription& inOutputFormat)
356{
357        if(mIsInitialized) {
358                CODEC_THROW(kAudioCodecStateError);
359        }
360       
361        //      check to make sure the output format is legal
362        if (inOutputFormat.mFormatID != kAudioFormatLinearPCM ||
363                inOutputFormat.mFormatFlags != kIntPCMOutFormatFlag || 
364                inOutputFormat.mBitsPerChannel != 16)
365        {
366                Codecprintf(NULL, "We only support 16 bit native endian signed integer for output\n");
367                CODEC_THROW(kAudioCodecUnsupportedFormatError);
368        }
369       
370        //      tell our base class about the new format
371        FFissionCodec::SetCurrentOutputFormat(inOutputFormat);
372}
373
374void FFissionDecoder::AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, 
375                                                                          UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription)
376{
377        const Byte *inData = (const Byte *)inInputData;
378       
379        if (inPacketDescription && ioNumberPackets) {
380                for (int i = 0; i < ioNumberPackets; i++) {
381                        UInt32 packetSize = inPacketDescription[i].mDataByteSize;
382                        inputBuffer.In(inData + inPacketDescription[i].mStartOffset, packetSize);
383                }
384        } else if (mInputFormat.mBytesPerPacket != 0) {
385                // no packet description, assume cbr
386                UInt32 amountToCopy = FFMIN(mInputFormat.mBytesPerPacket * ioNumberPackets, ioInputDataByteSize);
387                UInt32 numPackets = amountToCopy / mInputFormat.mBytesPerPacket;
388               
389                ioInputDataByteSize = amountToCopy;
390                ioNumberPackets = numPackets;
391               
392                for (int i = 0; i < numPackets; i++) {
393                        UInt32 packetSize = mInputFormat.mBytesPerPacket;
394                        inputBuffer.In(inData, packetSize);
395                        inData += mInputFormat.mBytesPerPacket;
396                }
397        } else {
398                // XiphQT throws this in this situation (we need packet descriptions, but don't get them)
399                // is there a better error to throw?
400                CODEC_THROW(kAudioCodecNotEnoughBufferSpaceError);
401        }
402}
403
404#define AV_RL16(x) EndianU16_LtoN(*(uint16_t *)(x))
405#define AV_RB16(x) EndianU16_BtoN(*(uint16_t *)(x))
406
407int produceDTSPassthroughPackets(Byte *outputBuffer, int *outBufUsed, uint8_t *packet, int packetSize, int channelCount, int bigEndian)
408{
409        if(packetSize < 96)
410                return 0;
411       
412        static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x00, 0x00 };
413        static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x00 };
414       
415        uint32_t mrk = AV_RB16(packet) << 16 | AV_RB16(packet + 2);
416        unsigned int frameSize = 0;
417        unsigned int blockCount = 0;
418        bool repackage = 0;
419
420        switch (mrk) {
421                case DCA_MARKER_RAW_BE:
422                        blockCount = (AV_RB16(packet + 4) >> 2) & 0x7f;
423                        frameSize = (AV_RB16(packet + 4) & 0x3) << 12 | (AV_RB16(packet + 6) >> 4) & 0xfff;
424                        repackage = 1;
425                        break;
426                case DCA_MARKER_RAW_LE:
427                        blockCount = (AV_RL16(packet + 4) >> 2) & 0x7f;
428                        frameSize = (AV_RL16(packet + 4) & 0x3) << 12 | (AV_RL16(packet + 6) >> 4) & 0xfff;
429                        repackage = 1;
430                        break;
431                case DCA_MARKER_14B_BE:
432                case DCA_MARKER_14B_LE:
433                default:
434                        return -1;
435        }
436
437        blockCount++;
438        frameSize++;
439       
440        int spdif_type;
441        switch (blockCount) {
442                case 16:
443                        spdif_type = 0x0b; //512-sample bursts
444                        break;
445                case 32:
446                        spdif_type = 0x0c; //1024-sample bursts
447                        break;
448                case 64:
449                        spdif_type = 0x0d; //2048-sample bursts
450                        break;
451                default:
452                        return -1;
453                        break;
454        }
455       
456        int totalSize = blockCount * 256 * channelCount / 4;
457        memset(outputBuffer, 0, totalSize);
458        int offset = 2;
459       
460        if(bigEndian)
461        {
462                memcpy(outputBuffer+offset, p_sync_be, 4);
463                offset += channelCount * 2;
464                outputBuffer[offset] = 0;
465                outputBuffer[offset+1] = spdif_type;
466                outputBuffer[offset+2] = (frameSize >> 5) & 0xff;
467                outputBuffer[offset+3] = (frameSize << 3) & 0xff;
468        }
469        else
470        {
471                memcpy(outputBuffer+offset, p_sync_le, 4);
472                offset += channelCount * 2;
473                outputBuffer[offset] = spdif_type;
474                outputBuffer[offset+1] = 0;
475                outputBuffer[offset+2] = (frameSize << 3) & 0xff;
476                outputBuffer[offset+3] = (frameSize >> 5) & 0xff;
477        }
478       
479        offset += channelCount * 2;
480       
481        if((mrk == DCA_MARKER_RAW_BE || mrk == DCA_MARKER_14B_BE) && !bigEndian)
482        {
483                int i;
484                int count = frameSize & ~0x3;
485                for(i=0; i<count; i+=4)
486                {
487                        outputBuffer[offset] = packet[i+1];
488                        outputBuffer[offset+1] = packet[i];
489                        outputBuffer[offset+2] = packet[i+3];
490                        outputBuffer[offset+3] = packet[i+2];
491                        offset += channelCount * 2;
492                }
493                switch (frameSize & 0x3) {
494                        case 3:
495                                outputBuffer[offset+3] = packet[i+2];
496                        case 2:
497                                outputBuffer[offset] = packet[i+1];
498                        case 1:
499                                outputBuffer[offset+1] = packet[i];
500                        default:
501                                break;
502                }
503        }
504        else
505        {
506                int i;
507                for(i=0; i<frameSize; i+=4)
508                {
509                        memcpy(outputBuffer + offset, packet+i, 4);
510                        offset += channelCount * 2;
511                }
512        }
513
514        *outBufUsed = totalSize;
515        return frameSize;
516}
517
518UInt32 FFissionDecoder::InterleaveSamples(void *outputDataUntyped, Byte *inputDataUntyped, int amountToCopy)
519{
520        SInt16 *outputData = (SInt16 *)outputDataUntyped;
521        SInt16 *inputData = (SInt16 *)inputDataUntyped;
522        int channelCount = avContext->channels;
523        int framesToCopy = amountToCopy / channelCount / 2;
524        for(int i=0; i<framesToCopy; i++)
525        {
526                for(int j=0; j<channelCount; j++)
527                {
528                        outputData[fullChannelMap[j]] = inputData[j];
529                }
530                outputData += channelCount;
531                inputData += channelCount;
532        }
533       
534        return framesToCopy * channelCount * 2;
535}
536
537UInt32 FFissionDecoder::ProduceOutputPackets(void* outOutputData,
538                                                                                         UInt32& ioOutputDataByteSize,  // number of bytes written to outOutputData
539                                                                                         UInt32& ioNumberPackets, 
540                                                                                         AudioStreamPacketDescription* outPacketDescription)
541{
542        UInt32 ans;
543       
544        if (!avCodec)
545                OpenAVCodec();
546       
547        if (!mIsInitialized || !avCodec)
548                CODEC_THROW(kAudioCodecStateError);
549       
550        UInt32 written = 0;
551        Byte *outData = (Byte *) outOutputData;
552       
553        // we have leftovers from the last packet, use that first
554        if (outBufUsed > 0) {
555                int amountToCopy = FFMIN(outBufUsed, ioOutputDataByteSize);
556                amountToCopy = InterleaveSamples(outData, outputBuffer, amountToCopy);
557                outBufUsed -= amountToCopy;
558                written += amountToCopy;
559               
560                if (outBufUsed > 0)
561                        memmove(outputBuffer, outputBuffer + amountToCopy, outBufUsed);
562        }
563       
564        // loop until we satisfy the request or run out of input data
565        while (written < ioOutputDataByteSize && inputBuffer.GetNumPackets() > 0) {
566                int packetSize = inputBuffer.GetCurrentPacketSize();
567                uint8_t *packet = inputBuffer.GetData();
568               
569                // decode one packet to our buffer
570                outBufUsed = outBufSize;
571                int len;
572                if(dtsPassthrough)
573                        len = produceDTSPassthroughPackets(outputBuffer, &outBufUsed, packet, packetSize, avContext->channels, mOutputFormat.mFormatFlags & kLinearPCMFormatFlagIsBigEndian);
574                else
575                {
576                        AVPacket pkt;
577                        av_init_packet(&pkt);
578                        pkt.data = packet;
579                        pkt.size = packetSize;
580                        len = avcodec_decode_audio3(avContext, (int16_t *)outputBuffer, &outBufUsed, &pkt);
581                }
582               
583                if (len < 0) {
584                        Codecprintf(NULL, "Error decoding audio frame\n");
585                        inputBuffer.Zap(packetSize);
586                        outBufUsed = 0;
587                        ioOutputDataByteSize = written;
588                        ioNumberPackets = ioOutputDataByteSize / (2 * mOutputFormat.NumberChannels());
589                        return kAudioCodecProduceOutputPacketFailure;
590                }
591                inputBuffer.Zap(len);
592               
593                // copy up to the amount requested
594                int amountToCopy = FFMIN(outBufUsed, ioOutputDataByteSize - written);
595                amountToCopy = InterleaveSamples(outData + written, outputBuffer, amountToCopy);
596                outBufUsed -= amountToCopy;
597                written += amountToCopy;
598               
599                // and save what's left over
600                if (outBufUsed > 0)
601                        memmove(outputBuffer, outputBuffer + amountToCopy, outBufUsed);
602        }
603       
604        if (written < ioOutputDataByteSize)
605                ans = kAudioCodecProduceOutputPacketNeedsMoreInputData;
606        else if (inputBuffer.GetNumPackets() > 0)
607                // we have an entire packet left to decode
608                ans = kAudioCodecProduceOutputPacketSuccessHasMore;
609        else
610                ans = kAudioCodecProduceOutputPacketSuccess;
611       
612        ioOutputDataByteSize = written;
613        ioNumberPackets = ioOutputDataByteSize / (2 * mOutputFormat.NumberChannels());
614       
615        return ans;
616}
617
618UInt32 FFissionDecoder::GetVersion() const
619{
620        return kFFusionCodecVersion;
621}
622
623// comment from XiphQT (variable frames per packet means FrameSize should be reported 0,
624// but apparently needs 1 on Intel?):
625/* The following line has been changed according to Apple engineers' suggestion
626   I received via Steve Nicolai (in response to *my* bugreport, I think...).
627   (Why don't they just implement the VBR-VFPP properly? *sigh*) */
628#ifdef TARGET_CPU_X86
629#define SHOULD_BE_ZERO 1
630#else
631#define SHOULD_BE_ZERO 0
632#endif
633
634void FFissionVBRDecoder::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData)
635{
636        switch (inPropertyID) {
637                case kAudioCodecPropertyPacketFrameSize:
638                case kAudioCodecPropertyHasVariablePacketByteSizes:
639                case kAudioCodecPropertyRequiresPacketDescription:
640                        if (ioPropertyDataSize != sizeof(UInt32))
641                                CODEC_THROW(kAudioCodecBadPropertySizeError);
642                        break;
643        }
644       
645        switch (inPropertyID) {
646                case kAudioCodecPropertyPacketFrameSize:
647                        *reinterpret_cast<UInt32*>(outPropertyData) = SHOULD_BE_ZERO;
648                        break;
649                       
650                case kAudioCodecPropertyHasVariablePacketByteSizes:
651                case kAudioCodecPropertyRequiresPacketDescription:
652                        *reinterpret_cast<UInt32*>(outPropertyData) = true;
653                        break;
654                       
655                default:
656                        FFissionDecoder::GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData);
657        }
658}
659
660
661extern "C"
662ComponentResult FFissionDecoderEntry(ComponentParameters* inParameters, FFissionDecoder* inThis)
663{
664        return ACCodecDispatch(inParameters, inThis);
665}
666
667extern "C"
668ComponentResult FFissionVBRDecoderEntry(ComponentParameters* inParameters, FFissionVBRDecoder* inThis)
669{
670        return ACCodecDispatch(inParameters, inThis);
671}
Note: See TracBrowser for help on using the repository browser.