2013-08-01 2 views
2

Получаю W/AudioRecord(17145): obtainBuffer timed out (is the CPU pegged?) user=11b7f820, server=11b7f820 после 1-2 часов записи. Очевидно, запись останавливается, так как read() из AudioRecord считывает 0 байтов. Я борюсь с этим уже более 2 недель и решения пока нет. Вот как я инициализирую объект audioRecord:AudioRecord прекращает запись через 1-2 часа

private void initPCMRecorder() throws Exception { 
     Log.d(getClass().getName(), "Initializing AudioRecord..."); 
     int channelConfig = nChannels == 1 ? AudioFormat.CHANNEL_IN_MONO: AudioFormat.CHANNEL_IN_STEREO; 
     bufferSize = AudioRecord.getMinBufferSize(sRate, channelConfig, aFormat); 
     if (bufferSize == AudioRecord.ERROR_BAD_VALUE) 
      Log.e(getClass().getName(), "Bad encoding value, see logcat");     
     else if (bufferSize == AudioRecord.ERROR) 
      Log.e(getClass().getName(), "Error creating buffer size"); 

     bufferSize *= 3; 
     buffer = new byte[bufferSize]; 

     //check if is not yet released 
     if(aRecorder != null){ 
      try { 
       aRecorder.release();  
      } catch (Exception e) { 
       Log.e(getClass().getName(), e.getMessage(), e); 
      }   
     } 

     System.out.println("Source="+aSource+"; sampRate="+sRate+"; format="+aFormat+"; bufSize="+bufferSize); 
     aRecorder = new AudioRecord(aSource, sRate, channelConfig, aFormat, bufferSize); 
     if (aRecorder.getState() != AudioRecord.STATE_INITIALIZED) { 
      throw new Exception("" + ErrorCodes.ERROR_CODE_0); 
     } 
     Log.d(getClass().getName(), "AudioRecord Initialized"); 
     state = State.INITIALIZING; 
    } 

и я читаю во вторичной теме. Обратите внимание, что я попытался использовать positionNotificationListener, но результат был тот же.

public void run() { 
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); 

    while (!stopped) { 
     while (!suspend) { 
      int result = aRecorder.read(buffer, 0, buffer.length); 
      if(result == AudioRecord.ERROR_INVALID_OPERATION){ 
       Log.e(getClass().getName(), "aRecorder.read() returns ERROR_INVALID_OPERATION !!!"); 
       continue; 
      }else if(result == AudioRecord.ERROR_BAD_VALUE){ 
       Log.e(getClass().getName(), "aRecorder.read() returns ERROR_BAD_VALUE !!!"); 
       continue; 
      }else if(result == 0){ 
       Log.w(getClass().getName(), "SKIP audio block."); 
       continue; 
      } 

      payloadSize += buffer.length; 

      //data processing/writing is done in another thread 
      WAVData audioData = new WAVData(buffer); 
      audioData.setGain(rGain); 
      audioData.setBitsPerSamples(bitsPerSample); 
      audioData.setNrChannels(nChannels); 
      if(writersArray.size()>=1) 
       writersArray.get(writersArray.size() - 1).add(audioData); 
     } 
     // lock here 
     synchronized (lock) { 
      try { 
       lock.wait(); 
      } catch (InterruptedException e) { 
       Thread.currentThread().interrupt(); 
       return; 
      } 
     } 
    } 
} 

EDIT (добавление ошибки из консоли - com.audioRec.android.recorder мое приложение):

