os/mm/devsound/sounddevbt/src/A2dpBlueTooth/headsetaudioif/A2dpCodecUtilities.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "A2dpCodecUtilities.h"
sl@0
    17
sl@0
    18
sl@0
    19
/**
sl@0
    20
A2dp codec utilities Panics
sl@0
    21
**/
sl@0
    22
enum TA2dpCodecUtilitiesPanic
sl@0
    23
	{
sl@0
    24
	EA2dpCodecUtilNoRemoteCodecConfig, //0
sl@0
    25
	EA2dpCodecUtilUnexpectedDataType, //1
sl@0
    26
	EA2dpCodecUtilUnsupportedDataType, //2
sl@0
    27
	EA2dpCodecUtilUnexpectedConfiguration, //3
sl@0
    28
	EA2dpCodecUtilDataMemberNotSet //4
sl@0
    29
	};
sl@0
    30
sl@0
    31
sl@0
    32
static void Panic(TA2dpCodecUtilitiesPanic aPanic)
sl@0
    33
// Panic client
sl@0
    34
	{
sl@0
    35
	_LIT(KA2dpCodecUtilitiesPanicName, "A2DP Codec Util Panic");
sl@0
    36
	User::Panic(KA2dpCodecUtilitiesPanicName, aPanic);
sl@0
    37
	}
sl@0
    38
sl@0
    39
sl@0
    40
