os/mm/devsound/sounddevbt/src/A2dpBlueTooth/headsetaudioif/A2dpCodecUtilities.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/devsound/sounddevbt/src/A2dpBlueTooth/headsetaudioif/A2dpCodecUtilities.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1238 @@
1.4 +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "A2dpCodecUtilities.h"
1.20 +
1.21 +
1.22 +/**
1.23 +A2dp codec utilities Panics
1.24 +**/
1.25 +enum TA2dpCodecUtilitiesPanic
1.26 + {
1.27 + EA2dpCodecUtilNoRemoteCodecConfig, //0
1.28 + EA2dpCodecUtilUnexpectedDataType, //1
1.29 + EA2dpCodecUtilUnsupportedDataType, //2
1.30 + EA2dpCodecUtilUnexpectedConfiguration, //3
1.31 + EA2dpCodecUtilDataMemberNotSet //4
1.32 + };
1.33 +
1.34 +
1.35 +static void Panic(TA2dpCodecUtilitiesPanic aPanic)
1.36 +// Panic client
1.37 + {
1.38 + _LIT(KA2dpCodecUtilitiesPanicName, "A2DP Codec Util Panic");
1.39 + User::Panic(KA2dpCodecUtilitiesPanicName, aPanic);
1.40 + }
1.41 +
1.42 +
1.43 +TInt TA2dpCodecCapabilityParser::GetSupportedSBCSampleRates(const TSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
1.44 + {
1.45 + TInt err = KErrNone;
1.46 + TSBCSamplingFrequencyBitmask samplingRatesBitMask = aCodecCaps.SamplingFrequencies();
1.47 + if (samplingRatesBitMask & E16kHz)
1.48 + {
1.49 + err = aSupportedDiscreteRates.Append(16000);
1.50 + }
1.51 + if (!err && (samplingRatesBitMask & E32kHz))
1.52 + {
1.53 + err = aSupportedDiscreteRates.Append(32000);
1.54 + }
1.55 + if (!err && (samplingRatesBitMask & E44100Hz))
1.56 + {
1.57 + err = aSupportedDiscreteRates.Append(44100);
1.58 + }
1.59 + if (!err && (samplingRatesBitMask & E48kHz))
1.60 + {
1.61 + err = aSupportedDiscreteRates.Append(48000);
1.62 + }
1.63 + return err;
1.64 + }
1.65 +
1.66 +
1.67 +TInt TA2dpCodecCapabilityParser::GetSupportedMPEG12SampleRates(const TNonSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
1.68 + {
1.69 + TInt err = KErrNone;
1.70 +
1.71 + TPtrC8 codecCapsData(aCodecCaps.CodecData());
1.72 +
1.73 + TMPEG12SamplingFrequencyBitmask samplingRatesBitMask = codecCapsData[1] & KA2dpMPEG12SamplingFrequencyMask;
1.74 +
1.75 + if (samplingRatesBitMask & EMPEG12_16kHz)
1.76 + {
1.77 + err = aSupportedDiscreteRates.Append(16000);
1.78 + }
1.79 + if (!err && samplingRatesBitMask & EMPEG12_22050Hz)
1.80 + {
1.81 + err = aSupportedDiscreteRates.Append(22050);
1.82 + }
1.83 + if (!err && samplingRatesBitMask & EMPEG12_24kHz)
1.84 + {
1.85 + err = aSupportedDiscreteRates.Append(24000);
1.86 + }
1.87 + if (!err && samplingRatesBitMask & EMPEG12_32kHz)
1.88 + {
1.89 + err = aSupportedDiscreteRates.Append(32000);
1.90 + }
1.91 + if (!err && samplingRatesBitMask & EMPEG12_44100Hz)
1.92 + {
1.93 + err = aSupportedDiscreteRates.Append(44100);
1.94 + }
1.95 + if (!err && samplingRatesBitMask & EMPEG12_48kHz)
1.96 + {
1.97 + err = aSupportedDiscreteRates.Append(48000);
1.98 + }
1.99 +
1.100 + return err;
1.101 + }
1.102 +
1.103 +
1.104 +TInt TA2dpCodecCapabilityParser::GetSupportedSampleRates(const TAvdtpMediaCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
1.105 + {
1.106 + TInt err = KErrNotSupported;
1.107 + switch(aCodecCaps.MediaCodecType())
1.108 + {
1.109 + case EAudioCodecSBC:
1.110 + err = GetSupportedSBCSampleRates(static_cast<const TSBCCodecCapabilities&>(aCodecCaps), aSupportedDiscreteRates);
1.111 + break;
1.112 + case EAudioCodecMPEG12Audio:
1.113 + err = GetSupportedMPEG12SampleRates(static_cast<const TNonSBCCodecCapabilities&>(aCodecCaps), aSupportedDiscreteRates);
1.114 + break;
1.115 + case EAudioCodecMPEG24AAC:
1.116 + break;
1.117 + case EAudioCodecATRAC:
1.118 + break;
1.119 + default:
1.120 + Panic(EA2dpCodecUtilUnexpectedDataType);
1.121 + break;
1.122 + }
1.123 + return err;
1.124 + }
1.125 +
1.126 +
1.127 +TInt TA2dpCodecCapabilityParser::GetSupportedSBCChannels(const TSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
1.128 + {
1.129 + TInt err = KErrNotSupported;
1.130 +
1.131 + TSBCChannelModeBitmask channelModesBitMask = aCodecCaps.ChannelModes();
1.132 +
1.133 + err = GetSupportedChannelsCommonCode(channelModesBitMask, aSupportedChannels, aStereoSupport);
1.134 +
1.135 + return err;
1.136 + }
1.137 +
1.138 +
1.139 +TInt TA2dpCodecCapabilityParser::GetSupportedMPEG12Channels(const TNonSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
1.140 + {
1.141 + TInt err = KErrNotSupported;
1.142 +
1.143 + TPtrC8 codecCapsData(aCodecCaps.CodecData());
1.144 + TSBCChannelModeBitmask channelModesBitMask = codecCapsData[0] & KA2dpMPEG12AudioChannelModeMask;
1.145 +
1.146 + err = GetSupportedChannelsCommonCode(channelModesBitMask, aSupportedChannels, aStereoSupport);
1.147 +
1.148 + return err;
1.149 + }
1.150 +
1.151 +
1.152 +/**
1.153 +MPEG12 uses the same channel mode bit mask as SBC so we'll factor out the common code
1.154 +and reuse the TSBCChannelModeBitmask for mp3 as well
1.155 +*/
1.156 +TInt TA2dpCodecCapabilityParser::GetSupportedChannelsCommonCode(TSBCChannelModeBitmask aChannelModesBitMask, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
1.157 + {
1.158 + TInt err = KErrNotSupported;
1.159 +
1.160 + if (aChannelModesBitMask & EMono)
1.161 + {
1.162 + err = aSupportedChannels.Append(EMMFMono);
1.163 + }
1.164 + if (!err)
1.165 + {
1.166 + if ((aChannelModesBitMask & EStereo) || (aChannelModesBitMask & EJointStereo))
1.167 + {
1.168 + err = aSupportedChannels.Append(EMMFStereo);
1.169 + aStereoSupport = EMMFInterleavedOnly;
1.170 + }
1.171 + }
1.172 + if (!err && (aChannelModesBitMask & EJointStereo))
1.173 + {
1.174 + //we have to cast as the TMMFStereoSupport is an enumeration
1.175 + //but is really should be a bitmap
1.176 + //but don't want to change it in order to preserve BC
1.177 + TUint aStereoSupportInt = static_cast<TUint>(aStereoSupport);
1.178 + aStereoSupportInt |= static_cast<TUint>(EMMFJoint);
1.179 + aStereoSupport = static_cast<TMMFStereoSupport>(aStereoSupportInt);
1.180 + }
1.181 + return err;
1.182 + }
1.183 +
1.184 +
1.185 +TInt TA2dpCodecCapabilityParser::GetSupportedChannels(const TAvdtpMediaCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
1.186 + {
1.187 + TInt err = KErrNotSupported;
1.188 + switch(aCodecCaps.MediaCodecType())
1.189 + {
1.190 + case EAudioCodecSBC:
1.191 + err = GetSupportedSBCChannels(static_cast<const TSBCCodecCapabilities&>(aCodecCaps), aSupportedChannels, aStereoSupport);
1.192 + break;
1.193 + case EAudioCodecMPEG12Audio:
1.194 + err = GetSupportedMPEG12Channels(static_cast<const TNonSBCCodecCapabilities&>(aCodecCaps), aSupportedChannels, aStereoSupport);
1.195 + break;
1.196 + case EAudioCodecMPEG24AAC:
1.197 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.198 + break;
1.199 + case EAudioCodecATRAC:
1.200 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.201 + break;
1.202 + default:
1.203 + Panic(EA2dpCodecUtilUnexpectedDataType);
1.204 + break;
1.205 + }
1.206 + return err;
1.207 + }
1.208 +
1.209 +
1.210 +/**
1.211 +static
1.212 +*/
1.213 +TUint8 TRTPa2dpCodecSpecificUtils::PayloadType(const TFourCC& aCodecDataType)
1.214 + {
1.215 + TUint8 payloadType = 0;
1.216 + switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
1.217 + {
1.218 + case KMMFFourCCCodeSBC:
1.219 + payloadType = KSbcRTPPayloadType;
1.220 + break;
1.221 + case KMMFFourCCCodeMP3:
1.222 + payloadType = KMPEG12RTPAudioPayloadType;
1.223 + break;
1.224 + case KMMFFourCCCodeAAC:
1.225 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.226 + break;
1.227 + case KMMFFourCCCodeATRAC3:
1.228 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.229 + break;
1.230 + default:
1.231 + Panic(EA2dpCodecUtilUnexpectedDataType);
1.232 + break;
1.233 + }
1.234 + return payloadType;
1.235 + }
1.236 +
1.237 +
1.238 +TUint TRTPa2dpCodecSpecificUtils::MediaPayloadHeaderLength(const TFourCC& aCodecDataType)
1.239 + {
1.240 + TUint mediaPayloadHeaderLength = 0;
1.241 + switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
1.242 + {
1.243 + case KMMFFourCCCodeSBC:
1.244 + mediaPayloadHeaderLength = KSbcRTPMediaPayloadHeaderLength;
1.245 + break;
1.246 + case KMMFFourCCCodeMP3:
1.247 + mediaPayloadHeaderLength = KMPEG12RTPMediaPayloadHeaderLength;
1.248 + break;
1.249 + case KMMFFourCCCodeAAC:
1.250 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.251 + break;
1.252 + case KMMFFourCCCodeATRAC3:
1.253 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.254 + break;
1.255 + default:
1.256 + Panic(EA2dpCodecUtilUnexpectedDataType);
1.257 + break;
1.258 + }
1.259 + return mediaPayloadHeaderLength;
1.260 + }
1.261 +
1.262 +
1.263 +
1.264 +TTimeIntervalMicroSeconds32 TFrameTimingUtils::FrameDuration(TUint aFrameLength, TUint aBitRate)
1.265 + {
1.266 + TUint frameDurationuS = (aFrameLength*8*1000000)/aBitRate;
1.267 + return TTimeIntervalMicroSeconds32(frameDurationuS);
1.268 + }
1.269 +
1.270 +
1.271 +TUint TFrameTimingUtils::CalculateSBCTimeStampIncrementPerFrame(TUint aFrameLength, TUint aBitRate, TUint aSampleRate)
1.272 + {
1.273 + //SBC uses the sampleRate clock as the timestamp clock A2DP spec 4.3.3.1
1.274 + TUint frameDurationuS = FrameDuration(aFrameLength, aBitRate).Int();
1.275 +
1.276 + return (frameDurationuS*aSampleRate)/1000000;
1.277 + }
1.278 +
1.279 +
1.280 +TUint TFrameTimingUtils::CalculateMPEG12TimeStampIncrementPerFrame(TUint aFrameLength, TUint aBitRate)
1.281 + {
1.282 + //MPEG12 uses a 90Khz clock as the timestamp clock RFC3551 section 4.5.13
1.283 + TUint frameDurationuS = FrameDuration(aFrameLength, aBitRate).Int();
1.284 +
1.285 + //div 1000000 as frame duration is in microseconds
1.286 + return (frameDurationuS*KMPEG12RTPTimeStampClock)/1000000;
1.287 + }
1.288 +
1.289 +
1.290 +TUint TFrameTimingUtils::TimeStampIncrementPerFrame(const TFourCC& aCodecDataType, TUint aFrameLength, TUint aBitRate, TUint aSampleRate)
1.291 + {
1.292 + TInt timeStampIncrement = 0;
1.293 + switch (const_cast<TFourCC&>(aCodecDataType).FourCC())
1.294 + {
1.295 + case KMMFFourCCCodeSBC:
1.296 + timeStampIncrement = CalculateSBCTimeStampIncrementPerFrame(aFrameLength, aBitRate, aSampleRate);
1.297 + break;
1.298 + case KMMFFourCCCodeMP3:
1.299 + timeStampIncrement = CalculateMPEG12TimeStampIncrementPerFrame(aFrameLength, aBitRate);
1.300 + break;
1.301 + case KMMFFourCCCodeAAC:
1.302 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.303 + break;
1.304 + case KMMFFourCCCodeATRAC3:
1.305 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.306 + break;
1.307 + default:
1.308 + //the datatype is a non A2DP datatype
1.309 + //which is not supported so panic
1.310 + Panic(EA2dpCodecUtilUnexpectedDataType);
1.311 + break;
1.312 + }
1.313 + return timeStampIncrement;
1.314 + }
1.315 +
1.316 +
1.317 +CA2dpLocalCodecCapabilities* CA2dpLocalCodecCapabilities::NewL()
1.318 + {
1.319 + return new(ELeave) CA2dpLocalCodecCapabilities();
1.320 + }
1.321 +
1.322 +
1.323 +CA2dpLocalCodecCapabilities::CA2dpLocalCodecCapabilities()
1.324 + {
1.325 +
1.326 + }
1.327 +
1.328 +
1.329 +CA2dpLocalCodecCapabilities::~CA2dpLocalCodecCapabilities()
1.330 + {
1.331 + delete iLocalCodecCapabilities;
1.332 + }
1.333 +
1.334 +
1.335 +TAvdtpMediaCodecCapabilities* CA2dpLocalCodecCapabilities::LocalCodecCapabilities(const TFourCC& aCodecDataType)
1.336 + {
1.337 + switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
1.338 + {
1.339 + case KMMFFourCCCodeSBC:
1.340 + iLocalCodecCapabilities = LocalSBCCodecCapabilities();
1.341 + break;
1.342 + case KMMFFourCCCodeMP3:
1.343 + iLocalCodecCapabilities = LocalMPEG12CodecCapabilities();
1.344 + break;
1.345 + case KMMFFourCCCodeAAC:
1.346 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.347 + break;
1.348 + case KMMFFourCCCodeATRAC3:
1.349 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.350 + break;
1.351 + default:
1.352 + Panic(EA2dpCodecUtilUnexpectedDataType);
1.353 + break;
1.354 + }
1.355 + return iLocalCodecCapabilities;
1.356 + }
1.357 +
1.358 +
1.359 +TSBCCodecCapabilities* CA2dpLocalCodecCapabilities::LocalSBCCodecCapabilities()
1.360 + {
1.361 + delete iLocalCodecCapabilities;
1.362 + iLocalCodecCapabilities = NULL;
1.363 + TSBCCodecCapabilities* localSbcCodecCapabilities = new TSBCCodecCapabilities();
1.364 + if (localSbcCodecCapabilities)
1.365 + {
1.366 + localSbcCodecCapabilities->SetSamplingFrequencies(E16kHz|E32kHz|E44100Hz|E48kHz);
1.367 + localSbcCodecCapabilities->SetChannelModes(EMono|EStereo|EJointStereo);
1.368 + localSbcCodecCapabilities->SetBlockLengths(EBlockLenFour|EBlockLenEight|EBlockLenTwelve|EBlockLenSixteen);
1.369 + localSbcCodecCapabilities->SetSubbands(EFourSubbands|EEightSubbands);
1.370 + localSbcCodecCapabilities->SetAllocationMethods(ELoudness|ESNR);
1.371 + localSbcCodecCapabilities->SetMinBitpoolValue(KMinBitPoolValue);
1.372 + localSbcCodecCapabilities->SetMaxBitpoolValue(KMaxBitPoolValue);
1.373 + }
1.374 + return localSbcCodecCapabilities;
1.375 + }
1.376 +
1.377 +
1.378 +TNonSBCCodecCapabilities* CA2dpLocalCodecCapabilities::LocalMPEG12CodecCapabilities()
1.379 + {
1.380 + delete iLocalCodecCapabilities;
1.381 + iLocalCodecCapabilities = NULL;
1.382 + TNonSBCCodecCapabilities* localSEPmpeg12CodecCapabilities = new TNonSBCCodecCapabilities(EAvdtpMediaTypeAudio, EAudioCodecMPEG12Audio);
1.383 + if (localSEPmpeg12CodecCapabilities)
1.384 + {
1.385 + TBuf8<4> mpeg12CodecCapabilitiesData;
1.386 +
1.387 + //MPEG12 channel modes are the same as SBC so we'll use SBC structure
1.388 + TSBCChannelModeBitmask channelModes = (EMono|EStereo);
1.389 + mpeg12CodecCapabilitiesData.Append(KA2dpMPEG12LayerMP3Supported | channelModes);
1.390 +
1.391 + //no MPF-2 support, will support 16-44100khz sample
1.392 + TInt8 samplingFrequencySupport = EMPEG12_16kHz|EMPEG12_22050Hz|EMPEG12_24kHz|EMPEG12_32kHz|EMPEG12_44100Hz;
1.393 + mpeg12CodecCapabilitiesData.Append(samplingFrequencySupport);
1.394 +
1.395 + //no VBR all bitrates <= 96kbs-1 except free format
1.396 + mpeg12CodecCapabilitiesData.Append(0);
1.397 + mpeg12CodecCapabilitiesData.Append(KA2dpMPEG12SupportedBitRateIndex);//all bit rates <= 96kbs-1
1.398 + localSEPmpeg12CodecCapabilities->SetCodecData(mpeg12CodecCapabilitiesData);
1.399 + }
1.400 + return localSEPmpeg12CodecCapabilities;
1.401 + }
1.402 +
1.403 +
1.404 +
1.405 +CA2dpAudioCodecConfiguration* CA2dpAudioCodecConfiguration::NewL()
1.406 + {
1.407 + return new(ELeave)CA2dpAudioCodecConfiguration();
1.408 + }
1.409 +
1.410 +
1.411 +CA2dpAudioCodecConfiguration::CA2dpAudioCodecConfiguration() : iHeadsetCodecDataType(KMMFFourCCCodeSBC), iSampleRate(KDefaultSampleRate), iChannels(KDefaultChannels), iStereoSupport(KDefaultStereoSupport)
1.412 + {
1.413 + }
1.414 +
1.415 +CA2dpAudioCodecConfiguration::~CA2dpAudioCodecConfiguration()
1.416 + {
1.417 + delete iRemoteCodecConfiguration;
1.418 + }
1.419 +
1.420 +
1.421 +void CA2dpAudioCodecConfiguration::Reset()
1.422 + {
1.423 + delete iRemoteCodecConfiguration;
1.424 + iRemoteCodecConfiguration = NULL;
1.425 + iHeadsetCodecDataType = KMMFFourCCCodeSBC;
1.426 + iSampleRate = KDefaultSampleRate;
1.427 + iChannels = KDefaultChannels;
1.428 + iStereoSupport = KDefaultStereoSupport;
1.429 + iLocalSBCCodecConfiguration.Reset();
1.430 + }
1.431 +
1.432 +/**
1.433 +Function used to return a TAvdtpMediaCodecCapabilities structure
1.434 +that can be used to configure the SEP at the remote end ie on the headset
1.435 +The capabilities are used to determine the configuration
1.436 +need to return by pointer rather than by ref as TAvdtpMediaCodecCapabilities is abstract
1.437 +Note that this parameter passed in treats the TAvdtpMediaCodecCapabilities as
1.438 +the capabilities of the code, whereas the returned TAvdtpMediaCodecCapabilities is a
1.439 +configuration ie a specific set of values that can be used to configure the remote codec
1.440 +
1.441 +@param aCodecCapabilities This is the capabilities supported by the remote codec
1.442 +@return The configuration for the remote codec
1.443 +*/
1.444 +//void CA2dpAudioCodecConfiguration::GetRemoteCodecConfiguration(const TAvdtpMediaCodecCapabilities& aRemoteCodecCapabilities, TAvdtpMediaCodecCapabilities& aRemoteCodecConfiguration)
1.445 +TAvdtpMediaCodecCapabilities* CA2dpAudioCodecConfiguration::UpdateRemoteCodecConfiguration(const TAvdtpMediaCodecCapabilities& aRemoteCodecCapabilities)
1.446 + {
1.447 + delete iRemoteCodecConfiguration;
1.448 + iRemoteCodecConfiguration = NULL;
1.449 + {
1.450 + //this hasn't been set yet so set it
1.451 + //first find out the capabilities of the codec
1.452 + switch (aRemoteCodecCapabilities.MediaCodecType())
1.453 + {
1.454 + case EAudioCodecSBC:
1.455 + iRemoteCodecConfiguration = GetRemoteSBCCodecConfiguration(static_cast<const TSBCCodecCapabilities&>(aRemoteCodecCapabilities));
1.456 + iHeadsetCodecDataType = KMMFFourCCCodeSBC;
1.457 + break;
1.458 + case EAudioCodecMPEG12Audio:
1.459 + iRemoteCodecConfiguration = GetRemoteMPEG12CodecConfiguration(static_cast<const TNonSBCCodecCapabilities&>(aRemoteCodecCapabilities));
1.460 + iHeadsetCodecDataType = KMMFFourCCCodeMP3;
1.461 + break;
1.462 + case EAudioCodecMPEG24AAC:
1.463 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.464 + break;
1.465 + case EAudioCodecATRAC:
1.466 + Panic(EA2dpCodecUtilUnsupportedDataType);
1.467 + break;
1.468 + default:
1.469 + //the datatype is a non A2DP datatype
1.470 + //which is not supported so panic
1.471 + Panic(EA2dpCodecUtilUnexpectedDataType);
1.472 + break;
1.473 + }
1.474 + }
1.475 + return iRemoteCodecConfiguration;
1.476 + }
1.477 +
1.478 +
1.479 +/**
1.480 +
1.481 +*/
1.482 +TSBCCodecCapabilities* CA2dpAudioCodecConfiguration::GetRemoteSBCCodecConfiguration(const TSBCCodecCapabilities& aCodecCaps)
1.483 + {
1.484 + TSBCCodecCapabilities* sbcCodecConfiguration = new TSBCCodecCapabilities();
1.485 +
1.486 + if (sbcCodecConfiguration)
1.487 + {
1.488 + //--sampling frequency--
1.489 + TSBCSamplingFrequencyBitmask freqs;
1.490 + switch(iSampleRate)
1.491 + {
1.492 + case 16000:
1.493 + freqs = E16kHz;
1.494 + break;
1.495 + case 32000:
1.496 + freqs = E32kHz;
1.497 + break;
1.498 + case 44100:
1.499 + freqs = E44100Hz;
1.500 + break;
1.501 + case 48000:
1.502 + freqs = E48kHz;
1.503 + break;
1.504 + default:
1.505 + freqs = E16kHz;
1.506 + break;
1.507 + }
1.508 + //check we really can support this sampling frequency
1.509 + //since we may be using the default which may not be supported
1.510 + //by the headset (even if the A2DP spec says it is mandatory)
1.511 + TSBCSamplingFrequencyBitmask samplingFreqsSupportedByHeadset = aCodecCaps.SamplingFrequencies();
1.512 + if (iForcedRemoteSBCCodecConfiguration)
1.513 + {
1.514 + samplingFreqsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->SamplingFrequencies();
1.515 + }
1.516 + if (!(freqs & samplingFreqsSupportedByHeadset))
1.517 + {//then the headset doesn't support the sampling frequency
1.518 + //this could happen if iSampleRate is a default that the headset doesn't support
1.519 + //note that evenif the default is a mandatory sample rate eg 44100
1.520 + //we still do not make any assumptions about what is supported
1.521 + if (samplingFreqsSupportedByHeadset & E16kHz)
1.522 + {
1.523 + iSampleRate = 16000;
1.524 + freqs = E16kHz;
1.525 + }
1.526 + else if (samplingFreqsSupportedByHeadset & E32kHz)
1.527 + {
1.528 + iSampleRate = 32000;
1.529 + freqs = E32kHz;
1.530 + }
1.531 + else if (samplingFreqsSupportedByHeadset & E44100Hz)
1.532 + {
1.533 + iSampleRate = 44100;
1.534 + freqs = E44100Hz;
1.535 + }
1.536 + else if (samplingFreqsSupportedByHeadset & E48kHz)
1.537 + {
1.538 + iSampleRate = 48000;
1.539 + freqs = E48kHz;
1.540 + }
1.541 + //else just keep as is
1.542 + }
1.543 + sbcCodecConfiguration->SetSamplingFrequencies(freqs);
1.544 +
1.545 + //--channels--
1.546 + TSBCChannelModeBitmask channelMode = EMono;
1.547 + TSBCChannelModeBitmask channelModesSupportedByHeadset = EMono;
1.548 + channelModesSupportedByHeadset = aCodecCaps.ChannelModes();
1.549 + if (iChannels == EMMFMono)
1.550 + {
1.551 + channelMode = EMono;
1.552 + }
1.553 + else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFInterleavedOnly))
1.554 + {
1.555 + channelMode = EStereo;
1.556 + }
1.557 + else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFJoint))
1.558 + {
1.559 + channelMode = EJointStereo;
1.560 + }
1.561 + if (!(channelMode & channelModesSupportedByHeadset))
1.562 + {
1.563 + //then we don't support the selected channel mode
1.564 + if (channelModesSupportedByHeadset & EMono)
1.565 + {
1.566 + iChannels = EMMFMono;
1.567 + iStereoSupport = EMMFNone;
1.568 + channelMode = EMono;
1.569 + }
1.570 + else if (channelModesSupportedByHeadset & EJointStereo)
1.571 + {
1.572 + iChannels = EMMFStereo;
1.573 + iStereoSupport = EMMFJoint;
1.574 + channelMode = EJointStereo;
1.575 + }
1.576 + else if (channelModesSupportedByHeadset & EStereo)
1.577 + {
1.578 + iChannels = EMMFStereo;
1.579 + iStereoSupport = EMMFInterleavedOnly;
1.580 + channelMode = EStereo;
1.581 + }
1.582 + }
1.583 + sbcCodecConfiguration->SetChannelModes(channelMode);
1.584 +
1.585 + //--block mode--
1.586 + //we'll choose a preference order of 16,12, 8,4
1.587 + //although there may be a more intelligent way of doing this
1.588 + //based on the other parameters.
1.589 + TSBCBlockLengthBitmask blockLength = EBlockLenSixteen;
1.590 + TSBCBlockLengthBitmask blockLengthsSupportedByHeadset = aCodecCaps.BlockLengths();
1.591 + if (iForcedRemoteSBCCodecConfiguration)
1.592 + {
1.593 + blockLengthsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->BlockLengths();
1.594 + }
1.595 + if (blockLengthsSupportedByHeadset & EBlockLenSixteen)
1.596 + {
1.597 + blockLength = EBlockLenSixteen;
1.598 + }
1.599 + else if (blockLengthsSupportedByHeadset & EBlockLenTwelve)
1.600 + {
1.601 + blockLength = EBlockLenTwelve;
1.602 + }
1.603 + else if (blockLengthsSupportedByHeadset & EBlockLenEight)
1.604 + {
1.605 + blockLength = EBlockLenEight;
1.606 + }
1.607 + else if (blockLengthsSupportedByHeadset & EBlockLenFour)
1.608 + {
1.609 + blockLength = EBlockLenFour;
1.610 + }
1.611 + sbcCodecConfiguration->SetBlockLengths(blockLength);
1.612 +
1.613 + //--subbands--
1.614 + //Subbands currently have a preference of 8 over 4
1.615 + TUint numberOfSubbands = 8; //used later for max bit pool value calculation
1.616 + TSBCSubbandsBitmask subbands = EEightSubbands;
1.617 + TSBCSubbandsBitmask subbandsSupportedByHeadset = aCodecCaps.Subbands();
1.618 + if (iForcedRemoteSBCCodecConfiguration)
1.619 + {
1.620 + subbandsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->Subbands();
1.621 + }
1.622 + if (subbandsSupportedByHeadset & EEightSubbands)
1.623 + {
1.624 + subbands = EEightSubbands;
1.625 + }
1.626 + else if (subbandsSupportedByHeadset & EFourSubbands)
1.627 + {
1.628 + subbands = EFourSubbands;
1.629 + numberOfSubbands = 4;
1.630 + }
1.631 + sbcCodecConfiguration->SetSubbands(subbands);
1.632 +
1.633 + //--Allocation--
1.634 + //although allocation support of SNR and loudness are mandatory the headset
1.635 + //may have reconfigured to use a particular allocation method
1.636 + //If both allocation methods are available we have to choose which one
1.637 + //so we'll choose a preference order of loudness over SNR
1.638 + TSBCAllocationMethodBitmask allocationMethod = ELoudness;
1.639 + TSBCAllocationMethodBitmask allocationMethodsSupportedByHeadset = aCodecCaps.AllocationMethods();
1.640 + if (iForcedRemoteSBCCodecConfiguration)
1.641 + {
1.642 + allocationMethodsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->AllocationMethods();
1.643 + }
1.644 + if (allocationMethodsSupportedByHeadset & ELoudness)
1.645 + {
1.646 + allocationMethod = ELoudness;
1.647 + }
1.648 + else if (allocationMethodsSupportedByHeadset & ESNR)
1.649 + {
1.650 + allocationMethod = ESNR;
1.651 + }
1.652 + sbcCodecConfiguration->SetAllocationMethods(allocationMethod);
1.653 +
1.654 + //--bitpool
1.655 + // The bitpool value must be in the range of 2-250 and must not exceed
1.656 + // 16*numberOfSubbands*channels
1.657 + // note that we don't normally play SBC directly, except for test purposes
1.658 + // in order to arbitary play any SBC file extra code would be required
1.659 + // to parse the SBC frame header to get the bitpool value
1.660 + // since for unit testing the the SBC test file is known to have a
1.661 + // bit pool value of 20, this shall be the default value
1.662 + // This code could be made more more intelligent and base the
1.663 + // bitpool value around table 4.7 in the A2DP specification
1.664 + TUint minBitPoolValue = KMinBitPoolValue;
1.665 + TUint maxBitPoolValue = KMaxBitPoolValue;
1.666 + if (KMinBitPoolValue < aCodecCaps.MinBitpoolValue())
1.667 + {
1.668 + minBitPoolValue = aCodecCaps.MinBitpoolValue();
1.669 + }
1.670 + if (KMaxBitPoolValue > aCodecCaps.MaxBitpoolValue())
1.671 + {
1.672 + TUint maxAllowableBitPoolValueForCurrentConfiguration = 16*iChannels*numberOfSubbands;
1.673 + maxBitPoolValue = aCodecCaps.MaxBitpoolValue();
1.674 + if (maxBitPoolValue > maxAllowableBitPoolValueForCurrentConfiguration)
1.675 + {
1.676 + maxBitPoolValue = maxAllowableBitPoolValueForCurrentConfiguration;
1.677 + }
1.678 + }
1.679 + sbcCodecConfiguration->SetMinBitpoolValue(minBitPoolValue);
1.680 + sbcCodecConfiguration->SetMaxBitpoolValue(maxBitPoolValue);
1.681 + }//if (sbcCodecConfiguration)
1.682 +
1.683 + return sbcCodecConfiguration;
1.684 + }
1.685 +
1.686 +
1.687 +/**
1.688 +internal function to get a remote codec configuration from the capabilities
1.689 +Note technically speaking MPEG12 refers to MPEG 1 & MPEG 2 audio layers 1,2 and 3
1.690 +however since mp1 & mp2 is rarely used in practice this
1.691 +will be MPEG 1 layer 3 ie mp3 in most case
1.692 +*/
1.693 +TNonSBCCodecCapabilities* CA2dpAudioCodecConfiguration::GetRemoteMPEG12CodecConfiguration(const TNonSBCCodecCapabilities& aCodecCaps)
1.694 + {
1.695 + TNonSBCCodecCapabilities* mpeg12CodecConfiguration = new TNonSBCCodecCapabilities(EAvdtpMediaTypeAudio, EAudioCodecMPEG12Audio);
1.696 + TBuf8<4> mpeg12CodecConfigurationData;//should be 4 make 6 for bug??
1.697 + if (mpeg12CodecConfiguration)
1.698 + {//codecData should contain data conformant to A2DP profile
1.699 + // codec specific information elements section A2DP 4.4.2
1.700 + TPtrC8 codecCapsData(aCodecCaps.CodecData());
1.701 + TInt8 mpegLayerSupport = codecCapsData[0] & KA2dpMPEG12LayerMask;
1.702 + if (!(mpegLayerSupport & KA2dpMPEG12LayerMP3Supported))
1.703 + {
1.704 + //then mp3 is not supported must be mp1 or mp2 which we don't support
1.705 + delete mpeg12CodecConfiguration;
1.706 + mpeg12CodecConfiguration = NULL;
1.707 + return mpeg12CodecConfiguration;
1.708 + }
1.709 + mpegLayerSupport = KA2dpMPEG12LayerMP3Supported; //mp3
1.710 + //we don't bother with CRC protection so don't check
1.711 +
1.712 + //the MPEG12 channel support structure is identical to
1.713 + //SBC so we'll use the SBC structure
1.714 + //--channels--
1.715 + TSBCChannelModeBitmask channelMode = EMono;
1.716 + TSBCChannelModeBitmask channelModesSupportedByHeadset = EMono;
1.717 + channelModesSupportedByHeadset = codecCapsData[0] & KA2dpMPEG12AudioChannelModeMask;
1.718 + if (iChannels == EMMFMono)
1.719 + {
1.720 + channelMode = EMono;
1.721 + }
1.722 + else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFInterleavedOnly))
1.723 + {
1.724 + channelMode = EStereo;
1.725 + }
1.726 + else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFJoint))
1.727 + {
1.728 + channelMode = EJointStereo;
1.729 + }
1.730 + if (!(channelMode & channelModesSupportedByHeadset))
1.731 + {
1.732 + //then we don't support the selected channel mode
1.733 + if (channelModesSupportedByHeadset & EMono)
1.734 + {
1.735 + iChannels = EMMFMono;
1.736 + iStereoSupport = EMMFNone;
1.737 + channelMode = EMono;
1.738 + }
1.739 + else if (channelModesSupportedByHeadset & EJointStereo)
1.740 + {
1.741 + iChannels = EMMFStereo;
1.742 + iStereoSupport = EMMFJoint;
1.743 + channelMode = EJointStereo;
1.744 + }
1.745 + else if (channelModesSupportedByHeadset & EStereo)
1.746 + {
1.747 + iChannels = EMMFStereo;
1.748 + iStereoSupport = EMMFInterleavedOnly;
1.749 + channelMode = EStereo;
1.750 + }
1.751 + }
1.752 + mpeg12CodecConfigurationData.Append(mpegLayerSupport | channelMode);
1.753 +
1.754 + //Media Payload Format
1.755 + //this ref implementation shall only support the media payload format
1.756 + //defined in RFC2250, RFC3119 is not supported
1.757 + //therefore there is no need to check this since MPF-1/RFC2250 is mandatory
1.758 +
1.759 + //--sampling frequency--
1.760 + //the mp3 sampling frequency mask is not the same as SBC so can't use TSBCSamplingFrequencyBitmask
1.761 + TMPEG12SamplingFrequencyBitmask freqs;
1.762 + switch(iSampleRate)
1.763 + {
1.764 + case 16000:
1.765 + freqs = EMPEG12_16kHz;
1.766 + break;
1.767 + case 22050:
1.768 + freqs = EMPEG12_22050Hz;
1.769 + break;
1.770 + case 24000:
1.771 + freqs = EMPEG12_24kHz;
1.772 + break;
1.773 + case 32000:
1.774 + freqs = EMPEG12_32kHz;
1.775 + break;
1.776 + case 44100:
1.777 + freqs = EMPEG12_44100Hz;
1.778 + break;
1.779 + case 48000:
1.780 + freqs = EMPEG12_48kHz;
1.781 + break;
1.782 + default:
1.783 + freqs = EMPEG12_16kHz;
1.784 + break;
1.785 + }
1.786 + //check we really can support this sampling frequency
1.787 + //since we may be using the default which may not be supported
1.788 + //by the headset (even if the A2DP spec says it is mandatory)
1.789 + TMPEG12SamplingFrequencyBitmask samplingFreqsSupportedByHeadset = codecCapsData[1] & KA2dpMPEG12SamplingFrequencyMask;
1.790 + if (!(freqs & samplingFreqsSupportedByHeadset))
1.791 + {//then the headset doesn't support the sampling frequency
1.792 + //this could happen if iSampleRate is a default that the headset doesn't support
1.793 + //note that evenif the default is a mandatory sample rate eg 44100
1.794 + //we still do not make any assumptions about what is supported
1.795 + if (samplingFreqsSupportedByHeadset & EMPEG12_16kHz)
1.796 + {
1.797 + iSampleRate = 16000;
1.798 + freqs = EMPEG12_16kHz;
1.799 + }
1.800 + else if (samplingFreqsSupportedByHeadset & EMPEG12_22050Hz)
1.801 + {
1.802 + iSampleRate = 22050;
1.803 + freqs = EMPEG12_22050Hz;
1.804 + }
1.805 + else if (samplingFreqsSupportedByHeadset & EMPEG12_24kHz)
1.806 + {
1.807 + iSampleRate = 24000;
1.808 + freqs = EMPEG12_24kHz;
1.809 + }
1.810 + else if (samplingFreqsSupportedByHeadset & EMPEG12_32kHz)
1.811 + {
1.812 + iSampleRate = 32000;
1.813 + freqs = EMPEG12_32kHz;
1.814 + }
1.815 + else if (samplingFreqsSupportedByHeadset & EMPEG12_44100Hz)
1.816 + {
1.817 + iSampleRate = 44100;
1.818 + freqs = EMPEG12_44100Hz;
1.819 + }
1.820 + else if (samplingFreqsSupportedByHeadset & EMPEG12_48kHz)
1.821 + {
1.822 + iSampleRate = 48000;
1.823 + freqs = EMPEG12_48kHz;
1.824 + }
1.825 + //else just keep as is
1.826 + }
1.827 + //set frequency, MPF-1
1.828 + mpeg12CodecConfigurationData.Append(freqs);
1.829 +
1.830 +
1.831 + //The casira pod only supports bit rates up to 96kbs-1
1.832 + //so check the headset supports these as well
1.833 + //we'll just mask with all the lower bit rates
1.834 + //all the lower bit rate support up to 96kbs-1are in octet 3
1.835 + //so just make out octet 2 bit rate support
1.836 + //also VBR = 0 as no VBR support
1.837 + mpeg12CodecConfigurationData.Append(0);
1.838 +
1.839 + //all bitrates <= 96kbs-1 except free format
1.840 + mpeg12CodecConfigurationData.Append(KA2dpMPEG12SupportedBitRateIndex & codecCapsData[3]);
1.841 + mpeg12CodecConfiguration->SetCodecData(mpeg12CodecConfigurationData);
1.842 + }
1.843 + return mpeg12CodecConfiguration;
1.844 + }
1.845 +
1.846 +
1.847 +/**
1.848 +Utility function get the codec capabilities used by Gavdp into the SBC codec paramerers
1.849 +used by the SBC codec
1.850 +The function uses the TSBCCodecCapabilities to generate a set of TSBCFrameParameters
1.851 +which can be used to configure the codec
1.852 +the remote codec configuration must have already been updated before calling
1.853 +this function
1.854 +
1.855 +@param aSBCFrameParameters These are set to the current configuration settings
1.856 +*/
1.857 +TSBCFrameParameters& CA2dpAudioCodecConfiguration::UpdateLocalSBCCodecConfiguration()
1.858 + {
1.859 + __ASSERT_DEBUG(iRemoteCodecConfiguration, Panic(EA2dpCodecUtilNoRemoteCodecConfig));
1.860 + __ASSERT_DEBUG((iHeadsetCodecDataType == KMMFFourCCCodeSBC) && (iRemoteCodecConfiguration->MediaCodecType() == EAudioCodecSBC), Panic(EA2dpCodecUtilUnexpectedDataType));
1.861 + TSBCCodecCapabilities* remoteSBCCodecConfiguration = static_cast<TSBCCodecCapabilities*>(iRemoteCodecConfiguration);
1.862 +
1.863 + //note that for sampling frequency and channels the capabilites
1.864 + //have already been checked in SetSampleRate and SetChannels
1.865 + //and once set we don't allow these to be reconfigured
1.866 + //so no need to check these again with the codecCaps
1.867 + //if set the iSampleRate should always be in agreement with
1.868 + //the settings on the remote codec
1.869 + TSBCFrameParameters::TSamplingFrequency SBCSamplingFrequency;
1.870 + switch(iSampleRate)
1.871 + {
1.872 + case 32000:
1.873 + SBCSamplingFrequency = TSBCFrameParameters::E32000Hz;
1.874 + break;
1.875 + case 44100:
1.876 + SBCSamplingFrequency = TSBCFrameParameters::E44100Hz;
1.877 + break;
1.878 + case 48000:
1.879 + SBCSamplingFrequency = TSBCFrameParameters::E48000Hz;
1.880 + break;
1.881 + default://[TODO] change default to 44100 when hardware
1.882 + //(ie BT support H2 or higher bandwidth support on Casira) supports it
1.883 + SBCSamplingFrequency = TSBCFrameParameters::E16000Hz;
1.884 + break;
1.885 + }
1.886 +
1.887 + iLocalSBCCodecConfiguration.SetSamplingFrequency(SBCSamplingFrequency);
1.888 +
1.889 + //although a block length of 4,8,12,16 are mandatory the headset
1.890 + //may have reconfigured to use a particular block length
1.891 + //If all block lengths are available we have to choose which one
1.892 + //For now we'll choose a preference order of 12,16,8,4
1.893 + //although there may be a more intelligent way of doing this
1.894 + //based on the other parameters.
1.895 + switch(remoteSBCCodecConfiguration->BlockLengths())
1.896 + {
1.897 + case EBlockLenTwelve:
1.898 + iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E12Blocks);
1.899 + break;
1.900 + case EBlockLenSixteen:
1.901 + iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E16Blocks);
1.902 + break;
1.903 + case EBlockLenEight:
1.904 + iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E8Blocks);
1.905 + break;
1.906 + case EBlockLenFour:
1.907 + iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E4Blocks);
1.908 + break;
1.909 + default:
1.910 + Panic(EA2dpCodecUtilUnexpectedConfiguration);
1.911 + break;
1.912 + }
1.913 +
1.914 +
1.915 + //channel mode
1.916 + //although the number of channels can't be changed on the fly
1.917 + //switching between stereo and joint stereo is supported
1.918 + //note different namespaces for EStereo & EJointStereo !
1.919 + TSBCFrameParameters::TChannelMode channelMode = TSBCFrameParameters::EMono;//default
1.920 + if (iChannels == EMMFStereo)
1.921 + {
1.922 + if (iStereoSupport & EMMFJoint)
1.923 + {
1.924 + channelMode = TSBCFrameParameters::EJointStereo;
1.925 + }
1.926 + else if (iStereoSupport & EMMFInterleavedOnly)
1.927 + {
1.928 + channelMode = TSBCFrameParameters::EStereo;
1.929 + }
1.930 + else
1.931 + {
1.932 + Panic(EA2dpCodecUtilUnexpectedConfiguration);
1.933 + }
1.934 + }
1.935 +
1.936 + iLocalSBCCodecConfiguration.SetChannelMode(channelMode);
1.937 +
1.938 + //Allocation
1.939 + //although allocation support of SNR and loudness are mandatory the headset
1.940 + //may have reconfigured to use a particular allocation method
1.941 + //If both allocation methods are available we have to choose which one
1.942 + //For now we'll choose a preference order of loudness followed by SNR
1.943 +
1.944 + switch(remoteSBCCodecConfiguration->AllocationMethods())
1.945 + {
1.946 + case ELoudness:
1.947 + iLocalSBCCodecConfiguration.SetAllocationMethod(TSBCFrameParameters::ELoudness);
1.948 + break;
1.949 + case ESNR:
1.950 + iLocalSBCCodecConfiguration.SetAllocationMethod(TSBCFrameParameters::ESNR);
1.951 + break;
1.952 + default:
1.953 + Panic(EA2dpCodecUtilUnexpectedConfiguration);
1.954 + break;
1.955 + }
1.956 +
1.957 +
1.958 + //Subbands currently have a preference of four over 8, but change to 8 later
1.959 + //when hardware is available to support higher bandwidth
1.960 + switch(remoteSBCCodecConfiguration->Subbands())
1.961 + {
1.962 + case EFourSubbands:
1.963 + iLocalSBCCodecConfiguration.SetSubbands(TSBCFrameParameters::E4Subbands);
1.964 + break;
1.965 + case EEightSubbands:
1.966 + iLocalSBCCodecConfiguration.SetSubbands(TSBCFrameParameters::E8Subbands);
1.967 + break;
1.968 + default:
1.969 + Panic(EA2dpCodecUtilUnexpectedConfiguration);
1.970 + break;
1.971 + }
1.972 +
1.973 + // note that we don't normally play SBC directly, except for test purposes
1.974 + // in order to arbitary play any SBC file extra code would be required
1.975 + // to parse the SBC frame header to get the bitpool value
1.976 + // since for unit testing the the SBC test file is known to have a
1.977 + // bit pool value of 20, this shall be the default value
1.978 + // This code could be made more more intelligent and base the
1.979 + // bitpool value around table 4.7 in the A2DP specification
1.980 + TUint bitPoolValue = KDefaultBitPoolValue; //default is 20
1.981 + if (KDefaultBitPoolValue < remoteSBCCodecConfiguration->MinBitpoolValue())
1.982 + {
1.983 + bitPoolValue = remoteSBCCodecConfiguration->MinBitpoolValue();
1.984 + }
1.985 + else if (KDefaultBitPoolValue > remoteSBCCodecConfiguration->MaxBitpoolValue())
1.986 + {
1.987 + bitPoolValue = remoteSBCCodecConfiguration->MaxBitpoolValue();
1.988 + }
1.989 + iLocalSBCCodecConfiguration.SetBitpool(bitPoolValue);
1.990 +
1.991 + return iLocalSBCCodecConfiguration;
1.992 + }
1.993 +
1.994 +
1.995 +/**
1.996 +Internal function to calculate the SBC buffer length required from the SBC frame parameters
1.997 +using the given pcm16 buffer length
1.998 +*/
1.999 +TUint CA2dpAudioCodecConfiguration::CalculateSBCBufferLength(TUint aPCM16BufferLength) const
1.1000 + {
1.1001 + //ASSERT data type = SBC
1.1002 +
1.1003 + //first calculate the number of PCM16 samples in one SBC frame
1.1004 + TUint numberOfSamplesPerSBCFrame = iLocalSBCCodecConfiguration.BlockLength()*iLocalSBCCodecConfiguration.Subbands();
1.1005 +
1.1006 + //calculate the number of bytes in one sample
1.1007 + TUint numberOfPCM16BytesPerSample = 2*iLocalSBCCodecConfiguration.Channels();
1.1008 +
1.1009 + TUint numberOfPCM16BytesPerSBCFrame = numberOfSamplesPerSBCFrame*numberOfPCM16BytesPerSample;
1.1010 +
1.1011 + TUint numberOfFrames = aPCM16BufferLength/numberOfPCM16BytesPerSBCFrame;
1.1012 +
1.1013 + TUint lengthOfSBCFrame = iLocalSBCCodecConfiguration.CalcFrameLength();
1.1014 +
1.1015 + return numberOfFrames*lengthOfSBCFrame;
1.1016 + }
1.1017 +
1.1018 +
1.1019 +/**
1.1020 +Test function to force the remote SBC codec configuration to that set in aRemoteCodecConfiguration
1.1021 +This function is just used for test purposes to set the SBC settings for
1.1022 +playing SBC data direct to the a2dpBTHeadsetAudioIf ie when the Data type is
1.1023 +set to SBC
1.1024 +It is up to the user to ensure that the headset supports the configuration
1.1025 +since this will bypass the normal capability check
1.1026 +*/
1.1027 +void CA2dpAudioCodecConfiguration::TEST_ForceRemoteSBCCodecConfiguration(const TSBCCodecCapabilities& aRemoteCodecConfiguration)
1.1028 + {
1.1029 + iForcedRemoteSBCCodecConfiguration = const_cast<TSBCCodecCapabilities*>(&aRemoteCodecConfiguration);
1.1030 + }
1.1031 +
1.1032 +
1.1033 +
1.1034 +
1.1035 +CA2dpCodecFrameHeaderParser* CA2dpCodecFrameHeaderParser::NewL(const TFourCC& aCodecDataType, const TDesC8& aHeader)
1.1036 + {
1.1037 + CA2dpCodecFrameHeaderParser* self = new (ELeave) CA2dpCodecFrameHeaderParser();
1.1038 + CleanupStack::PushL(self);
1.1039 + self->ConstructL(aCodecDataType, aHeader);
1.1040 + CleanupStack::Pop(self);
1.1041 + return self;
1.1042 + }
1.1043 +
1.1044 +
1.1045 +CA2dpCodecFrameHeaderParser::CA2dpCodecFrameHeaderParser()
1.1046 + {
1.1047 +
1.1048 + }
1.1049 +
1.1050 +
1.1051 +CA2dpCodecFrameHeaderParser::~CA2dpCodecFrameHeaderParser()
1.1052 + {
1.1053 +
1.1054 + }
1.1055 +
1.1056 +
1.1057 +/**
1.1058 +Only used for playing SBC test files
1.1059 +*/
1.1060 +void CA2dpCodecFrameHeaderParser::ParseSBCHeaderL(const TDesC8& aHeader)
1.1061 + {
1.1062 + if (aHeader[0] != KSbcFrameHeaderSyncWord)
1.1063 + {
1.1064 + User::Leave(KErrCorrupt); //not a valid sbc frame
1.1065 + }
1.1066 +
1.1067 + TUint samplingFrequency = (aHeader[1] & KSbcFrameHeaderSamplingFrequencyMask)>>6;
1.1068 + switch(samplingFrequency)
1.1069 + {
1.1070 + case TSBCFrameParameters::E16000Hz:
1.1071 + iSampleRate = 16000;
1.1072 + break;
1.1073 + case TSBCFrameParameters::E32000Hz:
1.1074 + iSampleRate = 32000;
1.1075 + break;
1.1076 + case TSBCFrameParameters::E44100Hz:
1.1077 + iSampleRate = 44100;
1.1078 + break;
1.1079 + case TSBCFrameParameters::E48000Hz:
1.1080 + iSampleRate = 48000;
1.1081 + break;
1.1082 + default:
1.1083 + User::Leave(KErrCorrupt);//not a valid header
1.1084 + break;
1.1085 + }
1.1086 +
1.1087 + TUint8 blocks = (aHeader[1] & KSbcFrameHeaderBlocksMask)>>4;
1.1088 + switch(blocks)
1.1089 + {
1.1090 + case TSBCFrameParameters::E4Blocks:
1.1091 + blocks = 4;
1.1092 + break;
1.1093 + case TSBCFrameParameters::E8Blocks:
1.1094 + blocks = 8;
1.1095 + break;
1.1096 + case TSBCFrameParameters::E12Blocks:
1.1097 + blocks = 12;
1.1098 + break;
1.1099 + case TSBCFrameParameters::E16Blocks:
1.1100 + blocks = 16;
1.1101 + break;
1.1102 + default:
1.1103 + User::Leave(KErrCorrupt);//not a valid header
1.1104 + break;
1.1105 + }
1.1106 + TUint8 channelMode = (aHeader[1] & KSbcFrameHeaderChannelModeMask)>>2;
1.1107 + TUint8 channels = 1;
1.1108 +
1.1109 + if (channelMode != TSBCFrameParameters::EMono)
1.1110 + {
1.1111 + channels = 2;
1.1112 + }
1.1113 +
1.1114 + TUint8 subbands = 4;
1.1115 + if (aHeader[1] & KSbcFrameHeaderSubbandsMask)
1.1116 + {
1.1117 + subbands = 8;
1.1118 + }
1.1119 +
1.1120 + TUint8 bitpool = aHeader[2];
1.1121 +
1.1122 + TUint temp = 0;
1.1123 + switch (channelMode)
1.1124 + {
1.1125 + case TSBCFrameParameters::EMono:
1.1126 + temp = blocks * bitpool; // blocks * bitpool
1.1127 + break;
1.1128 + case TSBCFrameParameters::EDualChannel:
1.1129 + temp = (blocks * bitpool) << 1; // blocks * bitpool * 2
1.1130 + break;
1.1131 + case TSBCFrameParameters::EStereo:
1.1132 + temp = blocks * bitpool; // blocks * bitpool
1.1133 + break;
1.1134 + case TSBCFrameParameters::EJointStereo:
1.1135 + temp = subbands + blocks * bitpool; // subbands + blocks * bitpool
1.1136 + break;
1.1137 + }
1.1138 +
1.1139 + iFrameLength = 4 + ( (subbands * channels) >> 1) + (temp >> 3);
1.1140 + if (temp & 0x7)
1.1141 + {
1.1142 + iFrameLength++;
1.1143 + }
1.1144 +
1.1145 + iBitRate = (8*iFrameLength*iSampleRate)/(subbands*blocks);
1.1146 + }
1.1147 +
1.1148 +
1.1149 +void CA2dpCodecFrameHeaderParser::ParseMPEG12HeaderL(const TDesC8& aHeader)
1.1150 + {
1.1151 + if (aHeader[0] != KMPEGAudioFrameHeaderSyncWord )
1.1152 + {
1.1153 + User::Leave(KErrCorrupt); //not a valid MPEG audio frame
1.1154 + }
1.1155 +
1.1156 + //check it's really mp3 as opposed to mp1 or mp2
1.1157 + if ((aHeader[1] & KMp3AudioFrameHeaderIdMask) != KMp3AudioFrameHeaderId)
1.1158 + {
1.1159 + User::Leave(KErrNotSupported); //either corrupt or mp1/mp2
1.1160 + }
1.1161 +
1.1162 + TUint8 sampleRateIndex = (aHeader[2] & KMp3FrameHeaderSamplingFrequencyMask)>>2;
1.1163 + switch(sampleRateIndex)
1.1164 + {
1.1165 + case 0x00:
1.1166 + iSampleRate = 44100;
1.1167 + break;
1.1168 + case 0x01:
1.1169 + iSampleRate = 48000;
1.1170 + break;
1.1171 + case 0x02:
1.1172 + iSampleRate = 32000;
1.1173 + break;
1.1174 + default:
1.1175 + User::Leave(KErrCorrupt); //invalid mp3 header?
1.1176 + break;
1.1177 + }
1.1178 + TUint8 bitRateIndex = (aHeader[2] & KMp3FrameHeaderBitRateIndexMask)>>4;
1.1179 + switch(bitRateIndex)
1.1180 + {
1.1181 + case EMp3BitRateIndex32000:
1.1182 + iBitRate = 32000;
1.1183 + break;
1.1184 + case EMp3BitRateIndex40000:
1.1185 + iBitRate = 40000;
1.1186 + break;
1.1187 + case EMp3BitRateIndex48000:
1.1188 + iBitRate = 48000;
1.1189 + break;
1.1190 + case EMp3BitRateIndex56000:
1.1191 + iBitRate = 56000;
1.1192 + break;
1.1193 + case EMp3BitRateIndex64000:
1.1194 + iBitRate = 64000;
1.1195 + break;
1.1196 + case EMp3BitRateIndex80000:
1.1197 + iBitRate = 80000;
1.1198 + break;
1.1199 + case EMp3BitRateIndex96000:
1.1200 + iBitRate = 96000;
1.1201 + break;
1.1202 + default:
1.1203 + User::Leave(KErrNotSupported);//don't support more than 96kbs-1
1.1204 + break;
1.1205 + }
1.1206 +
1.1207 + //this code should really be made more clever to take allowance for any padding
1.1208 + //and use a frame length such that if padding is used then take the lowest
1.1209 + //common multiple of frames tht gives a common frame length eg if the frames
1.1210 + //alternate between 100 and 101 bytes due to an extra padding byte everyother
1.1211 + //frame then set the frame length to 201;
1.1212 + TUint bitRateX144 = iBitRate*144;
1.1213 + iFrameLength = bitRateX144/iSampleRate;
1.1214 + }
1.1215 +
1.1216 +
1.1217 +/**
1.1218 +static
1.1219 +*/
1.1220 +void CA2dpCodecFrameHeaderParser::ConstructL(const TFourCC& aCodecDataType, const TDesC8& aHeader)
1.1221 + {
1.1222 + switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
1.1223 + {
1.1224 + case KMMFFourCCCodeSBC:
1.1225 + ParseSBCHeaderL(aHeader);
1.1226 + break;
1.1227 + case KMMFFourCCCodeMP3:
1.1228 + ParseMPEG12HeaderL(aHeader);
1.1229 + break;
1.1230 + case KMMFFourCCCodeAAC:
1.1231 + User::Leave(KErrNotSupported);
1.1232 + break;
1.1233 + case KMMFFourCCCodeATRAC3:
1.1234 + User::Leave(KErrNotSupported);
1.1235 + break;
1.1236 + default:
1.1237 + User::Leave(KErrNotSupported);
1.1238 + break;
1.1239 + }
1.1240 + }
1.1241 +