diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/mmfrawformat_8cpp_source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/mmfrawformat_8cpp_source.html Tue Mar 30 16:16:55 2010 +0100 @@ -0,0 +1,792 @@ + + +
+ +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 } +