Initial implementation of Android audio recording error handling.
BUG=b/34128648 R=henrika@webrtc.org Review-Url: https://codereview.webrtc.org/2620453004 . Cr-Commit-Position: refs/heads/master@{#16017}
This commit is contained in:
@ -52,6 +52,8 @@ import org.webrtc.VideoRenderer;
|
||||
import org.webrtc.VideoSource;
|
||||
import org.webrtc.VideoTrack;
|
||||
import org.webrtc.voiceengine.WebRtcAudioManager;
|
||||
import org.webrtc.voiceengine.WebRtcAudioRecord;
|
||||
import org.webrtc.voiceengine.WebRtcAudioRecord.WebRtcAudioRecordErrorCallback;
|
||||
import org.webrtc.voiceengine.WebRtcAudioUtils;
|
||||
|
||||
/**
|
||||
@ -426,6 +428,27 @@ public class PeerConnectionClient {
|
||||
WebRtcAudioUtils.setWebRtcBasedNoiseSuppressor(false);
|
||||
}
|
||||
|
||||
// Set audio record error callbacks.
|
||||
WebRtcAudioRecord.setErrorCallback(new WebRtcAudioRecordErrorCallback() {
|
||||
@Override
|
||||
public void onWebRtcAudioRecordInitError(String errorMessage) {
|
||||
Log.e(TAG, "onWebRtcAudioRecordInitError: " + errorMessage);
|
||||
reportError(errorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebRtcAudioRecordStartError(String errorMessage) {
|
||||
Log.e(TAG, "onWebRtcAudioRecordStartError: " + errorMessage);
|
||||
reportError(errorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWebRtcAudioRecordError(String errorMessage) {
|
||||
Log.e(TAG, "onWebRtcAudioRecordError: " + errorMessage);
|
||||
reportError(errorMessage);
|
||||
}
|
||||
});
|
||||
|
||||
// Create peer connection factory.
|
||||
if (!PeerConnectionFactory.initializeAndroidGlobals(
|
||||
context, true, true, peerConnectionParameters.videoCodecHwAcceleration)) {
|
||||
|
||||
@ -60,6 +60,20 @@ public class WebRtcAudioRecord {
|
||||
private static volatile boolean microphoneMute = false;
|
||||
private byte[] emptyBytes;
|
||||
|
||||
// Audio recording error handler functions.
|
||||
public static interface WebRtcAudioRecordErrorCallback {
|
||||
void onWebRtcAudioRecordInitError(String errorMessage);
|
||||
void onWebRtcAudioRecordStartError(String errorMessage);
|
||||
void onWebRtcAudioRecordError(String errorMessage);
|
||||
}
|
||||
|
||||
private static WebRtcAudioRecordErrorCallback errorCallback = null;
|
||||
|
||||
public static void setErrorCallback(WebRtcAudioRecordErrorCallback errorCallback) {
|
||||
Logging.d(TAG, "Set error callback");
|
||||
WebRtcAudioRecord.errorCallback = errorCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Audio thread which keeps calling ByteBuffer.read() waiting for audio
|
||||
* to be recorded. Feeds recorded data to the native counterpart as a
|
||||
@ -89,9 +103,11 @@ public class WebRtcAudioRecord {
|
||||
}
|
||||
nativeDataIsRecorded(bytesRead, nativeAudioRecord);
|
||||
} else {
|
||||
Logging.e(TAG, "AudioRecord.read failed: " + bytesRead);
|
||||
String errorMessage = "AudioRecord.read failed: " + bytesRead;
|
||||
Logging.e(TAG, errorMessage);
|
||||
if (bytesRead == AudioRecord.ERROR_INVALID_OPERATION) {
|
||||
keepAlive = false;
|
||||
reportWebRtcAudioRecordError(errorMessage);
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
@ -150,11 +166,11 @@ public class WebRtcAudioRecord {
|
||||
private int initRecording(int sampleRate, int channels) {
|
||||
Logging.d(TAG, "initRecording(sampleRate=" + sampleRate + ", channels=" + channels + ")");
|
||||
if (!WebRtcAudioUtils.hasPermission(context, android.Manifest.permission.RECORD_AUDIO)) {
|
||||
Logging.e(TAG, "RECORD_AUDIO permission is missing");
|
||||
reportWebRtcAudioRecordInitError("RECORD_AUDIO permission is missing");
|
||||
return -1;
|
||||
}
|
||||
if (audioRecord != null) {
|
||||
Logging.e(TAG, "InitRecording() called twice without StopRecording()");
|
||||
reportWebRtcAudioRecordInitError("InitRecording called twice without StopRecording.");
|
||||
return -1;
|
||||
}
|
||||
final int bytesPerFrame = channels * (BITS_PER_SAMPLE / 8);
|
||||
@ -174,7 +190,7 @@ public class WebRtcAudioRecord {
|
||||
int minBufferSize =
|
||||
AudioRecord.getMinBufferSize(sampleRate, channelConfig, AudioFormat.ENCODING_PCM_16BIT);
|
||||
if (minBufferSize == AudioRecord.ERROR || minBufferSize == AudioRecord.ERROR_BAD_VALUE) {
|
||||
Logging.e(TAG, "AudioRecord.getMinBufferSize failed: " + minBufferSize);
|
||||
reportWebRtcAudioRecordInitError("AudioRecord.getMinBufferSize failed: " + minBufferSize);
|
||||
return -1;
|
||||
}
|
||||
Logging.d(TAG, "AudioRecord.getMinBufferSize: " + minBufferSize);
|
||||
@ -188,12 +204,12 @@ public class WebRtcAudioRecord {
|
||||
audioRecord = new AudioRecord(AudioSource.VOICE_COMMUNICATION, sampleRate, channelConfig,
|
||||
AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Logging.e(TAG, e.getMessage());
|
||||
reportWebRtcAudioRecordInitError("AudioRecord ctor error: " + e.getMessage());
|
||||
releaseAudioResources();
|
||||
return -1;
|
||||
}
|
||||
if (audioRecord == null || audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
|
||||
Logging.e(TAG, "Failed to create a new AudioRecord instance");
|
||||
reportWebRtcAudioRecordInitError("Failed to create a new AudioRecord instance");
|
||||
releaseAudioResources();
|
||||
return -1;
|
||||
}
|
||||
@ -212,11 +228,12 @@ public class WebRtcAudioRecord {
|
||||
try {
|
||||
audioRecord.startRecording();
|
||||
} catch (IllegalStateException e) {
|
||||
Logging.e(TAG, "AudioRecord.startRecording failed: " + e.getMessage());
|
||||
reportWebRtcAudioRecordStartError("AudioRecord.startRecording failed: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
|
||||
Logging.e(TAG, "AudioRecord.startRecording failed");
|
||||
reportWebRtcAudioRecordStartError("AudioRecord.startRecording failed - incorrect state :"
|
||||
+ audioRecord.getRecordingState());
|
||||
return false;
|
||||
}
|
||||
audioThread = new AudioRecordThread("AudioRecordJavaThread");
|
||||
@ -283,4 +300,25 @@ public class WebRtcAudioRecord {
|
||||
audioRecord = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void reportWebRtcAudioRecordInitError(String errorMessage) {
|
||||
Logging.e(TAG, "Init recording error: " + errorMessage);
|
||||
if (errorCallback != null) {
|
||||
errorCallback.onWebRtcAudioRecordInitError(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportWebRtcAudioRecordStartError(String errorMessage) {
|
||||
Logging.e(TAG, "Start recording error: " + errorMessage);
|
||||
if (errorCallback != null) {
|
||||
errorCallback.onWebRtcAudioRecordStartError(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportWebRtcAudioRecordError(String errorMessage) {
|
||||
Logging.e(TAG, "Run-time recording error: " + errorMessage);
|
||||
if (errorCallback != null) {
|
||||
errorCallback.onWebRtcAudioRecordError(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user