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

如何正确停止Android openSLES录音机?,android,android-ndk,audiorecord,opensl,Android,Android Ndk,Audiorecord,Opensl,我有一个在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 0

我有一个在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;
  }

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

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

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

因此,伪代码如下所示:

  • 通过将记录状态设置为
    SL_RECORDSTATE\u STOPPED
    ,停止记录器,不要让更多缓冲区队列排队
  • 等待,直到通过检查计数器处理所有排队的缓冲区队列
  • 销毁记录器,并释放回调可能使用的其他资源(内存)
在将bufferques排队时,以及在opensl回调结束时,您必须以线程安全的方式自己统计排队/处理的缓冲区队列

您可以在等待所有处理发生时使用pthread mutex/conditions/broadcasting。(或者你可以使用一个简单的while循环,其中一些在里面睡觉。)