【问题标题】:How to stop Android openSLES audio recorder properly?如何正确停止 Android openSLES 录音机?
【发布时间】:2014-08-06 23:58:02
【问题描述】:

我有一个在 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 日志,这意味着缓冲区已读取但未使用。如何正确停止录制?

【问题讨论】:

    标签: android android-ndk audiorecord opensl


    【解决方案1】:

    首先,您应该在销毁记录器之前停止记录器,但这还不够。

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

    所以伪代码看起来像这样:

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

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

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

    【讨论】:

      猜你喜欢
      • 2016-09-19
      • 1970-01-01
      • 1970-01-01
      • 2013-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多