大体上思路是:媒体文件流化后,每播放一个缓冲的内容后,会回调MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
在这个函数里面再调NextBuffer()填充缓冲区。
1、定义类:
class CAudioPlayerEngine : public CBase,
public MMdaAudioPlayerCallback,
public MMdaAudioOutputStreamCallback
{
public:
//from MMdaAudioOutputStreamCallback
virtual void MaoscOpenComplete(TInt aError);
virtual void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer);
virtual void MaoscPlayComplete(TInt aError);
void OpenFileL();
void CloseFile();
private:
void ConstructL(CAudio3Engine* aEngine);
virtual ~CAudioPlayerEngine();
void NextBuffer();
void TBuf16ToTBuf8(const TDesC16 &aTbuf16, TDes8 &aTbuf8);
private:
RFs iSession;
TBuf8<KBufferSize*2> iBuffer;
RFs iSession_mp3;
TBuf16<KBufferSize> iBuffer16;
TInt iDecodeCount;//记录解码次数
TInt iFileError;
CMdaAudioOutputStream* iPlayerOutputStream;
CMP3DecodeEngine* iMP3DecodeEngine;
TMdaAudioDataSettings iStreamSettings;
};
2、关键部分的代码
void CAudioPlayerEngine::OpenFileL()
{
User::LeaveIfError(iSession_mp3.Connect());
iMP3DecodeEngine->OpenFile(iSession_mp3 , _L("c:\\play.mp3"));
iMP3DecodeEngine->SetResampleRate(16000);
iMP3DecodeEngine->DecodeStart();
iPlayerOutputStream->Open(&iStreamSettings);
}
void CAudioPlayerEngine::CloseFile()
{
iMP3DecodeEngine->DecodeStop();
iMP3DecodeEngine->CloseFile();
iSession_mp3.Close();
}
void CAudioPlayerEngine::ConstructL(CAudio3Engine* aEngine)
{
iDecodeCount = 0;
iMP3DecodeEngine = CMP3DecodeEngine::NewL();
iPlayerOutputStream=CMdaAudioOutputStream::NewL(*this);
CurVolumn=iPlayerOutputStream->MaxVolume()/2;
}
CAudioPlayerEngine::~CAudioPlayerEngine()
{
CloseFile();
if (iPlayerOutputStream)
{
delete iPlayerOutputStream;
iPlayerOutputStream=NULL;
}
if (iMP3DecodeEngine)
{
delete iMP3DecodeEngine;
iMP3DecodeEngine=NULL;
}
}
void CAudioPlayerEngine::NextBuffer()
{
iBuffer.Delete(0,iBuffer.Length());
iBuffer16.Delete(0,iBuffer16.Length());
if (iFileError==KErrNone)
{
if(iMP3DecodeEngine->DecodeOneFrame(iBuffer16)==-1) //解码一个桢
{
iPlayerOutputStream->Stop(); //音乐结束
return;
}
if(iBuffer16.Length()!=0)
{
iFileError=KErrNone;
iDecodeCount++;//记录桢数
}
else
{
iFileError=KErrEof;
}
//复制到原来的数组中
TBuf16ToTBuf8(iBuffer16,iBuffer);
TRAPD(err,iPlayerOutputStream->WriteL(iBuffer));
if (err!=KErrNone) Stop();
}
}
void CAudioPlayerEngine::MaoscOpenComplete(TInt aError)
{
if (aError==KErrNone)
{
iPlayerOutputStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate16000Hz,TMdaAudioDataSettings::EChannelsMono);
iPlayerOutputStream->SetVolume(CurVolumn);
iPlayerOutputStream->SetPriority(EPriorityMuchMore, EMdaPriorityPreferenceTimeAndQuality);
NextBuffer();
} else
{
EndPlay();
}
}
void CAudioPlayerEngine::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
{
if (aError == KErrNone)
{
NextBuffer();
}else
{
EndPlay();
}
}
void CAudioPlayerEngine::MaoscPlayComplete(TInt /*aError*/)
{
EndPlay();
}
void CAudioPlayerEngine::TBuf16ToTBuf8(const TDesC16 &aTbuf16, TDes8 &aTbuf8)
{
if(aTbuf16.Length()==0)
{
return;
}
TInt length = aTbuf16.Length()*2;
TPtrC ptr16(aTbuf16);
TPtrC8 ptr8((TText8*) ptr16.Ptr(),length);
TBuf8<1024> buf8(ptr8);
aTbuf8.Append(buf8);
}