internetradio2.0/mediaenginesrc/irmp3player.cpp
changeset 0 09774dfdd46b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internetradio2.0/mediaenginesrc/irmp3player.cpp	Mon Apr 19 14:01:53 2010 +0300
@@ -0,0 +1,1142 @@
+/*
+* 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;	
+	}