TInt TA2dpCodecCapabilityParser::GetSupportedSBCSampleRates(const TSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
sl@0
    41
	{
sl@0
    42
	TInt err = KErrNone;
sl@0
    43
	TSBCSamplingFrequencyBitmask samplingRatesBitMask = aCodecCaps.SamplingFrequencies();
sl@0
    44
	if (samplingRatesBitMask & E16kHz)
sl@0
    45
		{
sl@0
    46
		err = aSupportedDiscreteRates.Append(16000);
sl@0
    47
		}
sl@0
    48
	if (!err && (samplingRatesBitMask & E32kHz))
sl@0
    49
		{
sl@0
    50
		err = aSupportedDiscreteRates.Append(32000);
sl@0
    51
		}
sl@0
    52
	if (!err && (samplingRatesBitMask & E44100Hz))
sl@0
    53
		{
sl@0
    54
		err = aSupportedDiscreteRates.Append(44100);
sl@0
    55
		}
sl@0
    56
	if (!err && (samplingRatesBitMask & E48kHz))
sl@0
    57
		{
sl@0
    58
		err = aSupportedDiscreteRates.Append(48000);
sl@0
    59
		}
sl@0
    60
	return err;
sl@0
    61
	}
sl@0
    62
sl@0
    63
	
sl@0
    64
TInt TA2dpCodecCapabilityParser::GetSupportedMPEG12SampleRates(const TNonSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
sl@0
    65
	{
sl@0
    66
	TInt err = KErrNone;
sl@0
    67
	
sl@0
    68
	TPtrC8 codecCapsData(aCodecCaps.CodecData());
sl@0
    69
	
sl@0
    70
	TMPEG12SamplingFrequencyBitmask samplingRatesBitMask = codecCapsData[1] & KA2dpMPEG12SamplingFrequencyMask;
sl@0
    71
sl@0
    72
	if (samplingRatesBitMask & EMPEG12_16kHz)
sl@0
    73
		{
sl@0
    74
		err = aSupportedDiscreteRates.Append(16000);		
sl@0
    75
		}
sl@0
    76
	if (!err && samplingRatesBitMask & EMPEG12_22050Hz)
sl@0
    77
		{
sl@0
    78
		err = aSupportedDiscreteRates.Append(22050);	
sl@0
    79
		}
sl@0
    80
	if (!err && samplingRatesBitMask & EMPEG12_24kHz)
sl@0
    81
		{
sl@0
    82
		err = aSupportedDiscreteRates.Append(24000);	
sl@0
    83
		}
sl@0
    84
	if (!err && samplingRatesBitMask & EMPEG12_32kHz)
sl@0
    85
		{
sl@0
    86
		err = aSupportedDiscreteRates.Append(32000);		
sl@0
    87
		}
sl@0
    88
	if (!err && samplingRatesBitMask & EMPEG12_44100Hz)
sl@0
    89
		{
sl@0
    90
		err = aSupportedDiscreteRates.Append(44100);		
sl@0
    91
		}
sl@0
    92
	if (!err && samplingRatesBitMask & EMPEG12_48kHz)
sl@0
    93
		{
sl@0
    94
		err = aSupportedDiscreteRates.Append(48000);			
sl@0
    95
		}
sl@0
    96
				
sl@0
    97
	return err;
sl@0
    98
	}
sl@0
    99
	
sl@0
   100
	
sl@0
   101
TInt TA2dpCodecCapabilityParser::GetSupportedSampleRates(const TAvdtpMediaCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedDiscreteRates)
sl@0
   102
	{
sl@0
   103
	TInt err = KErrNotSupported;
sl@0
   104
	switch(aCodecCaps.MediaCodecType())
sl@0
   105
		{
sl@0
   106
		case EAudioCodecSBC:
sl@0
   107
			err = GetSupportedSBCSampleRates(static_cast<const TSBCCodecCapabilities&>(aCodecCaps), aSupportedDiscreteRates);
sl@0
   108
			break;
sl@0
   109
		case EAudioCodecMPEG12Audio:
sl@0
   110
			err = GetSupportedMPEG12SampleRates(static_cast<const TNonSBCCodecCapabilities&>(aCodecCaps), aSupportedDiscreteRates);
sl@0
   111
			break;
sl@0
   112
		case EAudioCodecMPEG24AAC:
sl@0
   113
			break;
sl@0
   114
		case EAudioCodecATRAC:
sl@0
   115
			break;
sl@0
   116
		default:
sl@0
   117
			Panic(EA2dpCodecUtilUnexpectedDataType);
sl@0
   118
			break;
sl@0
   119
		}
sl@0
   120
	return err;
sl@0
   121
	}
sl@0
   122
sl@0
   123
sl@0
   124
TInt TA2dpCodecCapabilityParser::GetSupportedSBCChannels(const TSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
sl@0
   125
	{
sl@0
   126
	TInt err = KErrNotSupported;
sl@0
   127
sl@0
   128
	TSBCChannelModeBitmask channelModesBitMask = aCodecCaps.ChannelModes();
sl@0
   129
	
sl@0
   130
	err = GetSupportedChannelsCommonCode(channelModesBitMask, aSupportedChannels, aStereoSupport);
sl@0
   131
	
sl@0
   132
	return err;
sl@0
   133
	}
sl@0
   134
sl@0
   135
	
sl@0
   136
TInt TA2dpCodecCapabilityParser::GetSupportedMPEG12Channels(const TNonSBCCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
sl@0
   137
	{
sl@0
   138
	TInt err = KErrNotSupported;
sl@0
   139
	
sl@0
   140
	TPtrC8 codecCapsData(aCodecCaps.CodecData());
sl@0
   141
	TSBCChannelModeBitmask channelModesBitMask = codecCapsData[0] & KA2dpMPEG12AudioChannelModeMask;
sl@0
   142
		
sl@0
   143
	err = GetSupportedChannelsCommonCode(channelModesBitMask, aSupportedChannels, aStereoSupport);
sl@0
   144
		
sl@0
   145
	return err;
sl@0
   146
	}
sl@0
   147
sl@0
   148
sl@0
   149
/**
sl@0
   150
MPEG12 uses the same channel mode bit mask as SBC so we'll factor out the common code
sl@0
   151
and reuse the TSBCChannelModeBitmask for mp3 as well
sl@0
   152
*/	
sl@0
   153
TInt TA2dpCodecCapabilityParser::GetSupportedChannelsCommonCode(TSBCChannelModeBitmask aChannelModesBitMask, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
sl@0
   154
	{
sl@0
   155
	TInt err = KErrNotSupported;
sl@0
   156
sl@0
   157
	if (aChannelModesBitMask & EMono)
sl@0
   158
		{
sl@0
   159
		err = aSupportedChannels.Append(EMMFMono);
sl@0
   160
		}
sl@0
   161
	if (!err)
sl@0
   162
		{
sl@0
   163
		if ((aChannelModesBitMask & EStereo) || (aChannelModesBitMask & EJointStereo))
sl@0
   164
			{
sl@0
   165
			err = aSupportedChannels.Append(EMMFStereo);
sl@0
   166
			aStereoSupport = EMMFInterleavedOnly;
sl@0
   167
			}
sl@0
   168
		}
sl@0
   169
	if (!err && (aChannelModesBitMask & EJointStereo))
sl@0
   170
		{
sl@0
   171
		//we have to cast as the TMMFStereoSupport is an enumeration
sl@0
   172
		//but is really should be a bitmap
sl@0
   173
		//but don't want to change it in order to preserve BC
sl@0
   174
		TUint aStereoSupportInt = static_cast<TUint>(aStereoSupport);
sl@0
   175
		aStereoSupportInt |= static_cast<TUint>(EMMFJoint);
sl@0
   176
		aStereoSupport = static_cast<TMMFStereoSupport>(aStereoSupportInt);
sl@0
   177
		}
sl@0
   178
	return err;
sl@0
   179
	}
sl@0
   180
sl@0
   181
sl@0
   182
TInt TA2dpCodecCapabilityParser::GetSupportedChannels(const TAvdtpMediaCodecCapabilities& aCodecCaps, RArray<TUint>& aSupportedChannels, TMMFStereoSupport& aStereoSupport)
sl@0
   183
	{
sl@0
   184
	TInt err = KErrNotSupported;
sl@0
   185
	switch(aCodecCaps.MediaCodecType())
sl@0
   186
		{
sl@0
   187
		case EAudioCodecSBC:
sl@0
   188
			err = GetSupportedSBCChannels(static_cast<const TSBCCodecCapabilities&>(aCodecCaps), aSupportedChannels, aStereoSupport);
sl@0
   189
			break;
sl@0
   190
		case EAudioCodecMPEG12Audio:
sl@0
   191
			err = GetSupportedMPEG12Channels(static_cast<const TNonSBCCodecCapabilities&>(aCodecCaps), aSupportedChannels, aStereoSupport);
sl@0
   192
			break;
sl@0
   193
		case EAudioCodecMPEG24AAC:
sl@0
   194
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   195
			break;
sl@0
   196
		case EAudioCodecATRAC:
sl@0
   197
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   198
			break;
sl@0
   199
		default:
sl@0
   200
			Panic(EA2dpCodecUtilUnexpectedDataType);
sl@0
   201
			break;
sl@0
   202
		}
sl@0
   203
	return err;
sl@0
   204
	}
sl@0
   205
sl@0
   206
	
sl@0
   207
/**
sl@0
   208
static
sl@0
   209
*/
sl@0
   210
TUint8 TRTPa2dpCodecSpecificUtils::PayloadType(const TFourCC& aCodecDataType)
sl@0
   211
	{
sl@0
   212
	TUint8 payloadType = 0;
sl@0
   213
	switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
sl@0
   214
		{
sl@0
   215
		case KMMFFourCCCodeSBC:
sl@0
   216
			payloadType = KSbcRTPPayloadType;
sl@0
   217
			break;
sl@0
   218
		case KMMFFourCCCodeMP3:
sl@0
   219
			payloadType = KMPEG12RTPAudioPayloadType; 
sl@0
   220
			break;
sl@0
   221
		case KMMFFourCCCodeAAC:
sl@0
   222
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   223
			break;
sl@0
   224
		case KMMFFourCCCodeATRAC3:
sl@0
   225
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   226
			break;
sl@0
   227
		default:
sl@0
   228
			Panic(EA2dpCodecUtilUnexpectedDataType);
sl@0
   229
			break;
sl@0
   230
		}
sl@0
   231
	return payloadType;
sl@0
   232
	}
sl@0
   233
sl@0
   234
sl@0
   235
TUint TRTPa2dpCodecSpecificUtils::MediaPayloadHeaderLength(const TFourCC& aCodecDataType)
sl@0
   236
	{
sl@0
   237
	TUint mediaPayloadHeaderLength = 0;
sl@0
   238
	switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
sl@0
   239
		{
sl@0
   240
		case KMMFFourCCCodeSBC:
sl@0
   241
			mediaPayloadHeaderLength = KSbcRTPMediaPayloadHeaderLength;
sl@0
   242
			break;
sl@0
   243
		case KMMFFourCCCodeMP3:
sl@0
   244
			mediaPayloadHeaderLength = KMPEG12RTPMediaPayloadHeaderLength;
sl@0
   245
			break;
sl@0
   246
		case KMMFFourCCCodeAAC:
sl@0
   247
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   248
			break;
sl@0
   249
		case KMMFFourCCCodeATRAC3:
sl@0
   250
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   251
			break;
sl@0
   252
		default:
sl@0
   253
			Panic(EA2dpCodecUtilUnexpectedDataType);
sl@0
   254
			break;
sl@0
   255
		}
sl@0
   256
	return mediaPayloadHeaderLength;
sl@0
   257
	}
sl@0
   258
sl@0
   259
sl@0
   260
	
sl@0
   261
TTimeIntervalMicroSeconds32 TFrameTimingUtils::FrameDuration(TUint aFrameLength, TUint aBitRate)
sl@0
   262
	{
sl@0
   263
	TUint frameDurationuS = (aFrameLength*8*1000000)/aBitRate;
sl@0
   264
	return TTimeIntervalMicroSeconds32(frameDurationuS);
sl@0
   265
	}
sl@0
   266
	
sl@0
   267
sl@0
   268
TUint TFrameTimingUtils::CalculateSBCTimeStampIncrementPerFrame(TUint aFrameLength, TUint aBitRate, TUint aSampleRate)
sl@0
   269
	{
sl@0
   270
	//SBC uses the sampleRate clock as the timestamp clock A2DP spec 4.3.3.1
sl@0
   271
	TUint frameDurationuS = FrameDuration(aFrameLength, aBitRate).Int();
sl@0
   272
	
sl@0
   273
	return (frameDurationuS*aSampleRate)/1000000;
sl@0
   274
	}
sl@0
   275
	
sl@0
   276
sl@0
   277
TUint TFrameTimingUtils::CalculateMPEG12TimeStampIncrementPerFrame(TUint aFrameLength, TUint aBitRate)
sl@0
   278
	{
sl@0
   279
	//MPEG12 uses a 90Khz clock as the timestamp clock RFC3551 section 4.5.13
sl@0
   280
	TUint frameDurationuS = FrameDuration(aFrameLength, aBitRate).Int();
sl@0
   281
sl@0
   282
	//div 1000000 as frame duration is in microseconds
sl@0
   283
	return (frameDurationuS*KMPEG12RTPTimeStampClock)/1000000;
sl@0
   284
	}
sl@0
   285
	
sl@0
   286
	
sl@0
   287
TUint TFrameTimingUtils::TimeStampIncrementPerFrame(const TFourCC& aCodecDataType, TUint aFrameLength, TUint aBitRate, TUint aSampleRate)
sl@0
   288
	{
sl@0
   289
	TInt timeStampIncrement = 0;
sl@0
   290
	switch (const_cast<TFourCC&>(aCodecDataType).FourCC())
sl@0
   291
		{
sl@0
   292
		case KMMFFourCCCodeSBC:
sl@0
   293
			timeStampIncrement = CalculateSBCTimeStampIncrementPerFrame(aFrameLength, aBitRate, aSampleRate);
sl@0
   294
			break;
sl@0
   295
		case KMMFFourCCCodeMP3:
sl@0
   296
			timeStampIncrement = CalculateMPEG12TimeStampIncrementPerFrame(aFrameLength, aBitRate);
sl@0
   297
			break;
sl@0
   298
		case KMMFFourCCCodeAAC:
sl@0
   299
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   300
			break;
sl@0
   301
		case KMMFFourCCCodeATRAC3:
sl@0
   302
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   303
			break;
sl@0
   304
		default:
sl@0
   305
			//the datatype is a non A2DP datatype
sl@0
   306
			//which is not supported so panic
sl@0
   307
			Panic(EA2dpCodecUtilUnexpectedDataType);
sl@0
   308
			break;
sl@0
   309
		}
sl@0
   310
	return timeStampIncrement;
sl@0
   311
	}
sl@0
   312
sl@0
   313
sl@0
   314
CA2dpLocalCodecCapabilities* CA2dpLocalCodecCapabilities::NewL()
sl@0
   315
	{
sl@0
   316
	return new(ELeave) CA2dpLocalCodecCapabilities();
sl@0
   317
	}
sl@0
   318
sl@0
   319
sl@0
   320
CA2dpLocalCodecCapabilities::CA2dpLocalCodecCapabilities()	
sl@0
   321
	{
sl@0
   322
	
sl@0
   323
	}
sl@0
   324
sl@0
   325
	
sl@0
   326
CA2dpLocalCodecCapabilities::~CA2dpLocalCodecCapabilities()
sl@0
   327
	{
sl@0
   328
	delete iLocalCodecCapabilities;
sl@0
   329
	}
sl@0
   330
sl@0
   331
	
sl@0
   332
TAvdtpMediaCodecCapabilities*  CA2dpLocalCodecCapabilities::LocalCodecCapabilities(const TFourCC& aCodecDataType)
sl@0
   333
	{
sl@0
   334
	switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
sl@0
   335
		{
sl@0
   336
		case KMMFFourCCCodeSBC:
sl@0
   337
			iLocalCodecCapabilities = LocalSBCCodecCapabilities();
sl@0
   338
			break;
sl@0
   339
		case KMMFFourCCCodeMP3:
sl@0
   340
			iLocalCodecCapabilities = LocalMPEG12CodecCapabilities();
sl@0
   341
			break;
sl@0
   342
		case KMMFFourCCCodeAAC:
sl@0
   343
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   344
			break;
sl@0
   345
		case KMMFFourCCCodeATRAC3:
sl@0
   346
			Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   347
			break;
sl@0
   348
		default:
sl@0
   349
			Panic(EA2dpCodecUtilUnexpectedDataType);
sl@0
   350
			break;
sl@0
   351
		}
sl@0
   352
	return iLocalCodecCapabilities;
sl@0
   353
	}
sl@0
   354
	
sl@0
   355
sl@0
   356
TSBCCodecCapabilities* CA2dpLocalCodecCapabilities::LocalSBCCodecCapabilities()
sl@0
   357
	{
sl@0
   358
	delete iLocalCodecCapabilities;
sl@0
   359
	iLocalCodecCapabilities = NULL;
sl@0
   360
	TSBCCodecCapabilities* localSbcCodecCapabilities = new TSBCCodecCapabilities();
sl@0
   361
	if (localSbcCodecCapabilities)
sl@0
   362
		{
sl@0
   363
		localSbcCodecCapabilities->SetSamplingFrequencies(E16kHz|E32kHz|E44100Hz|E48kHz);
sl@0
   364
		localSbcCodecCapabilities->SetChannelModes(EMono|EStereo|EJointStereo);
sl@0
   365
		localSbcCodecCapabilities->SetBlockLengths(EBlockLenFour|EBlockLenEight|EBlockLenTwelve|EBlockLenSixteen);
sl@0
   366
		localSbcCodecCapabilities->SetSubbands(EFourSubbands|EEightSubbands);
sl@0
   367
		localSbcCodecCapabilities->SetAllocationMethods(ELoudness|ESNR);
sl@0
   368
		localSbcCodecCapabilities->SetMinBitpoolValue(KMinBitPoolValue);
sl@0
   369
		localSbcCodecCapabilities->SetMaxBitpoolValue(KMaxBitPoolValue);
sl@0
   370
		}
sl@0
   371
	return localSbcCodecCapabilities;
sl@0
   372
	}
sl@0
   373
sl@0
   374
sl@0
   375
TNonSBCCodecCapabilities* CA2dpLocalCodecCapabilities::LocalMPEG12CodecCapabilities()
sl@0
   376
	{
sl@0
   377
	delete iLocalCodecCapabilities;
sl@0
   378
	iLocalCodecCapabilities = NULL;
sl@0
   379
	TNonSBCCodecCapabilities* localSEPmpeg12CodecCapabilities = new TNonSBCCodecCapabilities(EAvdtpMediaTypeAudio, EAudioCodecMPEG12Audio);
sl@0
   380
	if (localSEPmpeg12CodecCapabilities)
sl@0
   381
		{
sl@0
   382
		TBuf8<4>	mpeg12CodecCapabilitiesData;
sl@0
   383
sl@0
   384
		//MPEG12 channel modes are the same as SBC so we'll use SBC structure
sl@0
   385
		TSBCChannelModeBitmask channelModes = (EMono|EStereo);
sl@0
   386
		mpeg12CodecCapabilitiesData.Append(KA2dpMPEG12LayerMP3Supported | channelModes);
sl@0
   387
		
sl@0
   388
		//no MPF-2 support, will support 16-44100khz sample
sl@0
   389
		TInt8 samplingFrequencySupport = EMPEG12_16kHz|EMPEG12_22050Hz|EMPEG12_24kHz|EMPEG12_32kHz|EMPEG12_44100Hz;
sl@0
   390
		mpeg12CodecCapabilitiesData.Append(samplingFrequencySupport);
sl@0
   391
		
sl@0
   392
		//no VBR all bitrates <= 96kbs-1 except free format
sl@0
   393
		mpeg12CodecCapabilitiesData.Append(0);
sl@0
   394
		mpeg12CodecCapabilitiesData.Append(KA2dpMPEG12SupportedBitRateIndex);//all bit rates <= 96kbs-1
sl@0
   395
		localSEPmpeg12CodecCapabilities->SetCodecData(mpeg12CodecCapabilitiesData);
sl@0
   396
		}
sl@0
   397
	return localSEPmpeg12CodecCapabilities;
sl@0
   398
	}
sl@0
   399
sl@0
   400
sl@0
   401
	
sl@0
   402
CA2dpAudioCodecConfiguration* CA2dpAudioCodecConfiguration::NewL()
sl@0
   403
	{
sl@0
   404
	return new(ELeave)CA2dpAudioCodecConfiguration();
sl@0
   405
	}
sl@0
   406
	
sl@0
   407
sl@0
   408
CA2dpAudioCodecConfiguration::CA2dpAudioCodecConfiguration() : iHeadsetCodecDataType(KMMFFourCCCodeSBC), iSampleRate(KDefaultSampleRate), iChannels(KDefaultChannels), iStereoSupport(KDefaultStereoSupport)
sl@0
   409
	{	
sl@0
   410
	}
sl@0
   411
	
sl@0
   412
CA2dpAudioCodecConfiguration::~CA2dpAudioCodecConfiguration()
sl@0
   413
	{
sl@0
   414
	delete iRemoteCodecConfiguration;
sl@0
   415
	}
sl@0
   416
sl@0
   417
sl@0
   418
void CA2dpAudioCodecConfiguration::Reset()
sl@0
   419
	{
sl@0
   420
	delete iRemoteCodecConfiguration;
sl@0
   421
	iRemoteCodecConfiguration = NULL;
sl@0
   422
	iHeadsetCodecDataType = KMMFFourCCCodeSBC;
sl@0
   423
	iSampleRate = KDefaultSampleRate;
sl@0
   424
	iChannels = KDefaultChannels;
sl@0
   425
	iStereoSupport = KDefaultStereoSupport;
sl@0
   426
	iLocalSBCCodecConfiguration.Reset();
sl@0
   427
	}
sl@0
   428
sl@0
   429
/**
sl@0
   430
Function used to return a TAvdtpMediaCodecCapabilities structure
sl@0
   431
that can be used to configure the SEP at the remote end ie on the headset
sl@0
   432
The capabilities are used to determine the configuration
sl@0
   433
need to return by pointer rather than by ref as TAvdtpMediaCodecCapabilities is abstract
sl@0
   434
Note that this parameter passed in treats the  TAvdtpMediaCodecCapabilities as 
sl@0
   435
the capabilities of the code, whereas the returned TAvdtpMediaCodecCapabilities is a
sl@0
   436
configuration ie a specific set of values that can be used to configure the remote codec
sl@0
   437
sl@0
   438
@param aCodecCapabilities  This is the capabilities supported by the remote codec
sl@0
   439
@return The configuration for the remote codec
sl@0
   440
*/
sl@0
   441
//void CA2dpAudioCodecConfiguration::GetRemoteCodecConfiguration(const TAvdtpMediaCodecCapabilities& aRemoteCodecCapabilities, TAvdtpMediaCodecCapabilities& aRemoteCodecConfiguration)
sl@0
   442
TAvdtpMediaCodecCapabilities* CA2dpAudioCodecConfiguration::UpdateRemoteCodecConfiguration(const TAvdtpMediaCodecCapabilities& aRemoteCodecCapabilities)
sl@0
   443
	{
sl@0
   444
	delete iRemoteCodecConfiguration;
sl@0
   445
	iRemoteCodecConfiguration = NULL;
sl@0
   446
		{
sl@0
   447
		//this hasn't been set yet so set it
sl@0
   448
		//first find out the capabilities of the codec
sl@0
   449
		switch (aRemoteCodecCapabilities.MediaCodecType())
sl@0
   450
			{
sl@0
   451
			case EAudioCodecSBC:
sl@0
   452
				iRemoteCodecConfiguration = GetRemoteSBCCodecConfiguration(static_cast<const TSBCCodecCapabilities&>(aRemoteCodecCapabilities));
sl@0
   453
				iHeadsetCodecDataType = KMMFFourCCCodeSBC;
sl@0
   454
				break;
sl@0
   455
			case EAudioCodecMPEG12Audio:
sl@0
   456
				iRemoteCodecConfiguration = GetRemoteMPEG12CodecConfiguration(static_cast<const TNonSBCCodecCapabilities&>(aRemoteCodecCapabilities));
sl@0
   457
				iHeadsetCodecDataType = KMMFFourCCCodeMP3;
sl@0
   458
				break;
sl@0
   459
			case EAudioCodecMPEG24AAC:
sl@0
   460
				Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   461
				break;
sl@0
   462
			case EAudioCodecATRAC:
sl@0
   463
				Panic(EA2dpCodecUtilUnsupportedDataType);
sl@0
   464
				break;
sl@0
   465
			default:
sl@0
   466
				//the datatype is a non A2DP datatype
sl@0
   467
				//which is not supported so panic
sl@0
   468
				Panic(EA2dpCodecUtilUnexpectedDataType);
sl@0
   469
				break;
sl@0
   470
			}
sl@0
   471
		}
sl@0
   472
	return iRemoteCodecConfiguration;
sl@0
   473
	}
sl@0
   474
		
sl@0
   475
sl@0
   476
/**
sl@0
   477
sl@0
   478
*/
sl@0
   479
TSBCCodecCapabilities* CA2dpAudioCodecConfiguration::GetRemoteSBCCodecConfiguration(const TSBCCodecCapabilities& aCodecCaps)
sl@0
   480
	{
sl@0
   481
	TSBCCodecCapabilities* sbcCodecConfiguration = new TSBCCodecCapabilities();
sl@0
   482
	
sl@0
   483
	if (sbcCodecConfiguration)	
sl@0
   484
		{
sl@0
   485
		//--sampling frequency--
sl@0
   486
		TSBCSamplingFrequencyBitmask freqs;
sl@0
   487
		switch(iSampleRate)
sl@0
   488
			{
sl@0
   489
			case 16000:
sl@0
   490
				freqs = E16kHz;
sl@0
   491
				break;
sl@0
   492
			case 32000:
sl@0
   493
				freqs = E32kHz;
sl@0
   494
				break;
sl@0
   495
			case 44100:
sl@0
   496
				freqs = E44100Hz;
sl@0
   497
				break;
sl@0
   498
			case 48000:
sl@0
   499
				freqs = E48kHz;
sl@0
   500
				break;
sl@0
   501
			default:
sl@0
   502
				freqs = E16kHz;
sl@0
   503
				break;
sl@0
   504
			}
sl@0
   505
		//check we really can support this sampling frequency
sl@0
   506
		//since we may be using the default which may not be supported
sl@0
   507
		//by the headset (even if the A2DP spec says it is mandatory)
sl@0
   508
		TSBCSamplingFrequencyBitmask samplingFreqsSupportedByHeadset = aCodecCaps.SamplingFrequencies();
sl@0
   509
		if 	(iForcedRemoteSBCCodecConfiguration)
sl@0
   510
			{
sl@0
   511
			samplingFreqsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->SamplingFrequencies();
sl@0
   512
			}
sl@0
   513
		if (!(freqs & samplingFreqsSupportedByHeadset))
sl@0
   514
			{//then the headset doesn't support the sampling frequency
sl@0
   515
			//this could happen if iSampleRate is a default that the headset doesn't support
sl@0
   516
			//note that evenif the default is a mandatory sample rate eg 44100
sl@0
   517
			//we still do not make any assumptions about what is supported 
sl@0
   518
			if (samplingFreqsSupportedByHeadset & E16kHz)
sl@0
   519
				{
sl@0
   520
				iSampleRate = 16000;
sl@0
   521
				freqs = E16kHz;
sl@0
   522
				}
sl@0
   523
			else if (samplingFreqsSupportedByHeadset & E32kHz)
sl@0
   524
				{
sl@0
   525
				iSampleRate = 32000;
sl@0
   526
				freqs = E32kHz;
sl@0
   527
				}
sl@0
   528
			else if (samplingFreqsSupportedByHeadset & E44100Hz)
sl@0
   529
				{
sl@0
   530
				iSampleRate = 44100;
sl@0
   531
				freqs = E44100Hz;
sl@0
   532
				}
sl@0
   533
			else if (samplingFreqsSupportedByHeadset & E48kHz)
sl@0
   534
				{
sl@0
   535
				iSampleRate = 48000;
sl@0
   536
				freqs = E48kHz;
sl@0
   537
				}
sl@0
   538
			//else just keep as is
sl@0
   539
			}
sl@0
   540
			sbcCodecConfiguration->SetSamplingFrequencies(freqs);
sl@0
   541
			
sl@0
   542
		//--channels--
sl@0
   543
		TSBCChannelModeBitmask channelMode = EMono;
sl@0
   544
		TSBCChannelModeBitmask channelModesSupportedByHeadset = EMono;
sl@0
   545
		channelModesSupportedByHeadset = aCodecCaps.ChannelModes();
sl@0
   546
		if (iChannels == EMMFMono)
sl@0
   547
			{
sl@0
   548
			channelMode = EMono;
sl@0
   549
			}
sl@0
   550
		else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFInterleavedOnly))
sl@0
   551
			{
sl@0
   552
			channelMode = EStereo;
sl@0
   553
			}
sl@0
   554
		else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFJoint))
sl@0
   555
			{
sl@0
   556
			channelMode = EJointStereo;
sl@0
   557
			}
sl@0
   558
		if (!(channelMode & channelModesSupportedByHeadset))
sl@0
   559
			{
sl@0
   560
			//then we don't support the selected channel mode
sl@0
   561
			if (channelModesSupportedByHeadset & EMono)
sl@0
   562
				{
sl@0
   563
				iChannels = EMMFMono;
sl@0
   564
				iStereoSupport = EMMFNone;
sl@0
   565
				channelMode = EMono;
sl@0
   566
				}
sl@0
   567
			else if (channelModesSupportedByHeadset & EJointStereo)
sl@0
   568
				{
sl@0
   569
				iChannels = EMMFStereo;
sl@0
   570
				iStereoSupport = EMMFJoint;
sl@0
   571
				channelMode = EJointStereo;
sl@0
   572
				}
sl@0
   573
			else if (channelModesSupportedByHeadset & EStereo)
sl@0
   574
				{
sl@0
   575
				iChannels = EMMFStereo;
sl@0
   576
				iStereoSupport = EMMFInterleavedOnly;
sl@0
   577
				channelMode = EStereo;
sl@0
   578
				}
sl@0
   579
			}
sl@0
   580
		sbcCodecConfiguration->SetChannelModes(channelMode);	
sl@0
   581
	
sl@0
   582
		//--block mode--
sl@0
   583
		//we'll choose a preference order of 16,12, 8,4
sl@0
   584
		//although there may be a more intelligent way of doing this
sl@0
   585
		//based on the other parameters.
sl@0
   586
		TSBCBlockLengthBitmask blockLength = EBlockLenSixteen;
sl@0
   587
		TSBCBlockLengthBitmask blockLengthsSupportedByHeadset = aCodecCaps.BlockLengths();
sl@0
   588
		if 	(iForcedRemoteSBCCodecConfiguration)
sl@0
   589
			{
sl@0
   590
			blockLengthsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->BlockLengths();
sl@0
   591
			}
sl@0
   592
		if (blockLengthsSupportedByHeadset & EBlockLenSixteen)
sl@0
   593
			{
sl@0
   594
			blockLength = EBlockLenSixteen;
sl@0
   595
			}
sl@0
   596
		else if (blockLengthsSupportedByHeadset & EBlockLenTwelve)
sl@0
   597
			{
sl@0
   598
			blockLength = EBlockLenTwelve;
sl@0
   599
			}
sl@0
   600
		else if (blockLengthsSupportedByHeadset & EBlockLenEight)
sl@0
   601
			{
sl@0
   602
			blockLength = EBlockLenEight;
sl@0
   603
			}
sl@0
   604
		else if (blockLengthsSupportedByHeadset & EBlockLenFour)
sl@0
   605
			{
sl@0
   606
			blockLength = EBlockLenFour;
sl@0
   607
			}
sl@0
   608
		sbcCodecConfiguration->SetBlockLengths(blockLength);
sl@0
   609
	
sl@0
   610
		//--subbands--
sl@0
   611
		//Subbands currently have a preference of 8 over 4
sl@0
   612
		TUint numberOfSubbands = 8; //used later for max bit pool value calculation
sl@0
   613
		TSBCSubbandsBitmask subbands = EEightSubbands;
sl@0
   614
		TSBCSubbandsBitmask subbandsSupportedByHeadset = aCodecCaps.Subbands();
sl@0
   615
		if 	(iForcedRemoteSBCCodecConfiguration)
sl@0
   616
			{
sl@0
   617
			subbandsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->Subbands();
sl@0
   618
			}
sl@0
   619
		if (subbandsSupportedByHeadset & EEightSubbands)
sl@0
   620
			{
sl@0
   621
			subbands = EEightSubbands;
sl@0
   622
			}
sl@0
   623
		else if (subbandsSupportedByHeadset & EFourSubbands)
sl@0
   624
			{
sl@0
   625
			subbands = EFourSubbands;
sl@0
   626
			numberOfSubbands = 4;
sl@0
   627
			} 
sl@0
   628
		sbcCodecConfiguration->SetSubbands(subbands);
sl@0
   629
	
sl@0
   630
		//--Allocation--
sl@0
   631
		//although allocation support of SNR and loudness are mandatory the headset
sl@0
   632
		//may have reconfigured to use a particular allocation method
sl@0
   633
		//If both allocation methods are available we have to choose which one
sl@0
   634
		//so we'll choose a preference order of loudness over SNR
sl@0
   635
		TSBCAllocationMethodBitmask allocationMethod = ELoudness;
sl@0
   636
		TSBCAllocationMethodBitmask allocationMethodsSupportedByHeadset = aCodecCaps.AllocationMethods(); 
sl@0
   637
		if (iForcedRemoteSBCCodecConfiguration)
sl@0
   638
			{
sl@0
   639
			allocationMethodsSupportedByHeadset = iForcedRemoteSBCCodecConfiguration->AllocationMethods();
sl@0
   640
			}
sl@0
   641
		if (allocationMethodsSupportedByHeadset & ELoudness)
sl@0
   642
			{
sl@0
   643
			allocationMethod = ELoudness;
sl@0
   644
			}
sl@0
   645
		else if (allocationMethodsSupportedByHeadset & ESNR)
sl@0
   646
			{
sl@0
   647
			allocationMethod = ESNR;
sl@0
   648
			}
sl@0
   649
		sbcCodecConfiguration->SetAllocationMethods(allocationMethod);
sl@0
   650
sl@0
   651
		//--bitpool
sl@0
   652
		// The bitpool value must be in the range of 2-250 and must not exceed
sl@0
   653
		// 16*numberOfSubbands*channels
sl@0
   654
		// note that we don't normally play SBC directly, except for test purposes
sl@0
   655
		// in order to arbitary play any SBC file extra code would be required
sl@0
   656
		// to parse the SBC frame header to get the bitpool value
sl@0
   657
		// since for unit testing the the SBC test file is known to have a
sl@0
   658
		// bit pool value of 20, this shall be the default value
sl@0
   659
		// This code could be made more more intelligent and base the 
sl@0
   660
		// bitpool value around table 4.7 in the A2DP specification
sl@0
   661
		TUint minBitPoolValue = KMinBitPoolValue;
sl@0
   662
		TUint maxBitPoolValue = KMaxBitPoolValue; 
sl@0
   663
		if (KMinBitPoolValue < aCodecCaps.MinBitpoolValue())
sl@0
   664
			{
sl@0
   665
			minBitPoolValue = aCodecCaps.MinBitpoolValue();
sl@0
   666
			}
sl@0
   667
		if (KMaxBitPoolValue > aCodecCaps.MaxBitpoolValue())
sl@0
   668
			{
sl@0
   669
			TUint maxAllowableBitPoolValueForCurrentConfiguration = 16*iChannels*numberOfSubbands;
sl@0
   670
			maxBitPoolValue = aCodecCaps.MaxBitpoolValue();
sl@0
   671
			if (maxBitPoolValue > maxAllowableBitPoolValueForCurrentConfiguration)
sl@0
   672
				{
sl@0
   673
				maxBitPoolValue = maxAllowableBitPoolValueForCurrentConfiguration;
sl@0
   674
				}
sl@0
   675
			}
sl@0
   676
		sbcCodecConfiguration->SetMinBitpoolValue(minBitPoolValue);
sl@0
   677
		sbcCodecConfiguration->SetMaxBitpoolValue(maxBitPoolValue);
sl@0
   678
		}//if (sbcCodecConfiguration)
sl@0
   679
sl@0
   680
	return sbcCodecConfiguration;
sl@0
   681
	}
sl@0
   682
	
sl@0
   683
sl@0
   684
/**
sl@0
   685
internal function to get a remote codec configuration from the capabilities
sl@0
   686
Note technically speaking MPEG12 refers to MPEG 1 & MPEG 2 audio layers 1,2 and 3
sl@0
   687
however since mp1 & mp2 is rarely used in practice this 
sl@0
   688
will be MPEG 1 layer 3 ie mp3 in most case
sl@0
   689
*/
sl@0
   690
TNonSBCCodecCapabilities* CA2dpAudioCodecConfiguration::GetRemoteMPEG12CodecConfiguration(const TNonSBCCodecCapabilities& aCodecCaps)
sl@0
   691
	{
sl@0
   692
	TNonSBCCodecCapabilities* mpeg12CodecConfiguration = new TNonSBCCodecCapabilities(EAvdtpMediaTypeAudio, EAudioCodecMPEG12Audio);
sl@0
   693
	TBuf8<4>	mpeg12CodecConfigurationData;//should be 4 make 6 for bug??
sl@0
   694
	if (mpeg12CodecConfiguration)
sl@0
   695
		{//codecData should contain data conformant to A2DP profile
sl@0
   696
		// codec specific information elements section A2DP 4.4.2
sl@0
   697
		TPtrC8 codecCapsData(aCodecCaps.CodecData());
sl@0
   698
		TInt8 mpegLayerSupport = codecCapsData[0] & KA2dpMPEG12LayerMask;
sl@0
   699
		if (!(mpegLayerSupport & KA2dpMPEG12LayerMP3Supported))
sl@0
   700
			{
sl@0
   701
			//then mp3 is not supported must be mp1 or mp2 which we don't support
sl@0
   702
			delete mpeg12CodecConfiguration;
sl@0
   703
			mpeg12CodecConfiguration = NULL;
sl@0
   704
			return mpeg12CodecConfiguration;
sl@0
   705
			}
sl@0
   706
		mpegLayerSupport = KA2dpMPEG12LayerMP3Supported; //mp3
sl@0
   707
		//we don't bother with CRC protection so don't check
sl@0
   708
		
sl@0
   709
		//the MPEG12 channel support structure is identical to 
sl@0
   710
		//SBC so we'll use the SBC structure
sl@0
   711
		//--channels--
sl@0
   712
		TSBCChannelModeBitmask channelMode = EMono;
sl@0
   713
		TSBCChannelModeBitmask channelModesSupportedByHeadset = EMono;
sl@0
   714
		channelModesSupportedByHeadset = codecCapsData[0] & KA2dpMPEG12AudioChannelModeMask;
sl@0
   715
		if (iChannels == EMMFMono)
sl@0
   716
			{
sl@0
   717
			channelMode = EMono;
sl@0
   718
			}
sl@0
   719
		else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFInterleavedOnly))
sl@0
   720
			{
sl@0
   721
			channelMode = EStereo;
sl@0
   722
			}
sl@0
   723
		else if ((iChannels == EMMFStereo) && (iStereoSupport == EMMFJoint))
sl@0
   724
			{
sl@0
   725
			channelMode = EJointStereo;
sl@0
   726
			}
sl@0
   727
		if (!(channelMode & channelModesSupportedByHeadset))
sl@0
   728
			{
sl@0
   729
			//then we don't support the selected channel mode
sl@0
   730
			if (channelModesSupportedByHeadset & EMono)
sl@0
   731
				{
sl@0
   732
				iChannels = EMMFMono;
sl@0
   733
				iStereoSupport = EMMFNone;
sl@0
   734
				channelMode = EMono;
sl@0
   735
				}
sl@0
   736
			else if (channelModesSupportedByHeadset & EJointStereo)
sl@0
   737
				{
sl@0
   738
				iChannels = EMMFStereo;
sl@0
   739
				iStereoSupport = EMMFJoint;
sl@0
   740
				channelMode = EJointStereo;
sl@0
   741
				}
sl@0
   742
			else if (channelModesSupportedByHeadset & EStereo)
sl@0
   743
				{
sl@0
   744
				iChannels = EMMFStereo;
sl@0
   745
				iStereoSupport = EMMFInterleavedOnly;
sl@0
   746
				channelMode = EStereo;
sl@0
   747
				}
sl@0
   748
			}
sl@0
   749
		mpeg12CodecConfigurationData.Append(mpegLayerSupport | channelMode);
sl@0
   750
	
sl@0
   751
		//Media Payload Format 
sl@0
   752
		//this ref implementation shall only support the media payload format
sl@0
   753
		//defined in RFC2250, RFC3119 is not supported
sl@0
   754
		//therefore there is no need to check this since MPF-1/RFC2250 is mandatory
sl@0
   755
		
sl@0
   756
		//--sampling frequency--
sl@0
   757
		//the mp3 sampling frequency mask is not the same as SBC so can't use TSBCSamplingFrequencyBitmask
sl@0
   758
		TMPEG12SamplingFrequencyBitmask freqs;
sl@0
   759
		switch(iSampleRate)
sl@0
   760
			{
sl@0
   761
			case 16000:
sl@0
   762
				freqs = EMPEG12_16kHz;
sl@0
   763
				break;
sl@0
   764
			case 22050:
sl@0
   765
				freqs = EMPEG12_22050Hz;
sl@0
   766
				break;
sl@0
   767
			case 24000:
sl@0
   768
				freqs = EMPEG12_24kHz;
sl@0
   769
				break;
sl@0
   770
			case 32000:
sl@0
   771
				freqs = EMPEG12_32kHz;
sl@0
   772
				break;
sl@0
   773
			case 44100:
sl@0
   774
				freqs = EMPEG12_44100Hz;
sl@0
   775
				break;
sl@0
   776
			case 48000:
sl@0
   777
				freqs = EMPEG12_48kHz;
sl@0
   778
				break;
sl@0
   779
			default:
sl@0
   780
				freqs = EMPEG12_16kHz;
sl@0
   781
				break;
sl@0
   782
			}
sl@0
   783
		//check we really can support this sampling frequency
sl@0
   784
		//since we may be using the default which may not be supported
sl@0
   785
		//by the headset (even if the A2DP spec says it is mandatory)
sl@0
   786
		TMPEG12SamplingFrequencyBitmask samplingFreqsSupportedByHeadset = codecCapsData[1] & KA2dpMPEG12SamplingFrequencyMask;
sl@0
   787
		if (!(freqs & samplingFreqsSupportedByHeadset))
sl@0
   788
			{//then the headset doesn't support the sampling frequency
sl@0
   789
			//this could happen if iSampleRate is a default that the headset doesn't support
sl@0
   790
			//note that evenif the default is a mandatory sample rate eg 44100
sl@0
   791
			//we still do not make any assumptions about what is supported 
sl@0
   792
			if (samplingFreqsSupportedByHeadset & EMPEG12_16kHz)
sl@0
   793
				{
sl@0
   794
				iSampleRate = 16000;
sl@0
   795
				freqs = EMPEG12_16kHz;
sl@0
   796
				}
sl@0
   797
			else if (samplingFreqsSupportedByHeadset & EMPEG12_22050Hz)
sl@0
   798
				{
sl@0
   799
				iSampleRate = 22050;
sl@0
   800
				freqs = EMPEG12_22050Hz;
sl@0
   801
				}
sl@0
   802
			else if (samplingFreqsSupportedByHeadset & EMPEG12_24kHz)
sl@0
   803
				{
sl@0
   804
				iSampleRate = 24000;
sl@0
   805
				freqs = EMPEG12_24kHz;
sl@0
   806
				}
sl@0
   807
			else if (samplingFreqsSupportedByHeadset & EMPEG12_32kHz)
sl@0
   808
				{
sl@0
   809
				iSampleRate = 32000;
sl@0
   810
				freqs = EMPEG12_32kHz;
sl@0
   811
				}
sl@0
   812
			else if (samplingFreqsSupportedByHeadset & EMPEG12_44100Hz)
sl@0
   813
				{
sl@0
   814
				iSampleRate = 44100;
sl@0
   815
				freqs = EMPEG12_44100Hz;
sl@0
   816
				}
sl@0
   817
			else if (samplingFreqsSupportedByHeadset & EMPEG12_48kHz)
sl@0
   818
				{
sl@0
   819
				iSampleRate = 48000;
sl@0
   820
				freqs = EMPEG12_48kHz;
sl@0
   821
				}
sl@0
   822
			//else just keep as is
sl@0
   823
			}
sl@0
   824
		//set frequency, MPF-1
sl@0
   825
		mpeg12CodecConfigurationData.Append(freqs);
sl@0
   826
		
sl@0
   827
		
sl@0
   828
		//The casira pod only supports bit rates up to 96kbs-1
sl@0
   829
		//so check the headset supports these as well
sl@0
   830
		//we'll just mask with all the lower bit rates
sl@0
   831
		//all the lower bit rate support up to 96kbs-1are in octet 3
sl@0
   832
		//so just make out octet 2 bit rate support
sl@0
   833
		//also VBR = 0 as no VBR support
sl@0
   834
		mpeg12CodecConfigurationData.Append(0);
sl@0
   835
		
sl@0
   836
		//all bitrates <= 96kbs-1 except free format
sl@0
   837
		mpeg12CodecConfigurationData.Append(KA2dpMPEG12SupportedBitRateIndex & codecCapsData[3]);
sl@0
   838
		mpeg12CodecConfiguration->SetCodecData(mpeg12CodecConfigurationData);
sl@0
   839
		}
