在前面一篇文章中,我们讲解了audioTrack方式播放音频:audioTrack方式播放,本文使用openSLES方式来播放FFmpeg解码后的音频数据。
一、音频解码播放流程图
首先是关于FFmpeg音频解码的流程图,这个与解码流程基本一致:
然后与audioTrack方式不同的是,播放的那一步是采用openSLES,openSLES接口不在java层,而是在JNI层的,这个相对复杂一些。这里也做一下openSLES播放音频相关的流程图:
两者的流程是结合在一起,互相配合的。
二、音频解码并用openSLES播放整体流程
1、openSLES播放相关流程
先大概讲一下openSLES播放的相关流程:
(1)、创建引擎
创建openSLES引擎
//创建引擎
void createEngine(){
slCreateEngine(&engineObject,0,NULL,0,NULL,NULL);//创建引擎
(*engineObject)->Realize(engineObject,SL_BOOLEAN_FALSE);//实现engineObject接口对象
(*engineObject)->GetInterface(engineObject,SL_IID_ENGINE,&engineEngine);//通过引擎调用接口初始化SLEngineItf
}
(2)、创建混音器
创建openSLES混音器
//创建混音器
void createMixVolume(){
(*engineEngine)->CreateOutputMix(engineEngine,&outputMixObject,0,0,0);//用引擎对象创建混音器接口对象
(*outputMixObject)->Realize(outputMixObject,SL_BOOLEAN_FALSE);//实现混音器接口对象
SLresult sLresult = (*outputMixObject)->GetInterface(outputMixObject,SL_IID_ENVIRONMENTALREVERB,&outputMixEnvironmentalReverb);//利用混音器实例对象接口初始化具体的混音器对象
//设置
if (SL_RESULT_SUCCESS == sLresult) {
(*outputMixEnvironmentalReverb)->
SetEnvironmentalReverbProperties(outputMixEnvironmentalReverb, &settings);
}
}
(3)、创建播放器并播放
创建播放器并播放
//创建播放器
void createPlayer(JNIEnv *env,jstring input){
//初始化ffmpeg
unsigned int rate;
unsigned int channels;
createFFmpeg(env,(int *)&rate,(int *)&channels,input);
LOGE("RATE %d",rate);
LOGE("channels %d",channels);
/**
* typedef struct SLDataLocator_AndroidBufferQueue_ {
SLuint32 locatorType;//缓冲区队列类型
SLuint32 numBuffers;//buffer位数
}
*/
SLDataLocator_AndroidBufferQueue android_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2};
/**
typedef struct SLDataFormat_PCM_ {
SLuint32 formatType; pcm
SLuint32 numChannels; 通道数
SLuint32 samplesPerSec; 采样率