os/mm/devsound/sounddevbt/src/A2dpBlueTooth/headsetaudioif/A2dpCodecUtilities.cpp
Update contrib.
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "A2dpCodecUtilities.h"
20 A2dp codec utilities Panics
22 enum TA2dpCodecUtilitiesPanic
24 EA2dpCodecUtilNoRemoteCodecConfig, //0
25 EA2dpCodecUtilUnexpectedDataType, //1
26 EA2dpCodecUtilUnsupportedDataType, //2
27 EA2dpCodecUtilUnexpectedConfiguration, //3
28 EA2dpCodecUtilDataMemberNotSet //4
32 static void Panic(TA2dpCodecUtilitiesPanic aPanic)
35 _LIT(KA2dpCodecUtilitiesPanicName, "A2DP Codec Util Panic");
36 User::Panic(KA2dpCodecUtilitiesPanicName, aPanic);
40 TInt TA2dpCodecCapabilityParser::GetSupportedSBCSampleRates(const TSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
43 TSBCSamplingFrequencyBitmask samplingRatesBitMask = aCodecCaps.SamplingFrequencies();
44 if (samplingRatesBitMask & E16kHz)
46 err = aSupportedDiscreteRates.Append(16000);
48 if (!err && (samplingRatesBitMask & E32kHz))
50 err = aSupportedDiscreteRates.Append(32000);
52 if (!err && (samplingRatesBitMask & E44100Hz))
54 err = aSupportedDiscreteRates.Append(44100);
56 if (!err && (samplingRatesBitMask & E48kHz))
58 err = aSupportedDiscreteRates.Append(48000);
64 TInt TA2dpCodecCapabilityParser::GetSupportedMPEG12SampleRates(const TNonSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
68 TPtrC8 codecCapsData(aCodecCaps.CodecData());
70 TMPEG12SamplingFrequencyBitmask samplingRatesBitMask = codecCapsData[1] & KA2dpMPEG12SamplingFrequencyMask;
72 if (samplingRatesBitMask & EMPEG12_16kHz)
74 err = aSupportedDiscreteRates.Append(16000);
76 if (!err && samplingRatesBitMask & EMPEG12_22050Hz)
78 err = aSupportedDiscreteRates.Append(22050);
80 if (!err && samplingRatesBitMask & EMPEG12_24kHz)
82 err = aSupportedDiscreteRates.Append(24000);
84 if (!err && samplingRatesBitMask & EMPEG12_32kHz)
86 err = aSupportedDiscreteRates.Append(32000);
88 if (!err && samplingRatesBitMask & EMPEG12_44100Hz)
90 err = aSupportedDiscreteRates.Append(44100);
92 if (!err && samplingRatesBitMask & EMPEG12_48kHz)
94 err = aSupportedDiscreteRates.Append(48000);
101 TInt TA2dpCodecCapabilityParser::GetSupportedSampleRates(const TAvdtpMediaCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
103 TInt err = KErrNotSupported;
104 switch(aCodecCaps.MediaCodecType())
107 err = GetSupportedSBCSampleRates(static_cast<const TSBCCodecCapabilities&>(aCodecCaps), aSupportedDiscreteRates);
109 case EAudioCodecMPEG12Audio:
110 err = GetSupportedMPEG12SampleRates(static_cast<const TNonSBCCodecCapabilities&>(aCodecCaps), aSupportedDiscreteRates);
112 case EAudioCodecMPEG24AAC:
114 case EAudioCodecATRAC:
117 Panic(EA2dpCodecUtilUnexpectedDataType);
124 TInt TA2dpCodecCapabilityParser::GetSupportedSBCChannels(const TSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
126 TInt err = KErrNotSupported;
128 TSBCChannelModeBitmask channelModesBitMask = aCodecCaps.ChannelModes();
130 err = GetSupportedChannelsCommonCode(channelModesBitMask, aSupportedChannels, aStereoSupport);
136 TInt TA2dpCodecCapabilityParser::GetSupportedMPEG12Channels(const TNonSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
138 TInt err = KErrNotSupported;
140 TPtrC8 codecCapsData(aCodecCaps.CodecData());
141 TSBCChannelModeBitmask channelModesBitMask = codecCapsData[0] & KA2dpMPEG12AudioChannelModeMask;
143 err = GetSupportedChannelsCommonCode(channelModesBitMask, aSupportedChannels, aStereoSupport);
150 MPEG12 uses the same channel mode bit mask as SBC so we'll factor out the common code
151 and reuse the TSBCChannelModeBitmask for mp3 as well
153 TInt TA2dpCodecCapabilityParser::GetSupportedChannelsCommonCode(TSBCChannelModeBitmask aChannelModesBitMask, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
155 TInt err = KErrNotSupported;
157 if (aChannelModesBitMask & EMono)
159 err = aSupportedChannels.Append(EMMFMono);
163 if ((aChannelModesBitMask & EStereo) || (aChannelModesBitMask & EJointStereo))
165 err = aSupportedChannels.Append(EMMFStereo);
166 aStereoSupport = EMMFInterleavedOnly;
169 if (!err && (aChannelModesBitMask & EJointStereo))
171 //we have to cast as the TMMFStereoSupport is an enumeration
172 //but is really should be a bitmap
173 //but don't want to change it in order to preserve BC
174 TUint aStereoSupportInt = static_cast<TUint>(aStereoSupport);
175 aStereoSupportInt |= static_cast<TUint>(EMMFJoint);
176 aStereoSupport = static_cast<TMMFStereoSupport>(aStereoSupportInt);
182 TInt TA2dpCodecCapabilityParser::GetSupportedChannels(const TAvdtpMediaCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
184 TInt err = KErrNotSupported;
185 switch(aCodecCaps.MediaCodecType())
188 err = GetSupportedSBCChannels(static_cast<const TSBCCodecCapabilities&>(aCodecCaps), aSupportedChannels, aStereoSupport);
190 case EAudioCodecMPEG12Audio:
191 err = GetSupportedMPEG12Channels(static_cast<const TNonSBCCodecCapabilities&>(aCodecCaps), aSupportedChannels, aStereoSupport);
193 case EAudioCodecMPEG24AAC:
194 Panic(EA2dpCodecUtilUnsupportedDataType);
196 case EAudioCodecATRAC:
197 Panic(EA2dpCodecUtilUnsupportedDataType);
200 Panic(EA2dpCodecUtilUnexpectedDataType);
210 TUint8 TRTPa2dpCodecSpecificUtils::PayloadType(const TFourCC& aCodecDataType)
212 TUint8 payloadType = 0;
213 switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
215 case KMMFFourCCCodeSBC:
216 payloadType = KSbcRTPPayloadType;
218 case KMMFFourCCCodeMP3:
219 payloadType = KMPEG12RTPAudioPayloadType;
221 case KMMFFourCCCodeAAC:
222 Panic(EA2dpCodecUtilUnsupportedDataType);
224 case KMMFFourCCCodeATRAC3:
225 Panic(EA2dpCodecUtilUnsupportedDataType);
228 Panic(EA2dpCodecUtilUnexpectedDataType);
235 TUint TRTPa2dpCodecSpecificUtils::MediaPayloadHeaderLength(const TFourCC& aCodecDataType)
237 TUint mediaPayloadHeaderLength = 0;
238 switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
240 case KMMFFourCCCodeSBC:
241 mediaPayloadHeaderLength = KSbcRTPMediaPayloadHeaderLength;
243 case KMMFFourCCCodeMP3:
244 mediaPayloadHeaderLength = KMPEG12RTPMediaPayloadHeaderLength;
246 case KMMFFourCCCodeAAC:
247 Panic(EA2dpCodecUtilUnsupportedDataType);
249 case KMMFFourCCCodeATRAC3:
250 Panic(EA2dpCodecUtilUnsupportedDataType);
253 Panic(EA2dpCodecUtilUnexpectedDataType);
256 return mediaPayloadHeaderLength;
261 TTimeIntervalMicroSeconds32 TFrameTimingUtils::FrameDuration(TUint aFrameLength, TUint aBitRate)
263 TUint frameDurationuS = (aFrameLength*8*1000000)/aBitRate;
264 return TTimeIntervalMicroSeconds32(frameDurationuS);
268 TUint TFrameTimingUtils::CalculateSBCTimeStampIncrementPerFrame(TUint aFrameLength, TUint aBitRate, TUint aSampleRate)
270 //SBC uses the sampleRate clock as the timestamp clock A2DP spec 4.3.3.1
271 TUint frameDurationuS = FrameDuration(aFrameLength, aBitRate).Int();
273 return (frameDurationuS*aSampleRate)/1000000;
277 TUint TFrameTimingUtils::CalculateMPEG12TimeStampIncrementPerFrame(TUint aFrameLength, TUint aBitRate)
279 //MPEG12 uses a 90Khz clock as the timestamp clock RFC3551 section 4.5.13
280 TUint frameDurationuS = FrameDuration(aFrameLength, aBitRate).Int();
282 //div 1000000 as frame duration is in microseconds
283 return (frameDurationuS*KMPEG12RTPTimeStampClock)/1000000;
287 TUint TFrameTimingUtils::TimeStampIncrementPerFrame(const TFourCC& aCodecDataType, TUint aFrameLength, TUint aBitRate, TUint aSampleRate)
289 TInt timeStampIncrement = 0;
290 switch (const_cast<TFourCC&>(aCodecDataType).FourCC())
292 case KMMFFourCCCodeSBC:
293 timeStampIncrement = CalculateSBCTimeStampIncrementPerFrame(aFrameLength, aBitRate, aSampleRate);
295 case KMMFFourCCCodeMP3:
296 timeStampIncrement = CalculateMPEG12TimeStampIncrementPerFrame(aFrameLength, aBitRate);
298 case KMMFFourCCCodeAAC:
299 Panic(EA2dpCodecUtilUnsupportedDataType);
301 case KMMFFourCCCodeATRAC3:
302 Panic(EA2dpCodecUtilUnsupportedDataType);
305 //the datatype is a non A2DP datatype
306 //which is not supported so panic
307 Panic(EA2dpCodecUtilUnexpectedDataType);
310 return timeStampIncrement;
314 CA2dpLocalCodecCapabilities* CA2dpLocalCodecCapabilities::NewL()
316 return new(ELeave) CA2dpLocalCodecCapabilities();
320 CA2dpLocalCodecCapabilities::CA2dpLocalCodecCapabilities()
326 CA2dpLocalCodecCapabilities::~CA2dpLocalCodecCapabilities()
328 delete iLocalCodecCapabilities;
332 TAvdtpMediaCodecCapabilities* CA2dpLocalCodecCapabilities::LocalCodecCapabilities(const TFourCC& aCodecDataType)
334 switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
336 case KMMFFourCCCodeSBC:
337 iLocalCodecCapabilities = LocalSBCCodecCapabilities();
339 case KMMFFourCCCodeMP3:
340 iLocalCodecCapabilities = LocalMPEG12CodecCapabilities();
342 case KMMFFourCCCodeAAC:
343 Panic(EA2dpCodecUtilUnsupportedDataType);
345 case KMMFFourCCCodeATRAC3:
346 Panic(EA2dpCodecUtilUnsupportedDataType);
349 Panic(EA2dpCodecUtilUnexpectedDataType);
352 return iLocalCodecCapabilities;
356 TSBCCodecCapabilities* CA2dpLocalCodecCapabilities::LocalSBCCodecCapabilities()
358 delete iLocalCodecCapabilities;
359 iLocalCodecCapabilities = NULL;
360 TSBCCodecCapabilities* localSbcCodecCapabilities = new TSBCCodecCapabilities();
361 if (localSbcCodecCapabilities)
363 localSbcCodecCapabilities->SetSamplingFrequencies(E16kHz|E32kHz|E44100Hz|E48kHz);
364 localSbcCodecCapabilities->SetChannelModes(EMono|EStereo|EJointStereo);
365 localSbcCodecCapabilities->SetBlockLengths(EBlockLenFour|EBlockLenEight|EBlockLenTwelve|EBlockLenSixteen);
366 localSbcCodecCapabilities->SetSubbands(EFourSubbands|EEightSubbands);
367 localSbcCodecCapabilities->SetAllocationMethods(ELoudness|ESNR);
368 localSbcCodecCapabilities->SetMinBitpoolValue(KMinBitPoolValue);
369 localSbcCodecCapabilities->SetMaxBitpoolValue(KMaxBitPoolValue);
371 return localSbcCodecCapabilities;
375 TNonSBCCodecCapabilities* CA2dpLocalCodecCapabilities::LocalMPEG12CodecCapabilities()
377 delete iLocalCodecCapabilities;
378 iLocalCodecCapabilities = NULL;
379 TNonSBCCodecCapabilities* localSEPmpeg12CodecCapabilities = new TNonSBCCodecCapabilities(EAvdtpMediaTypeAudio, EAudioCodecMPEG12Audio);
380 if (localSEPmpeg12CodecCapabilities)
382 TBuf8<4> mpeg12CodecCapabilitiesData;
384 //MPEG12 channel modes are the same as SBC so we'll use SBC structure
385 TSBCChannelModeBitmask channelModes = (EMono|EStereo);
386 mpeg12CodecCapabilitiesData.Append(KA2dpMPEG12LayerMP3Supported | channelModes);
388 //no MPF-2 support, will support 16-44100khz sample
389 TInt8 samplingFrequencySupport = EMPEG12_16kHz|EMPEG12_22050Hz|EMPEG12_24kHz|EMPEG12_32kHz|EMPEG12_44100Hz;
390 mpeg12CodecCapabilitiesData.Append(samplingFrequencySupport);
392 //no VBR all bitrates <= 96kbs-1 except free format
393 mpeg12CodecCapabilitiesData.Append(0);
394 mpeg12CodecCapabilitiesData.Append(KA2dpMPEG12SupportedBitRateIndex);//all bit rates <= 96kbs-1
395 localSEPmpeg12CodecCapabilities->SetCodecData(mpeg12CodecCapabilitiesData);
397 return localSEPmpeg12CodecCapabilities;
402 CA2dpAudioCodecConfiguration* CA2dpAudioCodecConfiguration::NewL()
404 return new(ELeave)CA2dpAudioCodecConfiguration();
408 CA2dpAudioCodecConfiguration::CA2dpAudioCodecConfiguration() : iHeadsetCodecDataType(KMMFFourCCCodeSBC), iSampleRate(KDefaultSampleRate), iChannels(KDefaultChannels), iStereoSupport(KDefaultStereoSupport)
412 CA2dpAudioCodecConfiguration::~CA2dpAudioCodecConfiguration()
414 delete iRemoteCodecConfiguration;
418 void CA2dpAudioCodecConfiguration::Reset()
420 delete iRemoteCodecConfiguration;
421 iRemoteCodecConfiguration = NULL;
422 iHeadsetCodecDataType = KMMFFourCCCodeSBC;
423 iSampleRate = KDefaultSampleRate;
424 iChannels = KDefaultChannels;
425 iStereoSupport = KDefaultStereoSupport;
426 iLocalSBCCodecConfiguration.Reset();
430 Function used to return a TAvdtpMediaCodecCapabilities structure
431 that can be used to configure the SEP at the remote end ie on the headset
432 The capabilities are used to determine the configuration
433 need to return by pointer rather than by ref as TAvdtpMediaCodecCapabilities is abstract
434 Note that this parameter passed in treats the TAvdtpMediaCodecCapabilities as
435 the capabilities of the code, whereas the returned TAvdtpMediaCodecCapabilities is a
436 configuration ie a specific set of values that can be used to configure the remote codec
438 @param aCodecCapabilities This is the capabilities supported by the remote codec
439 @return The configuration for the remote codec
441 //void CA2dpAudioCodecConfiguration::GetRemoteCodecConfiguration(const TAvdtpMediaCodecCapabilities& aRemoteCodecCapabilities, TAvdtpMediaCodecCapabilities& aRemoteCodecConfiguration)
442 TAvdtpMediaCodecCapabilities* CA2dpAudioCodecConfiguration::UpdateRemoteCodecConfiguration(const TAvdtpMediaCodecCapabilities& aRemoteCodecCapabilities)
444 delete iRemoteCodecConfiguration;
445 iRemoteCodecConfiguration = NULL;
447 //this hasn't been set yet so set it
448 //first find out the capabilities of the codec
449 switch (aRemoteCodecCapabilities.MediaCodecType())
452 iRemoteCodecConfiguration = GetRemoteSBCCodecConfiguration(static_cast<const TSBCCodecCapabilities&>(aRemoteCodecCapabilities));
453 iHeadsetCodecDataType = KMMFFourCCCodeSBC;
455 case EAudioCodecMPEG12Audio:
456 iRemoteCodecConfiguration = GetRemoteMPEG12CodecConfiguration(static_cast<const TNonSBCCodecCapabilities&>(aRemoteCodecCapabilities));
457 iHeadsetCodecDataType = KMMFFourCCCodeMP3;
459 case EAudioCodecMPEG24AAC:
460 Panic(EA2dpCodecUtilUnsupportedDataType);
462 case EAudioCodecATRAC:
463 Panic(EA2dpCodecUtilUnsupportedDataType);
466 //the datatype is a non A2DP datatype
467 //which is not supported so panic
468 Panic(EA2dpCodecUtilUnexpectedDataType);
472 return iRemoteCodecConfiguration;
479 TSBCCodecCapabilities* CA2dpAudioCodecConfiguration::GetRemoteSBCCodecConfiguration(const TSBCCodecCapabilities& aCodecCaps)
481 TSBCCodecCapabilities* sbcCodecConfiguration = new TSBCCodecCapabilities();
483 if (sbcCodecConfiguration)
485 //--sampling frequency--
486 TSBCSamplingFrequencyBitmask freqs;
505 //check we really can support this sampling frequency
506 //since we may be using the default which may not be supported
507 //by the headset (even if the A2DP spec says it is mandatory)
508 TSBCSamplingFrequencyBitmask samplingFreqsSupportedByHeadset = aCodecCaps.SamplingFrequencies();
509 if (iForcedRemoteSBCCodecConfiguration)
511 samplingFreqsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->SamplingFrequencies();
513 if (!(freqs & samplingFreqsSupportedByHeadset))
514 {//then the headset doesn't support the sampling frequency
515 //this could happen if iSampleRate is a default that the headset doesn't support
516 //note that evenif the default is a mandatory sample rate eg 44100
517 //we still do not make any assumptions about what is supported
518 if (samplingFreqsSupportedByHeadset & E16kHz)
523 else if (samplingFreqsSupportedByHeadset & E32kHz)
528 else if (samplingFreqsSupportedByHeadset & E44100Hz)
533 else if (samplingFreqsSupportedByHeadset & E48kHz)
538 //else just keep as is
540 sbcCodecConfiguration->SetSamplingFrequencies(freqs);
543 TSBCChannelModeBitmask channelMode = EMono;
544 TSBCChannelModeBitmask channelModesSupportedByHeadset = EMono;
545 channelModesSupportedByHeadset = aCodecCaps.ChannelModes();
546 if (iChannels == EMMFMono)
550 else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFInterleavedOnly))
552 channelMode = EStereo;
554 else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFJoint))
556 channelMode = EJointStereo;
558 if (!(channelMode & channelModesSupportedByHeadset))
560 //then we don't support the selected channel mode
561 if (channelModesSupportedByHeadset & EMono)
563 iChannels = EMMFMono;
564 iStereoSupport = EMMFNone;
567 else if (channelModesSupportedByHeadset & EJointStereo)
569 iChannels = EMMFStereo;
570 iStereoSupport = EMMFJoint;
571 channelMode = EJointStereo;
573 else if (channelModesSupportedByHeadset & EStereo)
575 iChannels = EMMFStereo;
576 iStereoSupport = EMMFInterleavedOnly;
577 channelMode = EStereo;
580 sbcCodecConfiguration->SetChannelModes(channelMode);
583 //we'll choose a preference order of 16,12, 8,4
584 //although there may be a more intelligent way of doing this
585 //based on the other parameters.
586 TSBCBlockLengthBitmask blockLength = EBlockLenSixteen;
587 TSBCBlockLengthBitmask blockLengthsSupportedByHeadset = aCodecCaps.BlockLengths();
588 if (iForcedRemoteSBCCodecConfiguration)
590 blockLengthsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->BlockLengths();
592 if (blockLengthsSupportedByHeadset & EBlockLenSixteen)
594 blockLength = EBlockLenSixteen;
596 else if (blockLengthsSupportedByHeadset & EBlockLenTwelve)
598 blockLength = EBlockLenTwelve;
600 else if (blockLengthsSupportedByHeadset & EBlockLenEight)
602 blockLength = EBlockLenEight;
604 else if (blockLengthsSupportedByHeadset & EBlockLenFour)
606 blockLength = EBlockLenFour;
608 sbcCodecConfiguration->SetBlockLengths(blockLength);
611 //Subbands currently have a preference of 8 over 4
612 TUint numberOfSubbands = 8; //used later for max bit pool value calculation
613 TSBCSubbandsBitmask subbands = EEightSubbands;
614 TSBCSubbandsBitmask subbandsSupportedByHeadset = aCodecCaps.Subbands();
615 if (iForcedRemoteSBCCodecConfiguration)
617 subbandsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->Subbands();
619 if (subbandsSupportedByHeadset & EEightSubbands)
621 subbands = EEightSubbands;
623 else if (subbandsSupportedByHeadset & EFourSubbands)
625 subbands = EFourSubbands;
626 numberOfSubbands = 4;
628 sbcCodecConfiguration->SetSubbands(subbands);
631 //although allocation support of SNR and loudness are mandatory the headset
632 //may have reconfigured to use a particular allocation method
633 //If both allocation methods are available we have to choose which one
634 //so we'll choose a preference order of loudness over SNR
635 TSBCAllocationMethodBitmask allocationMethod = ELoudness;
636 TSBCAllocationMethodBitmask allocationMethodsSupportedByHeadset = aCodecCaps.AllocationMethods();
637 if (iForcedRemoteSBCCodecConfiguration)
639 allocationMethodsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->AllocationMethods();
641 if (allocationMethodsSupportedByHeadset & ELoudness)
643 allocationMethod = ELoudness;
645 else if (allocationMethodsSupportedByHeadset & ESNR)
647 allocationMethod = ESNR;
649 sbcCodecConfiguration->SetAllocationMethods(allocationMethod);
652 // The bitpool value must be in the range of 2-250 and must not exceed
653 // 16*numberOfSubbands*channels
654 // note that we don't normally play SBC directly, except for test purposes
655 // in order to arbitary play any SBC file extra code would be required
656 // to parse the SBC frame header to get the bitpool value
657 // since for unit testing the the SBC test file is known to have a
658 // bit pool value of 20, this shall be the default value
659 // This code could be made more more intelligent and base the
660 // bitpool value around table 4.7 in the A2DP specification
661 TUint minBitPoolValue = KMinBitPoolValue;
662 TUint maxBitPoolValue = KMaxBitPoolValue;
663 if (KMinBitPoolValue < aCodecCaps.MinBitpoolValue())
665 minBitPoolValue = aCodecCaps.MinBitpoolValue();
667 if (KMaxBitPoolValue > aCodecCaps.MaxBitpoolValue())
669 TUint maxAllowableBitPoolValueForCurrentConfiguration = 16*iChannels*numberOfSubbands;
670 maxBitPoolValue = aCodecCaps.MaxBitpoolValue();
671 if (maxBitPoolValue > maxAllowableBitPoolValueForCurrentConfiguration)
673 maxBitPoolValue = maxAllowableBitPoolValueForCurrentConfiguration;
676 sbcCodecConfiguration->SetMinBitpoolValue(minBitPoolValue);
677 sbcCodecConfiguration->SetMaxBitpoolValue(maxBitPoolValue);
678 }//if (sbcCodecConfiguration)
680 return sbcCodecConfiguration;
685 internal function to get a remote codec configuration from the capabilities
686 Note technically speaking MPEG12 refers to MPEG 1 & MPEG 2 audio layers 1,2 and 3
687 however since mp1 & mp2 is rarely used in practice this
688 will be MPEG 1 layer 3 ie mp3 in most case
690 TNonSBCCodecCapabilities* CA2dpAudioCodecConfiguration::GetRemoteMPEG12CodecConfiguration(const TNonSBCCodecCapabilities& aCodecCaps)
692 TNonSBCCodecCapabilities* mpeg12CodecConfiguration = new TNonSBCCodecCapabilities(EAvdtpMediaTypeAudio, EAudioCodecMPEG12Audio);
693 TBuf8<4> mpeg12CodecConfigurationData;//should be 4 make 6 for bug??
694 if (mpeg12CodecConfiguration)
695 {//codecData should contain data conformant to A2DP profile
696 // codec specific information elements section A2DP 4.4.2
697 TPtrC8 codecCapsData(aCodecCaps.CodecData());
698 TInt8 mpegLayerSupport = codecCapsData[0] & KA2dpMPEG12LayerMask;
699 if (!(mpegLayerSupport & KA2dpMPEG12LayerMP3Supported))
701 //then mp3 is not supported must be mp1 or mp2 which we don't support
702 delete mpeg12CodecConfiguration;
703 mpeg12CodecConfiguration = NULL;
704 return mpeg12CodecConfiguration;
706 mpegLayerSupport = KA2dpMPEG12LayerMP3Supported; //mp3
707 //we don't bother with CRC protection so don't check
709 //the MPEG12 channel support structure is identical to
710 //SBC so we'll use the SBC structure
712 TSBCChannelModeBitmask channelMode = EMono;
713 TSBCChannelModeBitmask channelModesSupportedByHeadset = EMono;
714 channelModesSupportedByHeadset = codecCapsData[0] & KA2dpMPEG12AudioChannelModeMask;
715 if (iChannels == EMMFMono)
719 else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFInterleavedOnly))
721 channelMode = EStereo;
723 else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFJoint))
725 channelMode = EJointStereo;
727 if (!(channelMode & channelModesSupportedByHeadset))
729 //then we don't support the selected channel mode
730 if (channelModesSupportedByHeadset & EMono)
732 iChannels = EMMFMono;
733 iStereoSupport = EMMFNone;
736 else if (channelModesSupportedByHeadset & EJointStereo)
738 iChannels = EMMFStereo;
739 iStereoSupport = EMMFJoint;
740 channelMode = EJointStereo;
742 else if (channelModesSupportedByHeadset & EStereo)
744 iChannels = EMMFStereo;
745 iStereoSupport = EMMFInterleavedOnly;
746 channelMode = EStereo;
749 mpeg12CodecConfigurationData.Append(mpegLayerSupport | channelMode);
751 //Media Payload Format
752 //this ref implementation shall only support the media payload format
753 //defined in RFC2250, RFC3119 is not supported
754 //therefore there is no need to check this since MPF-1/RFC2250 is mandatory
756 //--sampling frequency--
757 //the mp3 sampling frequency mask is not the same as SBC so can't use TSBCSamplingFrequencyBitmask
758 TMPEG12SamplingFrequencyBitmask freqs;
762 freqs = EMPEG12_16kHz;
765 freqs = EMPEG12_22050Hz;
768 freqs = EMPEG12_24kHz;
771 freqs = EMPEG12_32kHz;
774 freqs = EMPEG12_44100Hz;
777 freqs = EMPEG12_48kHz;
780 freqs = EMPEG12_16kHz;
783 //check we really can support this sampling frequency
784 //since we may be using the default which may not be supported
785 //by the headset (even if the A2DP spec says it is mandatory)
786 TMPEG12SamplingFrequencyBitmask samplingFreqsSupportedByHeadset = codecCapsData[1] & KA2dpMPEG12SamplingFrequencyMask;
787 if (!(freqs & samplingFreqsSupportedByHeadset))
788 {//then the headset doesn't support the sampling frequency
789 //this could happen if iSampleRate is a default that the headset doesn't support
790 //note that evenif the default is a mandatory sample rate eg 44100
791 //we still do not make any assumptions about what is supported
792 if (samplingFreqsSupportedByHeadset & EMPEG12_16kHz)
795 freqs = EMPEG12_16kHz;
797 else if (samplingFreqsSupportedByHeadset & EMPEG12_22050Hz)
800 freqs = EMPEG12_22050Hz;
802 else if (samplingFreqsSupportedByHeadset & EMPEG12_24kHz)
805 freqs = EMPEG12_24kHz;
807 else if (samplingFreqsSupportedByHeadset & EMPEG12_32kHz)
810 freqs = EMPEG12_32kHz;
812 else if (samplingFreqsSupportedByHeadset & EMPEG12_44100Hz)
815 freqs = EMPEG12_44100Hz;
817 else if (samplingFreqsSupportedByHeadset & EMPEG12_48kHz)
820 freqs = EMPEG12_48kHz;
822 //else just keep as is
824 //set frequency, MPF-1
825 mpeg12CodecConfigurationData.Append(freqs);
828 //The casira pod only supports bit rates up to 96kbs-1
829 //so check the headset supports these as well
830 //we'll just mask with all the lower bit rates
831 //all the lower bit rate support up to 96kbs-1are in octet 3
832 //so just make out octet 2 bit rate support
833 //also VBR = 0 as no VBR support
834 mpeg12CodecConfigurationData.Append(0);
836 //all bitrates <= 96kbs-1 except free format
837 mpeg12CodecConfigurationData.Append(KA2dpMPEG12SupportedBitRateIndex & codecCapsData[3]);
838 mpeg12CodecConfiguration->SetCodecData(mpeg12CodecConfigurationData);
840 return mpeg12CodecConfiguration;
845 Utility function get the codec capabilities used by Gavdp into the SBC codec paramerers
846 used by the SBC codec
847 The function uses the TSBCCodecCapabilities to generate a set of TSBCFrameParameters
848 which can be used to configure the codec
849 the remote codec configuration must have already been updated before calling
852 @param aSBCFrameParameters These are set to the current configuration settings
854 TSBCFrameParameters& CA2dpAudioCodecConfiguration::UpdateLocalSBCCodecConfiguration()
856 __ASSERT_DEBUG(iRemoteCodecConfiguration, Panic(EA2dpCodecUtilNoRemoteCodecConfig));
857 __ASSERT_DEBUG((iHeadsetCodecDataType == KMMFFourCCCodeSBC) && (iRemoteCodecConfiguration->MediaCodecType() == EAudioCodecSBC), Panic(EA2dpCodecUtilUnexpectedDataType));
858 TSBCCodecCapabilities* remoteSBCCodecConfiguration = static_cast<TSBCCodecCapabilities*>(iRemoteCodecConfiguration);
860 //note that for sampling frequency and channels the capabilites
861 //have already been checked in SetSampleRate and SetChannels
862 //and once set we don't allow these to be reconfigured
863 //so no need to check these again with the codecCaps
864 //if set the iSampleRate should always be in agreement with
865 //the settings on the remote codec
866 TSBCFrameParameters::TSamplingFrequency SBCSamplingFrequency;
870 SBCSamplingFrequency = TSBCFrameParameters::E32000Hz;
873 SBCSamplingFrequency = TSBCFrameParameters::E44100Hz;
876 SBCSamplingFrequency = TSBCFrameParameters::E48000Hz;
878 default://[TODO] change default to 44100 when hardware
879 //(ie BT support H2 or higher bandwidth support on Casira) supports it
880 SBCSamplingFrequency = TSBCFrameParameters::E16000Hz;
884 iLocalSBCCodecConfiguration.SetSamplingFrequency(SBCSamplingFrequency);
886 //although a block length of 4,8,12,16 are mandatory the headset
887 //may have reconfigured to use a particular block length
888 //If all block lengths are available we have to choose which one
889 //For now we'll choose a preference order of 12,16,8,4
890 //although there may be a more intelligent way of doing this
891 //based on the other parameters.
892 switch(remoteSBCCodecConfiguration->BlockLengths())
894 case EBlockLenTwelve:
895 iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E12Blocks);
897 case EBlockLenSixteen:
898 iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E16Blocks);
901 iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E8Blocks);
904 iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E4Blocks);
907 Panic(EA2dpCodecUtilUnexpectedConfiguration);
913 //although the number of channels can't be changed on the fly
914 //switching between stereo and joint stereo is supported
915 //note different namespaces for EStereo & EJointStereo !
916 TSBCFrameParameters::TChannelMode channelMode = TSBCFrameParameters::EMono;//default
917 if (iChannels == EMMFStereo)
919 if (iStereoSupport & EMMFJoint)
921 channelMode = TSBCFrameParameters::EJointStereo;
923 else if (iStereoSupport & EMMFInterleavedOnly)
925 channelMode = TSBCFrameParameters::EStereo;
929 Panic(EA2dpCodecUtilUnexpectedConfiguration);
933 iLocalSBCCodecConfiguration.SetChannelMode(channelMode);
936 //although allocation support of SNR and loudness are mandatory the headset
937 //may have reconfigured to use a particular allocation method
938 //If both allocation methods are available we have to choose which one
939 //For now we'll choose a preference order of loudness followed by SNR
941 switch(remoteSBCCodecConfiguration->AllocationMethods())
944 iLocalSBCCodecConfiguration.SetAllocationMethod(TSBCFrameParameters::ELoudness);
947 iLocalSBCCodecConfiguration.SetAllocationMethod(TSBCFrameParameters::ESNR);
950 Panic(EA2dpCodecUtilUnexpectedConfiguration);
955 //Subbands currently have a preference of four over 8, but change to 8 later
956 //when hardware is available to support higher bandwidth
957 switch(remoteSBCCodecConfiguration->Subbands())
960 iLocalSBCCodecConfiguration.SetSubbands(TSBCFrameParameters::E4Subbands);
963 iLocalSBCCodecConfiguration.SetSubbands(TSBCFrameParameters::E8Subbands);
966 Panic(EA2dpCodecUtilUnexpectedConfiguration);
970 // note that we don't normally play SBC directly, except for test purposes
971 // in order to arbitary play any SBC file extra code would be required
972 // to parse the SBC frame header to get the bitpool value
973 // since for unit testing the the SBC test file is known to have a
974 // bit pool value of 20, this shall be the default value
975 // This code could be made more more intelligent and base the
976 // bitpool value around table 4.7 in the A2DP specification
977 TUint bitPoolValue = KDefaultBitPoolValue; //default is 20
978 if (KDefaultBitPoolValue < remoteSBCCodecConfiguration->MinBitpoolValue())
980 bitPoolValue = remoteSBCCodecConfiguration->MinBitpoolValue();
982 else if (KDefaultBitPoolValue > remoteSBCCodecConfiguration->MaxBitpoolValue())
984 bitPoolValue = remoteSBCCodecConfiguration->MaxBitpoolValue();
986 iLocalSBCCodecConfiguration.SetBitpool(bitPoolValue);
988 return iLocalSBCCodecConfiguration;
993 Internal function to calculate the SBC buffer length required from the SBC frame parameters
994 using the given pcm16 buffer length
996 TUint CA2dpAudioCodecConfiguration::CalculateSBCBufferLength(TUint aPCM16BufferLength) const
998 //ASSERT data type = SBC
1000 //first calculate the number of PCM16 samples in one SBC frame
1001 TUint numberOfSamplesPerSBCFrame = iLocalSBCCodecConfiguration.BlockLength()*iLocalSBCCodecConfiguration.Subbands();
1003 //calculate the number of bytes in one sample
1004 TUint numberOfPCM16BytesPerSample = 2*iLocalSBCCodecConfiguration.Channels();
1006 TUint numberOfPCM16BytesPerSBCFrame = numberOfSamplesPerSBCFrame*numberOfPCM16BytesPerSample;
1008 TUint numberOfFrames = aPCM16BufferLength/numberOfPCM16BytesPerSBCFrame;
1010 TUint lengthOfSBCFrame = iLocalSBCCodecConfiguration.CalcFrameLength();
1012 return numberOfFrames*lengthOfSBCFrame;
1017 Test function to force the remote SBC codec configuration to that set in aRemoteCodecConfiguration
1018 This function is just used for test purposes to set the SBC settings for
1019 playing SBC data direct to the a2dpBTHeadsetAudioIf ie when the Data type is
1021 It is up to the user to ensure that the headset supports the configuration
1022 since this will bypass the normal capability check
1024 void CA2dpAudioCodecConfiguration::TEST_ForceRemoteSBCCodecConfiguration(const TSBCCodecCapabilities& aRemoteCodecConfiguration)
1026 iForcedRemoteSBCCodecConfiguration = const_cast<TSBCCodecCapabilities*>(&aRemoteCodecConfiguration);
1032 CA2dpCodecFrameHeaderParser* CA2dpCodecFrameHeaderParser::NewL(const TFourCC& aCodecDataType, const TDesC8& aHeader)
1034 CA2dpCodecFrameHeaderParser* self = new (ELeave) CA2dpCodecFrameHeaderParser();
1035 CleanupStack::PushL(self);
1036 self->ConstructL(aCodecDataType, aHeader);
1037 CleanupStack::Pop(self);
1042 CA2dpCodecFrameHeaderParser::CA2dpCodecFrameHeaderParser()
1048 CA2dpCodecFrameHeaderParser::~CA2dpCodecFrameHeaderParser()
1055 Only used for playing SBC test files
1057 void CA2dpCodecFrameHeaderParser::ParseSBCHeaderL(const TDesC8& aHeader)
1059 if (aHeader[0] != KSbcFrameHeaderSyncWord)
1061 User::Leave(KErrCorrupt); //not a valid sbc frame
1064 TUint samplingFrequency = (aHeader[1] & KSbcFrameHeaderSamplingFrequencyMask)>>6;
1065 switch(samplingFrequency)
1067 case TSBCFrameParameters::E16000Hz:
1068 iSampleRate = 16000;
1070 case TSBCFrameParameters::E32000Hz:
1071 iSampleRate = 32000;
1073 case TSBCFrameParameters::E44100Hz:
1074 iSampleRate = 44100;
1076 case TSBCFrameParameters::E48000Hz:
1077 iSampleRate = 48000;
1080 User::Leave(KErrCorrupt);//not a valid header
1084 TUint8 blocks = (aHeader[1] & KSbcFrameHeaderBlocksMask)>>4;
1087 case TSBCFrameParameters::E4Blocks:
1090 case TSBCFrameParameters::E8Blocks:
1093 case TSBCFrameParameters::E12Blocks:
1096 case TSBCFrameParameters::E16Blocks:
1100 User::Leave(KErrCorrupt);//not a valid header
1103 TUint8 channelMode = (aHeader[1] & KSbcFrameHeaderChannelModeMask)>>2;
1104 TUint8 channels = 1;
1106 if (channelMode != TSBCFrameParameters::EMono)
1111 TUint8 subbands = 4;
1112 if (aHeader[1] & KSbcFrameHeaderSubbandsMask)
1117 TUint8 bitpool = aHeader[2];
1120 switch (channelMode)
1122 case TSBCFrameParameters::EMono:
1123 temp = blocks * bitpool; // blocks * bitpool
1125 case TSBCFrameParameters::EDualChannel:
1126 temp = (blocks * bitpool) << 1; // blocks * bitpool * 2
1128 case TSBCFrameParameters::EStereo:
1129 temp = blocks * bitpool; // blocks * bitpool
1131 case TSBCFrameParameters::EJointStereo:
1132 temp = subbands + blocks * bitpool; // subbands + blocks * bitpool
1136 iFrameLength = 4 + ( (subbands * channels) >> 1) + (temp >> 3);
1142 iBitRate = (8*iFrameLength*iSampleRate)/(subbands*blocks);
1146 void CA2dpCodecFrameHeaderParser::ParseMPEG12HeaderL(const TDesC8& aHeader)
1148 if (aHeader[0] != KMPEGAudioFrameHeaderSyncWord )
1150 User::Leave(KErrCorrupt); //not a valid MPEG audio frame
1153 //check it's really mp3 as opposed to mp1 or mp2
1154 if ((aHeader[1] & KMp3AudioFrameHeaderIdMask) != KMp3AudioFrameHeaderId)
1156 User::Leave(KErrNotSupported); //either corrupt or mp1/mp2
1159 TUint8 sampleRateIndex = (aHeader[2] & KMp3FrameHeaderSamplingFrequencyMask)>>2;
1160 switch(sampleRateIndex)
1163 iSampleRate = 44100;
1166 iSampleRate = 48000;
1169 iSampleRate = 32000;
1172 User::Leave(KErrCorrupt); //invalid mp3 header?
1175 TUint8 bitRateIndex = (aHeader[2] & KMp3FrameHeaderBitRateIndexMask)>>4;
1176 switch(bitRateIndex)
1178 case EMp3BitRateIndex32000:
1181 case EMp3BitRateIndex40000:
1184 case EMp3BitRateIndex48000:
1187 case EMp3BitRateIndex56000:
1190 case EMp3BitRateIndex64000:
1193 case EMp3BitRateIndex80000:
1196 case EMp3BitRateIndex96000:
1200 User::Leave(KErrNotSupported);//don't support more than 96kbs-1
1204 //this code should really be made more clever to take allowance for any padding
1205 //and use a frame length such that if padding is used then take the lowest
1206 //common multiple of frames tht gives a common frame length eg if the frames
1207 //alternate between 100 and 101 bytes due to an extra padding byte everyother
1208 //frame then set the frame length to 201;
1209 TUint bitRateX144 = iBitRate*144;
1210 iFrameLength = bitRateX144/iSampleRate;
1217 void CA2dpCodecFrameHeaderParser::ConstructL(const TFourCC& aCodecDataType, const TDesC8& aHeader)
1219 switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
1221 case KMMFFourCCCodeSBC:
1222 ParseSBCHeaderL(aHeader);
1224 case KMMFFourCCCodeMP3:
1225 ParseMPEG12HeaderL(aHeader);
1227 case KMMFFourCCCodeAAC:
1228 User::Leave(KErrNotSupported);
1230 case KMMFFourCCCodeATRAC3:
1231 User::Leave(KErrNotSupported);
1234 User::Leave(KErrNotSupported);