void ACFLACCodec::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData) { // kAudioCodecPropertyMaximumPacketByteSize is handled in the Encoder or Decoder switch(inPropertyID) { case kAudioCodecPropertyFormatCFString: { if (ioPropertyDataSize != sizeof(CFStringRef)) { CODEC_THROW(kAudioCodecBadPropertySizeError); } CABundleLocker lock; CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("FLAC"), CFSTR("CodecNames"), GetCodecBundle(), CFSTR("")); *(CFStringRef*)outPropertyData = name; break; } case kAudioCodecPropertyRequiresPacketDescription: if(ioPropertyDataSize == sizeof(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = 1; } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyHasVariablePacketByteSizes: if(ioPropertyDataSize == sizeof(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = 1; // We are variable bitrate } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyPacketFrameSize: if(ioPropertyDataSize == sizeof(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = kFramesPerPacket; } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyMagicCookie: if(ioPropertyDataSize >= GetMagicCookieByteSize()) { GetMagicCookie(outPropertyData, ioPropertyDataSize); mMagicCookieLength = ioPropertyDataSize; } else { CODEC_THROW(kAudioCodecIllegalOperationError); } break; case kAudioCodecPropertyCurrentInputSampleRate: if(ioPropertyDataSize == sizeof(Float64)) { *reinterpret_cast<Float64*>(outPropertyData) = (Float64)(mInputFormat.mSampleRate); } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyCurrentOutputSampleRate: if(ioPropertyDataSize == sizeof(Float64)) { *reinterpret_cast<Float64*>(outPropertyData) = (Float64)(mOutputFormat.mSampleRate); } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyInputChannelLayout: case kAudioCodecPropertyOutputChannelLayout: AudioChannelLayout temp1AudioChannelLayout; memset(&temp1AudioChannelLayout, 0, sizeof(AudioChannelLayout)); if(ioPropertyDataSize == sizeof(AudioChannelLayout)) { temp1AudioChannelLayout.mChannelLayoutTag = sChannelLayoutTags[mInputFormat.mChannelsPerFrame - 1]; memcpy(outPropertyData, &temp1AudioChannelLayout, ioPropertyDataSize); } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyAvailableInputChannelLayouts: case kAudioCodecPropertyAvailableOutputChannelLayouts: if(ioPropertyDataSize == kMaxChannels * sizeof(AudioChannelLayoutTag)) { if(mIsInitialized) { AudioChannelLayoutTag temp2AudioChannelLayout[1]; temp2AudioChannelLayout[0] = sChannelLayoutTags[mInputFormat.mChannelsPerFrame - 1]; ioPropertyDataSize = sizeof(AudioChannelLayoutTag); memcpy(reinterpret_cast<AudioChannelLayoutTag*>(outPropertyData), temp2AudioChannelLayout, ioPropertyDataSize); } else { AudioChannelLayoutTag tempAudioChannelLayout[kMaxChannels]; tempAudioChannelLayout[0] = kAudioChannelLayoutTag_Mono; tempAudioChannelLayout[1] = kAudioChannelLayoutTag_Stereo; tempAudioChannelLayout[2] = kAudioChannelLayoutTag_MPEG_3_0_B; tempAudioChannelLayout[3] = kAudioChannelLayoutTag_MPEG_4_0_B; tempAudioChannelLayout[4] = kAudioChannelLayoutTag_MPEG_5_0_D; tempAudioChannelLayout[5] = kAudioChannelLayoutTag_MPEG_5_1_D; tempAudioChannelLayout[6] = kAudioChannelLayoutTag_AAC_6_1; tempAudioChannelLayout[7] = kAudioChannelLayoutTag_MPEG_7_1_B; memcpy(reinterpret_cast<AudioChannelLayoutTag*>(outPropertyData), tempAudioChannelLayout, ioPropertyDataSize); } } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyFormatInfo: if(ioPropertyDataSize == sizeof(AudioFormatInfo)) { AudioFormatInfo& formatInfo = *(AudioFormatInfo*)outPropertyData; // Check for cookie existence if((NULL != formatInfo.mMagicCookie) && (formatInfo.mMagicCookieSize > 0)) { UInt32 theByteSize = formatInfo.mMagicCookieSize; FLAC__StreamMetadata_StreamInfo theConfig; memset (&theConfig, 0, sizeof(FLAC__StreamMetadata_StreamInfo)); ParseMagicCookie(formatInfo.mMagicCookie, theByteSize, &theConfig); formatInfo.mASBD.mSampleRate = (Float64)theConfig.sample_rate; formatInfo.mASBD.mChannelsPerFrame = theConfig.channels; formatInfo.mASBD.mFramesPerPacket = theConfig.max_blocksize; formatInfo.mASBD.mBytesPerPacket = 0; // it's never CBR switch (theConfig.bits_per_sample) { case 16: formatInfo.mASBD.mFormatFlags = kFLACFormatFlag_16BitSourceData; break; case 20: formatInfo.mASBD.mFormatFlags = kFLACFormatFlag_20BitSourceData; break; case 24: formatInfo.mASBD.mFormatFlags = kFLACFormatFlag_24BitSourceData; break; case 32: formatInfo.mASBD.mFormatFlags = kFLACFormatFlag_32BitSourceData; break; default: // we don't support this formatInfo.mASBD.mFormatFlags = 0; break; } } else { // We don't have a cookie, we have to check the ASBD // according to the input formats UInt32 i; for(i = 0; i < GetNumberSupportedInputFormats(); ++i) { if(mInputFormatList[i].IsEqual(formatInfo.mASBD)) { // IsEqual will treat 0 values as wildcards -- we can't have that with the format flags UInt32 tempFormatFlags = formatInfo.mASBD.mFormatFlags; // Fill out missing entries CAStreamBasicDescription::FillOutFormat(formatInfo.mASBD, mInputFormatList[i]); if (tempFormatFlags == 0) { formatInfo.mASBD.mFormatFlags = 0; // anything assigned here would be bad. } break; } } if(i == GetNumberSupportedInputFormats()) { // No suitable settings found CODEC_THROW(kAudioCodecUnsupportedFormatError); } } } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; default: ACBaseCodec::GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData); } }
void ACBaseCodec::GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable) { switch(inPropertyID) { case kAudioCodecPropertyNameCFString: outPropertyDataSize = SizeOf32(CFStringRef); outWritable = false; break; case kAudioCodecPropertyManufacturerCFString: outPropertyDataSize = SizeOf32(CFStringRef); outWritable = false; break; case kAudioCodecPropertyFormatCFString: outPropertyDataSize = SizeOf32(CFStringRef); outWritable = false; break; case kAudioCodecPropertyRequiresPacketDescription: outPropertyDataSize = SizeOf32(UInt32); outWritable = false; break; case kAudioCodecPropertyMinimumNumberInputPackets : outPropertyDataSize = SizeOf32(UInt32); outWritable = false; break; case kAudioCodecPropertyMinimumNumberOutputPackets : outPropertyDataSize = SizeOf32(UInt32); outWritable = false; break; case kAudioCodecPropertyCurrentInputFormat: outPropertyDataSize = SizeOf32(AudioStreamBasicDescription); outWritable = true; break; case kAudioCodecPropertySupportedInputFormats: case kAudioCodecPropertyInputFormatsForOutputFormat: outPropertyDataSize = GetNumberSupportedInputFormats() * SizeOf32(AudioStreamBasicDescription); outWritable = false; break; case kAudioCodecPropertyCurrentOutputFormat: outPropertyDataSize = SizeOf32(AudioStreamBasicDescription); outWritable = true; break; case kAudioCodecPropertySupportedOutputFormats: case kAudioCodecPropertyOutputFormatsForInputFormat: outPropertyDataSize = GetNumberSupportedOutputFormats() * SizeOf32(AudioStreamBasicDescription); outWritable = false; break; case kAudioCodecPropertyMagicCookie: outPropertyDataSize = GetMagicCookieByteSize(); outWritable = true; break; case kAudioCodecPropertyInputBufferSize: outPropertyDataSize = SizeOf32(UInt32); outWritable = false; break; case kAudioCodecPropertyUsedInputBufferSize: outPropertyDataSize = SizeOf32(UInt32); outWritable = false; break; case kAudioCodecPropertyIsInitialized: outPropertyDataSize = SizeOf32(UInt32); outWritable = false; break; case kAudioCodecPropertyAvailableNumberChannels: outPropertyDataSize = SizeOf32(UInt32) * 2; // Mono, stereo outWritable = false; break; case kAudioCodecPropertyPrimeMethod: outPropertyDataSize = SizeOf32(UInt32); outWritable = false; break; case kAudioCodecPropertyPrimeInfo: outPropertyDataSize = SizeOf32(AudioCodecPrimeInfo); outWritable = false; break; case kAudioCodecPropertyDoesSampleRateConversion: outPropertyDataSize = SizeOf32(UInt32); outWritable = false; break; default: CODEC_THROW(kAudioCodecUnknownPropertyError); break; }; }