sl@0
   840
	return mpeg12CodecConfiguration;
sl@0
   841
	}
sl@0
   842
sl@0
   843
sl@0
   844
/**
sl@0
   845
Utility function get the codec capabilities used by Gavdp into the SBC codec paramerers
sl@0
   846
used by the SBC codec
sl@0
   847
The function uses the TSBCCodecCapabilities to generate a set of TSBCFrameParameters
sl@0
   848
which can be used to configure the codec
sl@0
   849
the remote codec configuration must have already been updated before calling
sl@0
   850
this function
sl@0
   851
sl@0
   852
@param aSBCFrameParameters  These are set to the current configuration settings
sl@0
   853
*/
sl@0
   854
TSBCFrameParameters& CA2dpAudioCodecConfiguration::UpdateLocalSBCCodecConfiguration()
sl@0
   855
	{
sl@0
   856
	__ASSERT_DEBUG(iRemoteCodecConfiguration, Panic(EA2dpCodecUtilNoRemoteCodecConfig));
sl@0
   857
	__ASSERT_DEBUG((iHeadsetCodecDataType == KMMFFourCCCodeSBC) && (iRemoteCodecConfiguration->MediaCodecType() == EAudioCodecSBC), Panic(EA2dpCodecUtilUnexpectedDataType));
sl@0
   858
	TSBCCodecCapabilities* remoteSBCCodecConfiguration =  static_cast<TSBCCodecCapabilities*>(iRemoteCodecConfiguration);
sl@0
   859
		
sl@0
   860
	//note that for sampling frequency and channels the capabilites
sl@0
   861
	//have already been checked in SetSampleRate and SetChannels
sl@0
   862
	//and once set we don't allow these to be reconfigured
sl@0
   863
	//so no need to check these again with the codecCaps
sl@0
   864
	//if set the iSampleRate should always be in agreement with 
sl@0
   865
	//the settings on the remote codec
sl@0
   866
	TSBCFrameParameters::TSamplingFrequency SBCSamplingFrequency;
sl@0
   867
	switch(iSampleRate)
sl@0
   868
		{
sl@0
   869
		case 32000:
sl@0
   870
			SBCSamplingFrequency = TSBCFrameParameters::E32000Hz;
sl@0
   871
			break;
sl@0
   872
		case 44100:
sl@0
   873
			SBCSamplingFrequency = TSBCFrameParameters::E44100Hz;
sl@0
   874
			break;
sl@0
   875
		case 48000:
sl@0
   876
			SBCSamplingFrequency = TSBCFrameParameters::E48000Hz;
sl@0
   877
			break;
sl@0
   878
		default://[TODO] change default to 44100 when hardware 
sl@0
   879
		//(ie BT support H2 or higher bandwidth support on Casira) supports it
sl@0
   880
			SBCSamplingFrequency = TSBCFrameParameters::E16000Hz;
sl@0
   881
			break;
sl@0
   882
		}
sl@0
   883
sl@0
   884
	iLocalSBCCodecConfiguration.SetSamplingFrequency(SBCSamplingFrequency);
sl@0
   885
	
sl@0
   886
	//although a block length of 4,8,12,16 are mandatory the headset
sl@0
   887
	//may have reconfigured to use a particular block length
sl@0
   888
	//If all block lengths are available we have to choose which one
sl@0
   889
	//For now we'll choose a preference order of 12,16,8,4
sl@0
   890
	//although there may be a more intelligent way of doing this
sl@0
   891
	//based on the other parameters.
sl@0
   892
	switch(remoteSBCCodecConfiguration->BlockLengths())
sl@0
   893
		{
sl@0
   894
		case EBlockLenTwelve:
sl@0
   895
			iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E12Blocks);
sl@0
   896
			break;
sl@0
   897
		case EBlockLenSixteen:
sl@0
   898
			iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E16Blocks);