08-02 12:30:38.162: D/dalvikvm(1451): GC_CONCURRENT freed 7867K, 36% free 18889K/29447K, paused 17ms+8ms, total 151ms 
08-02 12:30:38.953: D/dalvikvm(1451): GC_FOR_ALLOC freed 36K, 36% free 18892K/29447K, paused 46ms, total 47ms 
08-02 12:30:39.063: D/dalvikvm(1451): GC_CONCURRENT freed <1K, 29% free 21196K/29447K, paused 18ms+6ms, total 108ms 
08-02 12:30:59.004: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160 
08-02 12:30:59.515: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160 
08-02 12:31:00.035: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160 
08-02 12:31:00.526: W/com.audioRec.android.recorder.AudioRecorder$RecorderThread(703): SKIP audio block. 
08-02 12:31:00.766: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160 
08-02 12:31:01.297: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160 
08-02 12:31:01.797: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160 
08-02 12:31:02.308: W/AudioRecord(703): obtainBuffer timed out (is the CPU pegged?) user=00f49160, server=00f49160 
08-02 12:31:02.558: W/com.audioRec.android.recorder.AudioRecorder$RecorderThread(703): SKIP audio block. 
08-02 12:31:02.558: D/com.audioRec.android.recorder.AudioRecorder$RecorderThread(703): MUST RESET AUDIORECORD....obtainBuffer timed out ? 
08-02 12:31:02.568: D/com.audioRec.android.recorder.AudioRecorder$AudioRecordCalibrator(703): Calibrating AudioRecord object... 
08-02 12:31:08.494: E/alsa_pcm(257): Arec: error5 
08-02 12:31:08.494: W/AudioStreamInALSA(257): pcm_read() returned error n -5, Recovering from error 
08-02 12:31:08.615: E/ALSADevice(257): standby handle h 0x4234f358 
08-02 12:31:08.645: D/alsa_ucm(257): snd_use_case_set(): uc_mgr 0x42e24fb8 identifier _dismod value Capture Music 
08-02 12:31:08.645: D/alsa_ucm(257): Set mixer controls for Capture Music enable 0 
08-02 12:31:08.655: D/alsa_ucm(257): Setting mixer control: MultiMedia1 Mixer SLIM_0_TX, value: 0 
08-02 12:31:08.655: E/ALSADevice(257): Number of modifiers 0 
08-02 12:31:08.655: E/ALSADevice(257): usecase_type is 0 

Пожалуйста, помогите мне с этим. Единственное решение, которое приходит мне на ум, - проверить 2 последовательных чтения(), которые читают 0 байт и снова останавливают/запускают звуковой рекордер, но будут вызывать 0,5 секунды потерянной записи.

+0

Является ли это последовательным среди двух разных устройств? Потому что, если его разница производителя, то это может быть признаком большой проблемы. – JoxTraex

+0

Я заметил на моей Xperia Z. Я попробую сегодня с Galaxy mini, чтобы увидеть результаты. Я подозреваю, что режим Stamina Mode из моего Z «виноват», потому что при использовании другого приложения для записи из магазина я получаю уведомление: «Приложение Recordin предотвращает режим выносливости для экономии батареи ...» Это приложение способно удерживать телефон ослабленным, но мое не. Сегодня я буду тестировать с помощью другого телефона и сообщать вам об этом. –

+1

На Galaxy mini работает нормально. протестировали в течение 2:30 часов, и запись не прекратилась. –

ответ

0

Звуковые API-интерфейсы, как известно, сломаны на некоторых устройствах.

Что я могу предложить:

a. Выполните нормальное поведение по умолчанию (просто продолжайте запись, пока вам не нужно нормально останавливаться). Я предполагаю, что проблема возникает только на определенных моделях, поэтому поведение по умолчанию будет работать на большинстве устройств пользователей.

b. Определите тип устройства Build.MODEL и создайте массив строк моделей устройств, которые требуют обходного пути. Например, добавьте свою собственную модель устройства в список, а также расширьте ее из отчетов пользователей (если они есть).

c. В своей логике проверьте, работает ли вы на устройстве, которое требует обходного пути, и если да, выполните эвристику для идентификации проблемы - последовательное чтение 0 байтов из AudioRecord - и затем перезапустите ее.

Я обнаружил, что лучше всего изолировать обходные пути, подобные этим, в особых условиях, зависящих от запроса модели устройства, чтобы ваш «нормальный» код не загрязнялся.

+0

Спасибо за ваш ответ. Я уже делаю: если 2 последовательных чтения возвращают 0, перезапустите audioRecord, включите экран (затемненный) (если пользователь не снял это свойство с настроек) и продолжайте запись. Но, как вы полагаете, мой код стал грязным, поэтому ваш подход намного более изящный, у 2 есть 2 способа чтения/обработки записи. Проблема в том, что я должен ждать, пока пользователи будут жаловаться на то, что запись будет остановлена ​​через некоторое время, и добавьте свой телефон в список. –

+0

Если слишком много устройств с одной и той же проблемой, вы также можете использовать обходной путь как поведение по умолчанию (при условии, что оно не нарушит приложение на обычных устройствах). – SirKnigget