初始化解码器
image.png解码音频文件(mp3)为pcm数据并存入文件
image.png边解码(mp3)边播放
利用OpenSL ES播放
image.png
HAudio.cpp
//
// Created by 霍振鹏 on 2018/10/19.
//
#include "HAudio.h"
HAudio::HAudio(HPlayStatus *hPlayStatus,int sample_rate) {
this->hPlayStatus=hPlayStatus;
this->hQueue=new HQueue(hPlayStatus);
this->sample_rate=sample_rate;
buffer = (uint8_t *) av_malloc(44100 * 2 * 2);
}
HAudio::~HAudio() {
}
void *writeData(void *data)
{
HAudio *hAudio= (HAudio *) data;
hAudio->initOpenSLES();
pthread_exit(&hAudio->pthread);
}
void HAudio::play() {
//创建一个线程,准备写入pcm数据
pthread_create(&pthread,NULL,writeData,this);
}
//FILE *outFile=fopen("/storage/emulated/0/voiceplayer.pcm","w");
int HAudio::resampleAudio() {
if(LOG_DEBUG)
{
LOGI("开始写入pcm数据");
}
while(hPlayStatus!=NULL&&!hPlayStatus->exit)
{
if(LOG_DEBUG)
{
LOGI("进入循环");
}
AVPacket *avPacket=av_packet_alloc();
if(hQueue->getAvPacket(avPacket)!=0)
{
av_packet_free(&avPacket);
av_free(avPacket);
avPacket=NULL;
continue;
}
//return 0 on success
int ret=0;
ret=avcodec_send_packet(avCodecContext,avPacket);
if(ret!=0)
{
av_packet_free(&avPacket);
av_free(avPacket);
avPacket=NULL;
continue;
}
AVFrame *avFrame=av_frame_alloc();
ret =avcodec_receive_frame(avCodecContext,avFrame);
if(ret==0)
{
if(avFrame->channels>0&&avFrame->channel_layout==0)
{
avFrame->channel_layout=av_get_default_channel_layout(avFrame->channels);
}
else if(avFrame->channels==0&&avFrame->channel_layout>0)
{
avFrame->channel_layout=av_get_channel_layout_nb_channels(avFrame->channel_layout);
}
SwrContext *swrContext;
swrContext=swr_alloc_set_opts(
NULL,
AV_CH_LAYOUT_STEREO,
AV_SAMPLE_FMT_S16,
avFrame->sample_rate,
avFrame->channel_layout,
(AVSampleFormat) avFrame->format,
avFrame->sample_rate,
NULL,NULL
);
if(!swrContext||swr_init(swrContext)<0)
{
av_packet_free(&avPacket);
av_free(avPacket);
avPacket = NULL;
av_frame_free(&avFrame);
av_free(avFrame);
avFrame = NULL;
swr_free(&swrContext);
continue;
}
//return number of samples output per channel
int nb=swr_convert(
swrContext,
&buffer,
avFrame->nb_samples,
(const uint8_t **) avFrame->data,
avFrame->nb_samples
);
int out_channels=av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
data_size=nb*out_channels*av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
// fwrite(buffer,1,data_size,outFile);
LOGI("data_size is %d", data_size);
av_packet_free(&avPacket);
av_free(avPacket);
avPacket = NULL;
av_frame_free(&avFrame);
av_free(avFrame);
avFrame = NULL;
swr_free(&swrContext);
break;
} else{
av_packet_free(&avPacket);
av_free(avPacket);
avPacket=NULL;
av_frame_free(&avFrame);
av_free(avFrame);
avFrame=NULL;
continue;
}
}
// fclose(outFile);
return data_size;
}
void pcmBufferCallBack(SLAndroidSimpleBufferQueueItf bf, void * context)
{
HAudio *wlAudio = (HAudio *) context;
if(wlAudio != NULL)
{
int buffersize = wlAudio->resampleAudio();
if(buffersize > 0)
{
(* wlAudio-> pcmBufferQueue)->Enqueue( wlAudio->pcmBufferQueue, (char *) wlAudio-> buffer, buffersize);
}
}
}
void HAudio::initOpenSLES() {
SLresult result;
result = slCreateEngine(&engineObject, 0, 0, 0, 0, 0);
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
//第二步,创建混音器
const SLInterfaceID mids[1] = {SL_IID_ENVIRONMENTALREVERB};
const SLboolean mreq[1] = {SL_BOOLEAN_FALSE};
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, mids, mreq);
(void)result;
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
(void)result;
result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB, &outputMixEnvironmentalReverb);
if (SL_RESULT_SUCCESS == result) {
result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(
outputMixEnvironmentalReverb, &reverbSettings);
(void)result;
}
SLDataLocator_OutputMix outputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk = {&outputMix, 0};
// 第三步,配置PCM格式信息
SLDataLocator_AndroidSimpleBufferQueue android_queue={SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2};
SLDataFormat_PCM pcm={
SL_DATAFORMAT_PCM,//播放pcm格式的数据
2,//2个声道(立体声)
getCurrentSampleRateForOpensles(sample_rate),//44100hz的频率
SL_PCMSAMPLEFORMAT_FIXED_16,//位数 16位
SL_PCMSAMPLEFORMAT_FIXED_16,//和位数一致就行
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,//立体声(前左前右)
SL_BYTEORDER_LITTLEENDIAN//结束标志
};
SLDataSource slDataSource = {&android_queue, &pcm};
const SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};
const SLboolean req[1] = {SL_BOOLEAN_TRUE};
(*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slDataSource, &audioSnk, 1, ids, req);
//初始化播放器
(*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
// 得到接口后调用 获取Player接口
(*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &pcmPlayerPlay);
// 注册回调缓冲区 获取缓冲队列接口
(*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_BUFFERQUEUE, &pcmBufferQueue);
//缓冲接口回调
(*pcmBufferQueue)->RegisterCallback(pcmBufferQueue, pcmBufferCallBack, this);
// 获取播放状态接口
(*pcmPlayerPlay)->SetPlayState(pcmPlayerPlay, SL_PLAYSTATE_PLAYING);
pcmBufferCallBack(pcmBufferQueue, this);
}
int HAudio::getCurrentSampleRateForOpensles(int sample_rate) {
int rate = 0;
switch (sample_rate)
{
case 8000:
rate = SL_SAMPLINGRATE_8;
break;
case 11025:
rate = SL_SAMPLINGRATE_11_025;
break;
case 12000:
rate = SL_SAMPLINGRATE_12;
break;
case 16000:
rate = SL_SAMPLINGRATE_16;
break;
case 22050:
rate = SL_SAMPLINGRATE_22_05;
break;
case 24000:
rate = SL_SAMPLINGRATE_24;
break;
case 32000:
rate = SL_SAMPLINGRATE_32;
break;
case 44100:
rate = SL_SAMPLINGRATE_44_1;
break;
case 48000:
rate = SL_SAMPLINGRATE_48;
break;
case 64000:
rate = SL_SAMPLINGRATE_64;
break;
case 88200:
rate = SL_SAMPLINGRATE_88_2;
break;
case 96000:
rate = SL_SAMPLINGRATE_96;
break;
case 192000:
rate = SL_SAMPLINGRATE_192;
break;
default:
rate = SL_SAMPLINGRATE_44_1;
}
return rate;
}
网友评论