sl@0
   899
			break;
sl@0
   900
		case EBlockLenEight:
sl@0
   901
			iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E8Blocks);
sl@0
   902
			break;
sl@0
   903
		case EBlockLenFour:
sl@0
   904
			iLocalSBCCodecConfiguration.SetBlockLength(TSBCFrameParameters::E4Blocks);
sl@0
   905
			break;
sl@0
   906
		default:
sl@0
   907
			Panic(EA2dpCodecUtilUnexpectedConfiguration);
sl@0
   908
			break;
sl@0
   909
		}
sl@0
   910
	
sl@0
   911
	
sl@0
   912
	//channel mode
sl@0
   913
	//although the number of channels can't be changed on the fly
sl@0
   914
	//switching between stereo and joint stereo is supported
sl@0
   915
	//note different namespaces for EStereo & EJointStereo !
sl@0
   916
	TSBCFrameParameters::TChannelMode channelMode = TSBCFrameParameters::EMono;//default
sl@0
   917
	if (iChannels == EMMFStereo)
sl@0
   918
		{
sl@0
   919
		if (iStereoSupport & EMMFJoint)
sl@0
   920
			{
sl@0
   921
			channelMode = TSBCFrameParameters::EJointStereo;
sl@0
   922
			}
sl@0
   923
		else if (iStereoSupport & EMMFInterleavedOnly)
sl@0
   924
			{
sl@0
   925
			channelMode = TSBCFrameParameters::EStereo;
sl@0
   926
			}
sl@0
   927
		else
sl@0
   928
			{
sl@0
   929
			Panic(EA2dpCodecUtilUnexpectedConfiguration);
sl@0
   930
			}
sl@0
   931
		}
sl@0
   932
sl@0
   933
	iLocalSBCCodecConfiguration.SetChannelMode(channelMode);
sl@0
   934
	
sl@0
   935
	//Allocation
sl@0
   936
	//although allocation support of SNR and loudness are mandatory the headset
sl@0
   937
	//may have reconfigured to use a particular allocation method
sl@0
   938
	//If both allocation methods are available we have to choose which one
sl@0
   939
	//For now we'll choose a preference order of loudness followed by SNR
sl@0
   940
sl@0
   941
	switch(remoteSBCCodecConfiguration->AllocationMethods())
sl@0
   942
		{
sl@0
   943
		case ELoudness:
sl@0
   944
			iLocalSBCCodecConfiguration.SetAllocationMethod(TSBCFrameParameters::ELoudness);
sl@0
   945
			break;
sl@0
   946
		case ESNR:
sl@0
   947
			iLocalSBCCodecConfiguration.SetAllocationMethod(TSBCFrameParameters::ESNR);
sl@0
   948
			break;
sl@0
   949
		default:
sl@0
   950
			Panic(EA2dpCodecUtilUnexpectedConfiguration);
sl@0
   951
			break;
sl@0
   952
		}
sl@0
   953
	
sl@0
   954
	
sl@0
   955
	//Subbands currently have a preference of four over 8, but change to 8 later
