Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(955)

Unified Diff: media/audio/android/opensles_input.cc

Issue 23296008: Adding audio unit tests for Android (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: wjia@ Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/audio/android/opensles_input.h ('k') | media/audio/android/opensles_output.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/android/opensles_input.cc
diff --git a/media/audio/android/opensles_input.cc b/media/audio/android/opensles_input.cc
index 15c3eac3726389bb7f8d0a7f37ee4b8d35a82f91..60a94debef9897bdcd5c0214ab2f88319594ccc6 100644
--- a/media/audio/android/opensles_input.cc
+++ b/media/audio/android/opensles_input.cc
@@ -4,16 +4,17 @@
#include "media/audio/android/opensles_input.h"
+#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "media/audio/android/audio_manager_android.h"
-#define LOG_ON_FAILURE_AND_RETURN(op, ...) \
- do { \
- SLresult err = (op); \
- if (err != SL_RESULT_SUCCESS) { \
+#define LOG_ON_FAILURE_AND_RETURN(op, ...) \
+ do { \
+ SLresult err = (op); \
+ if (err != SL_RESULT_SUCCESS) { \
DLOG(ERROR) << #op << " failed: " << err; \
- return __VA_ARGS__; \
- } \
+ return __VA_ARGS__; \
+ } \
} while (0)
namespace media {
@@ -24,9 +25,10 @@ OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
callback_(NULL),
recorder_(NULL),
simple_buffer_queue_(NULL),
- active_queue_(0),
+ active_buffer_index_(0),
buffer_size_bytes_(0),
started_(false) {
+ DVLOG(2) << "OpenSLESInputStream::OpenSLESInputStream()";
format_.formatType = SL_DATAFORMAT_PCM;
format_.numChannels = static_cast<SLuint32>(params.channels());
// Provides sampling rate in milliHertz to OpenSLES.
@@ -47,6 +49,8 @@ OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
}
OpenSLESInputStream::~OpenSLESInputStream() {
+ DVLOG(2) << "OpenSLESInputStream::~OpenSLESInputStream()";
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!recorder_object_.Get());
DCHECK(!engine_object_.Get());
DCHECK(!recorder_);
@@ -55,6 +59,8 @@ OpenSLESInputStream::~OpenSLESInputStream() {
}
bool OpenSLESInputStream::Open() {
+ DVLOG(2) << "OpenSLESInputStream::Open()";
+ DCHECK(thread_checker_.CalledOnValidThread());
if (engine_object_.Get())
return false;
@@ -67,44 +73,59 @@ bool OpenSLESInputStream::Open() {
}
void OpenSLESInputStream::Start(AudioInputCallback* callback) {
+ DVLOG(2) << "OpenSLESInputStream::Start()";
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(callback);
DCHECK(recorder_);
DCHECK(simple_buffer_queue_);
if (started_)
return;
- // Enable the flags before streaming.
+ base::AutoLock lock(lock_);
+ DCHECK(callback_ == NULL || callback_ == callback);
callback_ = callback;
- active_queue_ = 0;
- started_ = true;
+ active_buffer_index_ = 0;
+ // Enqueues kMaxNumOfBuffersInQueue zero buffers to get the ball rolling.
+ // TODO(henrika): add support for Start/Stop/Start sequences when we are
+ // able to clear the buffer queue. There is currently a bug in the OpenSLES
+ // implementation which forces us to always call Stop() and Close() before
+ // calling Start() again.
SLresult err = SL_RESULT_UNKNOWN_ERROR;
- // Enqueues |kNumOfQueuesInBuffer| zero buffers to get the ball rolling.
- for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
+ for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
err = (*simple_buffer_queue_)->Enqueue(
- simple_buffer_queue_,
- audio_data_[i],
- buffer_size_bytes_);
+ simple_buffer_queue_, audio_data_[i], buffer_size_bytes_);
if (SL_RESULT_SUCCESS != err) {
HandleError(err);
+ started_ = false;
return;
}
}
- // Start the recording by setting the state to |SL_RECORDSTATE_RECORDING|.
+ // Start the recording by setting the state to SL_RECORDSTATE_RECORDING.
+ // When the object is in the SL_RECORDSTATE_RECORDING state, adding buffers
+ // will implicitly start the filling process.
err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
- if (SL_RESULT_SUCCESS != err)
+ if (SL_RESULT_SUCCESS != err) {
HandleError(err);
+ started_ = false;
+ return;
+ }
+
+ started_ = true;
}
void OpenSLESInputStream::Stop() {
+ DVLOG(2) << "OpenSLESInputStream::Stop()";
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!started_)
return;
- // Stop recording by setting the record state to |SL_RECORDSTATE_STOPPED|.
+ base::AutoLock lock(lock_);
+
+ // Stop recording by setting the record state to SL_RECORDSTATE_STOPPED.
LOG_ON_FAILURE_AND_RETURN(
- (*recorder_)->SetRecordState(recorder_,
- SL_RECORDSTATE_STOPPED));
+ (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_STOPPED));
// Clear the buffer queue to get rid of old data when resuming recording.
LOG_ON_FAILURE_AND_RETURN(
@@ -114,17 +135,30 @@ void OpenSLESInputStream::Stop() {
}
void OpenSLESInputStream::Close() {
+ DVLOG(2) << "OpenSLESInputStream::Close()";
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// Stop the stream if it is still recording.
Stop();
+ {
+ base::AutoLock lock(lock_);
+
+ if (callback_) {
+ callback_->OnClose(this);
wjia(left Chromium) 2013/09/10 16:33:35 Since none of us knows why callback is passed in a
henrika (OOO until Aug 14) 2013/09/11 13:25:01 Done.
+ callback_ = NULL;
+ }
- // Explicitly free the player objects and invalidate their associated
- // interfaces. They have to be done in the correct order.
- recorder_object_.Reset();
- engine_object_.Reset();
- simple_buffer_queue_ = NULL;
- recorder_ = NULL;
+ // Destroy the buffer queue recorder object and invalidate all associated
+ // interfaces.
+ recorder_object_.Reset();
+ simple_buffer_queue_ = NULL;
+ recorder_ = NULL;
- ReleaseAudioBuffer();
+ // Destroy the engine object. We don't store any associated interface for
+ // this object.
+ engine_object_.Reset();
+ ReleaseAudioBuffer();
+ }
audio_manager_->ReleaseInputStream(this);
}
@@ -134,9 +168,7 @@ double OpenSLESInputStream::GetMaxVolume() {
return 0.0;
}
-void OpenSLESInputStream::SetVolume(double volume) {
- NOTIMPLEMENTED();
-}
+void OpenSLESInputStream::SetVolume(double volume) { NOTIMPLEMENTED(); }
double OpenSLESInputStream::GetVolume() {
NOTIMPLEMENTED();
@@ -153,54 +185,47 @@ bool OpenSLESInputStream::GetAutomaticGainControl() {
}
bool OpenSLESInputStream::CreateRecorder() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!engine_object_.Get());
+ DCHECK(!recorder_object_.Get());
+ DCHECK(!recorder_);
+ DCHECK(!simple_buffer_queue_);
+
// Initializes the engine object with specific option. After working with the
// object, we need to free the object and its resources.
SLEngineOption option[] = {
- { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) }
- };
- LOG_ON_FAILURE_AND_RETURN(slCreateEngine(engine_object_.Receive(),
- 1,
- option,
- 0,
- NULL,
- NULL),
- false);
+ {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}};
+ LOG_ON_FAILURE_AND_RETURN(
+ slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL),
+ false);
// Realize the SL engine object in synchronous mode.
- LOG_ON_FAILURE_AND_RETURN(engine_object_->Realize(engine_object_.Get(),
- SL_BOOLEAN_FALSE),
- false);
+ LOG_ON_FAILURE_AND_RETURN(
+ engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false);
// Get the SL engine interface which is implicit.
SLEngineItf engine;
- LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(engine_object_.Get(),
- SL_IID_ENGINE,
- &engine),
+ LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface(
+ engine_object_.Get(), SL_IID_ENGINE, &engine),
false);
// Audio source configuration.
SLDataLocator_IODevice mic_locator = {
- SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
- SL_DEFAULTDEVICEID_AUDIOINPUT, NULL
- };
- SLDataSource audio_source = { &mic_locator, NULL };
+ SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
+ SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
+ SLDataSource audio_source = {&mic_locator, NULL};
// Audio sink configuration.
SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
- SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // Locator type.
- static_cast<SLuint32>(kNumOfQueuesInBuffer) // Number of buffers.
- };
- SLDataSink audio_sink = { &buffer_queue, &format_ };
+ SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
+ static_cast<SLuint32>(kMaxNumOfBuffersInQueue)};
+ SLDataSink audio_sink = {&buffer_queue, &format_};
// Create an audio recorder.
- const SLInterfaceID interface_id[] = {
- SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
- SL_IID_ANDROIDCONFIGURATION
- };
- const SLboolean interface_required[] = {
- SL_BOOLEAN_TRUE,
- SL_BOOLEAN_TRUE
- };
+ const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
+ SL_IID_ANDROIDCONFIGURATION};
+ const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+
// Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION.
LOG_ON_FAILURE_AND_RETURN(
(*engine)->CreateAudioRecorder(engine,
@@ -219,24 +244,24 @@ bool OpenSLESInputStream::CreateRecorder() {
&recorder_config),
false);
+ // Uses the main microphone tuned for audio communications.
SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
LOG_ON_FAILURE_AND_RETURN(
(*recorder_config)->SetConfiguration(recorder_config,
SL_ANDROID_KEY_RECORDING_PRESET,
- &stream_type, sizeof(SLint32)),
+ &stream_type,
+ sizeof(SLint32)),
false);
// Realize the recorder object in synchronous mode.
LOG_ON_FAILURE_AND_RETURN(
- recorder_object_->Realize(recorder_object_.Get(),
- SL_BOOLEAN_FALSE),
+ recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE),
false);
// Get an implicit recorder interface.
LOG_ON_FAILURE_AND_RETURN(
- recorder_object_->GetInterface(recorder_object_.Get(),
- SL_IID_RECORD,
- &recorder_),
+ recorder_object_->GetInterface(
+ recorder_object_.Get(), SL_IID_RECORD, &recorder_),
false);
// Get the simple buffer queue interface.
@@ -249,61 +274,66 @@ bool OpenSLESInputStream::CreateRecorder() {
// Register the input callback for the simple buffer queue.
// This callback will be called when receiving new data from the device.
LOG_ON_FAILURE_AND_RETURN(
- (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_,
- SimpleBufferQueueCallback,
- this),
+ (*simple_buffer_queue_)->RegisterCallback(
+ simple_buffer_queue_, SimpleBufferQueueCallback, this),
false);
return true;
}
void OpenSLESInputStream::SimpleBufferQueueCallback(
- SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) {
+ SLAndroidSimpleBufferQueueItf buffer_queue,
+ void* instance) {
OpenSLESInputStream* stream =
reinterpret_cast<OpenSLESInputStream*>(instance);
stream->ReadBufferQueue();
}
void OpenSLESInputStream::ReadBufferQueue() {
+ base::AutoLock lock(lock_);
if (!started_)
return;
- // TODO(xians): Get an accurate delay estimation.
+ TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue");
+
+ // TODO(henrika): Investigate if it is possible to get an accurate
+ // delay estimation.
callback_->OnData(this,
- audio_data_[active_queue_],
+ audio_data_[active_buffer_index_],
buffer_size_bytes_,
buffer_size_bytes_,
0.0);
// Done with this buffer. Send it to device for recording.
- SLresult err = (*simple_buffer_queue_)->Enqueue(
- simple_buffer_queue_,
- audio_data_[active_queue_],
- buffer_size_bytes_);
+ err = (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_,
+ audio_data_[active_buffer_index_],
+ buffer_size_bytes_);
if (SL_RESULT_SUCCESS != err)
HandleError(err);
- active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer;
+ active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue;
}
void OpenSLESInputStream::SetupAudioBuffer() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!audio_data_[0]);
- for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
+ for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
audio_data_[i] = new uint8[buffer_size_bytes_];
}
}
void OpenSLESInputStream::ReleaseAudioBuffer() {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (audio_data_[0]) {
- for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
- delete [] audio_data_[i];
+ for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) {
+ delete[] audio_data_[i];
audio_data_[i] = NULL;
}
}
}
void OpenSLESInputStream::HandleError(SLresult error) {
- DLOG(FATAL) << "OpenSLES Input error " << error;
+ DLOG(ERROR) << "OpenSLES Input error " << error;
if (callback_)
callback_->OnError(this);
}
« no previous file with comments | « media/audio/android/opensles_input.h ('k') | media/audio/android/opensles_output.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698