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..efe1720ffc84b751d40b258cd4e6db1bef18d63b 100644 | 
| --- a/content/renderer/media/media_stream_audio_source.cc | 
| +++ b/content/renderer/media/media_stream_audio_source.cc | 
| @@ -4,29 +4,26 @@ | 
| #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 "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_local_source_(is_local_source), | 
| + is_stopped_(false), | 
| weak_factory_(this) { | 
| - SetDeviceInfo(device_info); | 
| - SetStopCallback(stop_callback); | 
| + DVLOG(1) << "MediaStreamAudioSource@" << this << "::MediaStreamAudioSource(" | 
| + << (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@" << this << " is being destroyed."; | 
| } | 
| -MediaStreamAudioSource::~MediaStreamAudioSource() {} | 
| - | 
| // static | 
| MediaStreamAudioSource* MediaStreamAudioSource::From( | 
| const blink::WebMediaStreamSource& source) { | 
| @@ -37,50 +34,104 @@ MediaStreamAudioSource* MediaStreamAudioSource::From( | 
| return static_cast<MediaStreamAudioSource*>(source.getExtraData()); | 
| } | 
| -void MediaStreamAudioSource::DoStopSource() { | 
| - if (audio_capturer_) | 
| - audio_capturer_->Stop(); | 
| - if (webaudio_capturer_) | 
| - webaudio_capturer_->Stop(); | 
| -} | 
| +bool MediaStreamAudioSource::ConnectToTrack( | 
| + const blink::WebMediaStreamTrack& blink_track) { | 
| + DCHECK(thread_checker_.CalledOnValidThread()); | 
| + DCHECK(!blink_track.isNull()); | 
| -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; | 
| - } | 
| + // Sanity-check that there is not already a MediaStreamAudioTrack instance | 
| + // associated with |blink_track|. | 
| + if (MediaStreamAudioTrack::From(blink_track)) { | 
| + LOG(DFATAL) | 
| + << "Attempting to connect another source to a WebMediaStreamTrack."; | 
| + return false; | 
| } | 
| - factory_->CreateLocalAudioTrack(track); | 
| - callback.Run(this, MEDIA_DEVICE_OK, ""); | 
| + // Unless the source has already been permanently stopped, ensure it is | 
| + // started. If the source is not started, the new MediaStreamAudioTrack will | 
| + // be initialized to the stopped/ended state. | 
| + const bool initializing_ended_track = is_stopped_ || !EnsureSourceIsStarted(); | 
| + | 
| + // Create and initialize a new MediaStreamAudioTrack and pass ownership of it | 
| + // to the WebMediaStreamTrack. | 
| + blink::WebMediaStreamTrack mutable_blink_track = blink_track; | 
| + mutable_blink_track.setExtraData( | 
| + CreateMediaStreamAudioTrack(blink_track.id().utf8()).release()); | 
| + | 
| + // Start the track and add it as a consumer of audio from this source. | 
| + MediaStreamAudioTrack* const track = MediaStreamAudioTrack::From(blink_track); | 
| + DCHECK(track); | 
| + track->Start(base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo, | 
| + weak_factory_.GetWeakPtr(), track)); | 
| + track->SetEnabled(blink_track.isEnabled()); | 
| + DVLOG(1) << "Adding MediaStreamAudioTrack@" << track | 
| + << " as a consumer of MediaStreamAudioSource@" << this << '.'; | 
| + deliverer_.AddConsumer(track); | 
| + | 
| + // If the source failed to start, or has already been permanently stopped, | 
| + // stop the track to set its ready state to "ended." | 
| 
 
o1ka
2016/04/21 18:51:22
"ended."->"ended".
It's not quite clear what "read
 
miu
2016/04/21 20:42:30
Done.
 
o1ka
2016/04/22 11:29:25
Yes, I realized it, the problem about the comment
 
 | 
| + if (initializing_ended_track) | 
| + track->Stop(); | 
| 
 
o1ka
2016/04/21 18:51:22
Consumer is added at l.69 and it is removed here w
 
miu
2016/04/21 20:42:30
It was.  Per suggested (previous round of comments
 
o1ka
2016/04/22 11:29:25
Yes, I understand the reason of a changed, just wa
 
 | 
| + | 
| + return !initializing_ended_track; | 
| +} | 
| + | 
| +media::AudioParameters MediaStreamAudioSource::GetAudioParameters() const { | 
| + return deliverer_.GetAudioParameters(); | 
| +} | 
| + | 
| +void* MediaStreamAudioSource::GetClassIdentifier() const { | 
| + return nullptr; | 
| +} | 
| + | 
| +std::unique_ptr<MediaStreamAudioTrack> | 
| +MediaStreamAudioSource::CreateMediaStreamAudioTrack(const std::string& id) { | 
| + DCHECK(thread_checker_.CalledOnValidThread()); | 
| + return std::unique_ptr<MediaStreamAudioTrack>( | 
| + new MediaStreamAudioTrack(is_local_source())); | 
| +} | 
| + | 
| +bool MediaStreamAudioSource::EnsureSourceIsStarted() { | 
| + DCHECK(thread_checker_.CalledOnValidThread()); | 
| + DVLOG(1) << "MediaStreamAudioSource@" << this << "::EnsureSourceIsStarted()"; | 
| + return true; | 
| +} | 
| + | 
| +void MediaStreamAudioSource::EnsureSourceIsStopped() { | 
| + DCHECK(thread_checker_.CalledOnValidThread()); | 
| + DVLOG(1) << "MediaStreamAudioSource@" << this << "::EnsureSourceIsStopped()"; | 
| +} | 
| + | 
| +void MediaStreamAudioSource::SetFormat(const media::AudioParameters& params) { | 
| + DVLOG(1) << "MediaStreamAudioSource@" << this << "::SetFormat(" | 
| + << params.AsHumanReadableString() << "), was previously set to {" | 
| + << deliverer_.GetAudioParameters().AsHumanReadableString() << "}."; | 
| + deliverer_.OnSetFormat(params); | 
| +} | 
| + | 
| +void MediaStreamAudioSource::DeliverDataToTracks( | 
| + const media::AudioBus& audio_bus, | 
| + base::TimeTicks reference_time) { | 
| + deliverer_.OnData(audio_bus, reference_time); | 
| +} | 
| + | 
| +void MediaStreamAudioSource::DoStopSource() { | 
| + DCHECK(thread_checker_.CalledOnValidThread()); | 
| + EnsureSourceIsStopped(); | 
| + is_stopped_ = true; | 
| } | 
| 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)); | 
| - } | 
| - if (webaudio_capturer_) { | 
| - // A separate source is created for each track, so just stop the source. | 
| - webaudio_capturer_->Stop(); | 
| - } | 
| + DCHECK(thread_checker_.CalledOnValidThread()); | 
| + | 
| + const bool did_remove_last_track = deliverer_.RemoveConsumer(track); | 
| + DVLOG(1) << "Removed MediaStreamAudioTrack@" << track | 
| + << " as a consumer of MediaStreamAudioSource@" << this << '.'; | 
| + | 
| + // The W3C spec requires a source automatically stop when the last track is | 
| + // stopped. | 
| + if (!is_stopped_ && did_remove_last_track) | 
| + MediaStreamSource::StopSource(); | 
| } | 
| } // namespace content |