--- a/internetradio2.0/mediaenginesrc/irmp3player.cpp Tue Jul 06 14:07:20 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1142 +0,0 @@
-/*
-* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: ?Description
-*
-*/
-
-
-#include <AudioPreference.h>
-
-#include "irbuffercontainer.h"
-#include "irctrlcmdobserver.h"
-#include "irdebug.h"
-#include "irmediaenginebuffer.h"
-#include "irmp3player.h"
-#include "irmp3playerlocal.h"
-
-#ifdef __WINS__
-#include "irtestingaudioplayer.h"
-#endif //__WINS__
-
-
-
-// Constants
-const TInt KZero = 0;
-const TInt KOne = 1;
-const TInt KTwo = 2;
-const TInt KThree = 3;
-
-const TInt KTwentyFour = 24;
-const TInt KSixteen = 16;
-const TInt KEight = 8;
-const TInt KSamplesPerFrame1 = 576;
-const TInt KSamplesPerFrame2 = 1152;
-const TInt KOneFourFour = 144;
-const TInt KThousand = 1000;
-
-// ============================ MEMBER FUNCTIONS ===============================
-
-// ---------------------------------------------------------------------------
-// Function : NewL
-// function returns an instance of CIRMP3Player
-// Two phase constructor
-// ---------------------------------------------------------------------------
-//
-CIRMP3Player* CIRMP3Player::NewL()
- {
- IRLOG_DEBUG( "CIRMP3Player::NewL" );
- CIRMP3Player* self = CIRMP3Player::NewLC();
- CleanupStack::Pop(self);
- IRLOG_DEBUG( "CIRMP3Player::NewL - Exiting." );
- return self;
- }
-
-// ---------------------------------------------------------------------------
-// Function : NewLC
-// function creates an instance of CIRMP3Player
-// Two phase constructor
-// ---------------------------------------------------------------------------
-//
-CIRMP3Player* CIRMP3Player::NewLC()
- {
- IRLOG_DEBUG( "CIRMP3Player::NewLC" );
- CIRMP3Player* self = new (ELeave) CIRMP3Player;
- CleanupStack::PushL(self);
- self->ConstructL();
- IRLOG_DEBUG( "CIRMP3Player::NewLC - Exiting." );
- return self;
- }
-
-// ---------------------------------------------------------------------------
-// Function : ~CIRMP3Player
-// Default Destructor
-// ---------------------------------------------------------------------------
-//
-CIRMP3Player::~CIRMP3Player()
- {
- IRLOG_DEBUG( "CIRMP3Player::~CIRMP3Player" );
- //delete the instance of the player
- delete iAudioPlayer;
-
-#ifdef __WINS__
- if(iTestingAudioPlayer)
- {
- iTestingAudioPlayer->Close();
- delete iTestingAudioPlayer;
- iTestingAudioPlayer = NULL;
- }
- CActiveScheduler::Delete(iTestingAudioPlayer);
-
-#endif //__WINS__
-
- while(!iSinkBufferQ.IsEmpty())
- {
- //Deleting all the entries in sink buffers queue
- iTempBufferHolder = iSinkBufferQ.First();
- iSinkBufferQ.Remove(*iTempBufferHolder);
- delete iTempBufferHolder;
- }
- while(!iSourceBufferQ.IsEmpty())
- {
- //deleting all the entries in source buffers queue
- iTempBufferHolder = iSourceBufferQ.First();
- iSourceBufferQ.Remove(*iTempBufferHolder);
- delete iTempBufferHolder;
- }
- IRLOG_DEBUG( "CIRMP3Player::~CIRMP3Player - Exiting." );
- }
- //Function for Play control
-
-// ---------------------------------------------------------------------------
-// Function : Play
-// function to which intiate the player
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::Play()
- {
- IRLOG_DEBUG( "CIRMP3Player::Play" );
- //! then we have to stop it then restart the play from begining
- if ( EPlaying == iState )
- {
- //internally stopped before playing so no need of sending
- //stop status
- iSkipPlayCompleted = ETrue;
-
-#ifdef __WINS__
- iTestingAudioPlayer->Stop();
-#else
- iAudioPlayer->Stop();
-#endif //__WINS__
-
- iSkipPlayCompleted = EFalse;
- }
- iState = ENotReady;
- iStopState = EFalse;
- iBufferPercentage = KZeroPercentage;
-
- //note : using TRAP_IGNORE to suppress a codescanner warning
- //"Ignoring the return value from Open() functions"
- //this cannot be checked as this symbian API returns void
-#ifdef __WINS__
- TRAP_IGNORE ( iTestingAudioPlayer->Open() );
-#else
- //opening the current player component
- TRAP_IGNORE ( iAudioPlayer->Open(&iSettings) );
-#endif //__WINS__
- iChannel->SentRequest(EPlayingState,KErrNone);
- IRLOG_DEBUG( "CIRMP3Player::Play - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// Function : Stop
-// function to which stop the player
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::Stop()
- {
- IRLOG_DEBUG( "CIRMP3Player::Stop" );
- //If the current state is playing
- if ( EPlaying == iState )
- {
-#ifdef __WINS__
- iTestingAudioPlayer->Stop();
-#else
- iAudioPlayer->Stop();
-#endif //__WINS__
-
- }
- else
- {
- IRRDEBUG2("CIRMP3Player::Stop EStoppedPlaying", KNullDesC);
- //sending the updated status as stopped
- iChannel->SentRequest( EStoppedPlaying, KErrNone );
- }
- iState = EReadyToPlay;
- iStopState = ETrue;
- IRLOG_DEBUG( "CIRMP3Player::Stop - Exiting." );
- }
-
- //Functions for Volume Control
-
-// ---------------------------------------------------------------------------
-// Function : SetVolume
-// function to set the volume
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::SetVolume(TInt aVolume )
- {
- IRLOG_DEBUG( "CIRMP3Player::SetVolume" );
- //! If volume should be less than maximum value and greater than or equal to zero then set the volume
- if( KZeroVolume <= aVolume && iAudioPlayer->MaxVolume() >= aVolume )
- {
- iAudioPlayer->SetVolume( aVolume );
- iConfig.iVolume = iCurrentVolume = aVolume;
- }
- IRLOG_DEBUG( "CIRMP3Player::SetVolume - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// Function : MaxVolume
-// function to returns the maximum volume
-// ---------------------------------------------------------------------------
-//
-TInt CIRMP3Player::MaxVolume() const
- {
- IRLOG_DEBUG( "CIRMP3Player::MaxVolume" );
- return iAudioPlayer->MaxVolume();
- }
-
-// ---------------------------------------------------------------------------
-// Function : Volume
-// function to returns the volume, integer level of volume is the Output
-// ---------------------------------------------------------------------------
-//
-TInt CIRMP3Player::Volume() const
- {
- IRLOG_DEBUG( "CIRMP3Player::Volume" );
- return iAudioPlayer->Volume();
- }
-
- //Intialization of Codec Settings
-
-// ---------------------------------------------------------------------------
-// Function: Intialize
-// Set the codec type and sampling rate channel of stream
-// This is set to initial settings which is required to start the player
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::Intialize(TConfig& aConfig,TUint8* aInitParams,
- CIRCtrlCmdObserver* aChannel)
- {
- IRLOG_DEBUG( "CIRMP3Player::Intialize" );
- iInputBufferPtr = reinterpret_cast<TUint8*> (aInitParams); //instance of buffer
- iConfig = aConfig; //! Set all the configuration information like volume
- iPlayBufferSize = iConfig.iPlayBufferSize;
- iInputBufferSize = iConfig.iPlayBufferCount*iPlayBufferSize;
- iBufferOffset = iPlayBufferSize;
- iDataType.Set(KMMFFourCCCodeMP3); //! Set the data type as MP3
- iChannel = reinterpret_cast<CIRCtrlCmdObserver*> (aChannel);
- TRAPD(err,CreateBufferL()); // allocates buffer to the queue
- if( err )
- {
- IRRDEBUG2("CIRMP3Player::Intialize - EError", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- return;
- }
- iChannel->SentRequest(EPlayerChanged,KErrNone); //creates an instance of the player
- IRLOG_DEBUG( "CIRMP3Player::Intialize - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// Function: StopPlayerBuffering
-// Function is used to stop buffering
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::StopPlayerBuffering()
- {
- IRLOG_DEBUG( "CIRMP3Player::StopPlayerBuffering" );
- //stops the player from buffering
- iStopPlayerBuffering = ETrue;
- }
-
-// ---------------------------------------------------------------------------
-// Function: BufferFilled
-// Function which is called when network gets the buffer filled with data
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::BufferFilled()
- {
- IRLOG_DEBUG( "CIRMP3Player::BufferFilled" );
- if( !iNewPlayer )
- {
- if( !iSourceBufferQ.IsEmpty() )
- {
- //! Initially all unfilled buffers are in source buffer Queue
- //! Once the buffer in the source buffer queue is filled it is moved to queue of buffer
- //! to the sink
- iTempBufferHolder = iSourceBufferQ.First();
- iSourceBufferQ.Remove(*iTempBufferHolder);
- iSinkBufferQ.AddLast(*iTempBufferHolder);
- }
- }
-
- if( iFirstTime )
- {
- if( !iNewPlayer )
- {
- // During rebuffering only
- if( !iSourceBufferQ.IsEmpty() )
- {
- //if source buffer is empty
- //first buffer of source buffer is taken and refilled
- iTempBufferHolder = iSourceBufferQ.First();
- iTempbuffer = iTempBufferHolder->Des();
- iInputBuffer.Set(iTempbuffer,iPlayBufferSize,iPlayBufferSize);
- if( iStopState )
- {
- IRLOG_DEBUG( "CIRMP3Player::BufferFilled - Exiting (1)." );
- return;
- }
- if( !iStopPlayerBuffering )
- {
- //Calls the fill the buffer for next subsequent times
- //until the source buffer queue is empty
- iChannel->FilltheBuffer(iInputBuffer);
- }
- else
- {
- IRLOG_DEBUG( "CIRMP3Player::BufferFilled - Exiting (2)." );
- //if stopPlayerBuffering is set it has return without buffering
- return;
- }
- }
- else
- {
- //once it is rebuffered it has trigger play
- //it has to indicate that rebuffering has completed for client
-
- TInt err( KErrNone );
- if( !iReBuffering )
- {
- GetMP3AudioProperties();
- //Sets the audio properties of the player like sampling rate and channel
- TRAP(err, iAudioPlayer->SetAudioPropertiesL(iSettings.iSampleRate,
- iSettings.iChannels));
- if ( err )
- {
- IRRDEBUG2("CIRMP3Player::BufferFilled - EError", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- IRLOG_DEBUG( "CIRMP3Player::BufferFilled - Exiting (3)." );
- return;
- }
- }
- iReBuffering = EFalse;
- //buffer reached 100% headers are decoded ready to play
- iBufferPercentage = K100Percentage;
- iChannel->SentRequest( EBufferFillStop, iBufferPercentage );
-
- if( !iSinkBufferQ.IsEmpty() )
- {
- iTempBufferHolder = iSinkBufferQ.First();
- }
- iTempbuffer = iTempBufferHolder->Des();
-
- //Take first source buffer queue to be filled
- iInput.Set(iTempbuffer,iPlayBufferSize,iPlayBufferSize);
- iFirstTime = EFalse;
- iState = EPlaying;
- if( !iStopState )
- {
-
-#ifdef __WINS__
- iTestingAudioPlayer->Write();
-#else
- //writing to mmp based buffer to trigger play
- TRAP(err,iAudioPlayer->WriteL(iInput));
-
- if( err )
- {
- //error condition
- IRRDEBUG2("CIRMP3Player::BufferFilled - EError1", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- IRLOG_DEBUG( "CIRMP3Player::BufferFilled - Exiting (4)." );
- return;
- }
-#endif //__WINS__
- }
- //! Calls the play for the first time after rebuffering
-
- }
- }
- else
- {
- //First time when the player is created
- TInt err( KErrNone );
- GetMP3AudioProperties();
-
- //! Sets the audio properties of the player like sampling rate and channel
- //Sets the audio properties of the player like sampling rate and channel
- TRAP(err, iAudioPlayer->SetAudioPropertiesL(iSettings.iSampleRate,
- iSettings.iChannels));
- if ( err )
- {
- IRRDEBUG2("CIRMP3Player::BufferFilled - EError2", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- IRLOG_DEBUG( "CIRMP3Player::BufferFilled - Exiting (5)." );
- return;
- }
- //buffer percentage is 100%
- iBufferPercentage = K100Percentage;
- //indicating it has rebuffered
- iChannel->SentRequest( EBufferFadeInReady, iBufferPercentage );
-
- if( !iSinkBufferQ.IsEmpty() )
- {
- iTempBufferHolder = iSinkBufferQ.First();
- }
- iTempbuffer = iTempBufferHolder->Des();
-
- //first buffer of sink is taken and played
- iInput.Set(iTempbuffer,iPlayBufferSize,iPlayBufferSize);
- iNewPlayer = EFalse;
- iFirstTime = EFalse;
- iState = EPlaying;
-
- //Calls the play for the first time
- if( !iStopState )
- {
-#ifdef __WINS__
- iTestingAudioPlayer->Write();
-#else
- //writing to MMF buffers
- TRAP(err,iAudioPlayer->WriteL(iInput));
- if( err )
- {
- IRRDEBUG2("CIRMP3Player::BufferFilled - EError3", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- IRLOG_DEBUG( "CIRMP3Player::BufferFilled - Exiting (6)." );
- return;
- }
-#endif //__WINS__
- }
- }
- }
- IRLOG_DEBUG( "CIRMP3Player::BufferFilled - Exiting (7)." );
- }
-
-// ---------------------------------------------------------------------------
-// Function: CIRMP3Player
-// This function is the default constructor
-// ---------------------------------------------------------------------------
-//
-CIRMP3Player::CIRMP3Player() : iInputBuffer(NULL,0,0), iInput(NULL,0,0)
- {
- IRLOG_DEBUG( "CIRMP3Player::CIRMP3Player" );
- }
-
-// ---------------------------------------------------------------------------
-// Function: ConstructL
-// Two phase constructor is used to intialize data members
-// Function can leave if CMdaAudioOutputStream::NewL leaves
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::ConstructL()
- {
- IRLOG_DEBUG( "CIRMP3Player::ConstructL" );
-
- iAudioPlayer = CMdaAudioOutputStream::NewL(*this,KAudioPriorityRealOnePlayer,
- (TMdaPriorityPreference)KAudioPrefRealOneStreaming );
-
- //creates an instance of the player
-
-#ifdef __WINS__
- iTestingAudioPlayer = CIRTestingAudioPlayer::NewL(*this);
- CActiveScheduler::Add(iTestingAudioPlayer);
-#endif //__WINS__
-
- TInt f_off = _FOFF(CIRBufferContainer,iLink); //for the buffer queue which is maintained
-
- iSinkBufferQ.SetOffset(f_off); //It is Queue of buffer used by media Sink
- iSourceBufferQ.SetOffset(f_off); // Source of buffer which is ready to fill
-
- iNewPlayer = ETrue; //indicates that this a newly created player
- iStopPlayerBuffering = EFalse; //indicates whether to stop buffering
- iState = ENotReady; //current state not ready
- iNeedReBuffering = EFalse;//if rebuffering is required this is to set true
- iStopState = EFalse; //
- IRLOG_DEBUG( "CIRMP3Player::ConstructL - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// Function: CreateBufferL
-// Created buffers in sink buffer queue and allocates memory to sink buffer queues
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::CreateBufferL()
- {
- IRLOG_DEBUG( "CIRMP3Player::CreatebufferL" );
- TUint8* bufferaddress = iInputBufferPtr;
- //! source buffers not created since initially all buffers are filled with data and is ready to play
- //! Created buffers in sink buffer queue and allocates memory to sink buffer queues
- for(TInt buffercount = 0; buffercount < KIRInputBufferCount; buffercount++)
- {
- iTempBufferHolder = CIRBufferContainer::NewL(bufferaddress,
- iPlayBufferSize);
- iSinkBufferQ.AddLast(*iTempBufferHolder);
- bufferaddress += iBufferOffset;
- }
- IRLOG_DEBUG( "CIRMP3Player::CreatebufferL - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// Function: ReCreateBufferL
-// Recreates buffers of source queue
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::ReCreateBufferL()
- {
- IRLOG_DEBUG( "CIRMP3Player::ReCreateBufferL " );
- while(!iSinkBufferQ.IsEmpty())
- {
- //Deleting all the entries in sink buffers queue
- iTempBufferHolder = iSinkBufferQ.First();
- iSinkBufferQ.Remove(*iTempBufferHolder);
- delete iTempBufferHolder;
- iTempBufferHolder = NULL;
- }
- while(!iSourceBufferQ.IsEmpty())
- {
- //deleting all the entries in source buffers queue
- iTempBufferHolder = iSourceBufferQ.First();
- iSourceBufferQ.Remove(*iTempBufferHolder);
- delete iTempBufferHolder;
- iTempBufferHolder = NULL;
- }
- TUint8* bufferaddress = iInputBufferPtr;
- //reallocates the buffer to source buffer queue
- for(TInt buffercount = 0; buffercount < KIRInputBufferCount; buffercount++)
- {
- iTempBufferHolder = CIRBufferContainer::NewL(bufferaddress,
- iPlayBufferSize);
- iSourceBufferQ.AddLast(*iTempBufferHolder);
- bufferaddress += iBufferOffset;
- }
- IRLOG_DEBUG( "CIRMP3Player::ReCreateBufferL - Exiting." );
- }
-
-
-// ---------------------------------------------------------------------------
-// Function: GetMP3AudioProperties
-// extract all the information required to start the play from the stream
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::GetMP3AudioProperties()
- {
- IRLOG_DEBUG( "CIRMP3Player::GetMP3AudioProperties" );
- //Decoding MP3 header
- DoFindnDecodeMP3Header();
-
- //! Sets the sampling rate and channel information to data members
- switch(iAudioInfo.iSamplingRate)
- {
- case EMp3SamplingFreq8000: //sampling frequency 8000
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate8000Hz;
- }
- break;
- case EMp3SamplingFreq11025: //sampling frequency 11025
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate11025Hz;
- }
- break;
- case EMp3SamplingFreq12000: //sampling frequency 12000
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate12000Hz;
- }
- break;
- case EMp3SamplingFreq16000: //sampling frequency 16000
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate16000Hz;
- }
- break;
- case EMp3SamplingFreq22050: //sampling frequency 22050
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate22050Hz;
- }
- break;
- case EMp3SamplingFreq24000: //sampling frequency 24000
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate24000Hz;
- }
- break;
- case EMp3SamplingFreq32000: //sampling frequency 32000
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate32000Hz;
- }
- break;
- case EMp3SamplingFreq44100: //sampling frequency 44100
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate44100Hz;
- }
- break;
- case EMp3SamplingFreq48000: //sampling frequency 48000
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate48000Hz;
- }
- break;
- default: //default sampling frequency 22050
- {
- iSettings.iSampleRate = TMdaAudioDataSettings::ESampleRate22050Hz;
- }
- break;
- }
- //sets the channel information
- if( KMp3ChannelMono == iAudioInfo.iChannel ) //0 indicates mono
- {
- iSettings.iChannels = TMdaAudioDataSettings::EChannelsMono;
- }
- else //else 1 it indicates it is stereo
- {
- iSettings.iChannels = TMdaAudioDataSettings::EChannelsStereo;
- }
- IRLOG_DEBUG( "CIRMP3Player::GetMP3AudioProperties - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// Function: DoFindnDecodeMP3Header
-// Function is used to find the mp3 header and decode the mp3 header
-// This function do have hard coded values and these value remains as such
-// as long as the standard remains, so used as such
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::DoFindnDecodeMP3Header()
- {
- IRLOG_DEBUG( "CIRMP3Player::DoFindnDecodeMP3Header" );
- //first buffer is discarded
- TUint8* input = iInputBufferPtr;
- //end ptr is calculated
- TUint8* endptr = iInputBufferPtr + iInputBufferSize;
-
- //holds the 4 bytes of data
- TUint value = 0; //value zero is intialized
- TBool headerfound = EFalse;
-
- //value are to hardcoded as this is the standard way of implement
- // the MP3 header decoding
- while( input < endptr && !headerfound )
- {
- //stepsuccess indicates the success in each step or stage of header decoding,
- //incase of failure we will not go for next step
- TBool stepsuccess = EFalse;
- //initially no header is found
- //assign the value to zero initially for clearing the value
- //then assign next 32 bits of data to value
- value = 0; //value is cleared
- value |= input[0]<<KTwentyFour; //first 8 bit is shift 24bits copied (or) to "value"
- value |= input[1]<<KSixteen; //second 8 bit is shift 24bits copied (or) to "value"
- value |= input[2]<<KEight;//third 8 bit is shift 24bits copied (or) to "value"
- value |= input[KThree];//last 8 bit is shift 24bits copied (or) to "value"
-
- // sync bytes found
- // for performance reasons check already that it is not data within an empty frame (all bits set)
- // therefore check wether the bits for bitrate are all set -> means that this is no header
- if ( (input[0] == 0xFF) && ( ( input[1] & 0xE0 ) == 0xE0 ) && ( ( input[2] & 0xF0 ) != 0xF0 ) )
- {
- //header is found
- //first level of header decoding is success, so stepsuccess = ETrue
- stepsuccess = ETrue;
- //version information is stored in 2 bits starting from 19th bit of header
- //two get only 2bits we are doing an AND operation with 0b011 (0x03)
- TInt index = (value >> 19) & 0x03;
- //! Gets the version information of MPEG
-
- TInt version = index; //MPEG 2.5 00
- //reservered 01
- //MPEG 2 10
- //MPEG 1 11
- //if header information is 0x01
- iAudioInfo.iVersion = version;
- if( 0x01 == iAudioInfo.iVersion )
- {
- //bit pattern 0x01 indicates that version is reserved
- // and is considered as incorrect header information
- stepsuccess = EFalse;
- }
-
- else
- {
- //bit pattern 0x00 indictes MPEG version is 2.5
- //bit pattern 0x10 indictes MPEG version is 2
- //MPEG 2.5 (0x00) and MPEG 2 (0x10) version
- if( (0x00 == iAudioInfo.iVersion) ||
- (0x02 == iAudioInfo.iVersion) )
- {
- //576 samples per frame
- //there is 576 samples per frame
- iAudioInfo.iSamplesPerFrame = KSamplesPerFrame1;
- }
- else
- {
- //MPEG 1 version (0x11)
- //for MPEG 1 there is 1152 samples per frame
- iAudioInfo.iSamplesPerFrame = KSamplesPerFrame2;
- }
- }
-
- if( stepsuccess )
- {
- //layer information from the header is obtained from 2 bits starting 17th Bit
- //information is extracted to index.
- index = ( value >> 17 ) & 0x03;
- if( 0x01 != index ) //Layer 3 check if its layer 2 to layer 1
- { //we will consider the header is not proper
- stepsuccess = EFalse;
- }
- else
- {
- iAudioInfo.iLayer = 2; //Layer 3
- //for selection bitrate we have need a combination of MPEG version, layer information
- //and selection bits. the selection bits starts from 12th bits of mp3 header
- //the selection byte is extracted into the index
- index = (value >> 12) & 0x000F;
- TInt versionindex = 0;
- if( 0x11 == version )
- {
- //index of the array is 0
- versionindex = 0;
- }
- else
- {
- //index of array is 1
- versionindex = 1;
- }
- //getting the bit rate
- iAudioInfo.iBitRate =
- KBitRate[versionindex][iAudioInfo.iLayer][index];
- if( iAudioInfo.iBitRate == 0 ) //since bit rate is zero we consider as header is not proper
- {
- stepsuccess = EFalse;
- }
- }
- }
-
- if( stepsuccess )
- {
- //sampling rate is obtained by a combination of MPEG version and
- //selection bits. There are 2 selection bits starting from 10th bit
- //and is extracted (AND with 0x03) from header and stored in index
- index = ( value >> 10 ) & 0x03;
-
- //! Gets the sampling frequency
- iAudioInfo.iSamplingRate =
- KMP3SamplingRate[iAudioInfo.iVersion][index];
- if( 0 == iAudioInfo.iSamplingRate ) //if sampling rate is 0 it is invalidated
- {
- stepsuccess = EFalse;
- }
- //padding information is obtained from 9th bit of mp3 header
- iAudioInfo.iPadding = (value >> 9) & 0x01; //padding
-
- //the information for selection of channel is stored in 2bits starting from 6th bit of
- //mp3 header and is decoded and kept in index for selection of channel
- index = ( value >> 6 ) & 0x0003;
- iAudioInfo.iChannel = KChannelInfo[index]; //0 for mono and 1 for stereo
-
- //framesize = (144 * bitrate)/(padding + sampling rate)
- if( stepsuccess )
- {//multiplication of 1000 is to convert kbs to bs
- iAudioInfo.iFrameSize = (KOneFourFour * iAudioInfo.iBitRate * KThousand)
- /(iAudioInfo.iPadding + iAudioInfo.iSamplingRate);
- }
- //cross checking the header with next header
- //both sampling frequency matches the function will return ETrue else EFalse
- if( !CrossCheckHeader(input) )
- {
- stepsuccess = EFalse;
- }
- }
- if( stepsuccess )
- {
- //header is found
- headerfound = ETrue;
- }
- else
- {
- //header is not found
- input++;
- }
- } // sync bytes found
- else
- {
- //header sync bits doesn't match
- input++;
- }
- }
- IRLOG_DEBUG( "CIRMP3Player::DoFindnDecodeMP3Header - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// Function: CrossCheckHeader
-// Function is cross checks sampling rate
-// This function do have hard coded values and these value remains as such
-// as long as the standard remains, so used as such
-// ---------------------------------------------------------------------------
-//
-TBool CIRMP3Player::CrossCheckHeader(TUint8* aInput)
- {
- IRLOG_DEBUG( "CIRMP3Player::CrossCheckHeader" );
- if( !aInput )
- {
- return EFalse;
- }
- //next header is to taken
- TUint8* input = aInput + iAudioInfo.iSamplesPerFrame;
- TUint8* endptr = iInputBufferPtr + iInputBufferSize
- - KMp3FrameHeaderSize;
- TUint32 samplingrate = 0;
- TBool headerfound = EFalse;
-
- TUint value = 0;
- TInt version = 0;
- TUint channel = 0;
- TUint layer = 0;
- while( input < endptr && !headerfound )
- {
- //header is not found
- TInt successheader = EFalse;
- //assign the value to zero initially for clearing the value
- //then assign next 32 bits of data to value
- value = 0;
- value |= input[KZero]<<KTwentyFour;
- value |= input[KOne]<<KSixteen;
- value |= input[KTwo]<<KEight;
- value |= input[KThree];
-
- // sync bytes found
- // for performance reasons check already that it is not data within an empty frame (all bits set)
- // therefore check wether the bits for bitrate are all set -> means that this is no header
- if ( (input[0] == 0xFF) && ( ( input[1] & 0xE0 ) == 0xE0 ) && ( ( input[2] & 0xF0 ) != 0xF0 ) )
- {
- //header is obtained
- successheader = ETrue;
- //version information is stored in 2 bits starting from 19th bit of header
- //two get only 2bits we are doing an AND operation with 0b011 (0x03)
- TInt index = (value >> 19) & 0x03;
- //! Gets the version information of MPEG
-
- version = index; //MPEG 2.5 00
- //reservered 01
- //MPEG 2 10
- //MPEG 1 11
- //if header information is 0x01
- if( 0x01 == version ) //indicates that version is reserved and is considered
- { //as incorrect header information
- //header is not valid
- successheader = EFalse;
- input++;
- headerfound = EFalse;
- }
-
- index = ( value >> 6 ) & 0x0003;
- channel = KChannelInfo[index]; //0 for mono and 1 for stereo
-
- index = ( value >> 17 ) & 0x03;
- if ( index == 0x01 )
- layer = 2;
-
- if( successheader )
- {
- //sampling rate is obtained by a combination of MPEG version and
- //selection bits. There are 2 selection bits starting from 10th bit
- //and is extracted (AND with 0x03) from header and stored in index
- index = (value >> 10) & 0x03;
- //! Gets the sampling frequency
- samplingrate = KMP3SamplingRate[version][index];
- if( 0 == samplingrate ) //if sampling rate is 0 it is invalidated
- {
- //header is not valid
- input++;
- }
- else
- {
- //header is obtained
- headerfound = ETrue;
- }
- }
- } // sync bytes found
- else
- {
- //header is not valid
- input++;
- }
- }
- //if sampling rate match with one we initially decoded we return ETrue else EFalse
- // version change never possible
- // layer change never possible
- // sampling rate change never possible
- // from mono to stereo never possible
- if ( iAudioInfo.iSamplingRate == samplingrate && iAudioInfo.iVersion == version
- && iAudioInfo.iChannel == channel
- && iAudioInfo.iLayer == layer )
- {
- IRLOG_DEBUG( "CIRMP3Player::CrossCheckHeader - Exiting (1)." );
- return ETrue;
- }
- else
- {
- IRLOG_DEBUG( "CIRMP3Player::CrossCheckHeader - Exiting (2).");
- return EFalse;
- }
- }
-
-
- //Call back functions
-
-// ---------------------------------------------------------------------------
-// Function: MaoscBufferCopied
-// call back to be implemented for using CMdaAudioOutputStream
-// Call as callback from the CMdaAudioOutputStream::WriteL
-// after frame work has copied stream to a buffer
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
- {
- IRLOG_DEBUG( "CIRMP3Player::MaoscBufferCopied" );
- if( aError )
- {
- IRLOG_ERROR2( "CIRMP3Player::MaoscBufferCopied - Error in buffering (%d)", aError );
- //error in playing then return
- IRRDEBUG2("CIRMP3Player::MaoscBufferCopied - EError", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- return;
- }
- else
- {
- if ( iCurrentVolume < iConfig.iVolume )
- {
- iCurrentVolume = iConfig.iVolume;
- IRLOG_INFO2( "CIRMP3Player::MaoscBufferCopied - Setting volume to %d", iCurrentVolume );
- iAudioPlayer->SetVolume( iCurrentVolume );
- }
- if( iSinkBufferQ.IsEmpty() )
- {
- //previously played buffer is empty
- //should never happen
- IRRDEBUG2("CIRMP3Player::MaoscBufferCopied - EError1", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- return;
- }
- else
- {
- //previously played buffer is removed
- iTempBufferHolder = iSinkBufferQ.First();
- //played buffer is removed from sink queue
- iSinkBufferQ.Remove(*iTempBufferHolder);
- //removed buffer is appended to end of source queue
- iSourceBufferQ.AddLast(*iTempBufferHolder);
-
- //the first buffer of the source buffer is given to refill
- if( !iSourceBufferQ.IsEmpty() )
- {
- iTempBufferHolder = iSourceBufferQ.First();
- }
- //if stop is called during rebuffering
- if( !iStopPlayerBuffering )
- {
- // if player is stopped it has to stop buffering
- iTempbuffer = iTempBufferHolder->Des();
- iInputBuffer.Set(iTempbuffer,iPlayBufferSize,iPlayBufferSize);
- iChannel->FilltheBuffer(iInputBuffer);
- }
- //if stop state we have to return
- if( iStopState )
- {
- IRLOG_DEBUG( "CIRMP3Player::MaoscBufferCopied - Exiting (1)." );
- //should continue this loop unless play is triggered
- return;
- }
-
- //plays buffer if there buffer to play
- if( !iSinkBufferQ.IsEmpty() )
- {
- //sink Buffer queue has buffer to play
- iTempBufferHolder = iSinkBufferQ.First();
- iTempbuffer = iTempBufferHolder->Des();
-
- iInput.Set(iTempbuffer,iPlayBufferSize,iPlayBufferSize);
-
-#ifdef __WINS__
- iTestingAudioPlayer->Write();
-#else
- //writing to MMF buffer
- TRAPD(err,iAudioPlayer->WriteL(iInput));
-
- if( err )
- {
- IRRDEBUG2("CIRMP3Player::MaoscBufferCopied - EError2", KNullDesC);
- //if playing failed
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- return;
- }
-#endif //__WINS__
- }
- else
- {
- //rebuffering
- if( !iStopPlayerBuffering )
- {
- //if sink buffer is empty
- //we have to rebuffer
- iReBuffering = ETrue;
- Play();
- }
- }
- }
- }
- IRLOG_DEBUG( "CIRMP3Player::MaoscBufferCopied - Exiting (2)." );
- }
-
-// ---------------------------------------------------------------------------
-// Function: MaoscPlayComplete
-// call back to implement for using CMdaAudioOutputStream
-// Call as callback from the CMdaAudioOutputStream::WriteL
-// after play is completed
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::MaoscPlayComplete(TInt aError)
- {
- IRLOG_DEBUG( "CIRMP3Player::MaoscPlayComplete" );
- if( !iSkipPlayCompleted )
- {
- IRRDEBUG2("CIRMP3Player::MaoscPlayComplete EStoppedPlaying", KNullDesC);
-
- //sending the stop status
- iChannel->SentRequest( EStoppedPlaying, aError );
- }
- IRLOG_DEBUG( "CIRMP3Player::MaoscPlayComplete - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// Function: MaoscOpenComplete
-// call back implemented for using CMdaAudioOutputStream
-// Call as callback from the CMdaAudioOutputStream::Open
-// ---------------------------------------------------------------------------
-//
-void CIRMP3Player::MaoscOpenComplete( TInt aError )
- {
- IRLOG_DEBUG( "CIRMP3Player::MaoscOpenComplete" );
- if( aError )
- {
- IRLOG_ERROR( "CIRMP3Player::MaoscOpenComplete - error end" );
- IRRDEBUG2("CIRMP3Player::MaoscOpenComplete - EError", KNullDesC);
- //open failed
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- return;
- }
- else
- {
- TInt err( KErrNone );
-
-#ifdef __WINS__
- err=0;
-#else
- //Setting the data type of player as MP3
- TRAP(err, iAudioPlayer->SetDataTypeL(iDataType.FourCC())); //set type the data as MP3 type
-
- if ( err )
- {
- if ( KErrNotSupported == err )
- {
- IRRDEBUG2("CIRMP3Player::MaoscOpenComplete - EError1", KNullDesC);
- iChannel->SentRequest( EError, KErrNotSupported );
- }
- else
- {
- IRRDEBUG2("CIRMP3Player::MaoscOpenComplete - EError2", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- }
- return;
- }
-#endif //__WINS__
-
-
- //during rebuffering current volume is to be taken
- if( iNeedReBuffering )
- {
- iConfig.iVolume = iChannel->FetchVolume();
- }
-
- //Computes the current volume and sets the volume
- TInt index = iAudioPlayer->MaxVolume()/KNoVolumeLevels;
- iConfig.iVolume = iConfig.iVolume * index;
- //if the given volume is greater than max volume it made to maximum volume
- //this may happen if the first time volume exceeds the limits
- if( iConfig.iVolume > iAudioPlayer->MaxVolume() )
- {
- iConfig.iVolume = iAudioPlayer->MaxVolume();
- }
- //else if the given volume is less than zero it made to zero
- //this may happen if the first time volume goes below the limits
- if( iConfig.iVolume < KZeroVolume )
- {
- iConfig.iVolume = KZeroVolume;
- }
-
- // The actual setting of the volume is delayed to MaoscBufferCopied method.
- // This was due to some error in N91 sound subsystem, which caused the
- // volume not to adjust in some cases.
- iCurrentVolume = 0;
- iAudioPlayer->SetVolume( iCurrentVolume );
-
- iFirstTime = ETrue;
- iNeedReBuffering = ETrue;
-
- if( !iNewPlayer )
- {
- //player is rebuffering or stop and played
- TRAP(err,ReCreateBufferL());
- if ( err )
- {
- IRRDEBUG2("CIRMP3Player::MaoscOpenComplete - EError3", KNullDesC);
- iChannel->SentRequest( EError, KIRCtrlCmdGeneralPlayerError );
- return;
- }
-
- //initiates the refilling of buffers
- iTempBufferHolder = iSourceBufferQ.First();
- iTempbuffer = iTempBufferHolder->Des();
- iInputBuffer.Set(iTempbuffer,iPlayBufferSize,iPlayBufferSize);
- iChannel->SentRequest( EBufferFillStart, iBufferPercentage );
- //Call FilltheBuffer for first time
- iChannel->FilltheBuffer(iInputBuffer); //start fill the data
- }
- else
- {
- //First time playing
- BufferFilled();
- }
- }
- IRLOG_DEBUG( "CIRMP3Player::MaoscOpenComplete - Exiting." );
- }
-
-// ---------------------------------------------------------------------------
-// CIRMP3Player::GetMediaClientInstance()
-// Returns the Audio Player Instance
-// ---------------------------------------------------------------------------
-//
-CMdaAudioOutputStream* CIRMP3Player::GetAudioPlayer()
- {
- IRLOG_DEBUG( "CIRMP3Player::GetMediaClientInstance " );
- return iAudioPlayer;
- }