Index: content/renderer/media/local_media_stream_audio_source.cc |
diff --git a/content/renderer/media/local_media_stream_audio_source.cc b/content/renderer/media/local_media_stream_audio_source.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..36aee8cf4a3a1f9346c8e898a68de98aafa974bd |
--- /dev/null |
+++ b/content/renderer/media/local_media_stream_audio_source.cc |
@@ -0,0 +1,99 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/renderer/media/local_media_stream_audio_source.h" |
+ |
+#include "content/renderer/media/audio_device_factory.h" |
+#include "content/renderer/render_frame_impl.h" |
+ |
+namespace content { |
+ |
+LocalMediaStreamAudioSource::LocalMediaStreamAudioSource( |
+ int consumer_render_frame_id, |
+ const StreamDeviceInfo& device_info) |
+ : MediaStreamAudioSource(true /* is_local_source */), |
+ consumer_render_frame_id_(consumer_render_frame_id), |
+ session_id_(device_info.session_id) { |
+ DVLOG(1) << "LocalMediaStreamAudioSource::LocalMediaStreamAudioSource()"; |
+ MediaStreamSource::SetDeviceInfo(device_info); |
+ MediaStreamAudioSource::SetFormat(media::AudioParameters( |
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
+ static_cast<media::ChannelLayout>( |
+ device_info.device.input.channel_layout), |
+ device_info.device.input.sample_rate, |
+ 16, // Legacy parameter (data is always in 32-bit float format). |
+ // If specified, use frames_per_buffer; else, default to 10 ms. |
+ device_info.device.input.frames_per_buffer > 0 ? |
+ device_info.device.input.frames_per_buffer : |
+ device_info.device.input.sample_rate / 100)); |
+} |
+ |
+LocalMediaStreamAudioSource::~LocalMediaStreamAudioSource() { |
+ DVLOG(1) << "LocalMediaStreamAudioSource::~LocalMediaStreamAudioSource()"; |
+ // Superclass will call StopSource() just in case. |
+} |
+ |
+void LocalMediaStreamAudioSource::DoStopSource() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (is_stopped_) |
+ return; |
+ if (input_device_) { |
+ input_device_->Stop(); |
+ input_device_ = nullptr; |
+ VLOG(1) << "Stopped local audio input device (session_id=" << session_id_ |
+ << ") for render frame " << consumer_render_frame_id_ |
+ << " with audio parameters={" |
+ << GetAudioParameters().AsHumanReadableString() << "}."; |
+ } |
+ is_stopped_ = true; |
+} |
+ |
+bool LocalMediaStreamAudioSource::EnsureSourceIsStarted() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (is_stopped_) |
+ return false; |
+ if (input_device_) |
+ return true; |
+ |
+ // Sanity-check that the consuming RenderFrame still exists. This is |
+ // required by AudioDeviceFactory. |
+ if (!RenderFrameImpl::FromRoutingID(consumer_render_frame_id_)) { |
+ StopSource(); |
+ return false; |
+ } |
+ |
+ VLOG(1) << "Starting local audio input device (session_id=" << session_id_ |
+ << ") for render frame " << consumer_render_frame_id_ |
+ << " with audio parameters={" |
+ << GetAudioParameters().AsHumanReadableString() << "}."; |
+ |
+ input_device_ = AudioDeviceFactory::NewInputDevice(consumer_render_frame_id_); |
+ input_device_->Initialize(GetAudioParameters(), this, session_id_); |
+ input_device_->Start(); |
+ return true; |
+} |
+ |
+void LocalMediaStreamAudioSource::Capture(const media::AudioBus* audio_bus, |
+ int audio_delay_milliseconds, |
+ double volume, |
+ bool key_pressed) { |
+ DCHECK(audio_bus); |
+ // TODO(miu): Plumbing is needed to determine the actual capture timestamp |
+ // of the audio, instead of just snapshotting TimeTicks::Now(), for proper |
+ // audio/video sync. http://crbug.com/335335 |
+ MediaStreamAudioSource::DeliverDataToTracks( |
+ *audio_bus, |
+ base::TimeTicks::Now() - |
+ base::TimeDelta::FromMilliseconds(audio_delay_milliseconds)); |
+} |
+ |
+void LocalMediaStreamAudioSource::OnCaptureError(const std::string& why) { |
+ // As of this writing, this method doesn't get called for anything useful, |
+ // and all other implementors just log the message, but don't disconnect sinks |
+ // or take any other action. So, just log the error. |
+ LOG(ERROR) << why; |
+} |
+ |
+} // namespace content |