Как правильно остановить аудиорекордер Android openSLES?

У меня есть встроенный аудиорекордер, использующий openSLES в Android. Рекордер работает, но при вызове метода остановки он, кажется, продолжает писать буферы, так как я продолжаю получать логи:

...
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, что означает, что буфер читается, но не используется. Как правильно остановить запись?


person user2212461    schedule 06.08.2014    source источник


Ответы (1)


Во-первых, вы должны остановить записывающее устройство, прежде чем уничтожить его, но этого недостаточно.

Поскольку обратные вызовы OpenSL вызываются из собственного потока, остановка устройства записи из другого потока не означает немедленной остановки всех обратных вызовов. (Или новые обратные вызовы не будут вызываться.) Поэтому вам нужно «подсчитать», сколько буферов вы поставили в очередь, поэтому в обратном вызове вы можете подсчитать, сколько обратных вызовов было обработано.

Таким образом, псевдокод выглядит примерно так:

  • остановить рекордер, установив состояние записи в SL_RECORDSTATE_STOPPED, не ставить в очередь больше буферных очередей.
  • подождите, пока все буферные очереди, поставленные в очередь, не будут обработаны, проверив ваш счетчик (счетчики).
  • уничтожить рекордер и освободить другие ресурсы (память), которые могут использоваться вашим обратным вызовом.

При постановке в очередь буферных запросов и в конце обратных вызовов opensl вы должны самостоятельно подсчитывать поставленные в очередь/обработанные буферные очереди потокобезопасным способом.

Вы можете использовать мьютексы / условия / широковещание pthread, ожидая, пока произойдет вся обработка. (Или вы можете использовать простой цикл while с некоторыми спящими внутри.)

person Tamas    schedule 11.08.2014