Index: content/renderer/media/media_stream_audio_source.cc |
diff --git a/content/renderer/media/media_stream_audio_source.cc b/content/renderer/media/media_stream_audio_source.cc |
index d2027fd939e797db1171625fcf469f8466c2fd36..4ddae4ed06c76d8f9261d73d43ffe0be09239fb5 100644 |
--- a/content/renderer/media/media_stream_audio_source.cc |
+++ b/content/renderer/media/media_stream_audio_source.cc |
@@ -4,29 +4,29 @@ |
#include "content/renderer/media/media_stream_audio_source.h" |
-#include "content/renderer/media/webrtc_local_audio_track.h" |
-#include "content/renderer/render_frame_impl.h" |
+#include <algorithm> |
+ |
+#include "base/bind.h" |
+#include "content/renderer/media/media_stream_audio_track.h" |
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h" |
+#include "third_party/WebKit/public/platform/WebString.h" |
namespace content { |
-MediaStreamAudioSource::MediaStreamAudioSource( |
- int render_frame_id, |
- const StreamDeviceInfo& device_info, |
- const SourceStoppedCallback& stop_callback, |
- PeerConnectionDependencyFactory* factory) |
- : render_frame_id_(render_frame_id), factory_(factory), |
+MediaStreamAudioSource::MediaStreamAudioSource(bool is_local_source) |
+ : is_stopped_(false), |
+ is_local_source_(is_local_source), |
weak_factory_(this) { |
- SetDeviceInfo(device_info); |
- SetStopCallback(stop_callback); |
+ DVLOG(1) << "MediaStreamAudioSource::MediaStreamAudioSource(is a " |
+ << (is_local_source_ ? "local" : "remote") << " source)"; |
} |
-MediaStreamAudioSource::MediaStreamAudioSource() |
- : render_frame_id_(-1), factory_(NULL), weak_factory_(this) { |
+MediaStreamAudioSource::~MediaStreamAudioSource() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DVLOG(1) << "MediaStreamAudioSource::~MediaStreamAudioSource()"; |
+ DCHECK(is_stopped_) << "BUG: Subclass must ensure StopSource() is called."; |
o1ka
2016/03/30 15:00:57
Since this flag is supposed to be set by a child c
miu
2016/03/31 04:57:59
Fixed. As described in a comment below, I reworke
|
} |
-MediaStreamAudioSource::~MediaStreamAudioSource() {} |
- |
// static |
MediaStreamAudioSource* MediaStreamAudioSource::From( |
const blink::WebMediaStreamSource& source) { |
@@ -37,50 +37,122 @@ MediaStreamAudioSource* MediaStreamAudioSource::From( |
return static_cast<MediaStreamAudioSource*>(source.getExtraData()); |
} |
+bool MediaStreamAudioSource::ConnectToTrack( |
+ const blink::WebMediaStreamTrack& track) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(!track.isNull()); |
+ |
+ // Sanity-check that there is not already a MediaStreamAudioTrack instance |
+ // associated with |track|. |
+ if (MediaStreamAudioTrack::From(track)) { |
+ LOG(DFATAL) |
+ << "Attempting to connect another source to a WebMediaStreamTrack."; |
+ return false; |
+ } |
+ |
+ if (!EnsureSourceIsStarted()) |
+ return false; |
+ ConnectStartedSourceToTrack(track); |
+ return true; |
+} |
+ |
+media::AudioParameters MediaStreamAudioSource::GetAudioParameters() const { |
+ base::AutoLock auto_lock(lock_); |
+ return params_; |
+} |
+ |
+void* MediaStreamAudioSource::GetClassIdentifier() const { |
+ return nullptr; |
+} |
+ |
+scoped_ptr<MediaStreamAudioTrack> |
+MediaStreamAudioSource::CreateMediaStreamAudioTrack(const std::string& id) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ return make_scoped_ptr(new MediaStreamAudioTrack(is_local_source())); |
+} |
+ |
void MediaStreamAudioSource::DoStopSource() { |
- if (audio_capturer_) |
- audio_capturer_->Stop(); |
- if (webaudio_capturer_) |
- webaudio_capturer_->Stop(); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DVLOG(1) << "MediaStreamAudioSource::DoStopSource()"; |
+ if (is_stopped_) |
+ return; |
+ is_stopped_ = true; |
} |
-void MediaStreamAudioSource::AddTrack( |
- const blink::WebMediaStreamTrack& track, |
- const blink::WebMediaConstraints& constraints, |
- const ConstraintsCallback& callback) { |
- // TODO(xians): Properly implement for audio sources. |
- if (!local_audio_source_.get()) { |
- if (!factory_->InitializeMediaStreamAudioSource(render_frame_id_, |
- constraints, this)) { |
- // The source failed to start. |
- // UserMediaClientImpl rely on the |stop_callback| to be triggered when |
- // the last track is removed from the source. But in this case, the |
- // source is is not even started. So we need to fail both adding the |
- // track and trigger |stop_callback|. |
- callback.Run(this, MEDIA_DEVICE_TRACK_START_FAILURE, ""); |
- StopSource(); |
- return; |
- } |
- } |
+bool MediaStreamAudioSource::EnsureSourceIsStarted() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DVLOG(1) << "MediaStreamAudioSource::EnsureSourceIsStarted()"; |
+ if (is_stopped_) |
+ return false; |
+ return true; |
+} |
- factory_->CreateLocalAudioTrack(track); |
- callback.Run(this, MEDIA_DEVICE_OK, ""); |
+void MediaStreamAudioSource::SetFormat(const media::AudioParameters& params) { |
+ // Note: May be called on any thread. |
+ DCHECK(params.IsValid()); |
+ base::AutoLock auto_lock(lock_); |
+ DVLOG(1) << "MediaStreamAudioSource::SetFormat(" |
+ << params.AsHumanReadableString() << "), was previously set to {" |
+ << params_.AsHumanReadableString() << "}."; |
+ if (params_.Equals(params)) |
+ return; |
+ params_ = params; |
+ for (MediaStreamAudioTrack* track : tracks_) |
+ track->SetFormat(params); |
} |
-void MediaStreamAudioSource::StopAudioDeliveryTo(MediaStreamAudioTrack* track) { |
- DCHECK(track); |
- if (audio_capturer_) { |
- // The cast here is safe because only WebRtcLocalAudioTracks are ever used |
- // with WebRtcAudioCapturer sources. |
- // |
- // TODO(miu): That said, this ugly cast won't be necessary after my |
- // soon-upcoming refactoring change. |
- audio_capturer_->RemoveTrack(static_cast<WebRtcLocalAudioTrack*>(track)); |
+void MediaStreamAudioSource::DeliverDataToTracks( |
+ const media::AudioBus& audio_bus, |
+ base::TimeTicks reference_time) { |
+ // Note: May be called on any thread. |
+ base::AutoLock auto_lock(lock_); |
+ DCHECK(params_.IsValid()); |
+ for (MediaStreamAudioTrack* track : tracks_) |
+ track->DeliverDataToSinks(audio_bus, reference_time); |
+} |
+ |
+void MediaStreamAudioSource::ConnectStartedSourceToTrack( |
+ const blink::WebMediaStreamTrack& blink_track) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(!is_stopped_); |
+ |
+ // Create a MediaStreamAudioTrack to deliver audio data directly from the |
+ // calls to Capture() to all its managed sinks. Pass ownership of it to the |
+ // WebMediaStreamTrack. |
+ scoped_ptr<MediaStreamAudioTrack> track = |
+ CreateMediaStreamAudioTrack(blink_track.id().utf8()); |
+ track->Start(base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo, |
+ weak_factory_.GetWeakPtr(), track.get())); |
+ track->SetEnabled(blink_track.isEnabled()); |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ if (params_.IsValid()) |
+ track->SetFormat(params_); |
+ tracks_.push_back(track.get()); |
} |
- if (webaudio_capturer_) { |
- // A separate source is created for each track, so just stop the source. |
- webaudio_capturer_->Stop(); |
+ blink::WebMediaStreamTrack mutable_blink_track = blink_track; |
+ mutable_blink_track.setExtraData(track.release()); |
+} |
+ |
+void MediaStreamAudioSource::StopAudioDeliveryTo(MediaStreamAudioTrack* track) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ // Remove |track| from the list of tracks, which will immediatly halt all |
+ // further audio data delivery. |
+ bool did_remove_last_track = false; |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ const bool had_tracks = !tracks_.empty(); |
+ const auto it = std::find(tracks_.begin(), tracks_.end(), track); |
+ if (it != tracks_.end()) |
+ tracks_.erase(it); |
+ did_remove_last_track = had_tracks && tracks_.empty(); |
} |
+ // TODO(miu): Is this the behavior we want? Perhaps sources should be |
+ // explicitly closed, rather than auto-stop on the removal of the last track |
+ // (behavior preserved from the defunct WebRtcAudioCapturer::RemoveTrack())? |
+ if (!is_stopped_ && did_remove_last_track) |
+ StopSource(); |
} |
} // namespace content |