diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/mmfrawformat_8cpp-source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/mmfrawformat_8cpp-source.html Tue Mar 30 11:56:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,788 +0,0 @@ - -
-00001 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). -00002 // All rights reserved. -00003 // This component and the accompanying materials are made available -00004 // under the terms of "Eclipse Public License v1.0" -00005 // which accompanies this distribution, and is available -00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html". -00007 // -00008 // Initial Contributors: -00009 // Nokia Corporation - initial contribution. -00010 // -00011 // Contributors: -00012 // -00013 // Description: -00014 // -00015 -00016 // MMF framework headers -00017 #include <mmffile.h> -00018 #include <ecom.h> -00019 #include <mmfformatimplementationuids.hrh> -00020 #include <mmffourcc.h> -00021 -00022 #include "mmfrawformat.h" -00023 #include "UIDs.hrh" -00024 -00025 const TUint KFormatDefaultFrameSize(0x1000); //Set default frame size to 4 K -00026 const TUint KDefineIOBufferSize(0x0200); //easy to read clip buffer size -00027 const TUint KOneSecondInMicroSeconds(1000000); //1 Second -00028 const TUint KMono(1); -00029 const TUint KStereo(2); -00030 //this defines the valid sample rates for RAW -00031 const TUint KRawSampleRates[] = { 8000, 11025, 22050, 44100 }; -00032 -00033 -00034 // -00035 // CMMFRawFormatRead -00036 // -00037 -00038 // Factory function -00039 CMMFFormatDecode* CMMFRawFormatRead::NewL(MDataSource* aSource) -00040 { -00041 if ((aSource->DataSourceType()==KUidMmfDescriptorSource)|| -00042 (aSource->DataSourceType()==KUidMmfFileSource)) -00043 {//currently only files and descriptor MDataSources are supported -00044 CMMFRawFormatRead* self = new(ELeave)CMMFRawFormatRead; -00045 CleanupStack::PushL(self); -00046 self->ConstructL(aSource); -00047 CleanupStack::Pop(); -00048 return self; -00049 } -00050 else return NULL; -00051 } -00052 -00053 // Destructor -00054 CMMFRawFormatRead::~CMMFRawFormatRead() -00055 { -00056 delete iBuffer; -00057 } -00058 -00059 // Second-phase constructor -00060 void CMMFRawFormatRead::ConstructL(MDataSource* aSource) -00061 { -00062 // tell clip we're using it -00063 iClip = aSource; -00064 User::LeaveIfError(iClip->SourceThreadLogon(*this)); -00065 iClip->SourcePrimeL(); -00066 iFrameSize = KFormatDefaultFrameSize; -00067 iClipLength = (static_cast<CMMFClip*>(iClip))->Size(); -00068 } -00069 -00070 // Implementing MDataSource -00071 -00072 // Handle request to fill buffer with data from clip -00073 void CMMFRawFormatRead::FillBufferL(CMMFBuffer* aBuffer, MDataSink* aConsumer, TMediaId aMediaId ) -00074 { -00075 // check media id & pass onto the clip -00076 if (aMediaId.iMediaType != KUidMediaTypeAudio) User::Leave(KErrNotSupported); -00077 iDataPath = aConsumer; -00078 //assumes first frame is frame 1 -00079 TUint position = ((aBuffer->FrameNumber()-1)*iFrameSize)+iStartPosition; -00080 (static_cast<CMMFClip*>(iClip))->ReadBufferL(aBuffer, position, this); -00081 // notified of when buffer is full by BufferFilledL -00082 } -00083 -00084 // creates the buffer for the source -00085 // This overload supplies the sink buffer, as optimal source buffer size creation may depend on this -00086 CMMFBuffer* CMMFRawFormatRead::CreateSourceBufferL(TMediaId aMediaId, CMMFBuffer& aSinkBuffer, TBool &aReference) -00087 { -00088 if (aMediaId.iMediaType == KUidMediaTypeAudio) -00089 { -00090 NegotiateSourceBufferL(aSinkBuffer); //sets frame size to match sink buffer -00091 return CreateSourceBufferL(aMediaId, aReference); -00092 } -00093 else User::Leave(KErrNotSupported); -00094 return NULL; -00095 } -00096 -00097 // creates the buffer for the source -00098 CMMFBuffer* CMMFRawFormatRead::CreateSourceBufferL(TMediaId aMediaId, TBool &aReference) -00099 { -00100 if (aMediaId.iMediaType == KUidMediaTypeAudio) -00101 { -00102 // assume default frame size if haven't determined a better one -00103 if (!iFrameSize) iFrameSize = KFormatDefaultFrameSize; -00104 // sets aReference to false if a new CMMFBuffer is returned -00105 aReference = EFalse; -00106 return CreateSourceBufferOfSizeL(iFrameSize); -00107 } -00108 else User::Leave(KErrNotSupported); -00109 return NULL; -00110 } -00111 -00112 // Helper function to create and zero fill a buffer of specified size -00113 CMMFDataBuffer* CMMFRawFormatRead::CreateSourceBufferOfSizeL(TUint aSize) -00114 { -00115 //needs to create source buffer -00116 CMMFDataBuffer* buffer = CMMFDataBuffer::NewL(aSize); -00117 buffer->Data().FillZ(aSize); -00118 return buffer; -00119 } -00120 -00121 // Helper function to determine best source buffer size -00122 void CMMFRawFormatRead::NegotiateSourceBufferL(CMMFBuffer& aSinkBuffer) -00123 { -00124 // if sink buffer has a fixed size use this to determine source buffer size -00125 if (aSinkBuffer.Type() == KUidMmfDataBuffer) -00126 { -00127 // RAW is linear data, so can set target buffer to sink buffer size -00128 TUint sinkBufferLength = (static_cast<CMMFDataBuffer&>(aSinkBuffer)).Data().MaxLength(); -00129 if (sinkBufferLength == 0) sinkBufferLength = KFormatDefaultFrameSize; -00130 iFrameSize = sinkBufferLength; -00131 CalculateFrameTimeInterval(); -00132 } -00133 else -00134 User::Leave(KErrNotSupported); -00135 } -00136 -00137 // returns the codec FourCC code for the mediaId -00138 TFourCC CMMFRawFormatRead::SourceDataTypeCode(TMediaId aMediaId) -00139 { -00140 if (aMediaId.iMediaType == KUidMediaTypeAudio) return iFourCC; -00141 else return TFourCC(); //defaults to 'NULL' fourCC -00142 } -00143 -00144 // sets the codec FourCC code for the mediaId -00145 TInt CMMFRawFormatRead::SetSourceDataTypeCode(TFourCC aSinkFourCC, TMediaId aMediaId) -00146 { -00147 if (aMediaId.iMediaType != KUidMediaTypeAudio) return KErrNotSupported; -00148 else iFourCC = aSinkFourCC; -00149 -00150 if ((iFourCC == KMMFFourCCCodePCM16) || -00151 (iFourCC == KMMFFourCCCodePCM16B) || -00152 (iFourCC == KMMFFourCCCodePCMU16)) -00153 iBitsPerSample = 16; -00154 else if ((iFourCC == KMMFFourCCCodeIMAD) || -00155 (iFourCC == KMMFFourCCCodeIMAS)) -00156 iBitsPerSample = 4; -00157 else -00158 iBitsPerSample = 8; //default to 8 -00159 return KErrNone; -00160 } -00161 -00162 // Initiate use of the interface -00163 TInt CMMFRawFormatRead::SourceThreadLogon(MAsyncEventHandler& aEventHandler) -00164 {//pass through to source clip -00165 return(iClip->SourceThreadLogon(aEventHandler)); -00166 } -00167 -00168 // Prepare clip -00169 void CMMFRawFormatRead::SourcePrimeL() -00170 { -00171 iClip->SourcePrimeL(); -00172 CalculateFrameTimeInterval(); -00173 } -00174 -00175 // Play clip -00176 void CMMFRawFormatRead::SourcePlayL() -00177 { -00178 iClip->SourcePlayL(); -00179 } -00180 -00181 // Pause clip -00182 void CMMFRawFormatRead::SourcePauseL() -00183 { -00184 iClip->SourcePauseL(); //propagate state change down to clip -00185 } -00186 -00187 // Stop clip -00188 void CMMFRawFormatRead::SourceStopL() -00189 { -00190 iClip->SourceStopL(); -00191 } -00192 -00193 // End use of the interface -00194 void CMMFRawFormatRead::SourceThreadLogoff() -00195 { -00196 iClip->SourceThreadLogoff(); -00197 } -00198 -00199 // from MDataSink -00200 -00201 // called by MDataSource to pass back full buffer to the sink -00202 void CMMFRawFormatRead::BufferFilledL(CMMFBuffer* aBuffer) -00203 { -00204 //set position -00205 TTimeIntervalMicroSeconds position = //assumes frame numbers begin at frame 1 -00206 TTimeIntervalMicroSeconds(TInt64(aBuffer->FrameNumber()-1)*iFrameTimeInterval.Int64()); -00207 aBuffer->SetTimeToPlay(position); -00208 iDataPath->BufferFilledL(aBuffer); -00209 } -00210 -00211 -00212 // from CMMFFormatDecode -00213 -00214 // returns number of streams -00215 TUint CMMFRawFormatRead::Streams(TUid aMediaType) const -00216 { -00217 //need to check aMediaType for audio -00218 if (aMediaType == KUidMediaTypeAudio) return 1; //raw files can only have 1 audio stream -00219 else return 0; -00220 } -00221 -00222 // returns the time interval for one frame -00223 TTimeIntervalMicroSeconds CMMFRawFormatRead::FrameTimeInterval(TMediaId aMediaId) const -00224 { -00225 if (aMediaId.iMediaType == KUidMediaTypeAudio) return iFrameTimeInterval; -00226 else return TTimeIntervalMicroSeconds(0); -00227 } -00228 -00229 // returns the duration of the source clip -00230 TTimeIntervalMicroSeconds CMMFRawFormatRead::Duration(TMediaId aMediaId) const -00231 { -00232 if ((aMediaId.iMediaType == KUidMediaTypeAudio) && -00233 (iClipLength) && (iSampleRate) && (iBitsPerSample) && (iChannels)) -00234 {//we have enough values to calculate the duration -00235 TInt64 clipLength(iClipLength); -00236 clipLength*=KOneSecondInMicroSeconds; -00237 TTimeIntervalMicroSeconds duration = TTimeIntervalMicroSeconds(clipLength/iSampleRate); -00238 duration = TTimeIntervalMicroSeconds(duration.Int64()/(iBitsPerSample*iChannels)); -00239 duration = TTimeIntervalMicroSeconds(duration.Int64()*8); -00240 return duration; -00241 } -00242 else return TTimeIntervalMicroSeconds(0); -00243 } -00244 -00245 // helper function: calculates time between frames -00246 void CMMFRawFormatRead::CalculateFrameTimeInterval() -00247 { -00248 if ((iFrameSize) && (iSampleRate) && (iBitsPerSample) && (iChannels)) -00249 { -00250 iFrameTimeInterval = TTimeIntervalMicroSeconds((iFrameSize*KOneSecondInMicroSeconds)/iSampleRate); -00251 iFrameTimeInterval = -00252 TTimeIntervalMicroSeconds(iFrameTimeInterval.Int64()/(iBitsPerSample*iChannels)); -00253 iFrameTimeInterval = TTimeIntervalMicroSeconds(iFrameTimeInterval.Int64()*8); -00254 } -00255 } -00256 -00257 // called by sink to suggest a source buffer size -00258 void CMMFRawFormatRead::SuggestSourceBufferSize(TUint aSuggestedBufferSize) -00259 { -00260 iFrameSize = aSuggestedBufferSize; //set source format frame size to buffer size suggested by sink -00261 CalculateFrameTimeInterval(); -00262 } -00263 -00264 // set the number of channels -00265 TInt CMMFRawFormatRead::SetNumChannels(TUint aChannels) -00266 { -00267 TInt error = KErrNone; -00268 if ((aChannels == KMono)||(aChannels == KStereo)) iChannels = aChannels; -00269 else error = KErrNotSupported; //only alow one or two channels -00270 return error; -00271 } -00272 -00273 // set the sample rate -00274 TInt CMMFRawFormatRead::SetSampleRate(TUint aSampleRate) -00275 { -00276 TInt status = KErrNotSupported; -00277 //we'll iterate through the valid sample table -00278 TInt i = sizeof(KRawSampleRates) / sizeof(TUint); -00279 -00280 while ((i--) && (status != KErrNone)) -00281 { -00282 if (aSampleRate == KRawSampleRates[i]) -00283 { -00284 iSampleRate = aSampleRate; -00285 status = KErrNone; -00286 } -00287 } -00288 return status; -00289 } -00290 -00291 // helper function to read from clip -00292 void CMMFRawFormatRead::DoReadL(TInt aReadPosition) -00293 { -00294 STATIC_CAST(CMMFClip*,iClip)->ReadBufferL(iBuffer,aReadPosition); -00295 } -00296 -00297 // get the supported sample rates -00298 void CMMFRawFormatRead::GetSupportedSampleRatesL(RArray<TUint>& aSampleRates) -00299 { -00300 aSampleRates.Reset(); -00301 -00302 // Iterate through the valid sample table and append each value to aSampleRates -00303 TInt i = sizeof(KRawSampleRates) / sizeof(TUint); -00304 -00305 while (i--) -00306 { -00307 User::LeaveIfError(aSampleRates.Append(KRawSampleRates[i])); -00308 } -00309 } -00310 -00311 // get the supported channel number options -00312 void CMMFRawFormatRead::GetSupportedNumChannelsL(RArray<TUint>& aNumChannels) -00313 { -00314 aNumChannels.Reset(); -00315 User::LeaveIfError(aNumChannels.Append(KMono)); -00316 User::LeaveIfError(aNumChannels.Append(KStereo)); -00317 } -00318 -00319 // get the supported codecs -00320 void CMMFRawFormatRead::GetSupportedDataTypesL(TMediaId aMediaId, RArray<TFourCC>& aDataTypes) -00321 { -00322 if (aMediaId.iMediaType != KUidMediaTypeAudio) -00323 User::Leave(KErrNotSupported); -00324 aDataTypes.Reset(); -00325 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM16)); -00326 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM16B)); -00327 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCMU16)); -00328 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeIMAD)); -00329 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeIMAS)); -00330 } -00331 -00332 -00333 // -00334 // CMMFRawFormatWrite -00335 // -00336 -00337 // Factory function -00338 CMMFFormatEncode* CMMFRawFormatWrite::NewL(MDataSink* aSink) -00339 { -00340 if ((aSink->DataSinkType()==KUidMmfDescriptorSink)|| -00341 (aSink->DataSinkType()==KUidMmfFileSink)) -00342 {//currently only files and descriptor MDataSources are supported -00343 CMMFRawFormatWrite* self = new(ELeave)CMMFRawFormatWrite; -00344 CleanupStack::PushL(self); -00345 self->ConstructL(aSink); -00346 CleanupStack::Pop(); -00347 return STATIC_CAST(CMMFFormatEncode*, self); -00348 } -00349 else return NULL; -00350 } -00351 -00352 // destructor -00353 CMMFRawFormatWrite::~CMMFRawFormatWrite() -00354 { -00355 delete iBuffer; -00356 delete iConvertBuffer; -00357 delete iChannelAndSampleRateConverterFactory; -00358 } -00359 -00360 // second-phase construction -00361 void CMMFRawFormatWrite::ConstructL(MDataSink* aSink) -00362 { -00363 iClip = aSink; -00364 //first need to check if sink clip already exists to get settings. -00365 User::LeaveIfError(iClip->SinkThreadLogon(*this)); -00366 iClip->SinkPrimeL(); -00367 iBuffer = CreateSinkBufferOfSizeL(KDefineIOBufferSize); //512 easiest file size to read -00368 DoReadL(0);//read from beginning of clip -00369 if (iBuffer->Data().Size()> 0) -00370 { -00371 iClipAlreadyExists = ETrue; -00372 //There is no header, so data size is the same as the clip size in this case. -00373 iDataSize = iClipLength = STATIC_CAST(CMMFClip*,iClip)->Size(); -00374 } -00375 iFrameSize = KFormatDefaultFrameSize; -00376 } -00377 -00378 // from MDataSink -00379 -00380 // sink thread attaches -00381 TInt CMMFRawFormatWrite::SinkThreadLogon(MAsyncEventHandler& aEventHandler) -00382 {//pass through to sink clip -00383 return(iClip->SinkThreadLogon(aEventHandler)); -00384 } -00385 -00386 // helper function: calculates time between frames -00387 void CMMFRawFormatWrite::CalculateFrameTimeInterval() -00388 { -00389 if ((iFrameSize) && (iSampleRate) && (iBitsPerSample) && (iChannels)) -00390 { -00391 iFrameTimeInterval = TTimeIntervalMicroSeconds((iFrameSize*KOneSecondInMicroSeconds)/iSampleRate); -00392 iFrameTimeInterval = -00393 TTimeIntervalMicroSeconds((iFrameTimeInterval.Int64())/(iBitsPerSample*iChannels)); -00394 iFrameTimeInterval = TTimeIntervalMicroSeconds(iFrameTimeInterval.Int64()*8); -00395 } -00396 } -00397 -00398 // called if sink setup depends on source -00399 void CMMFRawFormatWrite::Negotiate(MDataSource& aSource) -00400 { -00401 if (aSource.DataSourceType() == KUidMmfAudioInput) -00402 { -00403 // could query the audio capabilities from DevSound for the settings below -00404 iSourceSampleRate = 8000; // assume 8KHz for now -00405 iSourceChannels = 1; //assume mono -00406 iSourceFourCC.Set(KMMFFourCCCodePCM16); //16 bit PCM -00407 } -00408 else if (aSource.DataSourceType() == KUidMmfFormatDecode) -00409 {//source is a clip so for now set sink settings to match source -00410 iSourceSampleRate = ((CMMFFormatDecode&)aSource).SampleRate(); -00411 iSourceChannels = ((CMMFFormatDecode&)aSource).NumChannels(); -00412 iSourceFourCC.Set(aSource.SourceDataTypeCode(TMediaId(KUidMediaTypeAudio))); -00413 iSourceWillSampleConvert = STATIC_CAST(CMMFFormatDecode&, aSource).SourceSampleConvert(); -00414 ((CMMFFormatDecode&)aSource).SuggestSourceBufferSize(iFrameSize); //for now suggest format src takes same buf size as sink?? -00415 //make the start position the end of the clip -00416 } -00417 else return; -00418 //set default sink parameters to be the same as the source -00419 if (iClipAlreadyExists) iStartPosition = iClipLength; -00420 if (!iSampleRate) iSampleRate = iSourceSampleRate; //might have already been set by custom command -00421 if (!iChannels) iChannels = iSourceChannels; -00422 if (!iBitsPerSample) -00423 { -00424 iFourCC.Set(iSourceFourCC); -00425 if ((iFourCC == KMMFFourCCCodePCM16) || -00426 (iFourCC == KMMFFourCCCodePCM16B) || -00427 (iFourCC == KMMFFourCCCodePCMU16)) -00428 iBitsPerSample = 16; -00429 else if ((iFourCC == KMMFFourCCCodeIMAD) || -00430 (iFourCC == KMMFFourCCCodeIMAS)) -00431 iBitsPerSample = 4; -00432 else -00433 iBitsPerSample = 8; //default to 8 -00434 } -00435 CalculateFrameTimeInterval(); -00436 } -00437 -00438 // Prime the sink to be accessed -00439 void CMMFRawFormatWrite::SinkPrimeL() -00440 { -00441 iClip->SinkPrimeL(); //propagate state change down to clip -00442 CalculateFrameTimeInterval(); -00443 } -00444 -00445 // Play the sink -00446 void CMMFRawFormatWrite::SinkPlayL() -00447 { -00448 iClip->SinkPlayL(); //propagate state change down to clip -00449 if ((iChannels != iSourceChannels) || (iSampleRate != iSourceSampleRate) && (!iSourceWillSampleConvert)) -00450 {//the source channels & sample rate don't match the formats - therefore need to do a conversion -00451 //currently only pcm16 is supported so return with an error if format not pcm16 -00452 if (iFourCC != KMMFFourCCCodePCM16) User::Leave(KErrNotSupported); -00453 iChannelAndSampleRateConverterFactory -00454 = new(ELeave)CMMFChannelAndSampleRateConverterFactory; -00455 iChannelAndSampleRateConverter = -00456 iChannelAndSampleRateConverterFactory->CreateConverterL( iSourceSampleRate, iSourceChannels, -00457 iSampleRate, iChannels); -00458 //need to create an intermediate buffer in which to place the converted data -00459 TUint convertedBufferFrameSize = (iFrameSize*iChannels)/iSourceChannels; -00460 iConvertBuffer = CreateSinkBufferOfSizeL(convertedBufferFrameSize); -00461 } -00462 iFileHasChanged = ETrue; //file will change if we start playing to it -00463 } -00464 -00465 // Pause the sink -00466 void CMMFRawFormatWrite::SinkPauseL() -00467 { -00468 iClip->SinkPauseL(); //propagate state change down to clip -00469 } -00470 -00471 // Stop the sink -00472 void CMMFRawFormatWrite::SinkStopL() -00473 { -00474 iClip->SinkStopL(); //propagate state change down to clip -00475 } -00476 -00477 // Detach from the sink -00478 void CMMFRawFormatWrite::SinkThreadLogoff() -00479 { -00480 iClip->SinkThreadLogoff(); //propagate down to clip -00481 } -00482 -00483 // Called by the CMMFDataPath to add a buffer to a clip -00484 void CMMFRawFormatWrite::EmptyBufferL(CMMFBuffer* aBuffer, MDataSource* aSupplier, TMediaId aMediaId) -00485 { -00486 //since raw always contains linear audio the sink buffer size can set the source buffer size -00487 -00488 //check media id &pass onto clip -00489 if (aMediaId.iMediaType!=KUidMediaTypeAudio) User::Leave(KErrNotSupported); -00490 iDataPath = aSupplier; -00491 -00492 // Check we haven't exceeded any set maximum on our clip length -00493 if (iMaximumClipSize > 0) -00494 { -00495 // Find the current clip size -00496 TInt currentClipLength = STATIC_CAST(CMMFClip*, iClip)->Size(); -00497 TInt bufferSize = aBuffer->BufferSize(); -00498 if ((currentClipLength + bufferSize) >= iMaximumClipSize) -00499 User::Leave(KErrEof); -00500 } -00501 -00502 //assumes first frame is frame 1 -00503 iBufferToEmpty = aBuffer; //save this so it can be returned to datapath -00504 TInt position = ((aBuffer->FrameNumber()-1)*iFrameSize)+iStartPosition; -00505 if (position < (TInt)iStartPosition) position = iStartPosition; //can't write before start of header -00506 if ((iChannelAndSampleRateConverter) && (!iSourceWillSampleConvert)) -00507 {//need to perform channel & sample rate conversion before writing to clip -00508 iFrameSize = iChannelAndSampleRateConverter->Convert(*(CMMFDataBuffer*)aBuffer,*iConvertBuffer); -00509 STATIC_CAST(CMMFClip*,iClip)->WriteBufferL(iConvertBuffer, position, this); -00510 } -00511 else -00512 {//no need to convert the data -00513 STATIC_CAST(CMMFClip*,iClip)->WriteBufferL(aBuffer, position, this); -00514 } -00515 iPos = position; //save current write position -00516 } -00517 -00518 // helper function to create buffer of specficed size -00519 CMMFDataBuffer* CMMFRawFormatWrite::CreateSinkBufferOfSizeL(TUint aSize) -00520 { -00521 //needs to create source buffer -00522 CMMFDataBuffer* buffer = CMMFDataBuffer::NewL(aSize); -00523 buffer->Data().FillZ(aSize); -00524 iBufferCreated = ETrue; -00525 return buffer; -00526 } -00527 -00528 // create buffer to receive data -00529 CMMFBuffer* CMMFRawFormatWrite::CreateSinkBufferL(TMediaId aMediaId, TBool &aReference) -00530 { -00531 if (aMediaId.iMediaType == KUidMediaTypeAudio) -00532 { -00533 if (!iFrameSize) iFrameSize = KFormatDefaultFrameSize; -00534 aReference = EFalse; -00535 return CreateSinkBufferOfSizeL(iFrameSize); -00536 } -00537 else User::Leave(KErrNotSupported); -00538 return NULL; -00539 } -00540 -00541 // gets the codec type -00542 TFourCC CMMFRawFormatWrite::SinkDataTypeCode(TMediaId aMediaId) -00543 { -00544 if (aMediaId.iMediaType == KUidMediaTypeAudio) return iFourCC; -00545 else return TFourCC(); //defaults to 'NULL' fourCC -00546 } -00547 -00548 // sets the codec type -00549 TInt CMMFRawFormatWrite::SetSinkDataTypeCode(TFourCC aSinkFourCC, TMediaId aMediaId) -00550 { -00551 if (aMediaId.iMediaType != KUidMediaTypeAudio) return KErrNotSupported; -00552 else iFourCC = aSinkFourCC; -00553 -00554 if ((iFourCC == KMMFFourCCCodePCM16) || -00555 (iFourCC == KMMFFourCCCodePCM16B) || -00556 (iFourCC == KMMFFourCCCodePCMU16)) -00557 iBitsPerSample = 16; -00558 else if ((iFourCC == KMMFFourCCCodeIMAD) || -00559 (iFourCC == KMMFFourCCCodeIMAS)) -00560 iBitsPerSample = 4; -00561 else -00562 iBitsPerSample = 8; //default to 8 -00563 -00564 return KErrNone; -00565 } -00566 -00567 // helper function to read data from clip -00568 void CMMFRawFormatWrite::DoReadL(TInt aReadPosition) -00569 { -00570 STATIC_CAST(CMMFClip*,iClip)->ReadBufferL(iBuffer,aReadPosition); -00571 } -00572 -00573 // helper function to write data to clip -00574 void CMMFRawFormatWrite::DoWriteL(TInt aWritePosition) -00575 { -00576 STATIC_CAST(CMMFClip*,iClip)->WriteBufferL(iBuffer,aWritePosition); -00577 } -00578 -00579 -00580 // from MDataSource -00581 -00582 // called by MDataSink to pass back emptied buffer to the source -00583 void CMMFRawFormatWrite::BufferEmptiedL(CMMFBuffer* aBuffer) -00584 { -00585 iDataSize+=aBuffer->BufferSize(); //total bytes written -00586 iPos += aBuffer->BufferSize(); //total bytes written so far - iPos is not always = iDataSize due to repositions -00587 if (iMaxPos < iPos) iMaxPos = iPos; //need iMaxPos incase we write data then repos to an earlier pos in the clip -00588 if (iBufferToEmpty != aBuffer) iDataPath->BufferEmptiedL(iBufferToEmpty); //need to return same buffer -00589 else iDataPath->BufferEmptiedL(aBuffer); -00590 } -00591 -00592 -00593 // from CMMFFormatEncode -00594 -00595 // set the number of channels -00596 TInt CMMFRawFormatWrite::SetNumChannels(TUint aChannels) -00597 { -00598 TInt error = KErrNone; -00599 if ((aChannels == KMono)||(aChannels == KStereo)) iChannels = aChannels; -00600 else error = KErrNotSupported; //only alow one or two channels -00601 return error; -00602 } -00603 -00604 // set the sample rate -00605 TInt CMMFRawFormatWrite::SetSampleRate(TUint aSampleRate) -00606 { -00607 TInt status = KErrNotSupported; -00608 //we'll iterate through the valid sample table -00609 TInt i = sizeof(KRawSampleRates) / sizeof(TUint); -00610 -00611 while ((i--) && (status != KErrNone)) -00612 { -00613 if (aSampleRate == KRawSampleRates[i]) -00614 { -00615 iSampleRate = aSampleRate; -00616 status = KErrNone; -00617 } -00618 } -00619 return status; -00620 } -00621 -00622 // get the frame interval -00623 TTimeIntervalMicroSeconds CMMFRawFormatWrite::FrameTimeInterval(TMediaId aMediaId) const -00624 { -00625 if (aMediaId.iMediaType == KUidMediaTypeAudio) return iFrameTimeInterval; -00626 else return TTimeIntervalMicroSeconds(0); -00627 } -00628 -00629 // returns the duration of the source clip -00630 TTimeIntervalMicroSeconds CMMFRawFormatWrite::Duration(TMediaId aMediaId) const -00631 { -00632 if ((aMediaId.iMediaType == KUidMediaTypeAudio) -00633 && (iDataSize) && (iSampleRate) && (iBitsPerSample) && (iChannels)) -00634 { -00635 TInt64 clipLength(iDataSize); -00636 clipLength*=KOneSecondInMicroSeconds; -00637 TTimeIntervalMicroSeconds duration = TTimeIntervalMicroSeconds(clipLength/iSampleRate); -00638 duration = -00639 TTimeIntervalMicroSeconds(duration.Int64()/(iBitsPerSample*iChannels)); -00640 duration = TTimeIntervalMicroSeconds(duration.Int64()*8); -00641 return duration; -00642 } -00643 else return TTimeIntervalMicroSeconds(0); -00644 } -00645 -00646 // Calculate and return the number of bytes used for on second of audio. -00647 TInt64 CMMFRawFormatWrite::BytesPerSecond() -00648 { -00649 TInt64 bitsPerSecond = iSampleRate * iBitsPerSample * iChannels ; -00650 TInt64 bytesPerSecond = bitsPerSecond/8; -00651 return bytesPerSecond ; -00652 } -00653 -00654 // Shortens the clip from the position specified to the end specified. -00655 void CMMFRawFormatWrite::CropL(TTimeIntervalMicroSeconds aPosition, TBool aToEnd ) -00656 { -00657 // Does clip have any size to crop -00658 if (!(STATIC_CAST(CMMFClip*,iClip)->Size())) User::Leave(KErrNotFound); //no clip to crop or clip is 0 bytes. -00659 -00660 -00661 // Is aPosition between the start and the end? -00662 if ( ( aPosition < TTimeIntervalMicroSeconds(0) ) || ( aPosition >= Duration( KUidMediaTypeAudio) ) ) -00663 User::Leave( KErrArgument ) ; -00664 -00665 // Convert aPostion to cropPosition in bytes -00666 -00667 TInt64 cropPosition64 = -00668 TInt64( ( aPosition.Int64() * iSampleRate * (iBitsPerSample/8) * iChannels ) /KOneSecondInMicroSeconds); -00669 TUint cropPosition = I64INT(cropPosition64); -00670 -00671 // Does cropPosition need adjustment to retain integrity? (assume not) -00672 -00673 TUint dataSize ; // This will be the size of the data left after cropping. -00674 -00675 if ( !aToEnd ) -00676 { -00677 // Shift the data physically -00678 // move the data in blocks -00679 // Create a CMMFDataBuffer and use CMMFClip to shift the data -00680 dataSize = iMaxPos - cropPosition ; -00681 if (( dataSize > 0 ) && (aPosition != TTimeIntervalMicroSeconds(0))) -00682 { -00683 TUint bufSize = ( dataSize < KDefineIOBufferSize ? dataSize : KDefineIOBufferSize ) ; //max bufSize 512 -00684 CMMFDataBuffer* buffer = CMMFDataBuffer::NewL(bufSize) ; -00685 CleanupStack::PushL( buffer ) ; -00686 -00687 TUint rPos = cropPosition ; // read position -00688 TUint wPos = 0; -00689 TInt dataToShift = ETrue ; -00690 while ( dataToShift ) -00691 { -00692 STATIC_CAST( CMMFClip*, iClip )->ReadBufferL( buffer, rPos ) ; // synchronous calls -00693 STATIC_CAST( CMMFClip*, iClip )->WriteBufferL( buffer, wPos ) ; -00694 if ( rPos > iMaxPos ) -00695 dataToShift = EFalse ; // past the end: Done -00696 else -00697 { // shift the pointers -00698 rPos += bufSize ; -00699 wPos += bufSize ; -00700 } -00701 }// while data to shift -00702 CleanupStack::PopAndDestroy( ) ; // buffer -00703 }// if data to shift -00704 }// crop to start -00705 else // crop to end -00706 dataSize = cropPosition ; -00707 -00708 iDataSize = dataSize ; -00709 iMaxPos = dataSize ; -00710 -00711 // Do the physical chop -00712 if ( iClip->DataSinkType() == KUidMmfFileSink ) -00713 { -00714 STATIC_CAST( CMMFFile*, iClip )->FileL().SetSize( iMaxPos ) ; -00715 iClipLength = iMaxPos; -00716 } -00717 } -00718 -00719 // get the supported sample rates -00720 void CMMFRawFormatWrite::GetSupportedSampleRatesL(RArray<TUint>& aSampleRates) -00721 { -00722 aSampleRates.Reset(); -00723 -00724 // Iterate through the valid sample table and append each value to aSampleRates -00725 TInt i = sizeof(KRawSampleRates) / sizeof(TUint); -00726 -00727 while (i--) -00728 { -00729 User::LeaveIfError(aSampleRates.Append(KRawSampleRates[i])); -00730 } -00731 } -00732 -00733 // get the supported channel number options -00734 void CMMFRawFormatWrite::GetSupportedNumChannelsL(RArray<TUint>& aNumChannels) -00735 { -00736 aNumChannels.Reset(); -00737 User::LeaveIfError(aNumChannels.Append(KMono)); -00738 User::LeaveIfError(aNumChannels.Append(KStereo)); -00739 } -00740 -00741 // set maximum clip size -00742 void CMMFRawFormatWrite::SetMaximumClipSize(TInt aBytes) -00743 { -00744 iMaximumClipSize = aBytes; -00745 } -00746 -00747 // get the supported codecs -00748 void CMMFRawFormatWrite::GetSupportedDataTypesL(TMediaId aMediaId, RArray<TFourCC>& aDataTypes) -00749 { -00750 if (aMediaId.iMediaType != KUidMediaTypeAudio) -00751 User::Leave(KErrNotSupported); -00752 aDataTypes.Reset(); -00753 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM16)); -00754 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCM16B)); -00755 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodePCMU16)); -00756 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeIMAD)); -00757 User::LeaveIfError(aDataTypes.Append(KMMFFourCCCodeIMAS)); -00758 } -00759 -00760 -00761 // __________________________________________________________________________ -00762 // Exported proxy for instantiation method resolution -00763 // Define the interface UIDs -00764 -00765 const TImplementationProxy ImplementationTable[] = -00766 { -00767 IMPLEMENTATION_PROXY_ENTRY(KRawDecoder, CMMFRawFormatRead::NewL), -00768 IMPLEMENTATION_PROXY_ENTRY(KRawEncoder, CMMFRawFormatWrite::NewL) -00769 }; -00770 -00771 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) -00772 { -00773 aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); -00774 -00775 return ImplementationTable; -00776 } -