(原)关于OpenSL ES播放音频数据的一个奇怪的问题

关于OpenSL ES播放音频数据的一个奇怪的问题html

Author:lihaiping1603@aliyun.comandroid

 

最近用业余时间作了一个android平台的播放器sdk,其中视频用的opengl es,音频用的opensl es 作渲染,其中整个播放器在音视频同步的过程当中,使用的视频同步到音频的方式,以音频做为主时钟。函数

今天在测试的过程当中发现一个奇怪的问题,我音频数据的填充,使用了单独的音频线程,这其中的实现,主要参考ijk的实现代码和方式。测试

整个流程方式:我在音频播放的过程当中设置的200ms的播放缓冲区给底层队列,当我把音频数据缓冲区填满之后,就wait_timeout(1s),若是在wait的过程当中,底层有回调,就会signal,从而唤醒wait函数,而后再查询缓冲区大小,是否能够填充数据,若是能够填充数据的话,就填充数据进去,同时在填充数据的函数中,经过计算音频的pts和缓冲区的剩余数据大小,来更新当前的音频播放时钟位置。其中问题就是出在更新音频时钟位置的这个地方,咱们计算剩余缓冲区的数据大小的时候,经过调用这个函数来获取底层数据的缓冲区延时:spa

 

 

 

经过计算state.count的计数来获取这个延时时间。线程

 

那么如今的问题现象是这样的,在视频正常播放的过程当中,我填充了200ms满的缓冲区音频数据去播放,在填充数据线程中wait,而后在大概过了120ms以后,底层回调:调试

 

 

 

 

发送信号唤醒wait函数,而后我去拷贝音频数据,拷贝完数据以后,计算时钟,这个时候查询底层缓冲区数据还剩多少,发现state.count=17,也就是说填满的时候20,如今获取还剩17,意思是中间难道只消耗了30ms的音频数据?不太可能啊,正常播放的状况下,120ms应该消耗120ms的音频数据才对啊,为啥这个地方只消耗了30ms的数据呢?视频

通过进一步的排查和分析,发现了问题,若是通过了120ms的播放时间,底层实际消耗的音频数据是为120ms,而他开始回调,并连续回调12次。但第一次回调的时候,咱们就唤醒了wait函数,这个时候咱们去拷贝数据,而从唤醒到拷贝数据完成,并从新获取底层缓冲区大小的的这个过程,由于时间很短,短到他12次的连续回调,实际上只完成了3次回调,这个时候咱们就去获取了state.count,发现它比以前只少了3次,因此误认为这个时间他只消耗了30ms的数据。由于state.count这个底层计数,他回调一次-1,并不会真正的实时反映实际的数据消耗过程。htm

那么个人代码和ijk的貌似看上去一致啊,为啥他的不会出现这个问题?后面思考发现问题所在,ijk在播放填充的数据线程中,经过回调给上层,他在上层的实现中实现了音频数据的解码,也就是正是这个解码函数产生的影响,他的这个耗时,彻底足以让底层的音频连续回调,回调完毕,因此再去拿数据之后,就是正确的结果。blog

本人主要是我的对调试的理解和记录,仅供参考。

 

 

 转载请注明出处:https://www.cnblogs.com/lihaiping/p/11739836.html

相关文章
相关标签/搜索