sl@0
   956
	//when hardware is available to support higher bandwidth
sl@0
   957
	switch(remoteSBCCodecConfiguration->Subbands())
sl@0
   958
		{
sl@0
   959
		case EFourSubbands:
sl@0
   960
			iLocalSBCCodecConfiguration.SetSubbands(TSBCFrameParameters::E4Subbands);
sl@0
   961
			break;
sl@0
   962
		case EEightSubbands:
sl@0
   963
			iLocalSBCCodecConfiguration.SetSubbands(TSBCFrameParameters::E8Subbands);
sl@0
   964
			break;
sl@0
   965
		default:
sl@0
   966
			Panic(EA2dpCodecUtilUnexpectedConfiguration);
sl@0
   967
			break;
sl@0
   968
		}
sl@0
   969
sl@0
   970
	// note that we don't normally play SBC directly, except for test purposes
sl@0
   971
	// in order to arbitary play any SBC file extra code would be required
sl@0
   972
	// to parse the SBC frame header to get the bitpool value
sl@0
   973
	// since for unit testing the the SBC test file is known to have a
sl@0
   974
	// bit pool value of 20, this shall be the default value
sl@0
   975
	// This code could be made more more intelligent and base the 
sl@0
   976
	// bitpool value around table 4.7 in the A2DP specification
