Bug 899159: clean up record issues in webrtc OpenSLES code + wallpaper r=padenot,derf,mwu

More to be done upstream and then will replace this
This commit is contained in:
Randell Jesup 2013-09-05 15:34:05 -04:00
parent b19a3179ee
commit 338aeac55f

View File

@ -67,8 +67,8 @@ AudioDeviceAndroidOpenSLES::AudioDeviceAndroidOpenSLES(const int32_t id)
agc_enabled_(false),
rec_thread_(NULL),
rec_timer_(*EventWrapper::Create()),
mic_sampling_rate_(N_REC_SAMPLES_PER_SEC * 1000),
speaker_sampling_rate_(N_PLAY_SAMPLES_PER_SEC * 1000),
mic_sampling_rate_(N_REC_SAMPLES_PER_SEC),
speaker_sampling_rate_(N_PLAY_SAMPLES_PER_SEC),
max_speaker_vol_(0),
min_speaker_vol_(0),
loundspeaker_on_(false),
@ -77,6 +77,7 @@ AudioDeviceAndroidOpenSLES::AudioDeviceAndroidOpenSLES(const int32_t id)
__FUNCTION__);
memset(rec_buf_, 0, sizeof(rec_buf_));
memset(play_buf_, 0, sizeof(play_buf_));
UpdateRecordingDelay();
}
AudioDeviceAndroidOpenSLES::~AudioDeviceAndroidOpenSLES() {
@ -1252,18 +1253,22 @@ int32_t AudioDeviceAndroidOpenSLES::CPULoad(
}
bool AudioDeviceAndroidOpenSLES::PlayoutWarning() const {
CriticalSectionScoped lock(&crit_sect_);
return (play_warning_ > 0);
}
bool AudioDeviceAndroidOpenSLES::PlayoutError() const {
CriticalSectionScoped lock(&crit_sect_);
return (play_error_ > 0);
}
bool AudioDeviceAndroidOpenSLES::RecordingWarning() const {
CriticalSectionScoped lock(&crit_sect_);
return (rec_warning_ > 0);
}
bool AudioDeviceAndroidOpenSLES::RecordingError() const {
CriticalSectionScoped lock(&crit_sect_);
return (rec_error_ > 0);
}
@ -1276,10 +1281,12 @@ void AudioDeviceAndroidOpenSLES::ClearPlayoutError() {
}
void AudioDeviceAndroidOpenSLES::ClearRecordingWarning() {
CriticalSectionScoped lock(&crit_sect_);
rec_warning_ = 0;
}
void AudioDeviceAndroidOpenSLES::ClearRecordingError() {
CriticalSectionScoped lock(&crit_sect_);
rec_error_ = 0;
}
@ -1351,79 +1358,107 @@ void AudioDeviceAndroidOpenSLES::RecorderSimpleBufferQueueCallback(
}
bool AudioDeviceAndroidOpenSLES::RecThreadFuncImpl() {
if (is_recording_) {
// TODO(leozwang): Add seting correct scheduling and thread priority.
// TODO(leozwang): Add seting correct scheduling and thread priority.
const unsigned int num_samples = mic_sampling_rate_ / 100;
const unsigned int num_bytes =
N_REC_CHANNELS * num_samples * sizeof(int16_t);
const unsigned int total_bytes = num_bytes;
int8_t buf[REC_MAX_TEMP_BUF_SIZE_PER_10ms];
const unsigned int num_samples = mic_sampling_rate_ / 100;
const unsigned int num_bytes =
N_REC_CHANNELS * num_samples * sizeof(int16_t);
const unsigned int total_bytes = num_bytes;
int8_t buf[REC_MAX_TEMP_BUF_SIZE_PER_10ms];
{
CriticalSectionScoped lock(&crit_sect_);
crit_sect_.Enter();
while (is_recording_) {
if (rec_voe_audio_queue_.size() <= 0) {
crit_sect_.Leave();
// Wait for max 40ms for incoming audio data before looping the
// poll and checking for ::Stop() being called (which waits for us
// to return). Actual time between audio callbacks will vary, but
// is based on AudioRecord min buffer sizes, which may be 15-80ms
// or more, depending on sampling frequency, but typically will be
// 25ish ms at 44100Hz. We also don't want to take "too long" to
// exit after ::Stop(). This value of 40ms is arbitrary.
rec_timer_.Wait(40);
crit_sect_.Enter();
if (rec_voe_audio_queue_.size() <= 0) {
rec_timer_.Wait(1);
// still no audio data; check for ::Stop()
crit_sect_.Leave();
return true;
}
int8_t* audio = rec_voe_audio_queue_.front();
rec_voe_audio_queue_.pop();
memcpy(buf, audio, total_bytes);
memset(audio, 0, total_bytes);
rec_voe_ready_queue_.push(audio);
}
UpdateRecordingDelay();
int8_t* audio = rec_voe_audio_queue_.front();
rec_voe_audio_queue_.pop();
memcpy(buf, audio, total_bytes);
memset(audio, 0, total_bytes);
rec_voe_ready_queue_.push(audio);
voe_audio_buffer_->SetRecordedBuffer(buf, num_samples);
voe_audio_buffer_->SetVQEData(playout_delay_, recording_delay_, 0);
// All other implementations UnLock around DeliverRecordedData() only
crit_sect_.Leave();
voe_audio_buffer_->DeliverRecordedData();
crit_sect_.Enter();
}
crit_sect_.Leave();
// if is_recording is false, we either *just* were started, or for some reason
// Stop() failed to get us to return for 10 seconds - and when we return here,
// Stop will kill us anyways.
rec_timer_.Wait(1);
return true;
}
void AudioDeviceAndroidOpenSLES::RecorderSimpleBufferQueueCallbackHandler(
SLAndroidSimpleBufferQueueItf queue_itf) {
if (is_recording_) {
const unsigned int num_samples = mic_sampling_rate_ / 100;
const unsigned int num_bytes =
N_REC_CHANNELS * num_samples * sizeof(int16_t);
const unsigned int total_bytes = num_bytes;
int8_t* audio;
{
CriticalSectionScoped lock(&crit_sect_);
audio = rec_queue_.front();
rec_queue_.pop();
rec_voe_audio_queue_.push(audio);
const unsigned int num_samples = mic_sampling_rate_ / 100;
const unsigned int num_bytes =
N_REC_CHANNELS * num_samples * sizeof(int16_t);
const unsigned int total_bytes = num_bytes;
int8_t* audio;
if (rec_voe_ready_queue_.size() <= 0) {
// Log Error.
rec_error_ = 1;
WEBRTC_OPENSL_TRACE(kTraceError, kTraceAudioDevice, id_,
" Audio Rec thread buffers underrun");
} else {
audio = rec_voe_ready_queue_.front();
rec_voe_ready_queue_.pop();
}
{
CriticalSectionScoped lock(&crit_sect_);
if (!is_recording_) {
return;
}
audio = rec_queue_.front();
rec_queue_.pop();
rec_voe_audio_queue_.push(audio);
rec_timer_.Set(); // wake up record thread to process it
int32_t res = (*queue_itf)->Enqueue(queue_itf,
audio,
total_bytes);
if (res != SL_RESULT_SUCCESS) {
WEBRTC_OPENSL_TRACE(kTraceWarning, kTraceAudioDevice, id_,
" recorder callback Enqueue failed, %d", res);
rec_warning_ = 1;
if (rec_voe_ready_queue_.size() <= 0) {
// Log Error.
rec_error_ = 1;
WEBRTC_OPENSL_TRACE(kTraceError, kTraceAudioDevice, id_,
" Audio Rec thread buffers underrun");
// This isn't good, but continuing (as it used to) is even worse.
// Worst case we end up with buffers building up at the other end or
// starved. To be fixed in full rewrite from upstream.
return;
} else {
rec_queue_.push(audio);
audio = rec_voe_ready_queue_.front();
rec_voe_ready_queue_.pop();
}
// TODO(leozwang): OpenSL ES doesn't support AudioRecorder
// volume control now, add it when it's ready.
}
int32_t res = (*queue_itf)->Enqueue(queue_itf,
audio,
total_bytes);
if (res != SL_RESULT_SUCCESS) {
WEBRTC_OPENSL_TRACE(kTraceWarning, kTraceAudioDevice, id_,
" recorder callback Enqueue failed, %d", res);
CriticalSectionScoped lock(&crit_sect_);
rec_warning_ = 1;
return;
} else {
rec_queue_.push(audio);
}
// TODO(leozwang): OpenSL ES doesn't support AudioRecorder
// volume control now, add it when it's ready.
}
void AudioDeviceAndroidOpenSLES::CheckErr(SLresult res) {
@ -1458,6 +1493,7 @@ int32_t AudioDeviceAndroidOpenSLES::InitSampleRate() {
mic_sampling_rate_ = N_REC_SAMPLES_PER_SEC;
speaker_sampling_rate_ = N_PLAY_SAMPLES_PER_SEC;
UpdateRecordingDelay();
WEBRTC_OPENSL_TRACE(kTraceStateInfo, kTraceAudioDevice, id_,
" mic sample rate (%d), speaker sample rate (%d)",