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

Generated by  doxygen 1.6.2