sl@0
   977
	TUint bitPoolValue = KDefaultBitPoolValue; //default is 20
sl@0
   978
	if (KDefaultBitPoolValue < remoteSBCCodecConfiguration->MinBitpoolValue())
sl@0
   979
		{
sl@0
   980
		bitPoolValue = remoteSBCCodecConfiguration->MinBitpoolValue();
sl@0
   981
		}
sl@0
   982
	else if (KDefaultBitPoolValue > remoteSBCCodecConfiguration->MaxBitpoolValue())
sl@0
   983
		{
sl@0
   984
		bitPoolValue = remoteSBCCodecConfiguration->MaxBitpoolValue();
sl@0
   985
		}
sl@0
   986
	iLocalSBCCodecConfiguration.SetBitpool(bitPoolValue); 
sl@0
   987
	
sl@0
   988
	return iLocalSBCCodecConfiguration;
sl@0
   989
	}	
sl@0
   990
sl@0
   991
	
sl@0
   992
/**
sl@0
   993
Internal function to calculate the SBC buffer length required from the SBC frame parameters
sl@0
   994
using the given pcm16 buffer length
sl@0
   995
*/
sl@0
   996
TUint CA2dpAudioCodecConfiguration::CalculateSBCBufferLength(TUint aPCM16BufferLength) const
sl@0
   997
	{
sl@0
   998
	//ASSERT data type = SBC
sl@0
   999
	
sl@0
  1000
	//first calculate the number of PCM16 samples in one SBC frame
sl@0
  1001
	TUint numberOfSamplesPerSBCFrame = iLocalSBCCodecConfiguration.BlockLength()*iLocalSBCCodecConfiguration.Subbands();
sl@0
  1002
	
sl@0
  1003
	//calculate the number of bytes in one sample
sl@0
  1004
	TUint numberOfPCM16BytesPerSample = 2*iLocalSBCCodecConfiguration.Channels();
sl@0
  1005
	
sl@0
  1006
	TUint numberOfPCM16BytesPerSBCFrame = numberOfSamplesPerSBCFrame*numberOfPCM16BytesPerSample;
sl@0
  1007
	
sl@0
  1008
	TUint numberOfFrames = aPCM16BufferLength/numberOfPCM16BytesPerSBCFrame;
sl@0
  1009
	
sl@0
  1010
	TUint lengthOfSBCFrame = iLocalSBCCodecConfiguration.CalcFrameLength();
sl@0
  1011
	
sl@0
  1012
	return numberOfFrames*lengthOfSBCFrame;
sl@0
  1013
	}
sl@0
  1014
	
sl@0
  1015
sl@0
  1016
/**
sl@0
  1017
Test function to force the remote SBC codec configuration to that set in aRemoteCodecConfiguration
sl@0
  1018
This function is just used for test purposes to set the SBC settings for
sl@0
  1019
playing SBC data direct to the a2dpBTHeadsetAudioIf ie when the Data type is 
sl@0
  1020
set to SBC
sl@0
  1021
It is up to the user to ensure that the headset supports the configuration
sl@0
  1022
since this will bypass the normal capability check
sl@0
  1023
*/	
sl@0
  1024
void CA2dpAudioCodecConfiguration::TEST_ForceRemoteSBCCodecConfiguration(const TSBCCodecCapabilities& aRemoteCodecConfiguration)
sl@0
  1025
	{
sl@0
  1026
	iForcedRemoteSBCCodecConfiguration = const_cast<TSBCCodecCapabilities*>(&aRemoteCodecConfiguration);
sl@0
  1027
	}
sl@0
  1028
sl@0
  1029
	
sl@0
  1030
sl@0
  1031
sl@0
  1032
CA2dpCodecFrameHeaderParser* CA2dpCodecFrameHeaderParser::NewL(const TFourCC& aCodecDataType, const TDesC8& aHeader)
sl@0
  1033
	{
sl@0
  1034
	CA2dpCodecFrameHeaderParser* self = new (ELeave) CA2dpCodecFrameHeaderParser();
sl@0
  1035
	CleanupStack::PushL(self);
sl@0
  1036
	self->ConstructL(aCodecDataType, aHeader);
sl@0
  1037
	CleanupStack::Pop(self);
sl@0
  1038
	return self;
sl@0
  1039
	}
sl@0
  1040
sl@0
  1041
sl@0
  1042
CA2dpCodecFrameHeaderParser::CA2dpCodecFrameHeaderParser()
sl@0
  1043
	{
sl@0
  1044
	
sl@0
  1045
	}
sl@0
  1046
sl@0
  1047
sl@0
  1048
CA2dpCodecFrameHeaderParser::~CA2dpCodecFrameHeaderParser()
sl@0
  1049
	{
sl@0
  1050
	
sl@0
  1051
	}	
sl@0
  1052
sl@0
  1053
sl@0
  1054
/**
sl@0
  1055
Only used for playing SBC test files
sl@0
  1056
*/
sl@0
  1057
