AudioRecord READ_BLOCKING 与 READ_NON_BLOCKING的区别
AudioRecord 录音时有两种读取模式,一种是AudioRecord.READ_BLOCKING,另外一种是AudioRecord.READ_NON_BLOCKING,但是对这两种模式的定义却比较模糊
/*** The read mode indicating the read operation will block until all data* requested has been read.*/
public final static int READ_BLOCKING = 0;/*** The read mode indicating the read operation will return immediately after* reading as much audio data as possible without blocking.*/
public final static int READ_NON_BLOCKING = 1;
只说一种是会阻塞直到数据读取成功,另外一种是立刻返回尽可能多的数据而不阻塞。那么假设我选择READ_NON_BLOCKING模式,会不会导致读取到的数据长度是变化的?这两种模式究竟有什么区别?
我们跟踪安卓的源码,AudioRecord.read最终会调用到frameworks/av/media/libaudioclient/AudioRecord.cpp:
ssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking)
{if (mTransfer != TRANSFER_SYNC) {return INVALID_OPERATION;}if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {// Validation. user is most-likely passing an error code, and it would// make the return value ambiguous (actualSize vs error).ALOGE("%s(%d) (buffer=%p, size=%zu (%zu)",__func__, mPortId, buffer, userSize, userSize);return BAD_VALUE;}ssize_t read = 0;Buffer audioBuffer;while (userSize >= mFrameSize) {audioBuffer.frameCount = userSize / mFrameSize;status_t err = obtainBuffer(&audioBuffer,blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking);if (err < 0) {if (read > 0) {break;}if (err == TIMED_OUT || err == -EINTR) {err = WOULD_BLOCK;}return ssize_t(err);}size_t bytesRead = audioBuffer.size;memcpy(buffer, audioBuffer.i8, bytesRead);buffer = ((char *) buffer) + bytesRead;userSize -= bytesRead;read += bytesRead;releaseBuffer(&audioBuffer);}if (read > 0) {mFramesRead += read / mFrameSize;// mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time.}return read;
}
可以看到,java层传过来的参数最终转换成布尔值blocking。在正常读取的时候,无论是否blocking,都会等到读取userSize之后再返回;在读取出错时,假设读取到了数据,无论是否blocking,最终也都会返回已读取的这部分数据。唯一的区别点在于obtainBuffer的传参,blocking等待时间为:ClientProxy::kForever,即INT_MAX sec,non_blocking等待时间为ClientProxy::kNonBlocking,即0。
const struct timespec ClientProxy::kForever = {INT_MAX /*tv_sec*/, 0 /*tv_nsec*/};
const struct timespec ClientProxy::kNonBlocking = {0 /*tv_sec*/, 0 /*tv_nsec*/};
需要注意的是,这个地方只是默认值,在obtainBuffer内部某些case下blocking也会被修改为non_blocking,例如
同时,在obtainBuffer内部也会进行一些状态判定,例如如果是未初始化等,无论是否blocking,都会直接返回error,只有状态正常,但是未能读取到数据时该参数才会生效
综上:
- 无论是否blocking,正常状态下都会读取到我们设置的bufferSize然后再返回;
- 无论是否blocking,在一些异常状态下都会不阻塞直接返回,例如状态错误等;
- 出错时无论是否blocking,都会返回已read的这部分size,有可能小于我们设置的bufferSize;
- 只有在状态正常但是数据未读取到时,blocking模式会进行阻塞等待,non_blocking直接返回WOULD_BLOCK的错误;
实际项目中验证发现情况4出现的概率还挺高的,会导致录音概率性有空白,推荐使用阻塞模式。
AudioRecord READ_BLOCKING 与 READ_NON_BLOCKING的区别相关推荐
- FFmpeg3.3.2+SDL2实现流媒体音频播放
我的视频课程(基础):<(NDK)FFmpeg打造Android万能音频播放器> 我的视频课程(进阶):<(NDK)FFmpeg打造Android视频播放器> 我的视频课程(编 ...
- Android音频录制方案,Android录音,录制其他App播放的声音
Android录音,录制其他App播放的声音 从Android10(SDK 29)版本开始,可以设置录音App的源为其他App,这样就可以录制其他App播放的声音 此方案有以下注意几点 设置了源为其他 ...
- Android录音并播放(mp3或amr格式)
Android项目中媒体是很多人头疼的一个问题,不仅仅因为处理起来很麻烦,而且不同的手机差别很大(和硬件,系统都有关系),今天就总结一下Android中的录音和播放,可保存成mp3或amr格式. 小米 ...
- Android如何将采集到的音频PCM文件转为WAV并保存
1.Android音频采集 添加权限 <uses-permission android:name="android.permission.RECORD_AUDIO" /> ...
- MediaPlayer/MediaRecorder与AudioTrack/AudioRecord区别(三十九)
android audio 生产者与消费者 简介 全面接触生产者/消费者问题是在操作系统原理中,并发性原理讨论的问题 生产者/消费者问题.最近的工作偏向音频,接着上一篇文章,用生产者,消费者模型来理解 ...
- android录音mediaRecord\AudioRecord\openSL\PCM tinyalsa总结和优缺点
常规录音 可以参考传送门_2learn MediaRecord 传统的android上,最简单的录音方式,莫过于MediaRecord. mMediaRecorder = new MediaRecor ...
- low latency playback、deep buffer playback、compressed offload playback的区别 学习学习
low latency playback.deep buffer playback.compressed offload playback的区别 https://blog.csdn.net/u0101 ...
- Android 音视频开发(一) -- 使用AudioRecord 录制PCM(录音);AudioTrack播放音频
前言,音视频这块,确实比较难入门,本着学习的态度,我这边也跟着 Android 音视频开发入门指南 打怪升级,留下个脚印,大家共勉. 音视频 系列文章 Android 音视频开发(一) – 使用Aud ...
- 音视频开发系列(27)AudioRecord录制PCM音频
目录 音频采集API AudioRecord和MediaRecorder介绍 PCM的介绍 AudioRecord的使用(构造.开始录制.停止录制.其他细节点) ffplay播放pcm pcm转为wa ...
最新文章
- python程序实例源代码-python下10个简单实例代码
- 【堆栈】最近有兴趣的几个问题
- HDU - 5459 Jesus Is Here(思维+非线性递推)
- [Abp 源码分析]后台作业与后台工作者
- docker容器状态跟踪及疑惑
- Linux群常见问题整理(一)[转]
- 数据结构二叉树的建立代码_二叉树就是这么简单
- HTML案例登录页面
- java调用cmd命令
- 云更新网吧系统服务器,云更新网吧服务器环境要求
- 解决 java 程序中 CPU 占用率过高问题
- c语言 日期加减天数返回日期 闰年,日期计算器(多图)
- Python初学(2)—— 基本数据类型
- 洛谷 P3817 小A的糖果
- SPP (Spatial Pyramid Pooling)
- 什么是3D摄影机,与普通摄影机有什么不同?
- 每天不知道吃什么,于是我做了个随机选择的小程序
- android系统锁屏锁怎么解决方法,忘了图案锁?这是你如何解锁Android模式锁定屏幕!...
- 安装实例中出现的ORA-27123和ORA-12532的错误
- 为王菲写的第二首歌《山河》
热门文章
- 计算光学成像(COI)实验室技能——matlab控制thorlabs位移平台(ActiveX控件)
- ios xib 初始化高度_iOS xib自定义,高度减少64
- 一个女孩从软件测试工程师到主管的成长
- ffmpeg处理音视频相关命令
- nutch+solor+elcipse安装配置
- html5 ios cookie,iOS cookie
- 安全学院“传承文化”暑期实践团参观秦始皇兵马俑
- 独立成分分析及Demo
- Angular5.x入门教程1
- 读《DevOps实践指南》笔记一