opensl的一般套路就不说了,网上都有,今天着重说一下callback调用的问题
先说一下opensl调用callback的原理:只有上一次callback时添加了数据才会自动会去调用下一次的callback,如果上一次callback没有获取到数据,那么就不会调用下一次callback,播放就会中断。
如果是播放录制好的音频文件是非常简单的,因为音频文件是连续不断的,opensl在初始化完成后直接手动调用一次callback开始获取音频解码文件,然后就会连续不断的调用callback,直至文件播放完。
如下
void Audio::pcmBufferCallBack1() {
//int buffersize = audio->reSampleAudio();
if(playstatus->exit)
return;
int buffersize = audio_buffer_fill(buffer, 48000 * 2 * 2);
clock += buffersize / ((double) (sampleRate * 2 * 2));
if (buffersize > 0) {
(*pcmBufferQueue)->Enqueue(pcmBufferQueue, (char *) buffer,buffersize);
}
}
但是如果是做直播类似的情况要播放实时音频流,情况就不一样了,因为音频是断断续续的,所以在没有音频数据后callback会自动断掉,然后在有新的音频数据来到的时候去手动调用callback。
我这边的例子是rtsp直播播放的音频,音频来了之后放入queue队列中,然后callback的时候会从queue中取数据解码播放
static void
play_audio(unsigned char *buffer, int bufsize, struct timeval pts) {
ga_log("play_audio");
if (!isAudioCom) {
isAudioCom = true;
}
if (isVideoCom && isAudioCom) {
AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = buffer;
avpkt.size = bufsize;
if (avpkt.size > 0) {
packet_queue_put(&audioq, &avpkt);
packet_queue_drop(&audioq);
pcount++;
if (pcount == 1) {
audio->pcmBufferCallBack1();
}
}
}
return;
}
没有音频数据的时候queue是空的,callback肯定获取不到数据,所以我的策略是在有新的音频数据包来的时候手动调用callback