Android: Update RecordedAudioToFileController
This CL refactors the way RecordedAudioToFileController is connected to AudioRecord. Instead of allowing to dynamically set and update the AudioSamplesCallback, it's set once at start time and then stopping is implemented in RecordedAudioToFileController by simply ignoring calls to onWebRtcAudioRecordSamplesReady. The reason for this CL is to reduce the amount of methods we need to add to the future AudioDeviceModule interface. The more functionality we can move to creation time in the ctor, the less methods we need to have in the interface. Bug: webrtc:7452 Change-Id: I462df275d8579c848e1d2c86cbd8e881da89cbf3 Reviewed-on: https://webrtc-review.googlesource.com/64988 Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Reviewed-by: Paulina Hensman <phensman@webrtc.org> Commit-Queue: Magnus Jedvert <magjed@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22653}
This commit is contained in:
committed by
Commit Bot
parent
ac9365ed64
commit
b93d030b55
@ -476,12 +476,6 @@ public class PeerConnectionClient {
|
||||
preferIsac = peerConnectionParameters.audioCodec != null
|
||||
&& peerConnectionParameters.audioCodec.equals(AUDIO_CODEC_ISAC);
|
||||
|
||||
if (peerConnectionParameters.useLegacyAudioDevice) {
|
||||
setupAudioDeviceLegacy();
|
||||
} else {
|
||||
setupAudioDevice();
|
||||
}
|
||||
|
||||
// It is possible to save a copy in raw PCM format on a file by checking
|
||||
// the "Save input audio to file" checkbox in the Settings UI. A callback
|
||||
// interface is set when this flag is enabled. As a result, a copy of recorded
|
||||
@ -490,14 +484,19 @@ public class PeerConnectionClient {
|
||||
if (peerConnectionParameters.saveInputAudioToFile) {
|
||||
if (!peerConnectionParameters.useOpenSLES) {
|
||||
Log.d(TAG, "Enable recording of microphone input audio to file");
|
||||
saveRecordedAudioToFile = new RecordedAudioToFileController(
|
||||
executor, peerConnectionParameters.useLegacyAudioDevice);
|
||||
saveRecordedAudioToFile = new RecordedAudioToFileController(executor);
|
||||
} else {
|
||||
// TODO(henrika): ensure that the UI reflects that if OpenSL ES is selected,
|
||||
// then the "Save inut audio to file" option shall be grayed out.
|
||||
Log.e(TAG, "Recording of input audio is not supported for OpenSL ES");
|
||||
}
|
||||
}
|
||||
|
||||
if (peerConnectionParameters.useLegacyAudioDevice) {
|
||||
setupAudioDeviceLegacy();
|
||||
} else {
|
||||
setupAudioDevice();
|
||||
}
|
||||
// Create peer connection factory.
|
||||
if (options != null) {
|
||||
Log.d(TAG, "Factory networkIgnoreMask option: " + options.networkIgnoreMask);
|
||||
@ -546,6 +545,8 @@ public class PeerConnectionClient {
|
||||
WebRtcAudioUtils.setWebRtcBasedNoiseSuppressor(false);
|
||||
}
|
||||
|
||||
WebRtcAudioRecord.setOnAudioSamplesReady(saveRecordedAudioToFile);
|
||||
|
||||
// Set audio record error callbacks.
|
||||
WebRtcAudioRecord.setErrorCallback(new WebRtcAudioRecordErrorCallback() {
|
||||
@Override
|
||||
@ -616,6 +617,8 @@ public class PeerConnectionClient {
|
||||
AudioDeviceModule.setWebRtcBasedNoiseSuppressor(false);
|
||||
}
|
||||
|
||||
AudioDeviceModule.setOnAudioSamplesReady(saveRecordedAudioToFile);
|
||||
|
||||
// Set audio record error callbacks.
|
||||
AudioDeviceModule.setErrorCallback(new AudioDeviceModule.AudioRecordErrorCallback() {
|
||||
@Override
|
||||
|
||||
@ -38,13 +38,12 @@ public class RecordedAudioToFileController
|
||||
private final ExecutorService executor;
|
||||
@Nullable
|
||||
private OutputStream rawAudioFileOutputStream = null;
|
||||
private boolean isRunning;
|
||||
private long fileSizeInBytes = 0;
|
||||
private boolean useLegacyAudioDevice;
|
||||
|
||||
public RecordedAudioToFileController(ExecutorService executor, boolean useLegacyAudioDevice) {
|
||||
public RecordedAudioToFileController(ExecutorService executor) {
|
||||
Log.d(TAG, "ctor");
|
||||
this.executor = executor;
|
||||
this.useLegacyAudioDevice = useLegacyAudioDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,11 +56,8 @@ public class RecordedAudioToFileController
|
||||
Log.e(TAG, "Writing to external media is not possible");
|
||||
return false;
|
||||
}
|
||||
// Register this class as receiver of recorded audio samples for storage.
|
||||
if (useLegacyAudioDevice) {
|
||||
WebRtcAudioRecord.setOnAudioSamplesReady(this);
|
||||
} else {
|
||||
AudioDeviceModule.setOnAudioSamplesReady(this);
|
||||
synchronized (lock) {
|
||||
isRunning = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -72,13 +68,8 @@ public class RecordedAudioToFileController
|
||||
*/
|
||||
public void stop() {
|
||||
Log.d(TAG, "stop");
|
||||
// De-register this class as receiver of recorded audio samples for storage.
|
||||
if (useLegacyAudioDevice) {
|
||||
WebRtcAudioRecord.setOnAudioSamplesReady(null);
|
||||
} else {
|
||||
AudioDeviceModule.setOnAudioSamplesReady(null);
|
||||
}
|
||||
synchronized (lock) {
|
||||
isRunning = false;
|
||||
if (rawAudioFileOutputStream != null) {
|
||||
try {
|
||||
rawAudioFileOutputStream.close();
|
||||
@ -116,6 +107,13 @@ public class RecordedAudioToFileController
|
||||
Log.d(TAG, "Opened file for recording: " + fileName);
|
||||
}
|
||||
|
||||
// Called when new audio samples are ready.
|
||||
@Override
|
||||
public void onWebRtcAudioRecordSamplesReady(WebRtcAudioRecord.AudioSamples samples) {
|
||||
onWebRtcAudioRecordSamplesReady(new AudioDeviceModule.AudioSamples(samples.getAudioFormat(),
|
||||
samples.getChannelCount(), samples.getSampleRate(), samples.getData()));
|
||||
}
|
||||
|
||||
// Called when new audio samples are ready.
|
||||
@Override
|
||||
public void onWebRtcAudioRecordSamplesReady(AudioDeviceModule.AudioSamples samples) {
|
||||
@ -124,43 +122,13 @@ public class RecordedAudioToFileController
|
||||
Log.e(TAG, "Invalid audio format");
|
||||
return;
|
||||
}
|
||||
// Open a new file for the first callback only since it allows us to add
|
||||
// audio parameters to the file name.
|
||||
synchronized (lock) {
|
||||
if (rawAudioFileOutputStream == null) {
|
||||
openRawAudioOutputFile(samples.getSampleRate(), samples.getChannelCount());
|
||||
fileSizeInBytes = 0;
|
||||
}
|
||||
}
|
||||
// Append the recorded 16-bit audio samples to the open output file.
|
||||
executor.execute(() -> {
|
||||
if (rawAudioFileOutputStream != null) {
|
||||
try {
|
||||
// Set a limit on max file size. 58348800 bytes corresponds to
|
||||
// approximately 10 minutes of recording in mono at 48kHz.
|
||||
if (fileSizeInBytes < MAX_FILE_SIZE_IN_BYTES) {
|
||||
// Writes samples.getData().length bytes to output stream.
|
||||
rawAudioFileOutputStream.write(samples.getData());
|
||||
fileSizeInBytes += samples.getData().length;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to write audio to file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Called when new audio samples are ready.
|
||||
@Override
|
||||
public void onWebRtcAudioRecordSamplesReady(WebRtcAudioRecord.AudioSamples samples) {
|
||||
// The native audio layer on Android should use 16-bit PCM format.
|
||||
if (samples.getAudioFormat() != AudioFormat.ENCODING_PCM_16BIT) {
|
||||
Log.e(TAG, "Invalid audio format");
|
||||
// Abort early if stop() has been called.
|
||||
if (!isRunning) {
|
||||
return;
|
||||
}
|
||||
// Open a new file for the first callback only since it allows us to add
|
||||
// audio parameters to the file name.
|
||||
synchronized (lock) {
|
||||
// Open a new file for the first callback only since it allows us to add audio parameters to
|
||||
// the file name.
|
||||
if (rawAudioFileOutputStream == null) {
|
||||
openRawAudioOutputFile(samples.getSampleRate(), samples.getChannelCount());
|
||||
fileSizeInBytes = 0;
|
||||
|
||||
Reference in New Issue
Block a user