examples/Multimedia/MmfExFormatPlugin/mmfrawformat.cpp

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         }

Generated by  doxygen 1.6.2