void CA2dpCodecFrameHeaderParser::ParseSBCHeaderL(const TDesC8& aHeader)
sl@0
  1058
	{
sl@0
  1059
	if (aHeader[0] != KSbcFrameHeaderSyncWord)
sl@0
  1060
		{
sl@0
  1061
		User::Leave(KErrCorrupt); //not a valid sbc frame
sl@0
  1062
		}
sl@0
  1063
	
sl@0
  1064
	TUint samplingFrequency = (aHeader[1] & KSbcFrameHeaderSamplingFrequencyMask)>>6;
sl@0
  1065
	switch(samplingFrequency)
sl@0
  1066
		{
sl@0
  1067
		case TSBCFrameParameters::E16000Hz:
sl@0
  1068
			iSampleRate = 16000;
sl@0
  1069
			break;
sl@0
  1070
		case TSBCFrameParameters::E32000Hz:
sl@0
  1071
			iSampleRate = 32000;
sl@0
  1072
			break;
sl@0
  1073
		case TSBCFrameParameters::E44100Hz:
sl@0
  1074
			iSampleRate = 44100;
sl@0
  1075
			break;
sl@0
  1076
		case TSBCFrameParameters::E48000Hz:
sl@0
  1077
			iSampleRate = 48000;
sl@0
  1078
			break;
sl@0
  1079
		default:
sl@0
  1080
			User::Leave(KErrCorrupt);//not a valid header
sl@0
  1081
			break;
sl@0
  1082
		}
sl@0
  1083
		
sl@0
  1084
	TUint8 blocks = (aHeader[1] & KSbcFrameHeaderBlocksMask)>>4;
sl@0
  1085
	switch(blocks)
sl@0
  1086
		{
sl@0
  1087
		case TSBCFrameParameters::E4Blocks:
sl@0
  1088
			blocks = 4;
sl@0
  1089
			break;
sl@0
  1090
		case TSBCFrameParameters::E8Blocks:
sl@0
  1091
			blocks = 8;
sl@0
  1092
			break;
sl@0
  1093
		case TSBCFrameParameters::E12Blocks:
sl@0
  1094
			blocks = 12;
sl@0
  1095
			break;
sl@0
  1096
		case TSBCFrameParameters::E16Blocks:
sl@0
  1097
			blocks = 16;
sl@0
  1098
			break;
sl@0
  1099
		default:
sl@0
  1100
			User::Leave(KErrCorrupt);//not a valid header
sl@0
  1101
			break;
sl@0
  1102
		}
sl@0
  1103
	TUint8 channelMode = (aHeader[1] & KSbcFrameHeaderChannelModeMask)>>2;
sl@0
  1104
	TUint8 channels = 1;
sl@0
  1105
	
sl@0
  1106
	if (channelMode != TSBCFrameParameters::EMono)
sl@0
  1107
		{
sl@0
  1108
		channels = 2;
sl@0
  1109
		}
sl@0
  1110
	
sl@0
  1111
	TUint8 subbands = 4;
sl@0
  1112
	if (aHeader[1] & KSbcFrameHeaderSubbandsMask)
sl@0
  1113
		{
sl@0
  1114
		subbands = 8;
sl@0
  1115
		}
sl@0
  1116
		
sl@0
  1117
	TUint8 bitpool = aHeader[2];
sl@0
  1118
	
sl@0
  1119
	TUint temp = 0;
sl@0
  1120
	switch (channelMode)
sl@0
  1121
		{
sl@0
  1122
		case TSBCFrameParameters::EMono:
sl@0
  1123
			temp = blocks * bitpool; // blocks * bitpool
sl@0
  1124
			break;	
sl@0
  1125
		case TSBCFrameParameters::EDualChannel:
sl@0
  1126
			temp = (blocks * bitpool) << 1; // blocks * bitpool * 2
sl@0
  1127
			break;	
sl@0
  1128
		case TSBCFrameParameters::EStereo:
sl@0
  1129
			temp = blocks * bitpool; // blocks * bitpool
sl@0
  1130
			break;	
sl@0
  1131
		case TSBCFrameParameters::EJointStereo:
sl@0
  1132
			temp = subbands + blocks * bitpool; // subbands + blocks * bitpool
sl@0
  1133
			break;
sl@0
  1134
		}
sl@0
  1135
		
sl@0
  1136
	iFrameLength = 4 + ( (subbands * channels) >> 1) + (temp >> 3);
sl@0
  1137
	if (temp & 0x7)
sl@0
  1138
		{
sl@0
  1139
		iFrameLength++;
sl@0
  1140
		}
sl@0
  1141
		
sl@0
  1142
	iBitRate = (8*iFrameLength*iSampleRate)/(subbands*blocks);
sl@0
  1143
	}
sl@0
  1144
sl@0
  1145
sl@0
  1146
void CA2dpCodecFrameHeaderParser::ParseMPEG12HeaderL(const TDesC8& aHeader)
sl@0
  1147
	{
sl@0
  1148
	if (aHeader[0] != KMPEGAudioFrameHeaderSyncWord )
sl@0
  1149
		{
sl@0
  1150
		User::Leave(KErrCorrupt); //not a valid MPEG audio frame
sl@0
  1151
		}
sl@0
  1152
	
sl@0
  1153
	//check it's really mp3 as opposed to mp1 or mp2
sl@0
  1154
	if ((aHeader[1] & KMp3AudioFrameHeaderIdMask) != KMp3AudioFrameHeaderId)
sl@0
  1155
		{
sl@0
  1156
		User::Leave(KErrNotSupported); //either corrupt or mp1/mp2
sl@0
  1157
		}
sl@0
  1158
	
sl@0
  1159
	TUint8 sampleRateIndex = (aHeader[2] & KMp3FrameHeaderSamplingFrequencyMask)>>2;
sl@0
  1160
	switch(sampleRateIndex)
sl@0
  1161
		{
sl@0
  1162
		case 0x00:
sl@0
  1163
			iSampleRate = 44100;
sl@0
  1164
			break;
sl@0
  1165
		case 0x01:
sl@0
  1166
			iSampleRate = 48000;
sl@0
  1167
			break;
sl@0
  1168
		case 0x02:
sl@0
  1169
			iSampleRate = 32000;
sl@0
  1170
			break;
sl@0
  1171
		default:
sl@0
  1172
			User::Leave(KErrCorrupt); //invalid mp3 header?
sl@0
  1173
			break;
sl@0
  1174
		}
sl@0
  1175
	TUint8 bitRateIndex = (aHeader[2] & KMp3FrameHeaderBitRateIndexMask)>>4;
sl@0
  1176
	switch(bitRateIndex)
sl@0
  1177
		{
sl@0
  1178
		case EMp3BitRateIndex32000:
sl@0
  1179
			iBitRate = 32000;
sl@0
  1180
			break;
sl@0
  1181
		case EMp3BitRateIndex40000:
sl@0
  1182
			iBitRate = 40000;
sl@0
  1183
			break;
sl@0
  1184
		case EMp3BitRateIndex48000:
sl@0
  1185
			iBitRate = 48000;
sl@0
  1186
			break;
sl@0
  1187
		case EMp3BitRateIndex56000:
sl@0
  1188
			iBitRate = 56000;
sl@0
  1189
			break;
sl@0
  1190
		case EMp3BitRateIndex64000:
sl@0
  1191
			iBitRate = 64000;
sl@0
  1192
			break;
sl@0
  1193
		case EMp3BitRateIndex80000:
sl@0
  1194
			iBitRate = 80000;
sl@0
  1195
			break;
sl@0
  1196
		case EMp3BitRateIndex96000:
sl@0
  1197
			iBitRate = 96000;
sl@0
  1198
			break;
sl@0
  1199
		default:
sl@0
  1200
			User::Leave(KErrNotSupported);//don't support more than 96kbs-1
sl@0
  1201
			break;
sl@0
  1202
		}
sl@0
  1203
	
sl@0
  1204
	//this code should really be made more clever to take allowance for any padding
sl@0
  1205
	//and use a frame length such that if padding is used then take the lowest
sl@0
  1206
	//common multiple of frames tht gives a common frame length eg if the frames
sl@0
  1207
	//alternate between 100 and 101 bytes due to an extra padding byte everyother
sl@0
  1208
	//frame then set the frame length to 201;	
sl@0
  1209
	TUint bitRateX144 = iBitRate*144;
sl@0
  1210
	iFrameLength = bitRateX144/iSampleRate;
sl@0
  1211
	}
sl@0
  1212
sl@0
  1213
	
sl@0
  1214
/**
sl@0
  1215
static
sl@0
  1216
*/	
sl@0
  1217
void CA2dpCodecFrameHeaderParser::ConstructL(const TFourCC& aCodecDataType, const TDesC8& aHeader)
sl@0
  1218
	{
sl@0
  1219
	switch(const_cast<TFourCC&>(aCodecDataType).FourCC())
sl@0
  1220
		{
sl@0
  1221
		case KMMFFourCCCodeSBC:
sl@0
  1222
			ParseSBCHeaderL(aHeader);
sl@0
  1223
			break;
sl@0
  1224
		case KMMFFourCCCodeMP3:
sl@0
  1225
			ParseMPEG12HeaderL(aHeader);
sl@0
  1226
			break;
sl@0
  1227
		case KMMFFourCCCodeAAC:
sl@0
  1228
			User::Leave(KErrNotSupported);
sl@0
  1229
			break;
sl@0
  1230
		case KMMFFourCCCodeATRAC3:
sl@0
  1231
			User::Leave(KErrNotSupported);
sl@0
  1232
			break;
sl@0
  1233
		default:
sl@0
  1234
			User::Leave(KErrNotSupported);
sl@0
  1235
			break;
sl@0
  1236
		}
sl@0
  1237
	}	
sl@0
  1238