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..6e99deb54cda931b947c7511889371100fe7b57f 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, ""); |
+ // Unless the source has already been permanently stopped, ensure it is |
+ // started. If the source cannot start, the new MediaStreamAudioTrack will be |
+ // initialized to the stopped/ended state. |
+ if (!is_stopped_) { |
+ if (!EnsureSourceIsStarted()) |
StopSource(); |
- return; |
- } |
} |
- 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()); |
+ |
+ // Propagate initial "enabled" state. |
+ MediaStreamAudioTrack* const track = MediaStreamAudioTrack::From(blink_track); |
+ DCHECK(track); |
+ track->SetEnabled(blink_track.isEnabled()); |
+ |
+ // If the source is stopped, do not start the track. |
+ if (is_stopped_) |
+ return false; |
+ |
+ track->Start(base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo, |
+ weak_factory_.GetWeakPtr(), track)); |
+ DVLOG(1) << "Adding MediaStreamAudioTrack@" << track |
+ << " as a consumer of MediaStreamAudioSource@" << this << '.'; |
+ deliverer_.AddConsumer(track); |
+ 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 |