您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
10. SLAudioPlay音频播放完成并测试对MP4文件音视频播放~1
发布时间:2021-06-12 11:50:46编辑:雪饮阅读()
首先在cpp/ IAudioPlay.cpp中實現GetData方法用來讀幀數據。同時實現update用來更新緩衝隊列:
#include "XLog.h"
XData IAudioPlay::GetData()
{
XData d;
while(!isExit)
{
framesMutex.lock();
if(!frames.empty())
{
d = frames.front();
frames.pop_front();
framesMutex.unlock();
return d;
}
framesMutex.unlock();
XSleep(1);
}
return d;
}
void IAudioPlay::Update(XData data)
{
XLOGE("IAudioPlay::Update %d",data.size);
//压入缓冲队列
if(data.size<=0|| !data.data) return;
while(!isExit)
{
framesMutex.lock();
if(frames.size() > maxFrame)
{
framesMutex.unlock();
XSleep(1);
continue;
}
frames.push_back(data);
framesMutex.unlock();
break;
}
}
在cpp/ SLAudioPlay.cpp中具體實現SLAudioPlay的播放:
同樣的,對於cpp/ SLAudioPlay.h中要聲明SLAudioPlay:
那麽是這哈,最後運行效果
#define XPLAY_IAUDIOPLAY_H
#include <list>
#include "IObserver.h"
#include "XParameter.h"
class IAudioPlay: public IObserver
{
public:
//缓冲满后阻塞
virtual void Update(XData data);
//获取缓冲数据,如没有则阻塞
virtual XData GetData();
virtual bool StartPlay(XParameter out) = 0;
//最大缓冲
int maxFrame = 100;
protected:
std::list <XData> frames;
std::mutex framesMutex;
};
#endif //XPLAY_IAUDIOPLAY_H
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include "XLog.h"
static SLObjectItf engineSL = NULL;
static SLEngineItf eng = NULL;
static SLObjectItf mix = NULL;
static SLObjectItf player = NULL;
static SLPlayItf iplayer = NULL;
static SLAndroidSimpleBufferQueueItf pcmQue = NULL;
SLAudioPlay::SLAudioPlay()
{
buf = new unsigned char[1024*1024];
}
SLAudioPlay::~SLAudioPlay()
{
delete buf;
buf = 0;
}
static SLEngineItf CreateSL()
{
SLresult re;
SLEngineItf en;
re = slCreateEngine(&engineSL,0,0,0,0,0);
if(re != SL_RESULT_SUCCESS) return NULL;
re = (*engineSL)->Realize(engineSL,SL_BOOLEAN_FALSE);
if(re != SL_RESULT_SUCCESS) return NULL;
re = (*engineSL)->GetInterface(engineSL,SL_IID_ENGINE,&en);
if(re != SL_RESULT_SUCCESS) return NULL;
return en;
}
void SLAudioPlay::PlayCall(void *bufq)
{
if(!bufq)return;
SLAndroidSimpleBufferQueueItf bf = (SLAndroidSimpleBufferQueueItf)bufq;
XLOGE("SLAudioPlay::PlayCall");
//阻塞
XData d = GetData();
if(d.size<=0)
{
XLOGE("GetData() size is 0");
return;
}
if(!buf)
return;
memcpy(buf,d.data,d.size);
(*bf)->Enqueue(bf,buf,d.size);
d.Drop();
}
static void PcmCall(SLAndroidSimpleBufferQueueItf bf,void *contex)
{
SLAudioPlay *ap = (SLAudioPlay *)contex;
if(!ap)
{
XLOGE("PcmCall failed contex is null!");
return;
}
ap->PlayCall((void *)bf);
}
bool SLAudioPlay::StartPlay(XParameter out)
{
//1 创建引擎
eng = CreateSL();
if(eng)
{
XLOGI("CreateSL success! ");
}
else
{
XLOGE("CreateSL failed! ");
return false;
}
//2 创建混音器
SLresult re = 0;
re = (*eng)->CreateOutputMix(eng,&mix,0,0,0);
if(re !=SL_RESULT_SUCCESS )
{
XLOGE("SL_RESULT_SUCCESS failed!");
return false;
}
re = (*mix)->Realize(mix,SL_BOOLEAN_FALSE);
if(re !=SL_RESULT_SUCCESS )
{
XLOGE("(*mix)->Realize failed!");
return false;
}
SLDataLocator_OutputMix outmix = {SL_DATALOCATOR_OUTPUTMIX,mix};
SLDataSink audioSink= {&outmix,0};
//3 配置音频信息
//缓冲队列
SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,10};
//音频格式
SLDataFormat_PCM pcm = {
SL_DATAFORMAT_PCM,
(SLuint32) out.channels,// 声道数
(SLuint32) out.sample_rate*1000,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN //字节序,小端
};
SLDataSource ds = {&que,&pcm};
//4 创建播放器
const SLInterfaceID ids[] = {SL_IID_BUFFERQUEUE};
const SLboolean req[] = {SL_BOOLEAN_TRUE};
re = (*eng)->CreateAudioPlayer(eng,&player,&ds,&audioSink,sizeof(ids)/sizeof(SLInterfaceID),ids,req);
if(re !=SL_RESULT_SUCCESS )
{
XLOGE("CreateAudioPlayer failed!");
return false;
} else{
XLOGI("CreateAudioPlayer success!");
}
(*player)->Realize(player,SL_BOOLEAN_FALSE);
//获取player接口
re = (*player)->GetInterface(player,SL_IID_PLAY,&iplayer);
if(re !=SL_RESULT_SUCCESS )
{
XLOGE("GetInterface SL_IID_PLAY failed!");
return false;
}
re = (*player)->GetInterface(player,SL_IID_BUFFERQUEUE,&pcmQue);
if(re !=SL_RESULT_SUCCESS )
{
XLOGE("GetInterface SL_IID_BUFFERQUEUE failed!");
return false;
}
//设置回调函数,播放队列空调用
(*pcmQue)->RegisterCallback(pcmQue,PcmCall,this);
//设置为播放状态
(*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING);
//启动队列回调
(*pcmQue)->Enqueue(pcmQue,"",1);
XLOGI("SLAudioPlay::StartPlay success!");
return true;
}
#define XPLAY_SLAUDIOPLAY_H
#include "IAudioPlay.h"
class SLAudioPlay: public IAudioPlay
{
public:
virtual bool StartPlay(XParameter out);
void PlayCall(void *bufq);
SLAudioPlay();
virtual ~SLAudioPlay();
protected:
unsigned char *buf = 0;
};
#endif //XPLAY_SLAUDIOPLAY_H
关键字词:SLAudioPlay
相关文章
-
无相关信息