Chromium Code Reviews| 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 |