(原)关于OpenSL ES播放音频数据的一个奇怪的问题
关于OpenSL ES播放音频数据的一个奇怪的问题
Author:lihaiping1603@aliyun.com
最近用业余时间做了一个android平台的播放器sdk,其中视频用的opengl es,音频用的opensl es 做渲染,其中整个播放器在音视频同步的过程中,使用的视频同步到音频的方式,以音频作为主时钟。
今天在测试的过程中发现一个奇怪的问题,我音频数据的填充,使用了单独的音频线程,这其中的实现,主要参考ijk的实现代码和方式。
整个流程方式:我在音频播放的过程中设置的200ms的播放缓冲区给底层队列,当我把音频数据缓冲区填满以后,就wait_timeout(1s),如果在wait的过程中,底层有回调,就会signal,从而唤醒wait函数,然后再查询缓冲区大小,是否可以填充数据,如果可以填充数据的话,就填充数据进去,同时在填充数据的函数中,通过计算音频的pts和缓冲区的剩余数据大小,来更新当前的音频播放时钟位置。其中问题就是出在更新音频时钟位置的这个地方,我们计算剩余缓冲区的数据大小的时候,通过调用这个函数来获取底层数据的缓冲区延时:

通过计算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,并不会真正的实时反映实际的数据消耗过程。
那么我的代码和ijk的貌似看上去一致啊,为啥他的不会出现这个问题?后面思考发现问题所在,ijk在播放填充的数据线程中,通过回调给上层,他在上层的实现中实现了音频数据的解码,也就是正是这个解码函数产生的影响,他的这个耗时,完全足以让底层的音频连续回调,回调完毕,所以再去拿数据以后,就是正确的结果。
本人主要是个人对调试的理解和记录,仅供参考。
转载请注明出处:https://www.cnblogs.com/lihaiping/p/11739836.html
(原)关于OpenSL ES播放音频数据的一个奇怪的问题的更多相关文章
- Android OpenSL ES 开发:Android OpenSL 录制 PCM 音频数据
一.实现说明 OpenSL ES的录音要比播放简单一些,在创建好引擎后,再创建好录音接口基本就可以录音了.在这里我们做的是流式录音,所以需要用至少2个buffer来缓存录制好的PCM数据,这里我们可以 ...
- Android 音视频深入 十四 FFmpeg与OpenSL ES 播放mp3音乐,能暂停(附源码下载)
项目地址https://github.com/979451341/FFmpegOpenslES 这次说的是FFmpeg解码mp3,数据给OpenSL ES播放,并且能够暂停. 1.创建引擎 slCre ...
- iOS 9音频应用播放音频之第一个ios9音频实例2
iOS 9音频应用播放音频之第一个ios9音频实例2 ios9音频应用关联 iOS9音频应用中对于在主视图上添加的视图或控件,在使用它们时必须要与插座变量进行关联.ios9插座变量其实就是为主视图中的 ...
- iOS 9音频应用播放音频之第一个ios9音频实例
iOS 9音频应用播放音频之第一个ios9音频实例 第一个ios9音频实例 为了让开发者可以对上面的内容有更加深入的了解,本节将实现播放音频的第一个实例.在此实例中会涉及到项目的创建.界面设计.关联以 ...
- Android音视频学习第7章:使用OpenSL ES进行音频解码
/* * *这里使用了transcode-1.1.7对wav文件进行解码.然后使用opensl es进行播放 * */ //用到的变量和结构体 WAV wav; //wav文件指针 SLObjectI ...
- OpenSL ES: 利用OpenSL ES播放一个存在于SDcard上的PCM文件
native-lib.cpp #include <jni.h> #include <string> #include <SLES/OpenSLES.h> #incl ...
- 【Android 多媒体应用】使用MediaCodec解码使用AudioTrack播放音频数据
1.MainActivity.java import android.app.Activity; import android.os.Bundle; import android.os.Environ ...
- 【Android 多媒体应用】使用MediaRecoder录制,MediaPlayer播放音频数据
1.MainActivity.java import android.annotation.TargetApi; import android.app.Activity; import android ...
- Android OpenSL ES 开发:OpenSL ES利用SoundTouch实现PCM音频的变速和变调
缘由 OpenSL ES 学习到现在已经知道 OpenSL ES 不仅能播放和录制PCM音频数据,还能改变声音大小.设置左声道或右声道播放.还能变速播放,可谓是播放音频的王者.但是变速有一点不好的就是 ...
随机推荐
- 浅谈flask源码之请求过程
更新时间:2018年07月26日 09:51:36 作者:Dear. 我要评论 这篇文章主要介绍了浅谈flask源码之请求过程,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随 ...
- HDU3572 Task Schedule(最大流+构图思维)
题意: 有N个任务M个机器,给每个任务i完成所花费的时间Pi且每个任务要在第Si天后开始,在第Ei天前结束,保证任务在(S,E)之间一定能完成. 每个机器在一天里只能运行一个任务,一个任务可以在中途更 ...
- python-uiautomator2
简单介绍 python-uiautomator2是一个自动化测试开源工具,仅支持Android平台的原生应用测试. 支持平台及语言 python-uiautomator2封装了谷歌自带的uiautom ...
- Java 并发,相关术语
Java 并发,相关术语: 术语 作用 synchronize 可修饰方法.代码块.类:介绍:https://www.cnblogs.com/zyxiaohuihui/p/9096882.html L ...
- 二维码与json都是数据交换格式
二维码与json都是数据交换格式: UI数据是人机数据交换格式.
- matlab基础向9:动画
先定义坐标变量,确定范围,画出起始静态图,存进图形变量h.通过对坐标的变化,把新的坐标放进图形变量h,再实时刷新看起来就是动态的. 1.动态的sin曲线 X = -2*pi:0.1:2*pi; Y = ...
- MySQL InnoDB primary key根节点常驻内存
mysql的InnoDB存储引擎在设计时是将根节点常驻内存的,也就是说查找某一键值的行记录时最多只需要1~3次磁盘I/O操作.
- linux查看大文件
du -h --max-depth=1
- where与having 的区别
二者的区别在于作用对象不同. where子句作用于基本表或视图,从中选择满足条件的一行或多行元祖. having短语作用于组,从中选择满足条件的组.这些组应该由group by 短句来进行分组.
- nginx之fastcgi配置参数及其缓存
CGI的由来 最早的Web服务器只能简单地响应浏览器发来的HTTP请求,并将存储在服务器上的HTML文件返回给浏览器,也就是静态html文件,但是后期随着网站功能增多网站开发也越来越复杂,以至于出现动 ...