繁体   English   中英

如何正确停止Android openSLES录音机?

[英]How to stop Android openSLES audio recorder properly?

我有一个在Android中使用openSLES的本地录音机。 记录器可以工作,但是当调用stop方法时,它似乎继续写缓冲区,因为我继续获取日志:

...
08-07 01:36:43.229: V/AudioRecord(6194): Overrun user: 61400, server: 61c00, flags 0001
08-07 01:36:43.239: V/AudioRecord(6194): Overrun user: 61400, server: 61c00, flags 0001
08-07 01:36:43.249: V/AudioRecord(6194): Overrun user: 61400, server: 61c00, flags 0001
...

我正在使用线程锁定方法来记录缓冲区,但是为什么在停止记录器后却得到了这些日志,如下所示:

typedef struct opensl_stream {
...
  SLObjectItf recorderObject;
  SLRecordItf recorderRecord;
  SLAndroidSimpleBufferQueueItf recorderBufferQueue;
...
} OPENSL_STREAM;

OPENSL_STREAM  *p;
//starting recorder
...
//stopping recorder
if (p->recorderObject != NULL) {
    (*p->recorderObject)->Destroy(p->recorderObject);
    p->recorderObject = NULL;
    p->recorderRecord = NULL;
    p->recorderBufferQueue = NULL;
  }

在尝试如上所述停止记录器后,我仍然得到AudioRecord(6194): Overrun user日志,这意味着已读取缓冲区但未使用缓冲区。 如何正确停止录制?

首先,您应该在销毁刻录机之前将其停止,但这还不够。

由于OpenSL回调是从其自己的线程中调用的,因此从另一个线程停止记录器并不意味着所有回调都立即停止。 (否则,将不会调用新的回调。)因此,您必须“计算”排队的缓冲区的数量,因此在回调中,您可以计算已处理了多少个回调。

因此,伪代码如下所示:

  • 通过将记录状态设置为SL_RECORDSTATE_STOPPED来停止记录器,不要排队更多的缓冲区队列。
  • 等待直到所有排队的缓冲区队列都通过检查计数器来处理。
  • 销毁记录器,并释放回调可能使用的其他资源(内存)。

在使quequeques入队时,以及在opensl回调结束时,您必须以线程安全的方式自己计算已入队/已处理的缓冲区队列。

您可以在等待所有处理发生时使用pthread互斥锁/条件/广播。 (或者您可以使用一个简单的while循环,其中一些在内部进行睡眠。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM