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

Unified Diff: content/renderer/media/webrtc_audio_capturer.cc

Issue 11783059: Ensures that WebRTC works for device selection using a different sample rate than default (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix after review from Chris Created 7 years, 11 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 | « content/renderer/media/webrtc_audio_capturer.h ('k') | content/renderer/media/webrtc_audio_device_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/renderer/media/webrtc_audio_capturer.cc
diff --git a/content/renderer/media/webrtc_audio_capturer.cc b/content/renderer/media/webrtc_audio_capturer.cc
index c668a979d462ca166d406e2791ab98586f1448c9..16836f2a7d900d8cef99e23dc514596f7679e3e8 100644
--- a/content/renderer/media/webrtc_audio_capturer.cc
+++ b/content/renderer/media/webrtc_audio_capturer.cc
@@ -44,7 +44,7 @@ static int GetBufferSizeForSampleRate(int sample_rate) {
} else {
buffer_size = (sample_rate / 100);
DCHECK_EQ(buffer_size * 100, sample_rate) <<
- "Sample rate not supported. Should have been caught in Init().";
+ "Sample rate not supported";
}
#elif defined(OS_LINUX) || defined(OS_OPENBSD)
// Based on tests using the current ALSA implementation in Chrome, we have
@@ -61,35 +61,92 @@ static int GetBufferSizeForSampleRate(int sample_rate) {
// static
scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() {
scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer();
- if (capturer->Initialize())
- return capturer;
+ return capturer;
+}
+
+bool WebRtcAudioCapturer::Initialize(media::ChannelLayout channel_layout,
+ int sample_rate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!sinks_.empty());
+ DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
+
+ media::AudioParameters::Format format =
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
+
+ DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
+ UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
+ channel_layout, media::CHANNEL_LAYOUT_MAX);
+
+ // Verify that the reported input channel configuration is supported.
+ if (channel_layout != media::CHANNEL_LAYOUT_MONO &&
+ channel_layout != media::CHANNEL_LAYOUT_STEREO) {
+ DLOG(ERROR) << channel_layout
+ << " is not a supported input channel configuration.";
+ return false;
+ }
+
+ DVLOG(1) << "Audio input hardware sample rate: " << sample_rate;
+ UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputSampleRate",
+ sample_rate, media::kUnexpectedAudioSampleRate);
+
+ // Verify that the reported input hardware sample rate is supported
+ // on the current platform.
+ if (std::find(&kValidInputRates[0],
+ &kValidInputRates[0] + arraysize(kValidInputRates),
+ sample_rate) ==
+ &kValidInputRates[arraysize(kValidInputRates)]) {
+ DLOG(ERROR) << sample_rate << " is not a supported input rate.";
+ return false;
+ }
+
+ int buffer_size = GetBufferSizeForSampleRate(sample_rate);
+
+ // Configure audio parameters for the default source.
+ params_.Reset(format, channel_layout, sample_rate, 16, buffer_size);
- return NULL;
+ // Tell all sinks which format we use.
+ for (SinkList::const_iterator it = sinks_.begin();
+ it != sinks_.end(); ++it) {
+ (*it)->SetCaptureFormat(params_);
+ }
+
+ buffer_.reset(new int16[params_.frames_per_buffer() * params_.channels()]);
+
+ // Create and configure the default audio capturing source. The |source_|
+ // will be overwritten if an external client later calls SetCapturerSource()
+ // providing an alternaive media::AudioCapturerSource.
+ SetCapturerSource(AudioDeviceFactory::NewInputDevice(),
+ channel_layout,
+ static_cast<float>(sample_rate));
+
+ return true;
}
WebRtcAudioCapturer::WebRtcAudioCapturer()
: source_(NULL),
running_(false),
buffering_(false) {
+ DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()";
}
WebRtcAudioCapturer::~WebRtcAudioCapturer() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(sinks_.empty());
DCHECK(!loopback_fifo_);
+ DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()";
}
void WebRtcAudioCapturer::AddCapturerSink(WebRtcAudioCapturerSink* sink) {
- {
- base::AutoLock auto_lock(lock_);
- DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
- sinks_.push_back(sink);
- }
-
- // Tell the |sink| which format we use.
- sink->SetCaptureFormat(params_);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "WebRtcAudioCapturer::AddCapturerSink()";
+ base::AutoLock auto_lock(lock_);
+ DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
+ sinks_.push_back(sink);
}
void WebRtcAudioCapturer::RemoveCapturerSink(WebRtcAudioCapturerSink* sink) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "WebRtcAudioCapturer::RemoveCapturerSink()";
base::AutoLock auto_lock(lock_);
for (SinkList::iterator it = sinks_.begin(); it != sinks_.end(); ++it) {
if (sink == *it) {
@@ -103,7 +160,8 @@ void WebRtcAudioCapturer::SetCapturerSource(
const scoped_refptr<media::AudioCapturerSource>& source,
media::ChannelLayout channel_layout,
float sample_rate) {
- DVLOG(1) << "SetCapturerSource()";
+ DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << ","
+ << "sample_rate=" << sample_rate << ")";
scoped_refptr<media::AudioCapturerSource> old_source;
{
base::AutoLock auto_lock(lock_);
@@ -114,9 +172,16 @@ void WebRtcAudioCapturer::SetCapturerSource(
source_ = source;
}
- // Detach the old source from normal recording.
- if (old_source) {
- old_source->Stop();
+ const bool no_default_audio_source_exists = !buffer_.get();
+
+ // Detach the old source from normal recording or perform first-time
+ // initialization if Initialize() has never been called. For the second
+ // case, the caller is not "taking over an ongoing session" but instead
+ // "taking control over a new session".
+ if (old_source || no_default_audio_source_exists) {
+ DVLOG(1) << "New capture source will now be utilized.";
+ if (old_source)
+ old_source->Stop();
// Dispatch the new parameters both to the sink(s) and to the new source.
// The idea is to get rid of any dependency of the microphone parameters
@@ -148,12 +213,14 @@ void WebRtcAudioCapturer::SetCapturerSource(
void WebRtcAudioCapturer::SetStopCallback(
const base::Closure& on_device_stopped_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::SetStopCallback()";
base::AutoLock auto_lock(lock_);
on_device_stopped_cb_ = on_device_stopped_cb;
}
void WebRtcAudioCapturer::PrepareLoopback() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::PrepareLoopback()";
base::AutoLock auto_lock(lock_);
DCHECK(!loopback_fifo_);
@@ -172,6 +239,7 @@ void WebRtcAudioCapturer::PrepareLoopback() {
}
void WebRtcAudioCapturer::CancelLoopback() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::CancelLoopback()";
base::AutoLock auto_lock(lock_);
buffering_ = false;
@@ -182,12 +250,14 @@ void WebRtcAudioCapturer::CancelLoopback() {
}
void WebRtcAudioCapturer::PauseBuffering() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::PauseBuffering()";
base::AutoLock auto_lock(lock_);
buffering_ = false;
}
void WebRtcAudioCapturer::ResumeBuffering() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::ResumeBuffering()";
base::AutoLock auto_lock(lock_);
if (buffering_)
@@ -197,56 +267,6 @@ void WebRtcAudioCapturer::ResumeBuffering() {
buffering_ = true;
}
-bool WebRtcAudioCapturer::Initialize() {
- DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
- // Ask the browser for the default audio input hardware sample-rate.
- // This request is based on a synchronous IPC message.
- // TODO(xians): we should ask for the native sample rate of a specific device.
- int sample_rate = GetAudioInputSampleRate();
- DVLOG(1) << "Audio input hardware sample rate: " << sample_rate;
- UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputSampleRate",
- sample_rate, media::kUnexpectedAudioSampleRate);
-
- // Verify that the reported input hardware sample rate is supported
- // on the current platform.
- if (std::find(&kValidInputRates[0],
- &kValidInputRates[0] + arraysize(kValidInputRates),
- sample_rate) ==
- &kValidInputRates[arraysize(kValidInputRates)]) {
- DLOG(ERROR) << sample_rate << " is not a supported input rate.";
- return false;
- }
-
- // Ask the browser for the default number of audio input channels.
- // This request is based on a synchronous IPC message.
- // TODO(xians): we should ask for the layout of a specific device.
- media::ChannelLayout channel_layout = GetAudioInputChannelLayout();
- DVLOG(1) << "Audio input hardware channels: " << channel_layout;
-
- media::AudioParameters::Format format =
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
- int buffer_size = GetBufferSizeForSampleRate(sample_rate);
- if (!buffer_size) {
- DLOG(ERROR) << "Unsupported platform";
- return false;
- }
-
- params_.Reset(format, channel_layout, sample_rate, 16, buffer_size);
-
- buffer_.reset(new int16[params_.frames_per_buffer() * params_.channels()]);
-
- // Create and configure the default audio capturing source. The |source_|
- // will be overwritten if the client call the source calls
- // SetCapturerSource().
- SetCapturerSource(
- AudioDeviceFactory::NewInputDevice(), channel_layout, sample_rate);
-
- UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
- channel_layout, media::CHANNEL_LAYOUT_MAX);
-
- return true;
-}
-
void WebRtcAudioCapturer::ProvideInput(media::AudioBus* dest) {
base::AutoLock auto_lock(lock_);
DCHECK(loopback_fifo_.get() != NULL);
@@ -264,7 +284,7 @@ void WebRtcAudioCapturer::ProvideInput(media::AudioBus* dest) {
dest->Zero();
// This warning is perfectly safe if it happens for the first audio
// frames. It should not happen in a steady-state mode.
- DLOG(WARNING) << "WARNING: loopback FIFO is empty.";
+ DVLOG(2) << "WARNING: loopback FIFO is empty.";
}
}
@@ -308,12 +328,12 @@ void WebRtcAudioCapturer::Stop() {
void WebRtcAudioCapturer::SetVolume(double volume) {
DVLOG(1) << "WebRtcAudioCapturer::SetVolume()";
base::AutoLock auto_lock(lock_);
-
if (source_)
source_->SetVolume(volume);
}
void WebRtcAudioCapturer::SetDevice(int session_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::SetDevice(" << session_id << ")";
base::AutoLock auto_lock(lock_);
if (source_)
@@ -327,6 +347,7 @@ void WebRtcAudioCapturer::SetAutomaticGainControl(bool enable) {
}
bool WebRtcAudioCapturer::IsInLoopbackMode() {
+ DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
return (loopback_fifo_ != NULL);
}
« no previous file with comments | « content/renderer/media/webrtc_audio_capturer.h ('k') | content/renderer/media/webrtc_audio_device_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698