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..e3028d6235babe486bf9f9ee5b59eeb8c880c674 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,106 @@ 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()); |
| + |
| + // 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; |
| + } |
| -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; |
| - } |
| + // Unless the source has already been permanently stopped, ensure it is |
| + // started. |
| + if (!is_stopped_) { |
| + if (!EnsureSourceIsStarted()) |
| + return false; |
|
perkj_chrome
2016/04/20 13:34:54
is it safe to return here? ie- that means that the
miu
2016/04/20 22:04:52
Done. I see your point. Agree that it's safer to
|
| } |
| - factory_->CreateLocalAudioTrack(track); |
| - callback.Run(this, MEDIA_DEVICE_OK, ""); |
| + // 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 has already been permanently stopped, stop the track to set |
| + // its ready state to "ended." |
| + if (is_stopped_) |
| + track->Stop(); |
| + |
| + return true; |
| +} |
| + |
| +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 |