examples/Multimedia/MmfExFormatPlugin/mmfrawformat.cpp

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

Generated by  doxygen 1.6.2