diff options
Diffstat (limited to 'chromium/content/renderer/media/webrtc')
69 files changed, 5298 insertions, 4115 deletions
diff --git a/chromium/content/renderer/media/webrtc/audio_codec_factory.cc b/chromium/content/renderer/media/webrtc/audio_codec_factory.cc index be2d15aa1c5..73abab19515 100644 --- a/chromium/content/renderer/media/webrtc/audio_codec_factory.cc +++ b/chromium/content/renderer/media/webrtc/audio_codec_factory.cc @@ -28,7 +28,7 @@ namespace { template <typename T> struct NotAdvertisedEncoder { using Config = typename T::Config; - static rtc::Optional<Config> SdpToConfig( + static absl::optional<Config> SdpToConfig( const webrtc::SdpAudioFormat& audio_format) { return T::SdpToConfig(audio_format); } @@ -42,7 +42,7 @@ struct NotAdvertisedEncoder { static std::unique_ptr<webrtc::AudioEncoder> MakeAudioEncoder( const Config& config, int payload_type, - rtc::Optional<webrtc::AudioCodecPairId> codec_pair_id) { + absl::optional<webrtc::AudioCodecPairId> codec_pair_id) { return T::MakeAudioEncoder(config, payload_type, codec_pair_id); } }; @@ -51,7 +51,7 @@ struct NotAdvertisedEncoder { template <typename T> struct NotAdvertisedDecoder { using Config = typename T::Config; - static rtc::Optional<Config> SdpToConfig( + static absl::optional<Config> SdpToConfig( const webrtc::SdpAudioFormat& audio_format) { return T::SdpToConfig(audio_format); } @@ -61,7 +61,7 @@ struct NotAdvertisedDecoder { } static std::unique_ptr<webrtc::AudioDecoder> MakeAudioDecoder( const Config& config, - rtc::Optional<webrtc::AudioCodecPairId> codec_pair_id) { + absl::optional<webrtc::AudioCodecPairId> codec_pair_id) { return T::MakeAudioDecoder(config, codec_pair_id); } }; diff --git a/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc new file mode 100644 index 00000000000..acb9937d405 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc @@ -0,0 +1,193 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h" + +namespace content { + +blink::WebMediaStreamTrack CreateWebMediaStreamTrack(const std::string& id) { + blink::WebMediaStreamSource web_source; + web_source.Initialize(blink::WebString::FromUTF8(id), + blink::WebMediaStreamSource::kTypeAudio, + blink::WebString::FromUTF8("audio_track"), false); + MediaStreamAudioSource* audio_source = new MediaStreamAudioSource(true); + // Takes ownership of |audio_source|. + web_source.SetExtraData(audio_source); + + blink::WebMediaStreamTrack web_track; + web_track.Initialize(web_source.Id(), web_source); + audio_source->ConnectToTrack(web_track); + return web_track; +} + +FakeRTCRtpSender::FakeRTCRtpSender(base::Optional<std::string> track_id, + std::vector<std::string> stream_ids) + : track_id_(std::move(track_id)), stream_ids_(std::move(stream_ids)) {} + +FakeRTCRtpSender::FakeRTCRtpSender(const FakeRTCRtpSender&) = default; + +FakeRTCRtpSender::~FakeRTCRtpSender() {} + +FakeRTCRtpSender& FakeRTCRtpSender::operator=(const FakeRTCRtpSender&) = + default; + +std::unique_ptr<blink::WebRTCRtpSender> FakeRTCRtpSender::ShallowCopy() const { + return std::make_unique<FakeRTCRtpSender>(*this); +} + +uintptr_t FakeRTCRtpSender::Id() const { + NOTIMPLEMENTED(); + return 0; +} + +blink::WebMediaStreamTrack FakeRTCRtpSender::Track() const { + return track_id_ ? CreateWebMediaStreamTrack(*track_id_) + : blink::WebMediaStreamTrack(); // null +} + +blink::WebVector<blink::WebString> FakeRTCRtpSender::StreamIds() const { + blink::WebVector<blink::WebString> web_stream_ids(stream_ids_.size()); + for (size_t i = 0; i < stream_ids_.size(); ++i) { + web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids_[i]); + } + return web_stream_ids; +} + +void FakeRTCRtpSender::ReplaceTrack(blink::WebMediaStreamTrack with_track, + blink::WebRTCVoidRequest request) { + NOTIMPLEMENTED(); +} + +std::unique_ptr<blink::WebRTCDTMFSenderHandler> +FakeRTCRtpSender::GetDtmfSender() const { + NOTIMPLEMENTED(); + return nullptr; +} + +std::unique_ptr<webrtc::RtpParameters> FakeRTCRtpSender::GetParameters() const { + NOTIMPLEMENTED(); + return nullptr; +} + +void FakeRTCRtpSender::SetParameters( + blink::WebVector<webrtc::RtpEncodingParameters>, + webrtc::DegradationPreference, + blink::WebRTCVoidRequest) { + NOTIMPLEMENTED(); +} + +void FakeRTCRtpSender::GetStats( + std::unique_ptr<blink::WebRTCStatsReportCallback>) { + NOTIMPLEMENTED(); +} + +FakeRTCRtpReceiver::FakeRTCRtpReceiver(const std::string& track_id, + std::vector<std::string> stream_ids) + : track_(CreateWebMediaStreamTrack(track_id)), + stream_ids_(std::move(stream_ids)) {} + +FakeRTCRtpReceiver::FakeRTCRtpReceiver(const FakeRTCRtpReceiver&) = default; + +FakeRTCRtpReceiver::~FakeRTCRtpReceiver() {} + +FakeRTCRtpReceiver& FakeRTCRtpReceiver::operator=(const FakeRTCRtpReceiver&) = + default; + +std::unique_ptr<blink::WebRTCRtpReceiver> FakeRTCRtpReceiver::ShallowCopy() + const { + return std::make_unique<FakeRTCRtpReceiver>(*this); +} + +uintptr_t FakeRTCRtpReceiver::Id() const { + NOTIMPLEMENTED(); + return 0; +} + +const blink::WebMediaStreamTrack& FakeRTCRtpReceiver::Track() const { + return track_; +} + +blink::WebVector<blink::WebString> FakeRTCRtpReceiver::StreamIds() const { + blink::WebVector<blink::WebString> web_stream_ids(stream_ids_.size()); + for (size_t i = 0; i < stream_ids_.size(); ++i) { + web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids_[i]); + } + return web_stream_ids; +} + +blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> +FakeRTCRtpReceiver::GetSources() { + NOTIMPLEMENTED(); + return {}; +} + +void FakeRTCRtpReceiver::GetStats( + std::unique_ptr<blink::WebRTCStatsReportCallback>) { + NOTIMPLEMENTED(); +} + +FakeRTCRtpTransceiver::FakeRTCRtpTransceiver( + base::Optional<std::string> mid, + FakeRTCRtpSender sender, + FakeRTCRtpReceiver receiver, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction) + : mid_(std::move(mid)), + sender_(std::move(sender)), + receiver_(std::move(receiver)), + stopped_(stopped), + direction_(std::move(direction)), + current_direction_(std::move(current_direction)) {} + +FakeRTCRtpTransceiver::~FakeRTCRtpTransceiver() {} + +blink::WebRTCRtpTransceiverImplementationType +FakeRTCRtpTransceiver::ImplementationType() const { + return blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver; +} + +uintptr_t FakeRTCRtpTransceiver::Id() const { + NOTIMPLEMENTED(); + return 0u; +} + +blink::WebString FakeRTCRtpTransceiver::Mid() const { + return mid_ ? blink::WebString::FromUTF8(*mid_) : blink::WebString(); +} + +std::unique_ptr<blink::WebRTCRtpSender> FakeRTCRtpTransceiver::Sender() const { + return sender_.ShallowCopy(); +} + +std::unique_ptr<blink::WebRTCRtpReceiver> FakeRTCRtpTransceiver::Receiver() + const { + return receiver_.ShallowCopy(); +} + +bool FakeRTCRtpTransceiver::Stopped() const { + return stopped_; +} + +webrtc::RtpTransceiverDirection FakeRTCRtpTransceiver::Direction() const { + return direction_; +} + +void FakeRTCRtpTransceiver::SetDirection( + webrtc::RtpTransceiverDirection direction) { + NOTIMPLEMENTED(); +} + +base::Optional<webrtc::RtpTransceiverDirection> +FakeRTCRtpTransceiver::CurrentDirection() const { + return current_direction_; +} + +base::Optional<webrtc::RtpTransceiverDirection> +FakeRTCRtpTransceiver::FiredDirection() const { + NOTIMPLEMENTED(); + return base::nullopt; +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h new file mode 100644 index 00000000000..7f8dbfed61a --- /dev/null +++ b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h @@ -0,0 +1,111 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_FAKE_RTC_RTP_TRANSCEIVER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_FAKE_RTC_RTP_TRANSCEIVER_H_ + +#include <memory> + +#include "content/renderer/media/stream/media_stream_audio_source.h" +#include "third_party/blink/public/platform/web_media_constraints.h" +#include "third_party/blink/public/platform/web_media_stream_source.h" +#include "third_party/blink/public/platform/web_media_stream_track.h" +#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h" +#include "third_party/blink/public/platform/web_rtc_rtp_contributing_source.h" +#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h" +#include "third_party/blink/public/platform/web_rtc_rtp_sender.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" + +namespace content { + +// TODO(https://crbug.com/868868): Similar methods to this exist in many content +// unittests. Move to a separate file and reuse it in all of them. +blink::WebMediaStreamTrack CreateWebMediaStreamTrack(const std::string& id); + +class CONTENT_EXPORT FakeRTCRtpSender : public blink::WebRTCRtpSender { + public: + FakeRTCRtpSender(base::Optional<std::string> track_id, + std::vector<std::string> stream_ids); + FakeRTCRtpSender(const FakeRTCRtpSender&); + ~FakeRTCRtpSender() override; + FakeRTCRtpSender& operator=(const FakeRTCRtpSender&); + + std::unique_ptr<blink::WebRTCRtpSender> ShallowCopy() const override; + uintptr_t Id() const override; + blink::WebMediaStreamTrack Track() const override; + blink::WebVector<blink::WebString> StreamIds() const override; + void ReplaceTrack(blink::WebMediaStreamTrack with_track, + blink::WebRTCVoidRequest request) override; + std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender() + const override; + std::unique_ptr<webrtc::RtpParameters> GetParameters() const override; + void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters>, + webrtc::DegradationPreference, + blink::WebRTCVoidRequest) override; + void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override; + + private: + base::Optional<std::string> track_id_; + std::vector<std::string> stream_ids_; +}; + +class CONTENT_EXPORT FakeRTCRtpReceiver : public blink::WebRTCRtpReceiver { + public: + FakeRTCRtpReceiver(const std::string& track_id, + std::vector<std::string> stream_ids); + FakeRTCRtpReceiver(const FakeRTCRtpReceiver&); + ~FakeRTCRtpReceiver() override; + FakeRTCRtpReceiver& operator=(const FakeRTCRtpReceiver&); + + std::unique_ptr<blink::WebRTCRtpReceiver> ShallowCopy() const override; + uintptr_t Id() const override; + const blink::WebMediaStreamTrack& Track() const override; + blink::WebVector<blink::WebString> StreamIds() const override; + blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> + GetSources() override; + void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override; + + private: + blink::WebMediaStreamTrack track_; + std::vector<std::string> stream_ids_; +}; + +class CONTENT_EXPORT FakeRTCRtpTransceiver + : public blink::WebRTCRtpTransceiver { + public: + FakeRTCRtpTransceiver( + base::Optional<std::string> mid, + FakeRTCRtpSender sender, + FakeRTCRtpReceiver receiver, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction); + ~FakeRTCRtpTransceiver() override; + + blink::WebRTCRtpTransceiverImplementationType ImplementationType() + const override; + uintptr_t Id() const override; + blink::WebString Mid() const override; + std::unique_ptr<blink::WebRTCRtpSender> Sender() const override; + std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override; + bool Stopped() const override; + webrtc::RtpTransceiverDirection Direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection direction) override; + base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() + const override; + base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() + const override; + + private: + base::Optional<std::string> mid_; + FakeRTCRtpSender sender_; + FakeRTCRtpReceiver receiver_; + bool stopped_; + webrtc::RtpTransceiverDirection direction_; + base::Optional<webrtc::RtpTransceiverDirection> current_direction_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_FAKE_RTC_RTP_TRANSCEIVER_H_ diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc index eb85960b29c..0e810df0728 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc @@ -71,6 +71,7 @@ class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate // Timestamp of the first received frame. base::TimeDelta start_timestamp_; + // WebRTC Chromium timestamp diff const base::TimeDelta time_diff_; }; @@ -117,16 +118,16 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame( scoped_refptr<media::VideoFrame> video_frame; scoped_refptr<webrtc::VideoFrameBuffer> buffer( incoming_frame.video_frame_buffer()); + const gfx::Size size(buffer->width(), buffer->height()); - if (buffer->type() == webrtc::VideoFrameBuffer::Type::kNative) { - video_frame = static_cast<WebRtcVideoFrameAdapter*>(buffer.get()) - ->getMediaVideoFrame(); - video_frame->set_timestamp(elapsed_timestamp); - } else { - const gfx::Size size(buffer->width(), buffer->height()); - const bool has_alpha = - buffer->type() == webrtc::VideoFrameBuffer::Type::kI420A; - if (has_alpha) { + switch (buffer->type()) { + case webrtc::VideoFrameBuffer::Type::kNative: { + video_frame = static_cast<WebRtcVideoFrameAdapter*>(buffer.get()) + ->getMediaVideoFrame(); + video_frame->set_timestamp(elapsed_timestamp); + break; + } + case webrtc::VideoFrameBuffer::Type::kI420A: { const webrtc::I420ABufferInterface* yuva_buffer = buffer->GetI420A(); video_frame = media::VideoFrame::WrapExternalYuvaData( media::PIXEL_FORMAT_I420A, size, gfx::Rect(size), size, @@ -136,36 +137,64 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame( const_cast<uint8_t*>(yuva_buffer->DataU()), const_cast<uint8_t*>(yuva_buffer->DataV()), const_cast<uint8_t*>(yuva_buffer->DataA()), elapsed_timestamp); - } else { - scoped_refptr<webrtc::PlanarYuvBuffer> yuv_buffer; - media::VideoPixelFormat pixel_format; - if (buffer->type() == webrtc::VideoFrameBuffer::Type::kI444) { - yuv_buffer = buffer->GetI444(); - pixel_format = media::PIXEL_FORMAT_I444; - } else { - yuv_buffer = buffer->ToI420(); - pixel_format = media::PIXEL_FORMAT_I420; - } - // Make a shallow copy. Both |frame| and |video_frame| will share a single - // reference counted frame buffer. Const cast and hope no one will - // overwrite the data. + break; + } + case webrtc::VideoFrameBuffer::Type::kI420: { + rtc::scoped_refptr<webrtc::I420BufferInterface> yuv_buffer = + buffer->ToI420(); video_frame = media::VideoFrame::WrapExternalYuvData( - pixel_format, size, gfx::Rect(size), size, yuv_buffer->StrideY(), - yuv_buffer->StrideU(), yuv_buffer->StrideV(), + media::PIXEL_FORMAT_I420, size, gfx::Rect(size), size, + yuv_buffer->StrideY(), yuv_buffer->StrideU(), yuv_buffer->StrideV(), const_cast<uint8_t*>(yuv_buffer->DataY()), const_cast<uint8_t*>(yuv_buffer->DataU()), const_cast<uint8_t*>(yuv_buffer->DataV()), elapsed_timestamp); + break; } - if (!video_frame) - return; - // The bind ensures that we keep a reference to the underlying buffer. - video_frame->AddDestructionObserver(base::BindOnce(&DoNothing, buffer)); + case webrtc::VideoFrameBuffer::Type::kI444: { + webrtc::I444BufferInterface* yuv_buffer = buffer->GetI444(); + video_frame = media::VideoFrame::WrapExternalYuvData( + media::PIXEL_FORMAT_I444, size, gfx::Rect(size), size, + yuv_buffer->StrideY(), yuv_buffer->StrideU(), yuv_buffer->StrideV(), + const_cast<uint8_t*>(yuv_buffer->DataY()), + const_cast<uint8_t*>(yuv_buffer->DataU()), + const_cast<uint8_t*>(yuv_buffer->DataV()), elapsed_timestamp); + break; + } + case webrtc::VideoFrameBuffer::Type::kI010: { + webrtc::I010BufferInterface* yuv_buffer = buffer->GetI010(); + // WebRTC defines I010 data as uint16 whereas Chromium uses uint8 for all + // video formats, so conversion and cast is needed. + video_frame = media::VideoFrame::WrapExternalYuvData( + media::PIXEL_FORMAT_YUV420P10, size, gfx::Rect(size), size, + yuv_buffer->StrideY() * 2, yuv_buffer->StrideU() * 2, + yuv_buffer->StrideV() * 2, + const_cast<uint8_t*>( + reinterpret_cast<const uint8_t*>(yuv_buffer->DataY())), + const_cast<uint8_t*>( + reinterpret_cast<const uint8_t*>(yuv_buffer->DataU())), + const_cast<uint8_t*>( + reinterpret_cast<const uint8_t*>(yuv_buffer->DataV())), + elapsed_timestamp); + break; + } + default: + NOTREACHED(); } + + if (!video_frame) + return; + + // The bind ensures that we keep a reference to the underlying buffer. + if (buffer->type() != webrtc::VideoFrameBuffer::Type::kNative) + video_frame->AddDestructionObserver(base::BindOnce(&DoNothing, buffer)); + + // Rotation may be explicitly set sometimes. if (incoming_frame.rotation() != webrtc::kVideoRotation_0) { video_frame->metadata()->SetRotation( media::VideoFrameMetadata::ROTATION, WebRTCToMediaVideoRotation(incoming_frame.rotation())); } + // Run render smoothness algorithm only when we don't have to render // immediately. if (!render_immediately) { @@ -235,7 +264,7 @@ void MediaStreamRemoteVideoSource::StopSourceImpl() { } rtc::VideoSinkInterface<webrtc::VideoFrame>* -MediaStreamRemoteVideoSource::SinkInterfaceForTest() { +MediaStreamRemoteVideoSource::SinkInterfaceForTesting() { return delegate_.get(); } diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h index 494b11b8f45..f07b411c77c 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h +++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h @@ -24,7 +24,7 @@ class TrackObserver; // to make sure there is no difference between a video track where the source is // a local source and a video track where the source is a remote video track. class CONTENT_EXPORT MediaStreamRemoteVideoSource - : public MediaStreamVideoSource { + : public MediaStreamVideoSource { public: explicit MediaStreamRemoteVideoSource( std::unique_ptr<TrackObserver> observer); @@ -44,7 +44,7 @@ class CONTENT_EXPORT MediaStreamRemoteVideoSource // Used by tests to test that a frame can be received and that the // MediaStreamRemoteVideoSource behaves as expected. - rtc::VideoSinkInterface<webrtc::VideoFrame>* SinkInterfaceForTest(); + rtc::VideoSinkInterface<webrtc::VideoFrame>* SinkInterfaceForTesting(); private: void OnChanged(webrtc::MediaStreamTrackInterface::TrackState state); diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc index 34db57bbd4b..e721651a012 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc @@ -36,7 +36,7 @@ class MediaStreamRemoteVideoSourceUnderTest explicit MediaStreamRemoteVideoSourceUnderTest( std::unique_ptr<TrackObserver> observer) : MediaStreamRemoteVideoSource(std::move(observer)) {} - using MediaStreamRemoteVideoSource::SinkInterfaceForTest; + using MediaStreamRemoteVideoSource::SinkInterfaceForTesting; }; class MediaStreamRemoteVideoSourceTest @@ -171,7 +171,7 @@ TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) { webrtc::I420Buffer::SetBlack(buffer); - source()->SinkInterfaceForTest()->OnFrame( + source()->SinkInterfaceForTesting()->OnFrame( webrtc::VideoFrame(buffer, webrtc::kVideoRotation_0, 1000)); run_loop.Run(); diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc index e84c5e83b71..30ea304614b 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc @@ -5,7 +5,6 @@ #include "content/renderer/media/webrtc/media_stream_track_metrics.h" #include <inttypes.h> -#include <set> #include <string> #include "base/md5.h" @@ -14,133 +13,44 @@ #include "content/public/common/service_names.mojom.h" #include "content/renderer/render_thread_impl.h" #include "services/service_manager/public/cpp/connector.h" -#include "third_party/webrtc/api/mediastreaminterface.h" - -using webrtc::AudioTrackVector; -using webrtc::MediaStreamInterface; -using webrtc::MediaStreamTrackInterface; -using webrtc::PeerConnectionInterface; -using webrtc::VideoTrackVector; namespace content { -namespace { -typedef std::set<std::string> IdSet; - -template <class T> -IdSet GetTrackIds(const std::vector<rtc::scoped_refptr<T>>& tracks) { - IdSet track_ids; - for (const auto& track : tracks) - track_ids.insert(track->id()); - return track_ids; -} - -// TODO(tommi): Consolidate this and TrackObserver since these implementations -// are fundamentally achieving the same thing (aside from specific logic inside -// the OnChanged callbacks). -class MediaStreamObserver - : public base::RefCountedThreadSafe<MediaStreamObserver>, - public webrtc::ObserverInterface { - public: - typedef base::Callback< - void(const IdSet& audio_track_ids, const IdSet& video_track_ids)> - OnChangedCallback; - - MediaStreamObserver( - const OnChangedCallback& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, - webrtc::MediaStreamInterface* stream) - : main_thread_(main_thread), stream_(stream), callback_(callback) { - signaling_thread_.DetachFromThread(); - stream_->RegisterObserver(this); - } - - const scoped_refptr<webrtc::MediaStreamInterface>& stream() const { - DCHECK(main_thread_->BelongsToCurrentThread()); - return stream_; - } - - void Unregister() { - DCHECK(main_thread_->BelongsToCurrentThread()); - callback_.Reset(); - stream_->UnregisterObserver(this); - stream_ = nullptr; - } - - private: - friend class base::RefCountedThreadSafe<MediaStreamObserver>; - ~MediaStreamObserver() override { - DCHECK(!stream_.get()) << "must have been unregistered before deleting"; - } - - // webrtc::ObserverInterface implementation. - void OnChanged() override { - DCHECK(signaling_thread_.CalledOnValidThread()); - main_thread_->PostTask( - FROM_HERE, base::BindOnce(&MediaStreamObserver::OnChangedOnMainThread, - this, GetTrackIds(stream_->GetAudioTracks()), - GetTrackIds(stream_->GetVideoTracks()))); - } - - void OnChangedOnMainThread(const IdSet& audio_track_ids, - const IdSet& video_track_ids) { - DCHECK(main_thread_->BelongsToCurrentThread()); - if (!callback_.is_null()) - callback_.Run(audio_track_ids, video_track_ids); - } - - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<webrtc::MediaStreamInterface> stream_; - OnChangedCallback callback_; // Only touched on the main thread. - base::ThreadChecker signaling_thread_; -}; - -} // namespace class MediaStreamTrackMetricsObserver { public: - MediaStreamTrackMetricsObserver( - MediaStreamTrackMetrics::StreamType stream_type, - MediaStreamInterface* stream, - MediaStreamTrackMetrics* owner); + MediaStreamTrackMetricsObserver(MediaStreamTrackMetrics::Direction direction, + MediaStreamTrackMetrics::Kind kind, + std::string track_id, + MediaStreamTrackMetrics* owner); ~MediaStreamTrackMetricsObserver(); - // Sends begin/end messages for all tracks currently tracked. - void SendLifetimeMessages(MediaStreamTrackMetrics::LifetimeEvent event); + // Sends begin/end messages for the track if not already reported. + void SendLifetimeMessageForTrack( + MediaStreamTrackMetrics::LifetimeEvent event); - MediaStreamInterface* stream() { + MediaStreamTrackMetrics::Direction direction() { DCHECK(thread_checker_.CalledOnValidThread()); - return observer_->stream().get(); + return direction_; } - MediaStreamTrackMetrics::StreamType stream_type() { + MediaStreamTrackMetrics::Kind kind() { DCHECK(thread_checker_.CalledOnValidThread()); - return stream_type_; + return kind_; } - private: - void OnChanged(const IdSet& audio_track_ids, const IdSet& video_track_ids); - - void ReportAddedAndRemovedTracks( - const IdSet& new_ids, - const IdSet& old_ids, - MediaStreamTrackMetrics::TrackType track_type); - - // Sends a lifetime message for the given tracks. OK to call with an - // empty |ids|, in which case the method has no side effects. - void ReportTracks(const IdSet& ids, - MediaStreamTrackMetrics::TrackType track_type, - MediaStreamTrackMetrics::LifetimeEvent event); + std::string track_id() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return track_id_; + } + private: // False until start/end of lifetime messages have been sent. bool has_reported_start_; bool has_reported_end_; - // IDs of audio and video tracks in the stream being observed. - IdSet audio_track_ids_; - IdSet video_track_ids_; - - MediaStreamTrackMetrics::StreamType stream_type_; - scoped_refptr<MediaStreamObserver> observer_; + MediaStreamTrackMetrics::Direction direction_; + MediaStreamTrackMetrics::Kind kind_; + std::string track_id_; // Non-owning. MediaStreamTrackMetrics* owner_; @@ -151,47 +61,46 @@ namespace { // Used with std::find_if. struct ObserverFinder { - ObserverFinder(MediaStreamTrackMetrics::StreamType stream_type, - MediaStreamInterface* stream) - : stream_type(stream_type), stream_(stream) {} + ObserverFinder(MediaStreamTrackMetrics::Direction direction, + MediaStreamTrackMetrics::Kind kind, + const std::string& track_id) + : direction_(direction), kind_(kind), track_id_(track_id) {} bool operator()( const std::unique_ptr<MediaStreamTrackMetricsObserver>& observer) { - return stream_ == observer->stream() && - stream_type == observer->stream_type(); + return direction_ == observer->direction() && kind_ == observer->kind() && + track_id_ == observer->track_id(); } - MediaStreamTrackMetrics::StreamType stream_type; - MediaStreamInterface* stream_; + MediaStreamTrackMetrics::Direction direction_; + MediaStreamTrackMetrics::Kind kind_; + std::string track_id_; }; } // namespace MediaStreamTrackMetricsObserver::MediaStreamTrackMetricsObserver( - MediaStreamTrackMetrics::StreamType stream_type, - MediaStreamInterface* stream, + MediaStreamTrackMetrics::Direction direction, + MediaStreamTrackMetrics::Kind kind, + std::string track_id, MediaStreamTrackMetrics* owner) : has_reported_start_(false), has_reported_end_(false), - audio_track_ids_(GetTrackIds(stream->GetAudioTracks())), - video_track_ids_(GetTrackIds(stream->GetVideoTracks())), - stream_type_(stream_type), - observer_(new MediaStreamObserver( - base::Bind(&MediaStreamTrackMetricsObserver::OnChanged, - base::Unretained(this)), - base::ThreadTaskRunnerHandle::Get(), - stream)), + direction_(direction), + kind_(kind), + track_id_(std::move(track_id)), owner_(owner) { + DCHECK(owner); } MediaStreamTrackMetricsObserver::~MediaStreamTrackMetricsObserver() { DCHECK(thread_checker_.CalledOnValidThread()); - observer_->Unregister(); - SendLifetimeMessages(MediaStreamTrackMetrics::DISCONNECTED); + SendLifetimeMessageForTrack( + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected); } -void MediaStreamTrackMetricsObserver::SendLifetimeMessages( +void MediaStreamTrackMetricsObserver::SendLifetimeMessageForTrack( MediaStreamTrackMetrics::LifetimeEvent event) { DCHECK(thread_checker_.CalledOnValidThread()); - if (event == MediaStreamTrackMetrics::CONNECTED) { + if (event == MediaStreamTrackMetrics::LifetimeEvent::kConnected) { // Both ICE CONNECTED and COMPLETED can trigger the first // start-of-life event, so we only report the first. if (has_reported_start_) @@ -199,7 +108,7 @@ void MediaStreamTrackMetricsObserver::SendLifetimeMessages( DCHECK(!has_reported_start_ && !has_reported_end_); has_reported_start_ = true; } else { - DCHECK(event == MediaStreamTrackMetrics::DISCONNECTED); + DCHECK(event == MediaStreamTrackMetrics::LifetimeEvent::kDisconnected); // We only report the first end-of-life event, since there are // several cases where end-of-life can be reached. We also don't @@ -209,10 +118,9 @@ void MediaStreamTrackMetricsObserver::SendLifetimeMessages( has_reported_end_ = true; } - ReportTracks(audio_track_ids_, MediaStreamTrackMetrics::AUDIO_TRACK, event); - ReportTracks(video_track_ids_, MediaStreamTrackMetrics::VIDEO_TRACK, event); + owner_->SendLifetimeMessage(track_id_, kind_, event, direction_); - if (event == MediaStreamTrackMetrics::DISCONNECTED) { + if (event == MediaStreamTrackMetrics::LifetimeEvent::kDisconnected) { // After disconnection, we can get reconnected, so we need to // forget that we've sent lifetime events, while retaining all // other state. @@ -222,76 +130,33 @@ void MediaStreamTrackMetricsObserver::SendLifetimeMessages( } } -void MediaStreamTrackMetricsObserver::OnChanged( - const IdSet& audio_track_ids, const IdSet& video_track_ids) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // We only report changes after our initial report, and never after - // our last report. - if (has_reported_start_ && !has_reported_end_) { - ReportAddedAndRemovedTracks(audio_track_ids, - audio_track_ids_, - MediaStreamTrackMetrics::AUDIO_TRACK); - ReportAddedAndRemovedTracks(video_track_ids, - video_track_ids_, - MediaStreamTrackMetrics::VIDEO_TRACK); - } - - // We always update our sets of tracks. - audio_track_ids_ = audio_track_ids; - video_track_ids_ = video_track_ids; -} - -void MediaStreamTrackMetricsObserver::ReportAddedAndRemovedTracks( - const IdSet& new_ids, - const IdSet& old_ids, - MediaStreamTrackMetrics::TrackType track_type) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(has_reported_start_ && !has_reported_end_); - - IdSet added_tracks = base::STLSetDifference<IdSet>(new_ids, old_ids); - IdSet removed_tracks = base::STLSetDifference<IdSet>(old_ids, new_ids); - - ReportTracks(added_tracks, track_type, MediaStreamTrackMetrics::CONNECTED); - ReportTracks( - removed_tracks, track_type, MediaStreamTrackMetrics::DISCONNECTED); -} - -void MediaStreamTrackMetricsObserver::ReportTracks( - const IdSet& ids, - MediaStreamTrackMetrics::TrackType track_type, - MediaStreamTrackMetrics::LifetimeEvent event) { - DCHECK(thread_checker_.CalledOnValidThread()); - for (IdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) { - owner_->SendLifetimeMessage(*it, track_type, event, stream_type_); - } -} - MediaStreamTrackMetrics::MediaStreamTrackMetrics() : ice_state_(webrtc::PeerConnectionInterface::kIceConnectionNew) {} MediaStreamTrackMetrics::~MediaStreamTrackMetrics() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (const auto& observer : observers_) { - observer->SendLifetimeMessages(DISCONNECTED); + observer->SendLifetimeMessageForTrack(LifetimeEvent::kDisconnected); } } -void MediaStreamTrackMetrics::AddStream(StreamType type, - MediaStreamInterface* stream) { +void MediaStreamTrackMetrics::AddTrack(Direction direction, + Kind kind, + const std::string& track_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - observers_.push_back( - std::make_unique<MediaStreamTrackMetricsObserver>(type, stream, this)); + observers_.push_back(std::make_unique<MediaStreamTrackMetricsObserver>( + direction, kind, std::move(track_id), this)); SendLifeTimeMessageDependingOnIceState(observers_.back().get()); } -void MediaStreamTrackMetrics::RemoveStream(StreamType type, - MediaStreamInterface* stream) { +void MediaStreamTrackMetrics::RemoveTrack(Direction direction, + Kind kind, + const std::string& track_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto it = std::find_if(observers_.begin(), observers_.end(), - ObserverFinder(type, stream)); + ObserverFinder(direction, kind, track_id)); if (it == observers_.end()) { - // Since external apps could call removeStream with a stream they + // Since external apps could call removeTrack() with a stream they // never added, this can happen without it being an error. return; } @@ -300,40 +165,41 @@ void MediaStreamTrackMetrics::RemoveStream(StreamType type, } void MediaStreamTrackMetrics::IceConnectionChange( - PeerConnectionInterface::IceConnectionState new_state) { + webrtc::PeerConnectionInterface::IceConnectionState new_state) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ice_state_ = new_state; for (const auto& observer : observers_) { SendLifeTimeMessageDependingOnIceState(observer.get()); } } + void MediaStreamTrackMetrics::SendLifeTimeMessageDependingOnIceState( MediaStreamTrackMetricsObserver* observer) { // There is a state transition diagram for these states at // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCIceConnectionState switch (ice_state_) { - case PeerConnectionInterface::kIceConnectionConnected: - case PeerConnectionInterface::kIceConnectionCompleted: - observer->SendLifetimeMessages(CONNECTED); + case webrtc::PeerConnectionInterface::kIceConnectionConnected: + case webrtc::PeerConnectionInterface::kIceConnectionCompleted: + observer->SendLifetimeMessageForTrack(LifetimeEvent::kConnected); break; - case PeerConnectionInterface::kIceConnectionFailed: - // We don't really need to handle FAILED (it is only supposed - // to be preceded by CHECKING so we wouldn't yet have sent a - // lifetime message) but we might as well use belt and - // suspenders and handle it the same as the other "end call" - // states. It will be ignored anyway if the call is not - // already connected. - case PeerConnectionInterface::kIceConnectionNew: - // It's a bit weird to count NEW as an end-lifetime event, but - // it's possible to transition directly from a connected state - // (CONNECTED or COMPLETED) to NEW, which can then be followed - // by a new connection. The observer will ignore the end - // lifetime event if it was not preceded by a begin-lifetime - // event. - case PeerConnectionInterface::kIceConnectionDisconnected: - case PeerConnectionInterface::kIceConnectionClosed: - observer->SendLifetimeMessages(DISCONNECTED); + case webrtc::PeerConnectionInterface::kIceConnectionFailed: + // We don't really need to handle FAILED (it is only supposed + // to be preceded by CHECKING so we wouldn't yet have sent a + // lifetime message) but we might as well use belt and + // suspenders and handle it the same as the other "end call" + // states. It will be ignored anyway if the call is not + // already connected. + case webrtc::PeerConnectionInterface::kIceConnectionNew: + // It's a bit weird to count NEW as an end-lifetime event, but + // it's possible to transition directly from a connected state + // (CONNECTED or COMPLETED) to NEW, which can then be followed + // by a new connection. The observer will ignore the end + // lifetime event if it was not preceded by a begin-lifetime + // event. + case webrtc::PeerConnectionInterface::kIceConnectionDisconnected: + case webrtc::PeerConnectionInterface::kIceConnectionClosed: + observer->SendLifetimeMessageForTrack(LifetimeEvent::kDisconnected); break; default: @@ -345,28 +211,28 @@ void MediaStreamTrackMetrics::SendLifeTimeMessageDependingOnIceState( } void MediaStreamTrackMetrics::SendLifetimeMessage(const std::string& track_id, - TrackType track_type, + Kind kind, LifetimeEvent event, - StreamType stream_type) { + Direction direction) { RenderThreadImpl* render_thread = RenderThreadImpl::current(); // |render_thread| can be NULL in certain cases when running as part // |of a unit test. if (render_thread) { - if (event == CONNECTED) { + if (event == LifetimeEvent::kConnected) { GetMediaStreamTrackMetricsHost()->AddTrack( - MakeUniqueId(track_id, stream_type), track_type == AUDIO_TRACK, - stream_type == RECEIVED_STREAM); + MakeUniqueId(track_id, direction), kind == Kind::kAudio, + direction == Direction::kReceive); } else { - DCHECK_EQ(DISCONNECTED, event); + DCHECK_EQ(LifetimeEvent::kDisconnected, event); GetMediaStreamTrackMetricsHost()->RemoveTrack( - MakeUniqueId(track_id, stream_type)); + MakeUniqueId(track_id, direction)); } } } uint64_t MediaStreamTrackMetrics::MakeUniqueIdImpl(uint64_t pc_id, const std::string& track_id, - StreamType stream_type) { + Direction direction) { // We use a hash over the |track| pointer and the PeerConnection ID, // plus a boolean flag indicating whether the track is remote (since // you might conceivably have a remote track added back as a sent @@ -376,10 +242,8 @@ uint64_t MediaStreamTrackMetrics::MakeUniqueIdImpl(uint64_t pc_id, // no longer be considered), just one with virtually zero chance of // collisions when faced with non-malicious data. std::string unique_id_string = - base::StringPrintf("%" PRIu64 " %s %d", - pc_id, - track_id.c_str(), - stream_type == RECEIVED_STREAM ? 1 : 0); + base::StringPrintf("%" PRIu64 " %s %d", pc_id, track_id.c_str(), + direction == Direction::kReceive ? 1 : 0); base::MD5Context ctx; base::MD5Init(&ctx); @@ -392,10 +256,10 @@ uint64_t MediaStreamTrackMetrics::MakeUniqueIdImpl(uint64_t pc_id, } uint64_t MediaStreamTrackMetrics::MakeUniqueId(const std::string& track_id, - StreamType stream_type) { + Direction direction) { return MakeUniqueIdImpl( reinterpret_cast<uint64_t>(reinterpret_cast<void*>(this)), track_id, - stream_type); + direction); } mojom::MediaStreamTrackMetricsHostPtr& diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h index 779318660ab..addd76a632b 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h +++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h @@ -15,10 +15,6 @@ #include "content/common/media/media_stream.mojom.h" #include "third_party/webrtc/api/peerconnectioninterface.h" -namespace webrtc { -class MediaStreamInterface; -} - namespace content { class MediaStreamTrackMetricsObserver; @@ -36,19 +32,16 @@ class CONTENT_EXPORT MediaStreamTrackMetrics { explicit MediaStreamTrackMetrics(); ~MediaStreamTrackMetrics(); - enum StreamType { SENT_STREAM, RECEIVED_STREAM }; - - enum TrackType { AUDIO_TRACK, VIDEO_TRACK }; - - enum LifetimeEvent { CONNECTED, DISCONNECTED }; + enum class Direction { kSend, kReceive }; + enum class Kind { kAudio, kVideo }; + enum class LifetimeEvent { kConnected, kDisconnected }; - // Starts tracking lifetimes of all the tracks in |stream| and any - // tracks added or removed to/from the stream until |RemoveStream| - // is called or this object's lifetime ends. - void AddStream(StreamType type, webrtc::MediaStreamInterface* stream); + // Starts tracking the lifetime of the track until |RemoveTrack| is called + // or this object's lifetime ends. + void AddTrack(Direction direction, Kind kind, const std::string& track_id); - // Stops tracking lifetimes of tracks in |stream|. - void RemoveStream(StreamType type, webrtc::MediaStreamInterface* stream); + // Stops tracking the lifetime of the track. + void RemoveTrack(Direction direction, Kind kind, const std::string& track_id); // Called to indicate changes in the ICE connection state for the // PeerConnection this object is associated with. Used to generate @@ -71,9 +64,9 @@ class CONTENT_EXPORT MediaStreamTrackMetrics { // PeerConnection), false for local streams (sent over a // PeerConnection). virtual void SendLifetimeMessage(const std::string& track_id, - TrackType track_type, + Kind kind, LifetimeEvent lifetime_event, - StreamType stream_type); + Direction direction); protected: // Calls SendLifetimeMessage for |observer| depending on |ice_state_|. @@ -86,12 +79,12 @@ class CONTENT_EXPORT MediaStreamTrackMetrics { // is a one-to-one relationship). uint64_t MakeUniqueIdImpl(uint64_t pc_id, const std::string& track, - StreamType stream_type); + Direction direction); private: // Make a unique ID for the given track, that is valid while the // track object and the PeerConnection it is attached to both exist. - uint64_t MakeUniqueId(const std::string& track, StreamType stream_type); + uint64_t MakeUniqueId(const std::string& track_id, Direction direction); mojom::MediaStreamTrackMetricsHostPtr& GetMediaStreamTrackMetricsHost(); diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc index d8819aa62a5..4fb4ff31bc0 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc @@ -78,8 +78,7 @@ class MockMediaStreamTrackMetrics : public MediaStreamTrackMetrics { virtual ~MockMediaStreamTrackMetrics() {} MOCK_METHOD4(SendLifetimeMessage, - void(const std::string&, TrackType, LifetimeEvent, StreamType)); - + void(const std::string&, Kind, LifetimeEvent, Direction)); using MediaStreamTrackMetrics::MakeUniqueIdImpl; }; @@ -170,88 +169,82 @@ TEST_F(MediaStreamTrackMetricsTest, MakeUniqueId) { // Lower 32 bits the same, upper 32 differ. EXPECT_NE( - metrics_->MakeUniqueIdImpl( - 0x1000000000000001, "x", MediaStreamTrackMetrics::RECEIVED_STREAM), - metrics_->MakeUniqueIdImpl( - 0x2000000000000001, "x", MediaStreamTrackMetrics::RECEIVED_STREAM)); + metrics_->MakeUniqueIdImpl(0x1000000000000001, "x", + MediaStreamTrackMetrics::Direction::kReceive), + metrics_->MakeUniqueIdImpl(0x2000000000000001, "x", + MediaStreamTrackMetrics::Direction::kReceive)); // Track ID differs. EXPECT_NE(metrics_->MakeUniqueIdImpl( - 42, "x", MediaStreamTrackMetrics::RECEIVED_STREAM), + 42, "x", MediaStreamTrackMetrics::Direction::kReceive), metrics_->MakeUniqueIdImpl( - 42, "y", MediaStreamTrackMetrics::RECEIVED_STREAM)); + 42, "y", MediaStreamTrackMetrics::Direction::kReceive)); // Remove vs. local track differs. EXPECT_NE(metrics_->MakeUniqueIdImpl( - 42, "x", MediaStreamTrackMetrics::RECEIVED_STREAM), + 42, "x", MediaStreamTrackMetrics::Direction::kReceive), metrics_->MakeUniqueIdImpl( - 42, "x", MediaStreamTrackMetrics::SENT_STREAM)); + 42, "x", MediaStreamTrackMetrics::Direction::kSend)); } TEST_F(MediaStreamTrackMetricsTest, BasicRemoteStreams) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kVideo, "video"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kReceive)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionDisconnected); } TEST_F(MediaStreamTrackMetricsTest, BasicLocalStreams) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); } @@ -259,341 +252,226 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamAddedAferIceConnect) { metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); } TEST_F(MediaStreamTrackMetricsTest, RemoteStreamAddedAferIceConnect) { metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); -} - -TEST_F(MediaStreamTrackMetricsTest, RemoteStreamTrackAdded) { - scoped_refptr<MockAudioTrackInterface> initial(MakeAudioTrack("initial")); - scoped_refptr<MockAudioTrackInterface> added(MakeAudioTrack("added")); - stream_->AddTrack(initial.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("initial", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - metrics_->IceConnectionChange( - PeerConnectionInterface::kIceConnectionConnected); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("added", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - AddAudioTrack(added.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("initial", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("added", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); + + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kVideo, "video"); } TEST_F(MediaStreamTrackMetricsTest, LocalStreamTrackRemoved) { - scoped_refptr<MockAudioTrackInterface> first(MakeAudioTrack("first")); - scoped_refptr<MockAudioTrackInterface> second(MakeAudioTrack("second")); - stream_->AddTrack(first.get()); - stream_->AddTrack(second.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("first", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("second", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "first"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "second"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "first", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "second", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("first", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - stream_->RemoveTrack(first.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("second", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("first", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "first"); + + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("second", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); } -TEST_F(MediaStreamTrackMetricsTest, LocalStreamModificationsBeforeAndAfter) { - scoped_refptr<MockAudioTrackInterface> first(MakeAudioTrack("first")); - scoped_refptr<MockAudioTrackInterface> second(MakeAudioTrack("second")); - stream_->AddTrack(first.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - // This gets added after we start observing, but no lifetime message - // should be sent at this point since the call is not connected. It - // should get sent only once it gets connected. - AddAudioTrack(second.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("first", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("second", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); +TEST_F(MediaStreamTrackMetricsTest, RemoveAfterDisconnect) { + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("first", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("second", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); // This happens after the call is disconnected so no lifetime // message should be sent. - RemoveAudioTrack(first.get()); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); } TEST_F(MediaStreamTrackMetricsTest, RemoteStreamMultipleDisconnects) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - stream_->AddTrack(audio.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionDisconnected); metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); - RemoveAudioTrack(audio.get()); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); } TEST_F(MediaStreamTrackMetricsTest, RemoteStreamConnectDisconnectTwice) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - stream_->AddTrack(audio.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); for (size_t i = 0; i < 2; ++i) { - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionDisconnected); } - RemoveAudioTrack(audio.get()); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); } TEST_F(MediaStreamTrackMetricsTest, LocalStreamRemovedNoDisconnect) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); } TEST_F(MediaStreamTrackMetricsTest, LocalStreamLargerTest) { - scoped_refptr<MockAudioTrackInterface> audio1(MakeAudioTrack("audio1")); - scoped_refptr<MockAudioTrackInterface> audio2(MakeAudioTrack("audio2")); - scoped_refptr<MockAudioTrackInterface> audio3(MakeAudioTrack("audio3")); - scoped_refptr<MockVideoTrackInterface> video1(MakeVideoTrack("video1")); - scoped_refptr<MockVideoTrackInterface> video2(MakeVideoTrack("video2")); - scoped_refptr<MockVideoTrackInterface> video3(MakeVideoTrack("video3")); - stream_->AddTrack(audio1.get()); - stream_->AddTrack(video1.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio1", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video1", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio2", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddAudioTrack(audio2.get()); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video2", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddVideoTrack(video2.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio1", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveAudioTrack(audio1.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio3", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddAudioTrack(audio3.get()); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video3", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddVideoTrack(video3.get()); - - // Add back audio1 - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio1", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddAudioTrack(audio1.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio2", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveAudioTrack(audio2.get()); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video2", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveVideoTrack(video2.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio1", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveAudioTrack(audio1.get()); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video1", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveVideoTrack(video1.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio3", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video3", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + + // Add back audio + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); } } // namespace content diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc index be896490fc6..837f67cfe22 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc @@ -28,8 +28,8 @@ namespace content { namespace { -rtc::Optional<bool> ToRtcOptionalBool(const base::Optional<bool>& value) { - return value ? rtc::Optional<bool>(*value) : rtc::Optional<bool>(); +absl::optional<bool> ToAbslOptionalBool(const base::Optional<bool>& value) { + return value ? absl::optional<bool>(*value) : absl::nullopt; } } // namespace @@ -39,8 +39,8 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSource public: WebRtcVideoSource(WebRtcVideoCapturerAdapter* capture_adapter, bool is_screencast, - rtc::Optional<bool> needs_denoising) - : VideoTrackSource(capture_adapter, false), + absl::optional<bool> needs_denoising) + : VideoTrackSource(false), capture_adapter_(capture_adapter), is_screencast_(is_screencast), needs_denoising_(needs_denoising) {} @@ -50,14 +50,19 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSource } bool is_screencast() const override { return is_screencast_; } - rtc::Optional<bool> needs_denoising() const override { + absl::optional<bool> needs_denoising() const override { return needs_denoising_; } + protected: + rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override { + return capture_adapter_.get(); + } + private: std::unique_ptr<WebRtcVideoCapturerAdapter> const capture_adapter_; const bool is_screencast_; - const rtc::Optional<bool> needs_denoising_; + const absl::optional<bool> needs_denoising_; }; namespace { @@ -84,6 +89,8 @@ webrtc::VideoTrackInterface::ContentHint ContentHintTypeToWebRtcContentHint( return webrtc::VideoTrackInterface::ContentHint::kFluid; case blink::WebMediaStreamTrack::ContentHintType::kVideoDetail: return webrtc::VideoTrackInterface::ContentHint::kDetailed; + case blink::WebMediaStreamTrack::ContentHintType::kVideoText: + return webrtc::VideoTrackInterface::ContentHint::kText; } NOTREACHED(); return webrtc::VideoTrackInterface::ContentHint::kNone; @@ -269,8 +276,8 @@ MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink( MediaStreamVideoTrack::GetVideoTrack(track); DCHECK(video_track); - rtc::Optional<bool> needs_denoising = - ToRtcOptionalBool(video_track->noise_reduction()); + absl::optional<bool> needs_denoising = + ToAbslOptionalBool(video_track->noise_reduction()); bool is_screencast = video_track->is_screencast(); base::Optional<double> min_frame_rate = video_track->min_frame_rate(); @@ -364,8 +371,8 @@ void MediaStreamVideoWebRtcSink::RequestRefreshFrame() { content::RequestRefreshFrameFromVideoTrack(connected_track()); } -rtc::Optional<bool> MediaStreamVideoWebRtcSink::SourceNeedsDenoisingForTesting() - const { +absl::optional<bool> +MediaStreamVideoWebRtcSink::SourceNeedsDenoisingForTesting() const { return video_source_->needs_denoising(); } diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h index 8ff0331d038..d8039286fa8 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h +++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h @@ -43,7 +43,7 @@ class CONTENT_EXPORT MediaStreamVideoWebRtcSink : public MediaStreamVideoSink { return video_track_.get(); } - rtc::Optional<bool> SourceNeedsDenoisingForTesting() const; + absl::optional<bool> SourceNeedsDenoisingForTesting() const; protected: // Implementation of MediaStreamSink. diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc index 5265f9477fb..d33db26d3c6 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc @@ -25,8 +25,8 @@ class MediaStreamVideoWebRtcSinkTest : public ::testing::Test { void SetVideoTrack() { registry_.Init("stream URL"); registry_.AddVideoTrack("test video track"); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - registry_.test_stream().VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + registry_.test_stream().VideoTracks(); track_ = video_tracks[0]; // TODO(hta): Verify that track_ is valid. When constraints produce // no valid format, using the track will cause a crash. @@ -36,8 +36,8 @@ class MediaStreamVideoWebRtcSinkTest : public ::testing::Test { registry_.Init("stream URL"); registry_.AddVideoTrack("test video track", VideoTrackAdapterSettings(), noise_reduction, false, 0.0); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - registry_.test_stream().VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + registry_.test_stream().VideoTracks(); track_ = video_tracks[0]; // TODO(hta): Verify that track_ is valid. When constraints produce // no valid format, using the track will cause a crash. diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc index ebc81901bd4..ee019112cb9 100644 --- a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc +++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc @@ -9,8 +9,10 @@ #include <vector> #include "base/logging.h" +#include "base/stl_util.h" #include "content/renderer/media/webrtc/mock_data_channel_impl.h" #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" +#include "content/renderer/media/webrtc/webrtc_util.h" #include "third_party/webrtc/api/rtpreceiverinterface.h" #include "third_party/webrtc/rtc_base/refcountedobject.h" @@ -58,19 +60,6 @@ class MockStreamCollection : public webrtc::StreamCollectionInterface { } return nullptr; } - std::vector<webrtc::MediaStreamInterface*> FindStreamsOfTrack( - webrtc::MediaStreamTrackInterface* track) { - std::vector<webrtc::MediaStreamInterface*> streams_of_track; - if (!track) - return streams_of_track; - for (size_t i = 0; i < streams_.size(); ++i) { - if (streams_.at(i)->FindAudioTrack(track->id()) || - streams_.at(i)->FindVideoTrack(track->id())) { - streams_of_track.push_back(streams_.at(i)); - } - } - return streams_of_track; - } void AddStream(MediaStreamInterface* stream) { streams_.push_back(stream); } @@ -95,8 +84,6 @@ class MockStreamCollection : public webrtc::StreamCollectionInterface { class MockDtmfSender : public DtmfSenderInterface { public: - explicit MockDtmfSender(AudioTrackInterface* track) - : track_(track), observer_(nullptr), duration_(0), inter_tone_gap_(0) {} void RegisterObserver(DtmfSenderObserverInterface* observer) override { observer_ = observer; } @@ -110,25 +97,21 @@ class MockDtmfSender : public DtmfSenderInterface { inter_tone_gap_ = inter_tone_gap; return true; } - const AudioTrackInterface* track() const override { return track_.get(); } std::string tones() const override { return tones_; } int duration() const override { return duration_; } int inter_tone_gap() const override { return inter_tone_gap_; } - protected: - ~MockDtmfSender() override {} - private: - rtc::scoped_refptr<AudioTrackInterface> track_; - DtmfSenderObserverInterface* observer_; + DtmfSenderObserverInterface* observer_ = nullptr; std::string tones_; - int duration_; - int inter_tone_gap_; + int duration_ = 0; + int inter_tone_gap_ = 0; }; FakeRtpSender::FakeRtpSender( - rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track) - : track_(std::move(track)) {} + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + std::vector<std::string> stream_ids) + : track_(std::move(track)), stream_ids_(std::move(stream_ids)) {} FakeRtpSender::~FakeRtpSender() {} @@ -158,11 +141,10 @@ std::string FakeRtpSender::id() const { } std::vector<std::string> FakeRtpSender::stream_ids() const { - NOTIMPLEMENTED(); - return {}; + return stream_ids_; } -webrtc::RtpParameters FakeRtpSender::GetParameters() const { +webrtc::RtpParameters FakeRtpSender::GetParameters() { NOTIMPLEMENTED(); return webrtc::RtpParameters(); } @@ -175,8 +157,7 @@ webrtc::RTCError FakeRtpSender::SetParameters( rtc::scoped_refptr<webrtc::DtmfSenderInterface> FakeRtpSender::GetDtmfSender() const { - NOTIMPLEMENTED(); - return nullptr; + return new rtc::RefCountedObject<MockDtmfSender>(); } FakeRtpReceiver::FakeRtpReceiver( @@ -226,6 +207,69 @@ std::vector<webrtc::RtpSource> FakeRtpReceiver::GetSources() const { return std::vector<webrtc::RtpSource>(); } +FakeRtpTransceiver::FakeRtpTransceiver( + cricket::MediaType media_type, + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction) + : media_type_(media_type), + sender_(std::move(sender)), + receiver_(std::move(receiver)), + mid_(ToAbslOptional(mid)), + stopped_(stopped), + direction_(direction), + current_direction_(ToAbslOptional(current_direction)) {} + +FakeRtpTransceiver::~FakeRtpTransceiver() {} + +cricket::MediaType FakeRtpTransceiver::media_type() const { + return media_type_; +} + +absl::optional<std::string> FakeRtpTransceiver::mid() const { + return mid_; +} + +rtc::scoped_refptr<webrtc::RtpSenderInterface> FakeRtpTransceiver::sender() + const { + return sender_; +} + +rtc::scoped_refptr<webrtc::RtpReceiverInterface> FakeRtpTransceiver::receiver() + const { + return receiver_; +} + +bool FakeRtpTransceiver::stopped() const { + return stopped_; +} + +webrtc::RtpTransceiverDirection FakeRtpTransceiver::direction() const { + return direction_; +} + +void FakeRtpTransceiver::SetDirection( + webrtc::RtpTransceiverDirection new_direction) { + NOTIMPLEMENTED(); +} + +absl::optional<webrtc::RtpTransceiverDirection> +FakeRtpTransceiver::current_direction() const { + return current_direction_; +} + +void FakeRtpTransceiver::Stop() { + NOTIMPLEMENTED(); +} + +void FakeRtpTransceiver::SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) { + NOTIMPLEMENTED(); +} + const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer"; const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer"; @@ -233,7 +277,6 @@ MockPeerConnectionImpl::MockPeerConnectionImpl( MockPeerConnectionDependencyFactory* factory, webrtc::PeerConnectionObserver* observer) : dependency_factory_(factory), - local_streams_(new rtc::RefCountedObject<MockStreamCollection>), remote_streams_(new rtc::RefCountedObject<MockStreamCollection>), hint_audio_(false), hint_video_(false), @@ -257,73 +300,42 @@ MockPeerConnectionImpl::MockPeerConnectionImpl( MockPeerConnectionImpl::~MockPeerConnectionImpl() {} -rtc::scoped_refptr<webrtc::StreamCollectionInterface> -MockPeerConnectionImpl::local_streams() { - return local_streams_; -} - -rtc::scoped_refptr<webrtc::StreamCollectionInterface> -MockPeerConnectionImpl::remote_streams() { - return remote_streams_; -} - -rtc::scoped_refptr<webrtc::RtpSenderInterface> MockPeerConnectionImpl::AddTrack( - webrtc::MediaStreamTrackInterface* track, - std::vector<webrtc::MediaStreamInterface*> streams) { +webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> +MockPeerConnectionImpl::AddTrack( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::vector<std::string>& stream_ids) { DCHECK(track); - DCHECK_EQ(1u, streams.size()); + DCHECK_EQ(1u, stream_ids.size()); for (const auto& sender : senders_) { if (sender->track() == track) - return nullptr; + return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER); } - for (auto* stream : streams) { - if (!local_streams_->find(stream->id())) { - stream_label_ = stream->id(); - local_streams_->AddStream(stream); + for (const auto& stream_id : stream_ids) { + if (!base::ContainsValue(local_stream_ids_, stream_id)) { + stream_label_ = stream_id; + local_stream_ids_.push_back(stream_id); } } - auto* sender = new rtc::RefCountedObject<FakeRtpSender>(track); + auto* sender = new rtc::RefCountedObject<FakeRtpSender>(track, stream_ids); senders_.push_back(sender); - return sender; + return rtc::scoped_refptr<webrtc::RtpSenderInterface>(sender); } -bool MockPeerConnectionImpl::RemoveTrack(webrtc::RtpSenderInterface* sender) { - auto it = std::find(senders_.begin(), senders_.end(), - static_cast<FakeRtpSender*>(sender)); +bool MockPeerConnectionImpl::RemoveTrack(webrtc::RtpSenderInterface* s) { + rtc::scoped_refptr<FakeRtpSender> sender = static_cast<FakeRtpSender*>(s); + auto it = std::find(senders_.begin(), senders_.end(), sender); if (it == senders_.end()) return false; senders_.erase(it); auto track = sender->track(); - for (auto* stream : local_streams_->FindStreamsOfTrack(track)) { - bool stream_has_senders = false; - for (const auto& track : stream->GetAudioTracks()) { - for (const auto& sender : senders_) { - if (sender->track() == track) { - stream_has_senders = true; - break; - } - } - } - for (const auto& track : stream->GetVideoTracks()) { - for (const auto& sender : senders_) { - if (sender->track() == track) { - stream_has_senders = true; - break; - } - } - } - if (!stream_has_senders) - local_streams_->RemoveStream(stream); - } - return true; -} -rtc::scoped_refptr<DtmfSenderInterface> -MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) { - if (!track) { - return nullptr; + for (const auto& stream_id : sender->stream_ids()) { + auto local_stream_it = std::find(local_stream_ids_.begin(), + local_stream_ids_.end(), stream_id); + if (local_stream_it != local_stream_ids_.end()) + local_stream_ids_.erase(local_stream_it); } - return new rtc::RefCountedObject<MockDtmfSender>(track); + return true; } std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> @@ -477,11 +489,6 @@ bool MockPeerConnectionImpl::AddIceCandidate( return candidate->ToString(&ice_sdp_); } -void MockPeerConnectionImpl::RegisterUMAObserver( - webrtc::UMAObserver* observer) { - NOTIMPLEMENTED(); -} - webrtc::RTCError MockPeerConnectionImpl::SetBitrate( const webrtc::BitrateSettings& bitrate) { NOTIMPLEMENTED(); diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h index da06e71438e..5d348e74b72 100644 --- a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h +++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h @@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/macros.h" +#include "base/optional.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/webrtc/api/peerconnectioninterface.h" #include "third_party/webrtc/api/stats/rtcstatsreport.h" @@ -22,7 +23,8 @@ class MockStreamCollection; class FakeRtpSender : public webrtc::RtpSenderInterface { public: - FakeRtpSender(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track); + FakeRtpSender(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + std::vector<std::string> stream_ids); ~FakeRtpSender() override; bool SetTrack(webrtc::MediaStreamTrackInterface* track) override; @@ -31,7 +33,7 @@ class FakeRtpSender : public webrtc::RtpSenderInterface { cricket::MediaType media_type() const override; std::string id() const override; std::vector<std::string> stream_ids() const override; - webrtc::RtpParameters GetParameters() const override; + webrtc::RtpParameters GetParameters() override; webrtc::RTCError SetParameters( const webrtc::RtpParameters& parameters) override; rtc::scoped_refptr<webrtc::DtmfSenderInterface> GetDtmfSender() @@ -39,6 +41,7 @@ class FakeRtpSender : public webrtc::RtpSenderInterface { private: rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track_; + std::vector<std::string> stream_ids_; }; class FakeRtpReceiver : public webrtc::RtpReceiverInterface { @@ -63,6 +66,43 @@ class FakeRtpReceiver : public webrtc::RtpReceiverInterface { std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams_; }; +class FakeRtpTransceiver : public webrtc::RtpTransceiverInterface { + public: + FakeRtpTransceiver( + cricket::MediaType media_type, + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction); + ~FakeRtpTransceiver() override; + + FakeRtpTransceiver& operator=(const FakeRtpTransceiver& other) = default; + + cricket::MediaType media_type() const override; + absl::optional<std::string> mid() const override; + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override; + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override; + bool stopped() const override; + webrtc::RtpTransceiverDirection direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection new_direction) override; + absl::optional<webrtc::RtpTransceiverDirection> current_direction() + const override; + void Stop() override; + void SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) override; + + private: + cricket::MediaType media_type_; + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender_; + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver_; + absl::optional<std::string> mid_; + bool stopped_; + webrtc::RtpTransceiverDirection direction_; + absl::optional<webrtc::RtpTransceiverDirection> current_direction_; +}; + // TODO(hbos): The use of fakes and mocks is the wrong approach for testing of // this. It introduces complexity, is error prone (not testing the right thing // and bugs in the mocks). This class is a maintenance burden and should be @@ -73,10 +113,16 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface { webrtc::PeerConnectionObserver* observer); // PeerConnectionInterface implementation. - rtc::scoped_refptr<webrtc::StreamCollectionInterface> - local_streams() override; - rtc::scoped_refptr<webrtc::StreamCollectionInterface> - remote_streams() override; + rtc::scoped_refptr<webrtc::StreamCollectionInterface> local_streams() + override { + NOTIMPLEMENTED(); + return nullptr; + } + rtc::scoped_refptr<webrtc::StreamCollectionInterface> remote_streams() + override { + NOTIMPLEMENTED(); + return nullptr; + } bool AddStream(webrtc::MediaStreamInterface* local_stream) override { NOTIMPLEMENTED(); return false; @@ -84,14 +130,10 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface { void RemoveStream(webrtc::MediaStreamInterface* local_stream) override { NOTIMPLEMENTED(); } - // TODO(hbos): Use AddTrack() taking stream labels instead of stream pointers. - // https://crbug.com/810708 - rtc::scoped_refptr<webrtc::RtpSenderInterface> AddTrack( - webrtc::MediaStreamTrackInterface* track, - std::vector<webrtc::MediaStreamInterface*> streams) override; + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> AddTrack( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::vector<std::string>& stream_ids) override; bool RemoveTrack(webrtc::RtpSenderInterface* sender) override; - rtc::scoped_refptr<webrtc::DtmfSenderInterface> - CreateDtmfSender(webrtc::AudioTrackInterface* track) override; std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> GetSenders() const override; std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> GetReceivers() @@ -174,7 +216,6 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface { bool SetConfiguration(const RTCConfiguration& configuration, webrtc::RTCError* error) override; bool AddIceCandidate(const webrtc::IceCandidateInterface* candidate) override; - void RegisterUMAObserver(webrtc::UMAObserver* observer) override; webrtc::RTCError SetBitrate(const webrtc::BitrateSettings& bitrate) override; @@ -207,7 +248,7 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface { MockPeerConnectionDependencyFactory* dependency_factory_; std::string stream_label_; - rtc::scoped_refptr<MockStreamCollection> local_streams_; + std::vector<std::string> local_stream_ids_; rtc::scoped_refptr<MockStreamCollection> remote_streams_; std::vector<rtc::scoped_refptr<FakeRtpSender>> senders_; std::unique_ptr<webrtc::SessionDescriptionInterface> local_desc_; diff --git a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc index 6d8afca21d7..a1ec79ef9f7 100644 --- a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc +++ b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc @@ -20,14 +20,13 @@ MockWebRTCPeerConnectionHandlerClient() .WillByDefault( testing::Invoke(this, &MockWebRTCPeerConnectionHandlerClient:: didGenerateICECandidateWorker)); - ON_CALL(*this, DidAddRemoteTrackForMock(_)) + ON_CALL(*this, DidAddReceiverPlanBForMock(_)) .WillByDefault(testing::Invoke( - this, - &MockWebRTCPeerConnectionHandlerClient::didAddRemoteTrackWorker)); - ON_CALL(*this, DidRemoveRemoteTrackForMock(_)) + this, &MockWebRTCPeerConnectionHandlerClient::didAddReceiverWorker)); + ON_CALL(*this, DidRemoveReceiverPlanBForMock(_)) .WillByDefault(testing::Invoke( this, - &MockWebRTCPeerConnectionHandlerClient::didRemoveRemoteTrackWorker)); + &MockWebRTCPeerConnectionHandlerClient::didRemoveReceiverWorker)); } MockWebRTCPeerConnectionHandlerClient:: @@ -40,17 +39,17 @@ void MockWebRTCPeerConnectionHandlerClient::didGenerateICECandidateWorker( candidate_mid_ = candidate->SdpMid().Utf8(); } -void MockWebRTCPeerConnectionHandlerClient::didAddRemoteTrackWorker( +void MockWebRTCPeerConnectionHandlerClient::didAddReceiverWorker( std::unique_ptr<blink::WebRTCRtpReceiver>* web_rtp_receiver) { - blink::WebVector<blink::WebMediaStream> web_streams = - (*web_rtp_receiver)->Streams(); - DCHECK_EQ(1u, web_streams.size()); - remote_stream_ = web_streams[0]; + blink::WebVector<blink::WebString> stream_ids = + (*web_rtp_receiver)->StreamIds(); + DCHECK_EQ(1u, stream_ids.size()); + remote_stream_id_ = stream_ids[0]; } -void MockWebRTCPeerConnectionHandlerClient::didRemoveRemoteTrackWorker( +void MockWebRTCPeerConnectionHandlerClient::didRemoveReceiverWorker( std::unique_ptr<blink::WebRTCRtpReceiver>* web_rtp_receiver) { - remote_stream_.Reset(); + remote_stream_id_ = blink::WebString(); } } // namespace content diff --git a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h index 6958818c8c2..32ec4d023d4 100644 --- a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h +++ b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h @@ -14,6 +14,7 @@ #include "third_party/blink/public/platform/web_rtc_ice_candidate.h" #include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h" #include "third_party/blink/public/platform/web_rtc_rtp_receiver.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" namespace content { @@ -27,33 +28,42 @@ class MockWebRTCPeerConnectionHandlerClient MOCK_METHOD0(NegotiationNeeded, void()); MOCK_METHOD1(DidGenerateICECandidate, void(scoped_refptr<blink::WebRTCICECandidate> candidate)); - MOCK_METHOD1(DidChangeSignalingState, void(SignalingState state)); + MOCK_METHOD1(DidChangeSignalingState, + void(webrtc::PeerConnectionInterface::SignalingState state)); MOCK_METHOD1(DidChangeICEGatheringState, void(ICEGatheringState state)); MOCK_METHOD1(DidChangeICEConnectionState, void(ICEConnectionState state)); - void DidAddRemoteTrack( + void DidAddReceiverPlanB( std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override { - DidAddRemoteTrackForMock(&web_rtp_receiver); + DidAddReceiverPlanBForMock(&web_rtp_receiver); } - void DidRemoveRemoteTrack( + void DidRemoveReceiverPlanB( std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override { - DidRemoveRemoteTrackForMock(&web_rtp_receiver); + DidRemoveReceiverPlanBForMock(&web_rtp_receiver); + } + void DidModifyTransceivers( + std::vector<std::unique_ptr<blink::WebRTCRtpTransceiver>> + web_transceivers, + bool is_remote_description) override { + DidModifyTransceiversForMock(&web_transceivers, is_remote_description); } MOCK_METHOD1(DidAddRemoteDataChannel, void(blink::WebRTCDataChannelHandler*)); MOCK_METHOD0(ReleasePeerConnectionHandler, void()); - MOCK_METHOD0(GetOriginTrials, WebRTCOriginTrials()); // Move-only arguments do not play nicely with MOCK, the workaround is to // EXPECT_CALL with these instead. - MOCK_METHOD1(DidAddRemoteTrackForMock, + MOCK_METHOD1(DidAddReceiverPlanBForMock, void(std::unique_ptr<blink::WebRTCRtpReceiver>*)); - MOCK_METHOD1(DidRemoveRemoteTrackForMock, + MOCK_METHOD1(DidRemoveReceiverPlanBForMock, void(std::unique_ptr<blink::WebRTCRtpReceiver>*)); + MOCK_METHOD2(DidModifyTransceiversForMock, + void(std::vector<std::unique_ptr<blink::WebRTCRtpTransceiver>>*, + bool)); void didGenerateICECandidateWorker( scoped_refptr<blink::WebRTCICECandidate> candidate); - void didAddRemoteTrackWorker( + void didAddReceiverWorker( std::unique_ptr<blink::WebRTCRtpReceiver>* stream_web_rtp_receivers); - void didRemoveRemoteTrackWorker( + void didRemoveReceiverWorker( std::unique_ptr<blink::WebRTCRtpReceiver>* stream_web_rtp_receivers); const std::string& candidate_sdp() const { return candidate_sdp_; } @@ -61,10 +71,10 @@ class MockWebRTCPeerConnectionHandlerClient return candidate_mline_index_; } const std::string& candidate_mid() const { return candidate_mid_ ; } - const blink::WebMediaStream& remote_stream() const { return remote_stream_; } + const blink::WebString& remote_stream_id() const { return remote_stream_id_; } private: - blink::WebMediaStream remote_stream_; + blink::WebString remote_stream_id_; std::string candidate_sdp_; int candidate_mline_index_; std::string candidate_mid_; diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc index d57e983c03b..d0c4b1b96f9 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc +++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc @@ -620,4 +620,30 @@ void PeerConnectionDependencyFactory::EnsureWebRtcAudioDeviceImpl() { audio_device_ = new rtc::RefCountedObject<WebRtcAudioDeviceImpl>(); } +std::unique_ptr<webrtc::RtpCapabilities> +PeerConnectionDependencyFactory::GetSenderCapabilities( + const std::string& kind) { + if (kind == "audio") { + return std::make_unique<webrtc::RtpCapabilities>( + GetPcFactory()->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO)); + } else if (kind == "video") { + return std::make_unique<webrtc::RtpCapabilities>( + GetPcFactory()->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)); + } + return nullptr; +} + +std::unique_ptr<webrtc::RtpCapabilities> +PeerConnectionDependencyFactory::GetReceiverCapabilities( + const std::string& kind) { + if (kind == "audio") { + return std::make_unique<webrtc::RtpCapabilities>( + GetPcFactory()->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_AUDIO)); + } else if (kind == "video") { + return std::make_unique<webrtc::RtpCapabilities>( + GetPcFactory()->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_VIDEO)); + } + return nullptr; +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h index 8f1cbd22a8c..db7919fe1e5 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h +++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h @@ -94,6 +94,13 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory int sdp_mline_index, const std::string& sdp); + // Returns the most optimistic view of the capabilities of the system for + // sending or receiving media of the given kind ("audio" or "video"). + virtual std::unique_ptr<webrtc::RtpCapabilities> GetSenderCapabilities( + const std::string& kind); + virtual std::unique_ptr<webrtc::RtpCapabilities> GetReceiverCapabilities( + const std::string& kind); + WebRtcAudioDeviceImpl* GetWebRtcAudioDevice(); void EnsureInitialized(); diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc index 85ce26f5918..4566c247f7b 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc +++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc @@ -87,39 +87,111 @@ static std::string SerializeAnswerOptions( return result.str(); } -static std::string SerializeMediaStreamComponent( - const blink::WebMediaStreamTrack& component) { - return component.Source().Id().Utf8(); -} - -static std::string SerializeMediaDescriptor( - const blink::WebMediaStream& stream) { - std::string id = stream.Id().Utf8(); - std::string result = "id: " + id; - blink::WebVector<blink::WebMediaStreamTrack> tracks; - stream.AudioTracks(tracks); - if (!tracks.IsEmpty()) { - result += ", audio: ["; - for (size_t i = 0; i < tracks.size(); ++i) { - result += SerializeMediaStreamComponent(tracks[i]); - if (i != tracks.size() - 1) - result += ", "; - } - result += "]"; +static std::string SerializeMediaStreamIds( + const blink::WebVector<blink::WebString>& stream_ids) { + if (!stream_ids.size()) + return "[]"; + std::string result = "["; + for (const auto& stream_id : stream_ids) { + if (result.size() > 2u) + result += ","; + result += "'" + stream_id.Utf8() + "'"; } - stream.VideoTracks(tracks); - if (!tracks.IsEmpty()) { - result += ", video: ["; - for (size_t i = 0; i < tracks.size(); ++i) { - result += SerializeMediaStreamComponent(tracks[i]); - if (i != tracks.size() - 1) - result += ", "; - } - result += "]"; + result += "]"; + return result; +} + +static const char* SerializeDirection( + webrtc::RtpTransceiverDirection direction) { + switch (direction) { + case webrtc::RtpTransceiverDirection::kSendRecv: + return "'sendrecv'"; + case webrtc::RtpTransceiverDirection::kSendOnly: + return "'sendonly'"; + case webrtc::RtpTransceiverDirection::kRecvOnly: + return "'recvonly'"; + case webrtc::RtpTransceiverDirection::kInactive: + return "'inactive'"; + } +} + +static const char* SerializeOptionalDirection( + const base::Optional<webrtc::RtpTransceiverDirection>& direction) { + return direction ? SerializeDirection(*direction) : "null"; +} + +static std::string SerializeSender(const std::string& indent, + const blink::WebRTCRtpSender& sender) { + std::string result = "{\n"; + // track:'id', + result += indent + " track:"; + if (sender.Track().IsNull()) { + result += "null"; + } else { + result += "'" + sender.Track().Source().Id().Utf8() + "'"; } + result += ",\n"; + // streams:['id,'id'], + result += indent + + " streams:" + SerializeMediaStreamIds(sender.StreamIds()) + ",\n"; + result += indent + "}"; + return result; +} + +static std::string SerializeReceiver(const std::string& indent, + const blink::WebRTCRtpReceiver& receiver) { + std::string result = "{\n"; + // track:'id', + DCHECK(!receiver.Track().IsNull()); + result += + indent + " track:'" + receiver.Track().Source().Id().Utf8() + "',\n"; + // streams:['id,'id'], + result += indent + + " streams:" + SerializeMediaStreamIds(receiver.StreamIds()) + + ",\n"; + result += indent + "}"; return result; } +static std::string SerializeTransceiver( + const blink::WebRTCRtpTransceiver& transceiver) { + if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + std::string result = "{\n"; + // mid:'foo', + if (transceiver.Mid().IsNull()) + result += " mid:null,\n"; + else + result += " mid:'" + transceiver.Mid().Utf8() + "',\n"; + // sender:{...}, + result += + " sender:" + SerializeSender(" ", *transceiver.Sender()) + ",\n"; + // receiver:{...}, + result += " receiver:" + SerializeReceiver(" ", *transceiver.Receiver()) + + ",\n"; + // stopped:false, + result += " stopped:" + + std::string(SerializeBoolean(transceiver.Stopped())) + ",\n"; + // direction:'sendrecv', + result += " direction:" + + std::string(SerializeDirection(transceiver.Direction())) + ",\n"; + // currentDirection:null, + result += " currentDirection:" + + std::string( + SerializeOptionalDirection(transceiver.CurrentDirection())) + + ",\n"; + result += "}"; + return result; + } + if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + return SerializeSender("", *transceiver.Sender()); + } + DCHECK(transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + return SerializeReceiver("", *transceiver.Receiver()); +} + static const char* SerializeIceTransportType( webrtc::PeerConnectionInterface::IceTransportsType type) { const char* transport_type = ""; @@ -216,15 +288,21 @@ static std::string SerializeConfiguration( // strings on chrome://webrtc-internals. static const char* GetSignalingStateString( - WebRTCPeerConnectionHandlerClient::SignalingState state) { + webrtc::PeerConnectionInterface::SignalingState state) { const char* result = ""; switch (state) { - GET_STRING_OF_STATE(SignalingStateStable) - GET_STRING_OF_STATE(SignalingStateHaveLocalOffer) - GET_STRING_OF_STATE(SignalingStateHaveRemoteOffer) - GET_STRING_OF_STATE(SignalingStateHaveLocalPrAnswer) - GET_STRING_OF_STATE(SignalingStateHaveRemotePrAnswer) - GET_STRING_OF_STATE(SignalingStateClosed) + case webrtc::PeerConnectionInterface::SignalingState::kStable: + return "SignalingStateStable"; + case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalOffer: + return "SignalingStateHaveLocalOffer"; + case webrtc::PeerConnectionInterface::SignalingState::kHaveRemoteOffer: + return "SignalingStateHaveRemoteOffer"; + case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalPrAnswer: + return "SignalingStateHaveLocalPrAnswer"; + case webrtc::PeerConnectionInterface::SignalingState::kHaveRemotePrAnswer: + return "SignalingStateHaveRemotePrAnswer"; + case webrtc::PeerConnectionInterface::SignalingState::kClosed: + return "SignalingStateClosed"; default: NOTREACHED(); break; @@ -264,6 +342,24 @@ static const char* GetIceGatheringStateString( return result; } +static const char* GetTransceiverUpdatedReasonString( + PeerConnectionTracker::TransceiverUpdatedReason reason) { + switch (reason) { + case PeerConnectionTracker::TransceiverUpdatedReason::kAddTransceiver: + return "addTransceiver"; + case PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack: + return "addTrack"; + case PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack: + return "removeTrack"; + case PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription: + return "setLocalDescription"; + case PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription: + return "setRemoteDescription"; + } + NOTREACHED(); + return nullptr; +} + // Builds a DictionaryValue from the StatsReport. // Note: // The format must be consistent with what webrtc_internals.js expects. @@ -613,30 +709,73 @@ void PeerConnectionTracker::TrackAddIceCandidate( SendPeerConnectionUpdate(id, event, value); } -void PeerConnectionTracker::TrackAddStream( +void PeerConnectionTracker::TrackAddTransceiver( RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, - Source source) { - DCHECK(main_thread_.CalledOnValidThread()); - int id = GetLocalIDForHandler(pc_handler); - if (id == -1) - return; - SendPeerConnectionUpdate( - id, source == SOURCE_LOCAL ? "addStream" : "onAddStream", - SerializeMediaDescriptor(stream)); + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index) { + TrackTransceiver("Added", pc_handler, reason, transceiver, transceiver_index); } -void PeerConnectionTracker::TrackRemoveStream( +void PeerConnectionTracker::TrackModifyTransceiver( RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, - Source source) { + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index) { + TrackTransceiver("Modified", pc_handler, reason, transceiver, + transceiver_index); +} + +void PeerConnectionTracker::TrackRemoveTransceiver( + RTCPeerConnectionHandler* pc_handler, + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index) { + TrackTransceiver("Removed", pc_handler, reason, transceiver, + transceiver_index); +} + +void PeerConnectionTracker::TrackTransceiver( + const char* callback_type_ending, + RTCPeerConnectionHandler* pc_handler, + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index) { DCHECK(main_thread_.CalledOnValidThread()); int id = GetLocalIDForHandler(pc_handler); if (id == -1) return; - SendPeerConnectionUpdate( - id, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream", - SerializeMediaDescriptor(stream)); + std::string callback_type; + if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + callback_type = "transceiver"; + } else if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + callback_type = "sender"; + } else { + callback_type = "receiver"; + } + callback_type += callback_type_ending; + + std::string result; + result += "Caused by: "; + result += GetTransceiverUpdatedReasonString(reason); + result += "\n\n"; + if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + result += "getTransceivers()"; + } else if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + result += "getSenders()"; + } else { + DCHECK_EQ( + transceiver.ImplementationType(), + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + result += "getReceivers()"; + } + result += "[" + base::UintToString(transceiver_index) + "]:"; + result += SerializeTransceiver(transceiver); + SendPeerConnectionUpdate(id, callback_type, result); } void PeerConnectionTracker::TrackCreateDataChannel( @@ -664,8 +803,8 @@ void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) { } void PeerConnectionTracker::TrackSignalingStateChange( - RTCPeerConnectionHandler* pc_handler, - WebRTCPeerConnectionHandlerClient::SignalingState state) { + RTCPeerConnectionHandler* pc_handler, + webrtc::PeerConnectionInterface::SignalingState state) { DCHECK(main_thread_.CalledOnValidThread()); int id = GetLocalIDForHandler(pc_handler); if (id == -1) @@ -779,11 +918,11 @@ int PeerConnectionTracker::GetLocalIDForHandler( void PeerConnectionTracker::SendPeerConnectionUpdate( int local_id, - const char* callback_type, + const std::string& callback_type, const std::string& value) { DCHECK(main_thread_.CalledOnValidThread()); GetPeerConnectionTrackerHost().get()->UpdatePeerConnection( - local_id, std::string(callback_type), value); + local_id, callback_type, value); } void PeerConnectionTracker::OverrideSendTargetForTesting(RenderThread* target) { @@ -797,6 +936,6 @@ PeerConnectionTracker::GetPeerConnectionTrackerHost() { &peer_connection_tracker_host_ptr_); } return peer_connection_tracker_host_ptr_; -}; +} } // namespace content diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker.h b/chromium/content/renderer/media/webrtc/peer_connection_tracker.h index 0c35de2047e..24e0fd85e1c 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_tracker.h +++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker.h @@ -16,6 +16,7 @@ #include "ipc/ipc_platform_file.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" #include "third_party/blink/public/platform/web_rtc_session_description.h" #include "third_party/webrtc/api/peerconnectioninterface.h" @@ -60,6 +61,16 @@ class CONTENT_EXPORT PeerConnectionTracker ACTION_CREATE_ANSWER }; + // In Plan B: "Transceiver" refers to RTCRtpSender or RTCRtpReceiver. + // In Unified Plan: "Transceiver" refers to RTCRtpTransceiver. + enum class TransceiverUpdatedReason { + kAddTransceiver, + kAddTrack, + kRemoveTrack, + kSetLocalDescription, + kSetRemoteDescription, + }; + // RenderThreadObserver implementation. bool OnControlMessageReceived(const IPC::Message& message) override; @@ -116,15 +127,31 @@ class CONTENT_EXPORT PeerConnectionTracker Source source, bool succeeded); - // Sends an update when a media stream is added. - virtual void TrackAddStream( + // Sends an update when a transceiver is added, modified or removed. This can + // happen as a result of any of the methods indicated by |reason|. + // In Plan B: |transceiver| refers to its Sender() or Receiver() depending on + // ImplementationType(). Example events: "senderAdded", "receiverRemoved". + // In Plan B: |transceiver| has a fully implemented ImplementationType(). + // Example events: "transceiverAdded", "transceiverModified". + // See peer_connection_tracker_unittest.cc for expected resulting event + // strings. + virtual void TrackAddTransceiver( RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, Source source); - - // Sends an update when a media stream is removed. - virtual void TrackRemoveStream( + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index); + virtual void TrackModifyTransceiver( RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, Source source); + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index); + // TODO(hbos): When Plan B is removed this is no longer applicable. + // https://crbug.com/857004 + virtual void TrackRemoveTransceiver( + RTCPeerConnectionHandler* pc_handler, + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index); // Sends an update when a DataChannel is created. virtual void TrackCreateDataChannel( @@ -137,7 +164,7 @@ class CONTENT_EXPORT PeerConnectionTracker // Sends an update when the signaling state of a PeerConnection has changed. virtual void TrackSignalingStateChange( RTCPeerConnectionHandler* pc_handler, - blink::WebRTCPeerConnectionHandlerClient::SignalingState state); + webrtc::PeerConnectionInterface::SignalingState state); // Sends an update when the Ice connection state // of a PeerConnection has changed. @@ -180,6 +207,12 @@ class CONTENT_EXPORT PeerConnectionTracker // is not registered, the return value will be -1. int GetLocalIDForHandler(RTCPeerConnectionHandler* handler) const; + void TrackTransceiver(const char* callback_type_ending, + RTCPeerConnectionHandler* pc_handler, + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index); + // IPC Message handler for getting all stats. void OnGetAllStats(); @@ -211,7 +244,7 @@ class CONTENT_EXPORT PeerConnectionTracker // |value| - A json serialized string containing all the information for the // update event. void SendPeerConnectionUpdate(int local_id, - const char* callback_type, + const std::string& callback_type, const std::string& value); RenderThread* SendTarget(); diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker_unittest.cc b/chromium/content/renderer/media/webrtc/peer_connection_tracker_unittest.cc index 647a6462d8c..84865974755 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_tracker_unittest.cc +++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker_unittest.cc @@ -8,6 +8,7 @@ #include "content/common/media/peer_connection_tracker.mojom.h" #include "content/common/media/peer_connection_tracker_messages.h" #include "content/public/test/mock_render_thread.h" +#include "content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h" #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h" #include "content/renderer/media/webrtc/rtc_peer_connection_handler.h" @@ -18,11 +19,42 @@ #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/platform/web_media_constraints.h" #include "third_party/blink/public/platform/web_rtc_offer_options.h" +#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h" +#include "third_party/blink/public/platform/web_rtc_rtp_sender.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" using ::testing::_; namespace content { +const char* kDefaultTransceiverString = + "getTransceivers()[0]:{\n" + " mid:null,\n" + " sender:{\n" + " track:'senderTrackId',\n" + " streams:['senderStreamId'],\n" + " },\n" + " receiver:{\n" + " track:'receiverTrackId',\n" + " streams:['receiverStreamId'],\n" + " },\n" + " stopped:false,\n" + " direction:'sendonly',\n" + " currentDirection:null,\n" + "}"; + +const char* kDefaultSenderString = + "getSenders()[0]:{\n" + " track:'senderTrackId',\n" + " streams:['senderStreamId'],\n" + "}"; + +const char* kDefaultReceiverString = + "getReceivers()[0]:{\n" + " track:'receiverTrackId',\n" + " streams:['receiverStreamId'],\n" + "}"; + class MockPeerConnectionTrackerHost : public mojom::PeerConnectionTrackerHost { public: MockPeerConnectionTrackerHost() : binding_(this) {} @@ -47,7 +79,41 @@ class MockPeerConnectionTrackerHost : public mojom::PeerConnectionTrackerHost { mojo::AssociatedBinding<mojom::PeerConnectionTrackerHost> binding_; }; +// Creates a transceiver that is expected to be logged as +// |kDefaultTransceiverString|, |kDefaultSenderString| or +// |kDefaultReceiverString| depending on if |implementation_type| refers to a +// fully implemented, sender-only or receiver-only transceiver. +// +// This is used in unittests that don't care about the specific attributes of +// the transceiver. +std::unique_ptr<blink::WebRTCRtpTransceiver> CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType implementation_type) { + std::unique_ptr<blink::WebRTCRtpTransceiver> transceiver; + FakeRTCRtpSender sender("senderTrackId", {"senderStreamId"}); + FakeRTCRtpReceiver receiver("receiverTrackId", {"receiverStreamId"}); + if (implementation_type == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + transceiver = std::make_unique<FakeRTCRtpTransceiver>( + base::nullopt, std::move(sender), std::move(receiver), + false /* stopped */, + webrtc::RtpTransceiverDirection::kSendOnly /* direction */, + base::nullopt /* current_direction */); + } else if (implementation_type == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + transceiver = std::make_unique<RTCRtpSenderOnlyTransceiver>( + std::make_unique<FakeRTCRtpSender>(sender)); + } else { + DCHECK_EQ( + implementation_type, + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + transceiver = std::make_unique<RTCRtpReceiverOnlyTransceiver>( + std::make_unique<FakeRTCRtpReceiver>(receiver)); + } + return transceiver; +} + namespace { + class MockSendTargetThread : public MockRenderThread { public: MOCK_METHOD1(OnAddPeerConnection, void(PeerConnectionInfo)); @@ -66,6 +132,7 @@ bool MockSendTargetThread::OnMessageReceived(const IPC::Message& msg) { return handled; } +// TODO(https://crbug.com/868868): Move this into a separate file. class MockPeerConnectionHandler : public RTCPeerConnectionHandler { public: MockPeerConnectionHandler() @@ -81,8 +148,30 @@ class MockPeerConnectionHandler : public RTCPeerConnectionHandler { }; class PeerConnectionTrackerTest : public ::testing::Test { - private: + public: + void CreateTrackerWithMocks() { + mock_host_.reset(new MockPeerConnectionTrackerHost()); + tracker_.reset( + new PeerConnectionTracker(mock_host_->CreateInterfacePtrAndBind())); + target_thread_.reset(new MockSendTargetThread()); + tracker_->OverrideSendTargetForTesting(target_thread_.get()); + } + + void CreateAndRegisterPeerConnectionHandler() { + mock_handler_.reset(new MockPeerConnectionHandler()); + EXPECT_CALL(*target_thread_, OnAddPeerConnection(_)); + tracker_->RegisterPeerConnection( + mock_handler_.get(), + webrtc::PeerConnectionInterface::RTCConfiguration(), + blink::WebMediaConstraints(), nullptr); + } + + protected: base::MessageLoop message_loop_; + std::unique_ptr<MockPeerConnectionTrackerHost> mock_host_; + std::unique_ptr<PeerConnectionTracker> tracker_; + std::unique_ptr<MockSendTargetThread> target_thread_; + std::unique_ptr<MockPeerConnectionHandler> mock_handler_; }; } // namespace @@ -92,47 +181,258 @@ TEST_F(PeerConnectionTrackerTest, CreatingObject) { } TEST_F(PeerConnectionTrackerTest, TrackCreateOffer) { - MockPeerConnectionTrackerHost mock_peer_connection_tracker_host; - PeerConnectionTracker tracker( - mock_peer_connection_tracker_host.CreateInterfacePtrAndBind()); - // mojom::PeerConnectionTrackerHostAssociatedPtr - // mock_peer_connection_tracker_host_ptr_ - // = mock_peer_connection_tracker_host.CreateInterfacePtrAndBind(); - // tracker.SetPeerConnectionTrackerHostForTesting(std::move(ptr1)); - // Note: blink::WebRTCOfferOptions is not mockable. So we can't write - // tests for anything but a null options parameter. + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + // Note: blink::WebRTCOfferOptions is not mockable. So we can't write tests + // for anything but a null options parameter. blink::WebRTCOfferOptions options(0, 0, false, false); - // Initialization stuff. This can be separated into a test class. - MockPeerConnectionHandler pc_handler; - MockSendTargetThread target_thread; - webrtc::PeerConnectionInterface::RTCConfiguration config; - blink::WebMediaConstraints constraints; - tracker.OverrideSendTargetForTesting(&target_thread); - EXPECT_CALL(target_thread, OnAddPeerConnection(_)); - tracker.RegisterPeerConnection(&pc_handler, config, constraints, nullptr); - // Back to the test. - EXPECT_CALL(mock_peer_connection_tracker_host, + EXPECT_CALL(*mock_host_, UpdatePeerConnection( _, "createOffer", "options: {offerToReceiveVideo: 0, offerToReceiveAudio: 0, " "voiceActivityDetection: false, iceRestart: false}")); - tracker.TrackCreateOffer(&pc_handler, options); + tracker_->TrackCreateOffer(mock_handler_.get(), options); base::RunLoop().RunUntilIdle(); } TEST_F(PeerConnectionTrackerTest, OnSuspend) { - PeerConnectionTracker tracker; - // Initialization stuff. - MockPeerConnectionHandler pc_handler; - MockSendTargetThread target_thread; - webrtc::PeerConnectionInterface::RTCConfiguration config; - blink::WebMediaConstraints constraints; - tracker.OverrideSendTargetForTesting(&target_thread); - EXPECT_CALL(target_thread, OnAddPeerConnection(_)); - tracker.RegisterPeerConnection(&pc_handler, config, constraints, nullptr); - EXPECT_CALL(pc_handler, CloseClientPeerConnection()); + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + EXPECT_CALL(*mock_handler_, CloseClientPeerConnection()); std::unique_ptr<IPC::Message> message(new PeerConnectionTracker_OnSuspend()); - tracker.OnControlMessageReceived(*message.get()); + tracker_->OnControlMessageReceived(*message.get()); +} + +TEST_F(PeerConnectionTrackerTest, AddTransceiverWithOptionalValuesPresent) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + FakeRTCRtpTransceiver transceiver( + "midValue", FakeRTCRtpSender("senderTrackId", {"streamIdA", "streamIdB"}), + FakeRTCRtpReceiver("receiverTrackId", {"streamIdC"}), true /* stopped */, + webrtc::RtpTransceiverDirection::kSendRecv /* direction */, + webrtc::RtpTransceiverDirection::kInactive /* current_direction */); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverAdded", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackAddTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, transceiver, + 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: addTrack\n" + "\n" + "getTransceivers()[0]:{\n" + " mid:'midValue',\n" + " sender:{\n" + " track:'senderTrackId',\n" + " streams:['streamIdA','streamIdB'],\n" + " },\n" + " receiver:{\n" + " track:'receiverTrackId',\n" + " streams:['streamIdC'],\n" + " },\n" + " stopped:true,\n" + " direction:'sendrecv',\n" + " currentDirection:'inactive',\n" + "}", + update_value); +} + +TEST_F(PeerConnectionTrackerTest, AddTransceiverWithOptionalValuesNull) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + FakeRTCRtpTransceiver transceiver( + base::nullopt, FakeRTCRtpSender(base::nullopt, {}), + FakeRTCRtpReceiver("receiverTrackId", {}), false /* stopped */, + webrtc::RtpTransceiverDirection::kInactive /* direction */, + base::nullopt /* current_direction */); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverAdded", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackAddTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kAddTransceiver, + transceiver, 1u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: addTransceiver\n" + "\n" + "getTransceivers()[1]:{\n" + " mid:null,\n" + " sender:{\n" + " track:null,\n" + " streams:[],\n" + " },\n" + " receiver:{\n" + " track:'receiverTrackId',\n" + " streams:[],\n" + " },\n" + " stopped:false,\n" + " direction:'inactive',\n" + " currentDirection:null,\n" + "}", + update_value); +} + +TEST_F(PeerConnectionTrackerTest, ModifyTransceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto transceiver = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverModified", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackModifyTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription, + *transceiver, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setLocalDescription\n" + "\n" + + std::string(kDefaultTransceiverString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, RemoveTransceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto transceiver = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverRemoved", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackRemoveTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, + *transceiver, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: removeTrack\n" + "\n" + + std::string(kDefaultTransceiverString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, AddSender) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto sender_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderAdded", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackAddTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription, + *sender_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setLocalDescription\n" + "\n" + + std::string(kDefaultSenderString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, ModifySender) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto sender_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderModified", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackModifyTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *sender_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultSenderString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, RemoveSender) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto sender_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderRemoved", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackRemoveTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *sender_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultSenderString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, AddReceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto receiver_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverAdded", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackAddTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultReceiverString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, ModifyReceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto receiver_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverModified", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackModifyTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultReceiverString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, RemoveReceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto receiver_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverRemoved", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackRemoveTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultReceiverString), + update_value); } // TODO(hta): Write tests for the other tracking functions. diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc index 8eb3a817560..4f5ff473c80 100644 --- a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc +++ b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc @@ -39,7 +39,7 @@ rtc::KeyParams WebRTCKeyParamsToKeyParams( } // A certificate generation request spawned by -// |RTCCertificateGenerator::generateCertificateWithOptionalExpiration|. This +// |GenerateCertificateWithOptionalExpiration|. This // is handled by a separate class so that reference counting can keep the // request alive independently of the |RTCCertificateGenerator| that spawned it. class RTCCertificateGeneratorRequest @@ -60,7 +60,7 @@ class RTCCertificateGeneratorRequest void GenerateCertificateAsync( const blink::WebRTCKeyParams& key_params, - const rtc::Optional<uint64_t>& expires_ms, + const absl::optional<uint64_t>& expires_ms, std::unique_ptr<blink::WebRTCCertificateCallback> observer) { DCHECK(main_thread_->BelongsToCurrentThread()); DCHECK(observer); @@ -80,7 +80,7 @@ class RTCCertificateGeneratorRequest void GenerateCertificateOnWorkerThread( const blink::WebRTCKeyParams key_params, - const rtc::Optional<uint64_t> expires_ms, + const absl::optional<uint64_t> expires_ms, CertificateCallbackPtr observer) { DCHECK(worker_thread_->BelongsToCurrentThread()); @@ -114,41 +114,40 @@ class RTCCertificateGeneratorRequest const scoped_refptr<base::SingleThreadTaskRunner> worker_thread_; }; -} // namespace - -void RTCCertificateGenerator::GenerateCertificate( +void GenerateCertificateWithOptionalExpiration( const blink::WebRTCKeyParams& key_params, + const absl::optional<uint64_t>& expires_ms, std::unique_ptr<blink::WebRTCCertificateCallback> observer, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - generateCertificateWithOptionalExpiration( - key_params, rtc::Optional<uint64_t>(), std::move(observer), task_runner); + DCHECK(WebRTCKeyParamsToKeyParams(key_params).IsValid()); + PeerConnectionDependencyFactory* pc_dependency_factory = + RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(); + pc_dependency_factory->EnsureInitialized(); + + scoped_refptr<RTCCertificateGeneratorRequest> request = + new RTCCertificateGeneratorRequest( + task_runner, pc_dependency_factory->GetWebRtcWorkerThread()); + request->GenerateCertificateAsync(key_params, expires_ms, + std::move(observer)); } -void RTCCertificateGenerator::GenerateCertificateWithExpiration( +} // namespace + +void RTCCertificateGenerator::GenerateCertificate( const blink::WebRTCKeyParams& key_params, - uint64_t expires_ms, std::unique_ptr<blink::WebRTCCertificateCallback> observer, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - generateCertificateWithOptionalExpiration(key_params, - rtc::Optional<uint64_t>(expires_ms), + GenerateCertificateWithOptionalExpiration(key_params, absl::nullopt, std::move(observer), task_runner); } -void RTCCertificateGenerator::generateCertificateWithOptionalExpiration( +void RTCCertificateGenerator::GenerateCertificateWithExpiration( const blink::WebRTCKeyParams& key_params, - const rtc::Optional<uint64_t>& expires_ms, + uint64_t expires_ms, std::unique_ptr<blink::WebRTCCertificateCallback> observer, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - DCHECK(IsSupportedKeyParams(key_params)); - PeerConnectionDependencyFactory* pc_dependency_factory = - RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(); - pc_dependency_factory->EnsureInitialized(); - - scoped_refptr<RTCCertificateGeneratorRequest> request = - new RTCCertificateGeneratorRequest( - task_runner, pc_dependency_factory->GetWebRtcWorkerThread()); - request->GenerateCertificateAsync( - key_params, expires_ms, std::move(observer)); + GenerateCertificateWithOptionalExpiration(key_params, expires_ms, + std::move(observer), task_runner); } bool RTCCertificateGenerator::IsSupportedKeyParams( diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h index 248cd21846c..5e29c7f62d4 100644 --- a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h +++ b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h @@ -10,7 +10,6 @@ #include "third_party/blink/public/platform/web_rtc_certificate.h" #include "third_party/blink/public/platform/web_rtc_certificate_generator.h" #include "third_party/blink/public/platform/web_rtc_key_params.h" -#include "third_party/webrtc/api/optional.h" namespace content { @@ -38,12 +37,6 @@ class RTCCertificateGenerator : public blink::WebRTCCertificateGenerator { blink::WebString pem_certificate) override; private: - void generateCertificateWithOptionalExpiration( - const blink::WebRTCKeyParams& key_params, - const rtc::Optional<uint64_t>& expires_ms, - std::unique_ptr<blink::WebRTCCertificateCallback> observer, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - DISALLOW_COPY_AND_ASSIGN(RTCCertificateGenerator); }; diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc index e972ef0a8dd..64bf108735c 100644 --- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc +++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc @@ -18,6 +18,7 @@ #include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" @@ -36,8 +37,7 @@ #include "content/renderer/media/webrtc/rtc_event_log_output_sink_proxy.h" #include "content/renderer/media/webrtc/rtc_stats.h" #include "content/renderer/media/webrtc/webrtc_audio_device_impl.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" -#include "content/renderer/media/webrtc/webrtc_set_remote_description_observer.h" +#include "content/renderer/media/webrtc/webrtc_set_description_observer.h" #include "content/renderer/media/webrtc/webrtc_uma_histograms.h" #include "content/renderer/render_thread_impl.h" #include "media/base/media_switches.h" @@ -49,6 +49,7 @@ #include "third_party/blink/public/platform/web_rtc_legacy_stats.h" #include "third_party/blink/public/platform/web_rtc_offer_options.h" #include "third_party/blink/public/platform/web_rtc_rtp_sender.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" #include "third_party/blink/public/platform/web_rtc_session_description.h" #include "third_party/blink/public/platform/web_rtc_session_description_request.h" #include "third_party/blink/public/platform/web_rtc_void_request.h" @@ -119,30 +120,6 @@ GetWebKitIceConnectionState( } } -blink::WebRTCPeerConnectionHandlerClient::SignalingState -GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) { - using blink::WebRTCPeerConnectionHandlerClient; - switch (state) { - case webrtc::PeerConnectionInterface::kStable: - return WebRTCPeerConnectionHandlerClient::kSignalingStateStable; - case webrtc::PeerConnectionInterface::kHaveLocalOffer: - return WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalOffer; - case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer: - return WebRTCPeerConnectionHandlerClient:: - kSignalingStateHaveLocalPrAnswer; - case webrtc::PeerConnectionInterface::kHaveRemoteOffer: - return WebRTCPeerConnectionHandlerClient::kSignalingStateHaveRemoteOffer; - case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer: - return WebRTCPeerConnectionHandlerClient:: - kSignalingStateHaveRemotePrAnswer; - case webrtc::PeerConnectionInterface::kClosed: - return WebRTCPeerConnectionHandlerClient::kSignalingStateClosed; - default: - NOTREACHED(); - return WebRTCPeerConnectionHandlerClient::kSignalingStateClosed; - } -} - blink::WebRTCSessionDescription CreateWebKitSessionDescription( const std::string& sdp, const std::string& type) { blink::WebRTCSessionDescription description; @@ -257,14 +234,13 @@ void GetNativeRtcConfiguration( } switch (blink_config.sdp_semantics) { - case blink::WebRTCSdpSemantics::kDefault: case blink::WebRTCSdpSemantics::kPlanB: webrtc_config->sdp_semantics = webrtc::SdpSemantics::kPlanB; break; case blink::WebRTCSdpSemantics::kUnifiedPlan: webrtc_config->sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; break; - default: + case blink::WebRTCSdpSemantics::kDefault: NOTREACHED(); } @@ -279,6 +255,16 @@ void GetNativeRtcConfiguration( webrtc_config->ice_candidate_pool_size = blink_config.ice_candidate_pool_size; } +absl::optional<bool> ConstraintToOptional( + const blink::WebMediaConstraints& constraints, + const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker) { + bool value; + if (GetConstraintValueAsBoolean(constraints, picker, &value)) { + return absl::optional<bool>(value); + } + return absl::nullopt; +} + void CopyConstraintsIntoRtcConfiguration( const blink::WebMediaConstraints constraints, webrtc::PeerConnectionInterface::RTCConfiguration* configuration) { @@ -329,7 +315,7 @@ void CopyConstraintsIntoRtcConfiguration( constraints, &blink::WebMediaTrackConstraintSet::goog_screencast_min_bitrate, &rate)) { - configuration->screencast_min_bitrate = rtc::Optional<int>(rate); + configuration->screencast_min_bitrate = rate; } configuration->combined_audio_video_bwe = ConstraintToOptional( constraints, @@ -338,42 +324,6 @@ void CopyConstraintsIntoRtcConfiguration( constraints, &blink::WebMediaTrackConstraintSet::enable_dtls_srtp); } -class SessionDescriptionRequestTracker { - public: - SessionDescriptionRequestTracker( - const base::WeakPtr<RTCPeerConnectionHandler>& handler, - const base::WeakPtr<PeerConnectionTracker>& tracker, - PeerConnectionTracker::Action action) - : handler_(handler), tracker_(tracker), action_(action) {} - - void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (tracker_ && handler_) { - std::string value; - if (desc) { - desc->ToString(&value); - value = "type: " + desc->type() + ", sdp: " + value; - } - tracker_->TrackSessionDescriptionCallback( - handler_.get(), action_, "OnSuccess", value); - } - } - - void TrackOnFailure(const webrtc::RTCError& error) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (handler_ && tracker_) { - tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, - "OnFailure", error.message()); - } - } - - private: - const base::WeakPtr<RTCPeerConnectionHandler> handler_; - const base::WeakPtr<PeerConnectionTracker> tracker_; - PeerConnectionTracker::Action action_; - base::ThreadChecker thread_checker_; -}; - // Class mapping responses from calls to libjingle CreateOffer/Answer and // the blink::WebRTCSessionDescriptionRequest. class CreateSessionDescriptionRequest @@ -387,8 +337,9 @@ class CreateSessionDescriptionRequest PeerConnectionTracker::Action action) : main_thread_(main_thread), webkit_request_(request), - tracker_(handler, tracker, action) { - } + handler_(handler), + tracker_(tracker), + action_(action) {} void OnSuccess(webrtc::SessionDescriptionInterface* desc) override { if (!main_thread_->BelongsToCurrentThread()) { @@ -398,7 +349,15 @@ class CreateSessionDescriptionRequest return; } - tracker_.TrackOnSuccess(desc); + if (tracker_ && handler_) { + std::string value; + if (desc) { + desc->ToString(&value); + value = "type: " + desc->type() + ", sdp: " + value; + } + tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, + "OnSuccess", value); + } webkit_request_.RequestSucceeded(CreateWebKitSessionDescription(desc)); webkit_request_.Reset(); delete desc; @@ -411,7 +370,10 @@ class CreateSessionDescriptionRequest return; } - tracker_.TrackOnFailure(error); + if (handler_ && tracker_) { + tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, + "OnFailure", error.message()); + } // TODO(hta): Convert CreateSessionDescriptionRequest.OnFailure webkit_request_.RequestFailed(error); webkit_request_.Reset(); @@ -430,62 +392,9 @@ class CreateSessionDescriptionRequest const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; blink::WebRTCSessionDescriptionRequest webkit_request_; - SessionDescriptionRequestTracker tracker_; -}; - -// Class mapping responses from calls to libjingle SetLocalDescription and a -// blink::WebRTCVoidRequest. -class SetLocalDescriptionRequest - : public webrtc::SetSessionDescriptionObserver { - public: - explicit SetLocalDescriptionRequest( - const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, - const blink::WebRTCVoidRequest& request, - const base::WeakPtr<RTCPeerConnectionHandler>& handler, - const base::WeakPtr<PeerConnectionTracker>& tracker, - PeerConnectionTracker::Action action) - : main_thread_(main_thread), - webkit_request_(request), - tracker_(handler, tracker, action) {} - - void OnSuccess() override { - if (!main_thread_->BelongsToCurrentThread()) { - main_thread_->PostTask( - FROM_HERE, - base::BindOnce(&SetLocalDescriptionRequest::OnSuccess, this)); - return; - } - tracker_.TrackOnSuccess(nullptr); - webkit_request_.RequestSucceeded(); - webkit_request_.Reset(); - } - void OnFailure(webrtc::RTCError error) override { - if (!main_thread_->BelongsToCurrentThread()) { - main_thread_->PostTask( - FROM_HERE, base::BindOnce(&SetLocalDescriptionRequest::OnFailure, - this, std::move(error))); - return; - } - tracker_.TrackOnFailure(error); - webkit_request_.RequestFailed(error); - webkit_request_.Reset(); - } - - protected: - ~SetLocalDescriptionRequest() override { - // This object is reference counted and its callback methods |OnSuccess| and - // |OnFailure| will be invoked on libjingle's signaling thread and posted to - // the main thread. Since the main thread may complete before the signaling - // thread has deferenced this object there is no guarantee that this object - // is destructed on the main thread. - DLOG_IF(ERROR, !webkit_request_.IsNull()) - << "SetLocalDescriptionRequest not completed. Shutting down?"; - } - - private: - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - blink::WebRTCVoidRequest webkit_request_; - SessionDescriptionRequestTracker tracker_; + const base::WeakPtr<RTCPeerConnectionHandler> handler_; + const base::WeakPtr<PeerConnectionTracker> tracker_; + PeerConnectionTracker::Action action_; }; blink::WebRTCLegacyStatsMemberType @@ -704,139 +613,6 @@ void GetRTCStatsOnSignalingThread( RTCStatsCollectorCallbackImpl::Create(main_thread, std::move(callback))); } -class PeerConnectionUMAObserver : public webrtc::UMAObserver { - public: - PeerConnectionUMAObserver() {} - ~PeerConnectionUMAObserver() override {} - void IncrementEnumCounter(webrtc::PeerConnectionEnumCounterType counter_type, - int counter, - int counter_max) override { - switch (counter_type) { - case webrtc::kEnumCounterAddressFamily: - UMA_HISTOGRAM_EXACT_LINEAR("WebRTC.PeerConnection.IPMetrics", counter, - counter_max); - break; - case webrtc::kEnumCounterIceCandidatePairTypeUdp: - UMA_HISTOGRAM_EXACT_LINEAR( - "WebRTC.PeerConnection.CandidatePairType_UDP", counter, - counter_max); - break; - case webrtc::kEnumCounterIceCandidatePairTypeTcp: - UMA_HISTOGRAM_EXACT_LINEAR( - "WebRTC.PeerConnection.CandidatePairType_TCP", counter, - counter_max); - break; - case webrtc::kEnumCounterDtlsHandshakeError: - UMA_HISTOGRAM_EXACT_LINEAR("WebRTC.PeerConnection.DtlsHandshakeError", - counter, counter_max); - break; - case webrtc::kEnumCounterIceRestart: - UMA_HISTOGRAM_EXACT_LINEAR("WebRTC.PeerConnection.IceRestartState", - counter, counter_max); - break; - case webrtc::kEnumCounterIceRegathering: - UMA_HISTOGRAM_EXACT_LINEAR("WebRTC.PeerConnection.IceRegatheringReason", - counter, counter_max); - break; - case webrtc::kEnumCounterKeyProtocol: - UMA_HISTOGRAM_ENUMERATION( - "WebRTC.PeerConnection.KeyProtocol", - static_cast<webrtc::KeyExchangeProtocolType>(counter), - webrtc::kEnumCounterKeyProtocolMax); - break; - case webrtc::kEnumCounterSdpSemanticNegotiated: - UMA_HISTOGRAM_ENUMERATION( - "WebRTC.PeerConnection.SdpSemanticNegotiated", - static_cast<webrtc::SdpSemanticNegotiated>(counter), - webrtc::kSdpSemanticNegotiatedMax); - break; - case webrtc::kEnumCounterKeyProtocolMediaType: - UMA_HISTOGRAM_ENUMERATION( - "WebRTC.PeerConnection.KeyProtocolByMedia", - static_cast<webrtc::KeyExchangeProtocolMedia>(counter), - webrtc::kEnumCounterKeyProtocolMediaTypeMax); - break; - case webrtc::kEnumCounterSdpFormatReceived: - UMA_HISTOGRAM_ENUMERATION( - "WebRTC.PeerConnection.SdpFormatReceived", - static_cast<webrtc::SdpFormatReceived>(counter), - webrtc::kSdpFormatReceivedMax); - break; - default: - // The default clause is expected to be reached when new enum types are - // added. - break; - } - } - - void IncrementSparseEnumCounter( - webrtc::PeerConnectionEnumCounterType counter_type, - int counter) override { - switch (counter_type) { - case webrtc::kEnumCounterAudioSrtpCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtpCryptoSuite.Audio", - counter); - break; - case webrtc::kEnumCounterAudioSslCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SslCipherSuite.Audio", - counter); - break; - case webrtc::kEnumCounterVideoSrtpCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtpCryptoSuite.Video", - counter); - break; - case webrtc::kEnumCounterVideoSslCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SslCipherSuite.Video", - counter); - break; - case webrtc::kEnumCounterDataSrtpCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtpCryptoSuite.Data", - counter); - break; - case webrtc::kEnumCounterDataSslCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SslCipherSuite.Data", - counter); - break; - case webrtc::kEnumCounterSrtpUnprotectError: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtpUnprotectError", - counter); - break; - case webrtc::kEnumCounterSrtcpUnprotectError: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtcpUnprotectError", - counter); - break; - default: - // The default clause is expected to reach when new enum types are - // added. - break; - } - } - - void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type, - int value) override { - // Runs on libjingle's signaling thread. - switch (type) { - case webrtc::kTimeToConnect: - UMA_HISTOGRAM_MEDIUM_TIMES( - "WebRTC.PeerConnection.TimeToConnect", - base::TimeDelta::FromMilliseconds(value)); - break; - case webrtc::kNetworkInterfaces_IPv4: - UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces", - value); - break; - case webrtc::kNetworkInterfaces_IPv6: - UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces", - value); - break; - default: - // The default clause is expected to reach when new enum types are - // added. - break; - } - } -}; - void ConvertOfferOptionsToWebrtcOfferOptions( const blink::WebRTCOfferOptions& options, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions* output) { @@ -890,15 +666,14 @@ std::set<RTCPeerConnectionHandler*>* GetPeerConnectionHandlers() { return handlers; } -// Counts the number of senders that have |web_stream| as an associated stream. +// Counts the number of senders that have |stream_id| as an associated stream. size_t GetLocalStreamUsageCount( const std::vector<std::unique_ptr<RTCRtpSender>>& rtp_senders, - const blink::WebMediaStream& web_stream) { + const std::string stream_id) { size_t usage_count = 0; for (const auto& sender : rtp_senders) { - for (const auto& stream_ref : sender->stream_refs()) { - if (stream_ref->adapter().web_stream().UniqueId() == - web_stream.UniqueId()) { + for (const auto& sender_stream_id : sender->state().stream_ids()) { + if (sender_stream_id == stream_id) { ++usage_count; break; } @@ -907,17 +682,16 @@ size_t GetLocalStreamUsageCount( return usage_count; } -// Counts the number of receivers that have |webrtc_stream| as an associated -// stream. -size_t GetRemoteStreamUsageCount( - const std::map<uintptr_t, std::unique_ptr<RTCRtpReceiver>>& rtp_receivers, - const webrtc::MediaStreamInterface* webrtc_stream) { - size_t usage_count = 0; - for (const auto& receiver_entry : rtp_receivers) { - if (receiver_entry.second->HasStream(webrtc_stream)) - ++usage_count; +bool IsRemoteStream( + const std::vector<std::unique_ptr<RTCRtpReceiver>>& rtp_receivers, + const std::string& stream_id) { + for (const auto& receiver : rtp_receivers) { + for (const auto& receiver_stream_id : receiver->state().stream_ids()) { + if (stream_id == receiver_stream_id) + return true; + } } - return usage_count; + return false; } enum SdpSemanticRequested { @@ -941,6 +715,13 @@ SdpSemanticRequested GetSdpSemanticRequested( return kSdpSemanticRequestedDefault; } +MediaStreamTrackMetrics::Kind MediaStreamTrackMetricsKind( + const blink::WebMediaStreamTrack& track) { + return track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio + ? MediaStreamTrackMetrics::Kind::kAudio + : MediaStreamTrackMetrics::Kind::kVideo; +} + } // namespace // Implementation of LocalRTCStatsRequest. @@ -978,175 +759,146 @@ void LocalRTCStatsResponse::addStats(const blink::WebRTCLegacyStats& stats) { impl_.AddStats(stats); } -// Processes the resulting state changes of a SetRemoteDescription call. -class RTCPeerConnectionHandler::WebRtcSetRemoteDescriptionObserverImpl - : public WebRtcSetRemoteDescriptionObserver { +// Processes the resulting state changes of a SetLocalDescription() or +// SetRemoteDescription() call. +class RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl + : public WebRtcSetDescriptionObserver { public: - WebRtcSetRemoteDescriptionObserverImpl( + WebRtcSetDescriptionObserverImpl( base::WeakPtr<RTCPeerConnectionHandler> handler, blink::WebRTCVoidRequest web_request, base::WeakPtr<PeerConnectionTracker> tracker, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + PeerConnectionTracker::Action action, + blink::WebRTCSdpSemantics sdp_semantics) : handler_(handler), main_thread_(task_runner), web_request_(web_request), - tracker_(tracker) {} + tracker_(tracker), + action_(action), + sdp_semantics_(sdp_semantics) { + DCHECK(sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB || + sdp_semantics_ == blink::WebRTCSdpSemantics::kUnifiedPlan); + } - void OnSetRemoteDescriptionComplete( - webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States> - states_or_error) override { - if (!states_or_error.ok()) { - auto& error = states_or_error.error(); + void OnSetDescriptionComplete( + webrtc::RTCError error, + WebRtcSetDescriptionObserver::States states) override { + if (!error.ok()) { if (tracker_ && handler_) { - tracker_->TrackSessionDescriptionCallback( - handler_.get(), - PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION, "OnFailure", - error.message()); + tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, + "OnFailure", error.message()); } web_request_.RequestFailed(error); web_request_.Reset(); return; } - auto& states = states_or_error.value(); if (handler_) { - // Determine which receivers have been removed before processing the - // removal as to not invalidate the iterator. - std::vector<RTCRtpReceiver*> removed_receivers; - for (auto it = handler_->rtp_receivers_.begin(); - it != handler_->rtp_receivers_.end(); ++it) { - if (ReceiverWasRemoved(*it->second, states.receiver_states)) - removed_receivers.push_back(it->second.get()); - } - - // Update stream states (which tracks belong to which streams). - for (auto& stream_state : GetStreamStates(states, removed_receivers)) { - stream_state.stream_ref->adapter().SetTracks( - std::move(stream_state.track_refs)); + handler_->OnSignalingChange(states.signaling_state); + + // Process the rest of the state changes differently depending on SDP + // semantics. + if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) { + ProcessStateChangesPlanB(std::move(states)); + } else { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + ProcessStateChangesUnifiedPlan(std::move(states)); } - // Process the addition of remote receivers/tracks. - for (auto& receiver_state : states.receiver_states) { - if (ReceiverWasAdded(receiver_state)) { - handler_->OnAddRemoteTrack(receiver_state.receiver, - std::move(receiver_state.track_ref), - std::move(receiver_state.stream_refs)); - } - } - // Process the removal of remote receivers/tracks. - for (auto* removed_receiver : removed_receivers) - handler_->OnRemoveRemoteTrack(removed_receiver->webrtc_receiver()); if (tracker_) { - tracker_->TrackSessionDescriptionCallback( - handler_.get(), - PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION, "OnSuccess", - ""); + tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, + "OnSuccess", ""); } } - // Resolve the promise in a post to ensure any events scheduled for - // dispatching will have fired by the time the promise is resolved. - // TODO(hbos): Don't schedule/post to fire events/resolve the promise. - // Instead, do it all synchronously. This must happen as the last step - // before returning so that all effects of SRD have occurred when the event - // executes. https://crbug.com/788558 - main_thread_->PostTask( - FROM_HERE, - base::BindOnce( - &RTCPeerConnectionHandler::WebRtcSetRemoteDescriptionObserverImpl:: - ResolvePromise, - this)); + if (action_ == PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION) { + // Resolve the promise in a post to ensure any events scheduled for + // dispatching will have fired by the time the promise is resolved. + // TODO(hbos): Don't schedule/post to fire events/resolve the promise. + // Instead, do it all synchronously. This must happen as the last step + // before returning so that all effects of SRD have occurred when the + // event executes. https://crbug.com/788558 + main_thread_->PostTask( + FROM_HERE, + base::BindOnce(&RTCPeerConnectionHandler:: + WebRtcSetDescriptionObserverImpl::ResolvePromise, + this)); + } else { + // Resolve promise immediately if we can. https://crbug.com/788558 still + // needs to be addressed for "setLocalDescription(answer)" rejecting a + // transceiver in Unified Plan, but this is a minor edge-case. + ResolvePromise(); + } } private: - ~WebRtcSetRemoteDescriptionObserverImpl() override {} - - // Describes which tracks belong to a stream in terms of AdapterRefs. - struct StreamState { - StreamState( - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> stream_ref) - : stream_ref(std::move(stream_ref)) {} - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> stream_ref; - std::vector<std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>> - track_refs; - }; + ~WebRtcSetDescriptionObserverImpl() override {} void ResolvePromise() { web_request_.RequestSucceeded(); web_request_.Reset(); } - bool ReceiverWasAdded(const WebRtcReceiverState& receiver_state) { - return handler_->rtp_receivers_.find( - RTCRtpReceiver::getId(receiver_state.receiver.get())) == - handler_->rtp_receivers_.end(); + void ProcessStateChangesPlanB(WebRtcSetDescriptionObserver::States states) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kPlanB); + // Determine which receivers have been removed before processing the + // removal as to not invalidate the iterator. + std::vector<RTCRtpReceiver*> removed_receivers; + for (auto it = handler_->rtp_receivers_.begin(); + it != handler_->rtp_receivers_.end(); ++it) { + if (ReceiverWasRemoved(*(*it), states.transceiver_states)) + removed_receivers.push_back(it->get()); + } + + // Process the addition of remote receivers/tracks. + for (auto& transceiver_state : states.transceiver_states) { + if (ReceiverWasAdded(transceiver_state)) { + handler_->OnAddReceiverPlanB(transceiver_state.MoveReceiverState()); + } + } + // Process the removal of remote receivers/tracks. + for (auto* removed_receiver : removed_receivers) { + handler_->OnRemoveReceiverPlanB(RTCRtpReceiver::getId( + removed_receiver->state().webrtc_receiver().get())); + } } - bool ReceiverWasRemoved( - const RTCRtpReceiver& receiver, - const std::vector<WebRtcReceiverState>& receiver_states) { - for (const auto& receiver_state : receiver_states) { - if (receiver_state.receiver == receiver.webrtc_receiver()) + bool ReceiverWasAdded(const RtpTransceiverState& transceiver_state) { + uintptr_t receiver_id = RTCRtpReceiver::getId( + transceiver_state.receiver_state()->webrtc_receiver().get()); + for (const auto& receiver : handler_->rtp_receivers_) { + if (receiver->Id() == receiver_id) return false; } return true; } - // Determines the stream states from the current state of receivers and the - // receivers that are about to be removed. Produces a stable order of streams. - std::vector<StreamState> GetStreamStates( - const WebRtcSetRemoteDescriptionObserver::States& states, - const std::vector<RTCRtpReceiver*>& removed_receivers) { - states.CheckInvariants(); - std::vector<StreamState> stream_states; - // The receiver's track belongs to all of its streams. A stream may be - // associated with multiple tracks (multiple receivers). - for (auto& receiver_state : states.receiver_states) { - for (auto& stream_ref : receiver_state.stream_refs) { - CHECK(stream_ref); - CHECK(stream_ref->adapter().is_initialized()); - CHECK(!stream_ref->adapter().web_stream().IsNull()); - CHECK(stream_ref->adapter().webrtc_stream()); - auto* stream_state = - GetOrAddStreamStateForStream(*stream_ref, &stream_states); - auto track_ref = receiver_state.track_ref->Copy(); - CHECK(!track_ref->web_track().IsNull()); - CHECK(track_ref->webrtc_track()); - stream_state->track_refs.push_back(std::move(track_ref)); - } - } - // The track of removed receivers do not belong to any stream. Make sure we - // have a stream state for any streams belonging to receivers about to be - // removed in case it was the last receiver referencing that stream. - for (auto* removed_receiver : removed_receivers) { - for (auto& stream_ref : removed_receiver->StreamAdapterRefs()) { - CHECK(!stream_ref->adapter().web_stream().IsNull()); - CHECK(stream_ref->adapter().webrtc_stream()); - GetOrAddStreamStateForStream(*stream_ref, &stream_states); - } - } - states.CheckInvariants(); - return stream_states; - } - - StreamState* GetOrAddStreamStateForStream( - const WebRtcMediaStreamAdapterMap::AdapterRef& stream_ref, - std::vector<StreamState>* stream_states) { - auto* webrtc_stream = stream_ref.adapter().webrtc_stream().get(); - for (auto& stream_state : *stream_states) { - if (stream_state.stream_ref->adapter().webrtc_stream().get() == - webrtc_stream) { - return &stream_state; + bool ReceiverWasRemoved( + const RTCRtpReceiver& receiver, + const std::vector<RtpTransceiverState>& transceiver_states) { + for (const auto& transceiver_state : transceiver_states) { + if (transceiver_state.receiver_state()->webrtc_receiver() == + receiver.state().webrtc_receiver()) { + return false; } } - stream_states->push_back(StreamState(stream_ref.Copy())); - return &stream_states->back(); + return true; + } + + void ProcessStateChangesUnifiedPlan( + WebRtcSetDescriptionObserver::States states) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + handler_->OnModifyTransceivers( + std::move(states.transceiver_states), + action_ == PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION); } base::WeakPtr<RTCPeerConnectionHandler> handler_; scoped_refptr<base::SequencedTaskRunner> main_thread_; blink::WebRTCVoidRequest web_request_; base::WeakPtr<PeerConnectionTracker> tracker_; + PeerConnectionTracker::Action action_; + blink::WebRTCSdpSemantics sdp_semantics_; }; // Receives notifications from a PeerConnection object about state changes. The @@ -1181,19 +933,8 @@ class RTCPeerConnectionHandler::Observer friend class base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>; ~Observer() override = default; - void OnSignalingChange( - PeerConnectionInterface::SignalingState new_state) override { - if (!main_thread_->BelongsToCurrentThread()) { - main_thread_->PostTask( - FROM_HERE, - base::BindOnce(&RTCPeerConnectionHandler::Observer::OnSignalingChange, - this, new_state)); - } else if (handler_) { - handler_->OnSignalingChange(new_state); - } - } - // TODO(hbos): Remove once no longer mandatory to implement. + void OnSignalingChange(PeerConnectionInterface::SignalingState) override {} void OnAddStream(rtc::scoped_refptr<MediaStreamInterface>) override {} void OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface>) override {} @@ -1293,9 +1034,8 @@ RTCPeerConnectionHandler::RTCPeerConnectionHandler( track_adapter_map_( new WebRtcMediaStreamTrackAdapterMap(dependency_factory_, task_runner)), - stream_adapter_map_(new WebRtcMediaStreamAdapterMap(dependency_factory_, - task_runner, - track_adapter_map_)), + // This will be overwritten to the actual value used at Initialize(). + sdp_semantics_(blink::WebRTCSdpSemantics::kDefault), task_runner_(std::move(task_runner)), weak_factory_(this) { CHECK(client_); @@ -1304,7 +1044,7 @@ RTCPeerConnectionHandler::RTCPeerConnectionHandler( } RTCPeerConnectionHandler::~RTCPeerConnectionHandler() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); Stop(); @@ -1317,15 +1057,16 @@ RTCPeerConnectionHandler::~RTCPeerConnectionHandler() { } void RTCPeerConnectionHandler::associateWithFrame(blink::WebLocalFrame* frame) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(frame); frame_ = frame; } bool RTCPeerConnectionHandler::Initialize( const blink::WebRTCConfiguration& server_configuration, - const blink::WebMediaConstraints& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + const blink::WebMediaConstraints& options, + blink::WebRTCSdpSemantics original_sdp_semantics_value) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(frame_); CHECK(!initialize_called_); @@ -1334,6 +1075,9 @@ bool RTCPeerConnectionHandler::Initialize( peer_connection_tracker_ = RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr(); + sdp_semantics_ = server_configuration.sdp_semantics; + DCHECK(sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB || + sdp_semantics_ == blink::WebRTCSdpSemantics::kUnifiedPlan); GetNativeRtcConfiguration(server_configuration, &configuration_); // Choose between RTC smoothness algorithm and prerenderer smoothing. @@ -1363,12 +1107,9 @@ bool RTCPeerConnectionHandler::Initialize( options, frame_); } - uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>(); - native_peer_connection_->RegisterUMAObserver(uma_observer_.get()); - UMA_HISTOGRAM_ENUMERATION( "WebRTC.PeerConnection.SdpSemanticRequested", - GetSdpSemanticRequested(server_configuration.sdp_semantics), + GetSdpSemanticRequested(original_sdp_semantics_value), kSdpSemanticRequestedMax); return true; @@ -1378,11 +1119,14 @@ bool RTCPeerConnectionHandler::InitializeForTest( const blink::WebRTCConfiguration& server_configuration, const blink::WebMediaConstraints& options, const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); CHECK(!initialize_called_); initialize_called_ = true; + sdp_semantics_ = server_configuration.sdp_semantics; + DCHECK(sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB || + sdp_semantics_ == blink::WebRTCSdpSemantics::kUnifiedPlan); GetNativeRtcConfiguration(server_configuration, &configuration_); peer_connection_observer_ = @@ -1402,7 +1146,7 @@ bool RTCPeerConnectionHandler::InitializeForTest( void RTCPeerConnectionHandler::CreateOffer( const blink::WebRTCSessionDescriptionRequest& request, const blink::WebMediaConstraints& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer"); scoped_refptr<CreateSessionDescriptionRequest> description_request( @@ -1424,7 +1168,7 @@ void RTCPeerConnectionHandler::CreateOffer( void RTCPeerConnectionHandler::CreateOffer( const blink::WebRTCSessionDescriptionRequest& request, const blink::WebRTCOfferOptions& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer"); scoped_refptr<CreateSessionDescriptionRequest> description_request( @@ -1446,7 +1190,7 @@ void RTCPeerConnectionHandler::CreateOffer( void RTCPeerConnectionHandler::CreateAnswer( const blink::WebRTCSessionDescriptionRequest& request, const blink::WebMediaConstraints& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer"); scoped_refptr<CreateSessionDescriptionRequest> description_request( new rtc::RefCountedObject<CreateSessionDescriptionRequest>( @@ -1466,7 +1210,7 @@ void RTCPeerConnectionHandler::CreateAnswer( void RTCPeerConnectionHandler::CreateAnswer( const blink::WebRTCSessionDescriptionRequest& request, const blink::WebRTCAnswerOptions& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer"); scoped_refptr<CreateSessionDescriptionRequest> description_request( new rtc::RefCountedObject<CreateSessionDescriptionRequest>( @@ -1491,7 +1235,7 @@ bool IsOfferOrAnswer(const webrtc::SessionDescriptionInterface* native_desc) { void RTCPeerConnectionHandler::SetLocalDescription( const blink::WebRTCVoidRequest& request, const blink::WebRTCSessionDescription& description) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription"); std::string sdp = description.Sdp().Utf8(); @@ -1532,18 +1276,27 @@ void RTCPeerConnectionHandler::SetLocalDescription( } } - scoped_refptr<SetLocalDescriptionRequest> set_request( - new rtc::RefCountedObject<SetLocalDescriptionRequest>( - task_runner_, request, weak_factory_.GetWeakPtr(), - peer_connection_tracker_, - PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION)); + scoped_refptr<WebRtcSetDescriptionObserverImpl> content_observer( + new WebRtcSetDescriptionObserverImpl( + weak_factory_.GetWeakPtr(), request, peer_connection_tracker_, + task_runner_, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION, + sdp_semantics_)); + + bool surface_receivers_only = + (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB); + scoped_refptr<webrtc::SetSessionDescriptionObserver> webrtc_observer( + WebRtcSetLocalDescriptionObserverHandler::Create( + task_runner_, signaling_thread(), native_peer_connection_, + track_adapter_map_, content_observer, surface_receivers_only) + .get()); signaling_thread()->PostTask( FROM_HERE, base::BindOnce( &RunClosureWithTrace, base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription, - native_peer_connection_, base::RetainedRef(set_request), + native_peer_connection_, + base::RetainedRef(webrtc_observer), base::Unretained(native_desc)), "SetLocalDescription")); } @@ -1551,7 +1304,7 @@ void RTCPeerConnectionHandler::SetLocalDescription( void RTCPeerConnectionHandler::SetRemoteDescription( const blink::WebRTCVoidRequest& request, const blink::WebRTCSessionDescription& description) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription"); std::string sdp = description.Sdp().Utf8(); std::string type = description.GetType().Utf8(); @@ -1592,15 +1345,19 @@ void RTCPeerConnectionHandler::SetRemoteDescription( } } - scoped_refptr<WebRtcSetRemoteDescriptionObserverImpl> content_observer( - new WebRtcSetRemoteDescriptionObserverImpl( + scoped_refptr<WebRtcSetDescriptionObserverImpl> content_observer( + new WebRtcSetDescriptionObserverImpl( weak_factory_.GetWeakPtr(), request, peer_connection_tracker_, - task_runner_)); + task_runner_, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION, + sdp_semantics_)); + bool surface_receivers_only = + (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB); rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> webrtc_observer(WebRtcSetRemoteDescriptionObserverHandler::Create( - task_runner_, native_peer_connection_, - stream_adapter_map_, content_observer) + task_runner_, signaling_thread(), + native_peer_connection_, track_adapter_map_, + content_observer, surface_receivers_only) .get()); signaling_thread()->PostTask( @@ -1619,7 +1376,7 @@ void RTCPeerConnectionHandler::SetRemoteDescription( } blink::WebRTCSessionDescription RTCPeerConnectionHandler::LocalDescription() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription"); // Since local_description returns a pointer to a non-reference-counted object @@ -1640,7 +1397,7 @@ blink::WebRTCSessionDescription RTCPeerConnectionHandler::LocalDescription() { } blink::WebRTCSessionDescription RTCPeerConnectionHandler::RemoteDescription() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription"); // Since local_description returns a pointer to a non-reference-counted object // that lives on the signaling thread, we cannot fetch a pointer to it and use @@ -1661,7 +1418,7 @@ blink::WebRTCSessionDescription RTCPeerConnectionHandler::RemoteDescription() { webrtc::RTCErrorType RTCPeerConnectionHandler::SetConfiguration( const blink::WebRTCConfiguration& blink_config) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setConfiguration"); GetNativeRtcConfiguration(blink_config, &configuration_); @@ -1680,7 +1437,7 @@ webrtc::RTCErrorType RTCPeerConnectionHandler::SetConfiguration( bool RTCPeerConnectionHandler::AddICECandidate( const blink::WebRTCVoidRequest& request, scoped_refptr<blink::WebRTCICECandidate> candidate) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate"); // Libjingle currently does not accept callbacks for addICECandidate. // For that reason we are going to call callbacks from here. @@ -1698,7 +1455,7 @@ bool RTCPeerConnectionHandler::AddICECandidate( bool RTCPeerConnectionHandler::AddICECandidate( scoped_refptr<blink::WebRTCICECandidate> candidate) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate"); std::unique_ptr<webrtc::IceCandidateInterface> native_candidate( dependency_factory_->CreateIceCandidate(candidate->SdpMid().Utf8(), @@ -1724,7 +1481,7 @@ bool RTCPeerConnectionHandler::AddICECandidate( void RTCPeerConnectionHandler::OnaddICECandidateResult( const blink::WebRTCVoidRequest& webkit_request, bool result) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult"); if (!result) { // We don't have the actual error code from the libjingle, so for now @@ -1739,7 +1496,7 @@ void RTCPeerConnectionHandler::OnaddICECandidateResult( void RTCPeerConnectionHandler::GetStats( const blink::WebRTCStatsRequest& request) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); scoped_refptr<LocalRTCStatsRequest> inner_request( new rtc::RefCountedObject<LocalRTCStatsRequest>(request)); getStats(inner_request); @@ -1747,7 +1504,7 @@ void RTCPeerConnectionHandler::GetStats( void RTCPeerConnectionHandler::getStats( const scoped_refptr<LocalRTCStatsRequest>& request) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats"); rtc::scoped_refptr<webrtc::StatsObserver> observer( @@ -1777,7 +1534,7 @@ void RTCPeerConnectionHandler::GetStats( webrtc::StatsObserver* observer, webrtc::PeerConnectionInterface::StatsOutputLevel level, rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> selector) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); signaling_thread()->PostTask( FROM_HERE, base::BindOnce(&GetStatsOnSignalingThread, native_peer_connection_, level, @@ -1786,96 +1543,347 @@ void RTCPeerConnectionHandler::GetStats( void RTCPeerConnectionHandler::GetStats( std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); signaling_thread()->PostTask( FROM_HERE, base::BindOnce(&GetRTCStatsOnSignalingThread, task_runner_, native_peer_connection_, std::move(callback))); } -std::unique_ptr<blink::WebRTCRtpSender> RTCPeerConnectionHandler::AddTrack( +webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> +RTCPeerConnectionHandler::AddTransceiverWithTrack( + const blink::WebMediaStreamTrack& web_track, + const webrtc::RtpTransceiverInit& init) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref = + track_adapter_map_->GetOrCreateLocalTrackAdapter(web_track); + TransceiverStateSurfacer transceiver_state_surfacer(task_runner_, + signaling_thread()); + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + error_or_transceiver; + RunSynchronousClosureOnSignalingThread( + base::BindRepeating( + &RTCPeerConnectionHandler::AddTransceiverWithTrackOnSignalingThread, + base::Unretained(this), base::RetainedRef(track_ref->webrtc_track()), + base::ConstRef(init), base::Unretained(&transceiver_state_surfacer), + base::Unretained(&error_or_transceiver)), + "AddTransceiverWithTrackOnSignalingThread"); + if (!error_or_transceiver.ok()) { + // Don't leave the surfacer in a pending state. + transceiver_state_surfacer.ObtainStates(); + return error_or_transceiver.MoveError(); + } + + auto transceiver_states = transceiver_state_surfacer.ObtainStates(); + auto transceiver = + CreateOrUpdateTransceiver(std::move(transceiver_states[0])); + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = + std::move(transceiver); + return std::move(web_transceiver); +} + +void RTCPeerConnectionHandler::AddTransceiverWithTrackOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track, + webrtc::RtpTransceiverInit init, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>* + error_or_transceiver) { + *error_or_transceiver = + native_peer_connection_->AddTransceiver(webrtc_track, init); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (error_or_transceiver->ok()) + transceivers.push_back(error_or_transceiver->value()); + transceiver_state_surfacer->Initialize(track_adapter_map_, transceivers); +} + +webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> +RTCPeerConnectionHandler::AddTransceiverWithKind( + std::string kind, + const webrtc::RtpTransceiverInit& init) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + cricket::MediaType media_type; + if (kind == webrtc::MediaStreamTrackInterface::kAudioKind) { + media_type = cricket::MEDIA_TYPE_AUDIO; + } else { + DCHECK_EQ(kind, webrtc::MediaStreamTrackInterface::kVideoKind); + media_type = cricket::MEDIA_TYPE_VIDEO; + } + TransceiverStateSurfacer transceiver_state_surfacer(task_runner_, + signaling_thread()); + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + error_or_transceiver; + RunSynchronousClosureOnSignalingThread( + base::BindRepeating(&RTCPeerConnectionHandler:: + AddTransceiverWithMediaTypeOnSignalingThread, + base::Unretained(this), base::ConstRef(media_type), + base::ConstRef(init), + base::Unretained(&transceiver_state_surfacer), + base::Unretained(&error_or_transceiver)), + "AddTransceiverWithMediaTypeOnSignalingThread"); + if (!error_or_transceiver.ok()) { + // Don't leave the surfacer in a pending state. + transceiver_state_surfacer.ObtainStates(); + return error_or_transceiver.MoveError(); + } + + auto transceiver_states = transceiver_state_surfacer.ObtainStates(); + auto transceiver = + CreateOrUpdateTransceiver(std::move(transceiver_states[0])); + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = + std::move(transceiver); + return std::move(web_transceiver); +} + +void RTCPeerConnectionHandler::AddTransceiverWithMediaTypeOnSignalingThread( + cricket::MediaType media_type, + webrtc::RtpTransceiverInit init, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>* + error_or_transceiver) { + *error_or_transceiver = + native_peer_connection_->AddTransceiver(media_type, init); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (error_or_transceiver->ok()) + transceivers.push_back(error_or_transceiver->value()); + transceiver_state_surfacer->Initialize(track_adapter_map_, transceivers); +} + +webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> +RTCPeerConnectionHandler::AddTrack( const blink::WebMediaStreamTrack& track, const blink::WebVector<blink::WebMediaStream>& streams) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::AddTrack"); - // Get or create the associated track and stream adapters. - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter = + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref = track_adapter_map_->GetOrCreateLocalTrackAdapter(track); - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapters(streams.size()); - std::vector<webrtc::MediaStreamInterface*> webrtc_streams(streams.size()); - for (size_t i = 0; i < streams.size(); ++i) { - stream_adapters[i] = - stream_adapter_map_->GetOrCreateLocalStreamAdapter(streams[i]); - webrtc_streams[i] = stream_adapters[i]->adapter().webrtc_stream().get(); - } - - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender = - native_peer_connection_->AddTrack(track_adapter->webrtc_track(), - webrtc_streams); - if (!webrtc_sender) - return nullptr; - DCHECK(FindSender(RTCRtpSender::getId(webrtc_sender)) == rtp_senders_.end()); - rtp_senders_.push_back(std::make_unique<RTCRtpSender>( - native_peer_connection_, task_runner_, signaling_thread(), - stream_adapter_map_, std::move(webrtc_sender), std::move(track_adapter), - std::move(stream_adapters))); - for (const auto& stream_ref : rtp_senders_.back()->stream_refs()) { - if (GetLocalStreamUsageCount(rtp_senders_, - stream_ref->adapter().web_stream()) == 1u) { + std::vector<std::string> stream_ids(streams.size()); + for (size_t i = 0; i < streams.size(); ++i) + stream_ids[i] = streams[i].Id().Utf8(); + + // Invoke native AddTrack() on the signaling thread and surface the resulting + // transceiver (Plan B: sender only). + // TODO(hbos): Implement and surface full transceiver support under Unified + // Plan. https://crbug.com/777617 + TransceiverStateSurfacer transceiver_state_surfacer(task_runner_, + signaling_thread()); + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> + error_or_sender; + RunSynchronousClosureOnSignalingThread( + base::BindRepeating( + &RTCPeerConnectionHandler::AddTrackOnSignalingThread, + base::Unretained(this), base::RetainedRef(track_ref->webrtc_track()), + std::move(stream_ids), base::Unretained(&transceiver_state_surfacer), + base::Unretained(&error_or_sender)), + "AddTrackOnSignalingThread"); + DCHECK(transceiver_state_surfacer.is_initialized()); + if (!error_or_sender.ok()) { + // Don't leave the surfacer in a pending state. + transceiver_state_surfacer.ObtainStates(); + return error_or_sender.MoveError(); + } + track_metrics_.AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetricsKind(track), + track.Id().Utf8()); + + auto transceiver_states = transceiver_state_surfacer.ObtainStates(); + DCHECK_EQ(transceiver_states.size(), 1u); + auto transceiver_state = std::move(transceiver_states[0]); + + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver; + if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) { + // Plan B: Create sender only. + DCHECK(transceiver_state.sender_state()); + auto webrtc_sender = transceiver_state.sender_state()->webrtc_sender(); + DCHECK(FindSender(RTCRtpSender::getId(webrtc_sender.get())) == + rtp_senders_.end()); + RtpSenderState sender_state = transceiver_state.MoveSenderState(); + DCHECK(sender_state.is_initialized()); + rtp_senders_.push_back(std::make_unique<RTCRtpSender>( + native_peer_connection_, track_adapter_map_, std::move(sender_state))); + web_transceiver = std::make_unique<RTCRtpSenderOnlyTransceiver>( + std::make_unique<RTCRtpSender>(*rtp_senders_.back().get())); + } else { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + // Unified Plan: Create or recycle a transceiver. + auto transceiver = CreateOrUpdateTransceiver(std::move(transceiver_state)); + web_transceiver = std::move(transceiver); + } + if (peer_connection_tracker_) { + size_t transceiver_index = GetTransceiverIndex(*web_transceiver.get()); + peer_connection_tracker_->TrackAddTransceiver( + this, PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, + *web_transceiver.get(), transceiver_index); + } + for (const auto& stream_id : rtp_senders_.back()->state().stream_ids()) { + if (GetLocalStreamUsageCount(rtp_senders_, stream_id) == 1u) { // This is the first occurrence of this stream. - if (peer_connection_tracker_) { - peer_connection_tracker_->TrackAddStream( - this, stream_ref->adapter().web_stream(), - PeerConnectionTracker::SOURCE_LOCAL); - } PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter(); - track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM, - stream_ref->adapter().webrtc_stream().get()); } } - return rtp_senders_.back()->ShallowCopy(); + return web_transceiver; +} + +void RTCPeerConnectionHandler::AddTrackOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + std::vector<std::string> stream_ids, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>>* + error_or_sender) { + *error_or_sender = native_peer_connection_->AddTrack(track, stream_ids); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (error_or_sender->ok()) { + auto sender = error_or_sender->value(); + if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) { + transceivers = {new SurfaceSenderStateOnly(sender)}; + } else { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> + transceiver_for_sender = nullptr; + for (const auto& transceiver : + native_peer_connection_->GetTransceivers()) { + if (transceiver->sender() == sender) { + transceiver_for_sender = transceiver; + break; + } + } + DCHECK(transceiver_for_sender); + transceivers = {transceiver_for_sender}; + } + } + transceiver_state_surfacer->Initialize(track_adapter_map_, + std::move(transceivers)); } -bool RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) { - DCHECK(thread_checker_.CalledOnValidThread()); +webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> +RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::RemoveTrack"); + if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) { + if (RemoveTrackPlanB(web_sender)) { + // In Plan B, null indicates success. + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = nullptr; + return std::move(web_transceiver); + } + // TODO(hbos): Surface RTCError from third_party/webrtc when + // peerconnectioninterface.h is updated. https://crbug.com/webrtc/9534 + return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE); + } + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + return RemoveTrackUnifiedPlan(web_sender); +} + +bool RTCPeerConnectionHandler::RemoveTrackPlanB( + blink::WebRTCRtpSender* web_sender) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kPlanB); + auto web_track = web_sender->Track(); auto it = FindSender(web_sender->Id()); if (it == rtp_senders_.end()) return false; if (!(*it)->RemoveFromPeerConnection(native_peer_connection_.get())) return false; - auto stream_refs = (*it)->stream_refs(); - // TODO(hbos): In Unified Plan, senders are never removed. The lower layer - // needs to tell us what to do with the sender: Update its states and/or - // remove it. https://crbug.com/799030 + track_metrics_.RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetricsKind(web_track), + web_track.Id().Utf8()); + if (peer_connection_tracker_) { + auto sender_only_transceiver = + std::make_unique<RTCRtpSenderOnlyTransceiver>( + std::make_unique<RTCRtpSender>(*it->get())); + size_t sender_index = GetTransceiverIndex(*sender_only_transceiver); + peer_connection_tracker_->TrackRemoveTransceiver( + this, PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, + *sender_only_transceiver.get(), sender_index); + } + std::vector<std::string> stream_ids = (*it)->state().stream_ids(); rtp_senders_.erase(it); - for (const auto& stream_ref : stream_refs) { - if (GetLocalStreamUsageCount(rtp_senders_, - stream_ref->adapter().web_stream()) == 0u) { + for (const auto& stream_id : stream_ids) { + if (GetLocalStreamUsageCount(rtp_senders_, stream_id) == 0u) { // This was the last occurrence of this stream. - if (peer_connection_tracker_) { - peer_connection_tracker_->TrackRemoveStream( - this, stream_ref->adapter().web_stream(), - PeerConnectionTracker::SOURCE_LOCAL); - } PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter(); - track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, - stream_ref->adapter().webrtc_stream().get()); } } return true; } +webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> +RTCPeerConnectionHandler::RemoveTrackUnifiedPlan( + blink::WebRTCRtpSender* web_sender) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + auto it = FindSender(web_sender->Id()); + if (it == rtp_senders_.end()) + return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER); + const auto& sender = *it; + auto webrtc_sender = sender->state().webrtc_sender(); + + TransceiverStateSurfacer transceiver_state_surfacer(task_runner_, + signaling_thread()); + bool result; + RunSynchronousClosureOnSignalingThread( + base::BindRepeating( + &RTCPeerConnectionHandler::RemoveTrackUnifiedPlanOnSignalingThread, + base::Unretained(this), base::RetainedRef(webrtc_sender), + base::Unretained(&transceiver_state_surfacer), + base::Unretained(&result)), + "RemoveTrackUnifiedPlanOnSignalingThread"); + DCHECK(transceiver_state_surfacer.is_initialized()); + if (!result) { + // Don't leave the surfacer in a pending state. + transceiver_state_surfacer.ObtainStates(); + // TODO(hbos): Surface RTCError from third_party/webrtc when + // peerconnectioninterface.h is updated. https://crbug.com/webrtc/9534 + return webrtc::RTCError(webrtc::RTCErrorType::INTERNAL_ERROR); + } + + auto transceiver_states = transceiver_state_surfacer.ObtainStates(); + DCHECK_EQ(transceiver_states.size(), 1u); + auto transceiver_state = std::move(transceiver_states[0]); + + // Update the transceiver. + auto transceiver = CreateOrUpdateTransceiver(std::move(transceiver_state)); + if (peer_connection_tracker_) { + size_t transceiver_index = GetTransceiverIndex(*transceiver); + peer_connection_tracker_->TrackModifyTransceiver( + this, PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, + *transceiver.get(), transceiver_index); + } + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = + std::move(transceiver); + return web_transceiver; +} + +void RTCPeerConnectionHandler::RemoveTrackUnifiedPlanOnSignalingThread( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + TransceiverStateSurfacer* transceiver_state_surfacer, + bool* result) { + *result = native_peer_connection_->RemoveTrack(sender); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (*result) { + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver_for_sender = + nullptr; + for (const auto& transceiver : native_peer_connection_->GetTransceivers()) { + if (transceiver->sender() == sender) { + transceiver_for_sender = transceiver; + break; + } + } + DCHECK(transceiver_for_sender); + transceivers = {transceiver_for_sender}; + } + transceiver_state_surfacer->Initialize(track_adapter_map_, + std::move(transceivers)); +} + void RTCPeerConnectionHandler::CloseClientPeerConnection() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (!is_closed_) client_->ClosePeerConnection(); } void RTCPeerConnectionHandler::StartEventLog(IPC::PlatformFileForTransit file, int64_t max_file_size_bytes) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(file != IPC::InvalidPlatformFileForTransit()); // TODO(eladalon): StartRtcEventLog() return value is not useful; remove it // or find a way to be able to use it. @@ -1885,7 +1893,7 @@ void RTCPeerConnectionHandler::StartEventLog(IPC::PlatformFileForTransit file, } void RTCPeerConnectionHandler::StartEventLog() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); // TODO(eladalon): StartRtcEventLog() return value is not useful; remove it // or find a way to be able to use it. // https://crbug.com/775415 @@ -1896,13 +1904,13 @@ void RTCPeerConnectionHandler::StartEventLog() { } void RTCPeerConnectionHandler::StopEventLog() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); native_peer_connection_->StopRtcEventLog(); } void RTCPeerConnectionHandler::OnWebRtcEventLogWrite( const std::string& output) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (peer_connection_tracker_) { peer_connection_tracker_->TrackRtcEventLogWrite(this, output); } @@ -1911,7 +1919,7 @@ void RTCPeerConnectionHandler::OnWebRtcEventLogWrite( blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::CreateDataChannel( const blink::WebString& label, const blink::WebRTCDataChannelInit& init) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel"); DVLOG(1) << "createDataChannel label " << label.Utf8(); @@ -1943,7 +1951,7 @@ blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::CreateDataChannel( } void RTCPeerConnectionHandler::Stop() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DVLOG(1) << "RTCPeerConnectionHandler::stop"; if (is_closed_ || !native_peer_connection_.get()) @@ -1964,22 +1972,20 @@ blink::WebString RTCPeerConnectionHandler::Id() const { void RTCPeerConnectionHandler::OnSignalingChange( webrtc::PeerConnectionInterface::SignalingState new_state) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange"); - blink::WebRTCPeerConnectionHandlerClient::SignalingState state = - GetWebKitSignalingState(new_state); if (peer_connection_tracker_) - peer_connection_tracker_->TrackSignalingStateChange(this, state); + peer_connection_tracker_->TrackSignalingStateChange(this, new_state); if (!is_closed_) - client_->DidChangeSignalingState(state); + client_->DidChangeSignalingState(new_state); } // Called any time the IceConnectionState changes void RTCPeerConnectionHandler::OnIceConnectionChange( webrtc::PeerConnectionInterface::IceConnectionState new_state) { TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange"); - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); ReportICEState(new_state); if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) { ice_connection_checking_start_ = base::TimeTicks::Now(); @@ -2014,7 +2020,7 @@ void RTCPeerConnectionHandler::OnIceConnectionChange( // Called any time the IceGatheringState changes void RTCPeerConnectionHandler::OnIceGatheringChange( webrtc::PeerConnectionInterface::IceGatheringState new_state) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange"); if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) { @@ -2039,7 +2045,7 @@ void RTCPeerConnectionHandler::OnIceGatheringChange( } void RTCPeerConnectionHandler::OnRenegotiationNeeded() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded"); if (peer_connection_tracker_) peer_connection_tracker_->TrackOnRenegotiationNeeded(this); @@ -2047,89 +2053,129 @@ void RTCPeerConnectionHandler::OnRenegotiationNeeded() { client_->NegotiationNeeded(); } -void RTCPeerConnectionHandler::OnAddRemoteTrack( - scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - remote_track_adapter_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - remote_stream_adapter_refs) { - DCHECK(thread_checker_.CalledOnValidThread()); - TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddRemoteTrack"); - - for (const auto& remote_stream_adapter_ref : remote_stream_adapter_refs) { +void RTCPeerConnectionHandler::OnAddReceiverPlanB( + RtpReceiverState receiver_state) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + DCHECK(receiver_state.is_initialized()); + TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddReceiverPlanB"); + auto web_track = receiver_state.track_ref()->web_track(); + // Update metrics. + track_metrics_.AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetricsKind(web_track), + web_track.Id().Utf8()); + for (const auto& stream_id : receiver_state.stream_ids()) { // New remote stream? - if (GetRemoteStreamUsageCount( - rtp_receivers_, - remote_stream_adapter_ref->adapter().webrtc_stream().get()) == 0) { - // Update metrics. - // TODO(hbos): Update metrics to correspond to track added/removed events, - // not streams. https://crbug.com/765170 - if (peer_connection_tracker_) { - peer_connection_tracker_->TrackAddStream( - this, remote_stream_adapter_ref->adapter().web_stream(), - PeerConnectionTracker::SOURCE_REMOTE); - } + if (!IsRemoteStream(rtp_receivers_, stream_id)) PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter(); - track_metrics_.AddStream( - MediaStreamTrackMetrics::RECEIVED_STREAM, - remote_stream_adapter_ref->adapter().webrtc_stream().get()); - } } - - uintptr_t receiver_id = RTCRtpReceiver::getId(webrtc_receiver.get()); - DCHECK(rtp_receivers_.find(receiver_id) == rtp_receivers_.end()); - const std::unique_ptr<RTCRtpReceiver>& rtp_receiver = - rtp_receivers_ - .insert(std::make_pair( - receiver_id, - std::make_unique<RTCRtpReceiver>( - native_peer_connection_, task_runner_, signaling_thread(), - webrtc_receiver.get(), std::move(remote_track_adapter_ref), - std::move(remote_stream_adapter_refs)))) - .first->second; + uintptr_t receiver_id = + RTCRtpReceiver::getId(receiver_state.webrtc_receiver().get()); + DCHECK(FindReceiver(receiver_id) == rtp_receivers_.end()); + auto rtp_receiver = std::make_unique<RTCRtpReceiver>( + native_peer_connection_, std::move(receiver_state)); + rtp_receivers_.push_back(std::make_unique<RTCRtpReceiver>(*rtp_receiver)); + if (peer_connection_tracker_) { + auto receiver_only_transceiver = + std::make_unique<RTCRtpReceiverOnlyTransceiver>( + std::make_unique<RTCRtpReceiver>(*rtp_receiver)); + size_t receiver_index = GetTransceiverIndex(*receiver_only_transceiver); + peer_connection_tracker_->TrackAddTransceiver( + this, + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only_transceiver.get(), receiver_index); + } if (!is_closed_) - client_->DidAddRemoteTrack(rtp_receiver->ShallowCopy()); + client_->DidAddReceiverPlanB(rtp_receiver->ShallowCopy()); } -void RTCPeerConnectionHandler::OnRemoveRemoteTrack( - scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver) { - DCHECK(thread_checker_.CalledOnValidThread()); - TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveRemoteTrack"); +void RTCPeerConnectionHandler::OnRemoveReceiverPlanB(uintptr_t receiver_id) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveReceiverPlanB"); - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - remote_stream_adapter_refs; - { - uintptr_t receiver_id = RTCRtpReceiver::getId(webrtc_receiver.get()); - auto it = rtp_receivers_.find(receiver_id); - DCHECK(it != rtp_receivers_.end()); - remote_stream_adapter_refs = it->second->StreamAdapterRefs(); - if (!is_closed_) - client_->DidRemoveRemoteTrack(it->second->ShallowCopy()); - rtp_receivers_.erase(it); - } - - for (const auto& remote_stream_adapter_ref : remote_stream_adapter_refs) { - // Was this the last usage of the remote stream? - if (GetRemoteStreamUsageCount( - rtp_receivers_, - remote_stream_adapter_ref->adapter().webrtc_stream().get()) == 0) { - // Update metrics. - track_metrics_.RemoveStream( - MediaStreamTrackMetrics::RECEIVED_STREAM, - remote_stream_adapter_ref->adapter().webrtc_stream().get()); - PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter(); - if (peer_connection_tracker_) { - peer_connection_tracker_->TrackRemoveStream( - this, remote_stream_adapter_ref->adapter().web_stream(), - PeerConnectionTracker::SOURCE_REMOTE); + auto it = FindReceiver(receiver_id); + DCHECK(it != rtp_receivers_.end()); + auto receiver = std::make_unique<RTCRtpReceiver>(*(*it)); + // Update metrics. + track_metrics_.RemoveTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetricsKind(receiver->Track()), + receiver->Track().Id().Utf8()); + if (peer_connection_tracker_) { + auto receiver_only_transceiver = + std::make_unique<RTCRtpReceiverOnlyTransceiver>( + std::make_unique<RTCRtpReceiver>(*receiver)); + size_t receiver_index = GetTransceiverIndex(*receiver_only_transceiver); + peer_connection_tracker_->TrackRemoveTransceiver( + this, + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only_transceiver.get(), receiver_index); + } + rtp_receivers_.erase(it); + for (const auto& stream_id : receiver->state().stream_ids()) { + // This was the last occurence of the stream? + if (!IsRemoteStream(rtp_receivers_, stream_id)) + PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter(); + } + if (!is_closed_) + client_->DidRemoveReceiverPlanB(std::move(receiver)); +} + +void RTCPeerConnectionHandler::OnModifyTransceivers( + std::vector<RtpTransceiverState> transceiver_states, + bool is_remote_description) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + std::vector<std::unique_ptr<blink::WebRTCRtpTransceiver>> web_transceivers( + transceiver_states.size()); + PeerConnectionTracker::TransceiverUpdatedReason update_reason = + !is_remote_description ? PeerConnectionTracker::TransceiverUpdatedReason:: + kSetLocalDescription + : PeerConnectionTracker::TransceiverUpdatedReason:: + kSetRemoteDescription; + for (size_t i = 0; i < transceiver_states.size(); ++i) { + // Figure out if this transceiver is new or if setting the state modified + // the transceiver such that it should be logged by the + // |peer_connection_tracker_|. + uintptr_t transceiver_id = RTCRtpTransceiver::GetId( + transceiver_states[i].webrtc_transceiver().get()); + auto it = FindTransceiver(transceiver_id); + bool transceiver_is_new = (it == rtp_transceivers_.end()); + bool transceiver_was_modified = false; + if (!transceiver_is_new) { + const auto& previous_state = (*it)->state(); + transceiver_was_modified = + previous_state.mid() != transceiver_states[i].mid() || + previous_state.stopped() != transceiver_states[i].stopped() || + previous_state.direction() != transceiver_states[i].direction() || + previous_state.current_direction() != + transceiver_states[i].current_direction(); + } + + // Update the transceiver. + web_transceivers[i] = + CreateOrUpdateTransceiver(std::move(transceiver_states[i])); + + // Log a "transcieverAdded" or "transceiverModified" event in + // chrome://webrtc-internals if new or modified. + if (peer_connection_tracker_ && + (transceiver_is_new || transceiver_was_modified)) { + size_t transceiver_index = GetTransceiverIndex(*web_transceivers[i]); + if (transceiver_is_new) { + peer_connection_tracker_->TrackAddTransceiver( + this, update_reason, *web_transceivers[i].get(), transceiver_index); + } else if (transceiver_was_modified) { + peer_connection_tracker_->TrackModifyTransceiver( + this, update_reason, *web_transceivers[i].get(), transceiver_index); } } } + if (!is_closed_) { + client_->DidModifyTransceivers(std::move(web_transceivers), + is_remote_description); + } } void RTCPeerConnectionHandler::OnDataChannel( std::unique_ptr<RtcDataChannelHandler> handler) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl"); if (peer_connection_tracker_) { @@ -2144,7 +2190,7 @@ void RTCPeerConnectionHandler::OnDataChannel( void RTCPeerConnectionHandler::OnIceCandidate( const std::string& sdp, const std::string& sdp_mid, int sdp_mline_index, int component, int address_family) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl"); scoped_refptr<blink::WebRTCICECandidate> web_candidate = blink::WebRTCICECandidate::Create(blink::WebString::FromUTF8(sdp), @@ -2224,16 +2270,103 @@ RTCPeerConnectionHandler::FindSender(uintptr_t id) { return rtp_senders_.end(); } +std::vector<std::unique_ptr<RTCRtpReceiver>>::iterator +RTCPeerConnectionHandler::FindReceiver(uintptr_t id) { + for (auto it = rtp_receivers_.begin(); it != rtp_receivers_.end(); ++it) { + if ((*it)->Id() == id) + return it; + } + return rtp_receivers_.end(); +} + +std::vector<std::unique_ptr<RTCRtpTransceiver>>::iterator +RTCPeerConnectionHandler::FindTransceiver(uintptr_t id) { + for (auto it = rtp_transceivers_.begin(); it != rtp_transceivers_.end(); + ++it) { + if ((*it)->Id() == id) + return it; + } + return rtp_transceivers_.end(); +} + +size_t RTCPeerConnectionHandler::GetTransceiverIndex( + const blink::WebRTCRtpTransceiver& web_transceiver) { + if (web_transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + for (size_t i = 0; i < rtp_transceivers_.size(); ++i) { + if (web_transceiver.Id() == rtp_transceivers_[i]->Id()) + return i; + } + } else if (web_transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + const auto web_sender = web_transceiver.Sender(); + for (size_t i = 0; i < rtp_senders_.size(); ++i) { + if (web_sender->Id() == rtp_senders_[i]->Id()) + return i; + } + } else { + RTC_DCHECK( + web_transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + const auto web_receiver = web_transceiver.Receiver(); + for (size_t i = 0; i < rtp_receivers_.size(); ++i) { + if (web_receiver->Id() == rtp_receivers_[i]->Id()) + return i; + } + } + NOTREACHED(); + return 0u; +} + +std::unique_ptr<RTCRtpTransceiver> +RTCPeerConnectionHandler::CreateOrUpdateTransceiver( + RtpTransceiverState transceiver_state) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + DCHECK(transceiver_state.is_initialized()); + DCHECK(transceiver_state.sender_state()); + DCHECK(transceiver_state.receiver_state()); + auto webrtc_transceiver = transceiver_state.webrtc_transceiver(); + auto webrtc_sender = transceiver_state.sender_state()->webrtc_sender(); + auto webrtc_receiver = transceiver_state.receiver_state()->webrtc_receiver(); + + std::unique_ptr<RTCRtpTransceiver> transceiver; + auto it = FindTransceiver(RTCRtpTransceiver::GetId(webrtc_transceiver.get())); + if (it == rtp_transceivers_.end()) { + // Create a new transceiver, including a sender and a receiver. + transceiver = std::make_unique<RTCRtpTransceiver>( + native_peer_connection_, track_adapter_map_, + std::move(transceiver_state)); + rtp_transceivers_.push_back(transceiver->ShallowCopy()); + DCHECK(FindSender(RTCRtpSender::getId(webrtc_sender.get())) == + rtp_senders_.end()); + rtp_senders_.push_back( + std::make_unique<RTCRtpSender>(*transceiver->content_sender())); + DCHECK(FindReceiver(RTCRtpReceiver::getId(webrtc_receiver.get())) == + rtp_receivers_.end()); + rtp_receivers_.push_back( + std::make_unique<RTCRtpReceiver>(*transceiver->content_receiver())); + } else { + // Update the transceiver. This also updates the sender and receiver. + transceiver = (*it)->ShallowCopy(); + transceiver->set_state(std::move(transceiver_state)); + DCHECK(FindSender(RTCRtpSender::getId(webrtc_sender.get())) != + rtp_senders_.end()); + DCHECK(FindReceiver(RTCRtpReceiver::getId(webrtc_receiver.get())) != + rtp_receivers_.end()); + } + return transceiver; +} + scoped_refptr<base::SingleThreadTaskRunner> RTCPeerConnectionHandler::signaling_thread() const { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); return dependency_factory_->GetWebRtcSignalingThread(); } void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread( const base::Closure& closure, const char* trace_event_name) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread()); if (!thread.get() || thread->BelongsToCurrentThread()) { TRACE_EVENT0("webrtc", trace_event_name); @@ -2251,7 +2384,7 @@ void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread( void RTCPeerConnectionHandler::ReportICEState( webrtc::PeerConnectionInterface::IceConnectionState new_state) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (ice_state_seen_[new_state]) return; ice_state_seen_[new_state] = true; @@ -2260,7 +2393,7 @@ void RTCPeerConnectionHandler::ReportICEState( } void RTCPeerConnectionHandler::ResetUMAStats() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); num_local_candidates_ipv6_ = 0; num_local_candidates_ipv4_ = 0; ice_connection_checking_start_ = base::TimeTicks(); diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h index a4b038365d2..74cb1b77c1a 100644 --- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h +++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h @@ -18,15 +18,15 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread.h" -#include "base/threading/thread_checker.h" #include "content/common/content_export.h" #include "content/renderer/media/webrtc/media_stream_track_metrics.h" #include "content/renderer/media/webrtc/rtc_rtp_receiver.h" #include "content/renderer/media/webrtc/rtc_rtp_sender.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" +#include "content/renderer/media/webrtc/transceiver_state_surfacer.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "ipc/ipc_platform_file.h" #include "third_party/blink/public/platform/web_media_stream_source.h" +#include "third_party/blink/public/platform/web_rtc_configuration.h" #include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h" #include "third_party/blink/public/platform/web_rtc_stats_request.h" #include "third_party/blink/public/platform/web_rtc_stats_response.h" @@ -45,6 +45,7 @@ namespace content { class PeerConnectionDependencyFactory; class PeerConnectionTracker; class RtcDataChannelHandler; +class SetLocalDescriptionRequest; // Mockable wrapper for blink::WebRTCStatsResponse class CONTENT_EXPORT LocalRTCStatsResponse : public rtc::RefCountInterface { @@ -107,8 +108,10 @@ class CONTENT_EXPORT RTCPeerConnectionHandler const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker); // blink::WebRTCPeerConnectionHandler implementation - bool Initialize(const blink::WebRTCConfiguration& server_configuration, - const blink::WebMediaConstraints& options) override; + bool Initialize( + const blink::WebRTCConfiguration& server_configuration, + const blink::WebMediaConstraints& options, + blink::WebRTCSdpSemantics original_sdp_semantics_value) override; void CreateOffer(const blink::WebRTCSessionDescriptionRequest& request, const blink::WebMediaConstraints& options) override; @@ -143,10 +146,17 @@ class CONTENT_EXPORT RTCPeerConnectionHandler void GetStats(const blink::WebRTCStatsRequest& request) override; void GetStats( std::unique_ptr<blink::WebRTCStatsReportCallback> callback) override; - std::unique_ptr<blink::WebRTCRtpSender> AddTrack( + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> + AddTransceiverWithTrack(const blink::WebMediaStreamTrack& web_track, + const webrtc::RtpTransceiverInit& init) override; + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> + AddTransceiverWithKind(std::string kind, + const webrtc::RtpTransceiverInit& init) override; + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> AddTrack( const blink::WebMediaStreamTrack& web_track, const blink::WebVector<blink::WebMediaStream>& web_streams) override; - bool RemoveTrack(blink::WebRTCRtpSender* web_sender) override; + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> RemoveTrack( + blink::WebRTCRtpSender* web_sender) override; blink::WebRTCDataChannelHandler* CreateDataChannel( const blink::WebString& label, @@ -185,8 +195,10 @@ class CONTENT_EXPORT RTCPeerConnectionHandler class Observer; friend class Observer; - class WebRtcSetRemoteDescriptionObserverImpl; - friend class WebRtcSetRemoteDescriptionObserverImpl; + class WebRtcSetDescriptionObserverImpl; + friend class WebRtcSetDescriptionObserverImpl; + class SetLocalDescriptionRequest; + friend class SetLocalDescriptionRequest; void OnSignalingChange( webrtc::PeerConnectionInterface::SignalingState new_state); @@ -195,14 +207,10 @@ class CONTENT_EXPORT RTCPeerConnectionHandler void OnIceGatheringChange( webrtc::PeerConnectionInterface::IceGatheringState new_state); void OnRenegotiationNeeded(); - void OnAddRemoteTrack( - scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - remote_track_adapter_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - remote_stream_adapter_refs); - void OnRemoveRemoteTrack( - scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver); + void OnAddReceiverPlanB(RtpReceiverState receiver_state); + void OnRemoveReceiverPlanB(uintptr_t receiver_id); + void OnModifyTransceivers(std::vector<RtpTransceiverState> transceiver_states, + bool is_remote_description); void OnDataChannel(std::unique_ptr<RtcDataChannelHandler> handler); void OnIceCandidate(const std::string& sdp, const std::string& sdp_mid, @@ -240,7 +248,47 @@ class CONTENT_EXPORT RTCPeerConnectionHandler void ReportFirstSessionDescriptions(const FirstSessionDescription& local, const FirstSessionDescription& remote); + void AddTransceiverWithTrackOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track, + webrtc::RtpTransceiverInit init, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>* + error_or_transceiver); + void AddTransceiverWithMediaTypeOnSignalingThread( + cricket::MediaType media_type, + webrtc::RtpTransceiverInit init, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>* + error_or_transceiver); + void AddTrackOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + std::vector<std::string> stream_ids, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>>* + error_or_sender); + bool RemoveTrackPlanB(blink::WebRTCRtpSender* web_sender); + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> + RemoveTrackUnifiedPlan(blink::WebRTCRtpSender* web_sender); + void RemoveTrackUnifiedPlanOnSignalingThread( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + TransceiverStateSurfacer* transceiver_state_surfacer, + bool* result); std::vector<std::unique_ptr<RTCRtpSender>>::iterator FindSender(uintptr_t id); + std::vector<std::unique_ptr<RTCRtpReceiver>>::iterator FindReceiver( + uintptr_t id); + std::vector<std::unique_ptr<RTCRtpTransceiver>>::iterator FindTransceiver( + uintptr_t id); + // For full transceiver implementations, returns the index of + // |rtp_transceivers_| that correspond to |web_transceiver|. + // For sender-only transceiver implementations, returns the index of + // |rtp_senders_| that correspond to |web_transceiver.Sender()|. + // For receiver-only transceiver implementations, returns the index of + // |rtp_receivers_| that correspond to |web_transceiver.Receiver()|. + // NOTREACHED()-crashes if no correspondent is found. + size_t GetTransceiverIndex( + const blink::WebRTCRtpTransceiver& web_transceiver); + std::unique_ptr<RTCRtpTransceiver> CreateOrUpdateTransceiver( + RtpTransceiverState transceiver_state); scoped_refptr<base::SingleThreadTaskRunner> signaling_thread() const; @@ -254,8 +302,6 @@ class CONTENT_EXPORT RTCPeerConnectionHandler // first call fails. bool initialize_called_; - base::ThreadChecker thread_checker_; - // |client_| is a weak pointer to the blink object (blink::RTCPeerConnection) // that owns this object. // It is valid for the lifetime of this object. @@ -279,20 +325,20 @@ class CONTENT_EXPORT RTCPeerConnectionHandler // needs to reference it, and automatically disposed when there are no longer // any components referencing it. scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; - // Map and owners of stream adapters. Every stream that is in use by the peer - // connection has an associated blink and webrtc layer representation of it. - // The map keeps track of the relationship between |blink::WebMediaStream|s - // and |webrtc::MediaStreamInterface|s. Stream adapters are created on the fly - // when a component (such as a sender or receiver) needs to reference it, and - // automatically disposed when there are no longer any components referencing - // it. - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map_; + // In Plan B, senders and receivers are added or removed independently of one + // another. In Unified Plan, senders and receivers are created in pairs as + // transceivers. Transceivers may become inactive, but are never removed. + // The value of this member affects the behavior of some methods and what + // information is surfaced from webrtc. After Initialize(), this is the actual + // mode used, meaning "kDefault" is no longer a valid value. + // TODO(hbos): Implement transceiver behaviors. https://crbug.com/777617 + blink::WebRTCSdpSemantics sdp_semantics_; // Content layer correspondents of |webrtc::RtpSenderInterface|. std::vector<std::unique_ptr<RTCRtpSender>> rtp_senders_; - // Maps |RTCRtpReceiver::getId|s of |webrtc::RtpReceiverInterface|s to the - // corresponding content layer receivers. The set of receivers is needed in - // order to keep its associated track's and streams' adapters alive. - std::map<uintptr_t, std::unique_ptr<RTCRtpReceiver>> rtp_receivers_; + // Content layer correspondents of |webrtc::RtpReceiverInterface|. + std::vector<std::unique_ptr<RTCRtpReceiver>> rtp_receivers_; + // Content layer correspondents of |webrtc::RtpTransceiverInterface|. + std::vector<std::unique_ptr<RTCRtpTransceiver>> rtp_transceivers_; base::WeakPtr<PeerConnectionTracker> peer_connection_tracker_; @@ -308,7 +354,6 @@ class CONTENT_EXPORT RTCPeerConnectionHandler // To make sure the observers are released after native_peer_connection_, // they have to come first. scoped_refptr<Observer> peer_connection_observer_; - scoped_refptr<webrtc::UMAObserver> uma_observer_; // |native_peer_connection_| is the libjingle native PeerConnection object. scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_; diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc index 3d9ade84d75..51a6af48d59 100644 --- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc @@ -23,7 +23,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "content/child/child_process.h" -#include "content/renderer/media/mock_audio_device_factory.h" +#include "content/renderer/media/audio/mock_audio_device_factory.h" #include "content/renderer/media/stream/media_stream_audio_source.h" #include "content/renderer/media/stream/media_stream_audio_track.h" #include "content/renderer/media/stream/media_stream_source.h" @@ -171,14 +171,21 @@ class MockPeerConnectionTracker : public PeerConnectionTracker { scoped_refptr<blink::WebRTCICECandidate> candidate, Source source, bool succeeded)); - MOCK_METHOD3(TrackAddStream, + MOCK_METHOD4(TrackAddTransceiver, void(RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, - Source source)); - MOCK_METHOD3(TrackRemoveStream, + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index)); + MOCK_METHOD4(TrackModifyTransceiver, void(RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, - Source source)); + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index)); + MOCK_METHOD4(TrackRemoveTransceiver, + void(RTCPeerConnectionHandler* pc_handler, + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index)); MOCK_METHOD1(TrackOnIceComplete, void(RTCPeerConnectionHandler* pc_handler)); MOCK_METHOD3(TrackCreateDataChannel, @@ -188,11 +195,11 @@ class MockPeerConnectionTracker : public PeerConnectionTracker { MOCK_METHOD1(TrackStop, void(RTCPeerConnectionHandler* pc_handler)); MOCK_METHOD2(TrackSignalingStateChange, void(RTCPeerConnectionHandler* pc_handler, - WebRTCPeerConnectionHandlerClient::SignalingState state)); + webrtc::PeerConnectionInterface::SignalingState state)); MOCK_METHOD2( TrackIceConnectionStateChange, void(RTCPeerConnectionHandler* pc_handler, - WebRTCPeerConnectionHandlerClient::ICEConnectionState state)); + MockWebRTCPeerConnectionHandlerClient::ICEConnectionState state)); MOCK_METHOD2( TrackIceGatheringStateChange, void(RTCPeerConnectionHandler* pc_handler, @@ -273,6 +280,7 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { pc_handler_ = CreateRTCPeerConnectionHandlerUnderTest(); mock_tracker_.reset(new NiceMock<MockPeerConnectionTracker>()); blink::WebRTCConfiguration config; + config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB; blink::WebMediaConstraints constraints; EXPECT_TRUE(pc_handler_->InitializeForTest( config, constraints, mock_tracker_.get()->AsWeakPtr())); @@ -373,14 +381,9 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { } void StopAllTracks(const blink::WebMediaStream& stream) { - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - stream.AudioTracks(audio_tracks); - for (const auto& track : audio_tracks) + for (const auto& track : stream.AudioTracks()) MediaStreamAudioTrack::From(track)->Stop(); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - stream.VideoTracks(video_tracks); - for (const auto& track : video_tracks) + for (const auto& track : stream.VideoTracks()) MediaStreamVideoTrack::GetVideoTrack(track)->Stop(); } @@ -390,22 +393,26 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { bool AddStream(const blink::WebMediaStream& web_stream) { size_t senders_size_before_add = senders_.size(); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - web_stream.AudioTracks(web_audio_tracks); - for (const auto& web_audio_track : web_audio_tracks) { - auto sender = pc_handler_->AddTrack( + for (const auto& web_audio_track : web_stream.AudioTracks()) { + auto error_or_transceiver = pc_handler_->AddTrack( web_audio_track, std::vector<blink::WebMediaStream>({web_stream})); - if (sender) { + if (error_or_transceiver.ok()) { + DCHECK_EQ( + error_or_transceiver.value()->ImplementationType(), + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + auto sender = error_or_transceiver.value()->Sender(); senders_.push_back(std::unique_ptr<RTCRtpSender>( static_cast<RTCRtpSender*>(sender.release()))); } } - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - web_stream.VideoTracks(web_video_tracks); - for (const auto& web_video_track : web_video_tracks) { - auto sender = pc_handler_->AddTrack( + for (const auto& web_video_track : web_stream.VideoTracks()) { + auto error_or_transceiver = pc_handler_->AddTrack( web_video_track, std::vector<blink::WebMediaStream>({web_stream})); - if (sender) { + if (error_or_transceiver.ok()) { + DCHECK_EQ( + error_or_transceiver.value()->ImplementationType(), + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + auto sender = error_or_transceiver.value()->Sender(); senders_.push_back(std::unique_ptr<RTCRtpSender>( static_cast<RTCRtpSender*>(sender.release()))); } @@ -424,20 +431,16 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { bool RemoveStream(const blink::WebMediaStream& web_stream) { size_t senders_size_before_remove = senders_.size(); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - web_stream.AudioTracks(web_audio_tracks); // TODO(hbos): With Unified Plan senders are not removed. // https://crbug.com/799030 - for (const auto& web_audio_track : web_audio_tracks) { + for (const auto& web_audio_track : web_stream.AudioTracks()) { auto it = FindSenderForTrack(web_audio_track); - if (it != senders_.end() && pc_handler_->RemoveTrack((*it).get())) + if (it != senders_.end() && pc_handler_->RemoveTrack((*it).get()).ok()) senders_.erase(it); } - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - web_stream.VideoTracks(web_video_tracks); - for (const auto& web_video_track : web_video_tracks) { + for (const auto& web_video_track : web_stream.VideoTracks()) { auto it = FindSenderForTrack(web_video_track); - if (it != senders_.end() && pc_handler_->RemoveTrack((*it).get())) + if (it != senders_.end() && pc_handler_->RemoveTrack((*it).get()).ok()) senders_.erase(it); } return senders_size_before_remove > senders_.size(); @@ -607,12 +610,12 @@ TEST_F(RTCPeerConnectionHandlerTest, NoCallbacksToClientAfterStop) { pc_handler_->observer()->OnIceConnectionChange( webrtc::PeerConnectionInterface::kIceConnectionDisconnected); - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)).Times(0); + EXPECT_CALL(*mock_client_.get(), DidAddReceiverPlanBForMock(_)).Times(0); rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( AddRemoteMockMediaStream("remote_stream", "video", "audio")); InvokeOnAddStream(remote_stream); - EXPECT_CALL(*mock_client_.get(), DidRemoveRemoteTrackForMock(_)).Times(0); + EXPECT_CALL(*mock_client_.get(), DidRemoveReceiverPlanBForMock(_)).Times(0); InvokeOnRemoveStream(remote_stream); EXPECT_CALL(*mock_client_.get(), DidAddRemoteDataChannel(_)).Times(0); @@ -762,6 +765,7 @@ TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescriptionParseError) { TEST_F(RTCPeerConnectionHandlerTest, setConfiguration) { blink::WebRTCConfiguration config; + config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB; EXPECT_CALL(*mock_tracker_.get(), TrackSetConfiguration(pc_handler_.get(), _)); @@ -775,6 +779,7 @@ TEST_F(RTCPeerConnectionHandlerTest, setConfiguration) { // blink error and false is returned. TEST_F(RTCPeerConnectionHandlerTest, setConfigurationError) { blink::WebRTCConfiguration config; + config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB; mock_peer_connection_->set_setconfiguration_error_type( webrtc::RTCErrorType::INVALID_MODIFICATION); @@ -802,22 +807,25 @@ TEST_F(RTCPeerConnectionHandlerTest, addAndRemoveStream) { blink::WebMediaStream local_stream( CreateLocalMediaStream(stream_label)); - EXPECT_CALL(*mock_tracker_.get(), - TrackAddStream(pc_handler_.get(), _, - PeerConnectionTracker::SOURCE_LOCAL)); - EXPECT_CALL(*mock_tracker_.get(), - TrackRemoveStream(pc_handler_.get(), _, - PeerConnectionTracker::SOURCE_LOCAL)); + EXPECT_CALL( + *mock_tracker_.get(), + TrackAddTransceiver( + pc_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, _, _)) + .Times(2); + EXPECT_CALL( + *mock_tracker_.get(), + TrackRemoveTransceiver( + pc_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, _, _)) + .Times(2); EXPECT_TRUE(AddStream(local_stream)); EXPECT_EQ(stream_label, mock_peer_connection_->stream_label()); - EXPECT_EQ(1u, - mock_peer_connection_->local_streams()->at(0)->GetAudioTracks().size()); - EXPECT_EQ(1u, - mock_peer_connection_->local_streams()->at(0)->GetVideoTracks().size()); + EXPECT_EQ(2u, mock_peer_connection_->GetSenders().size()); EXPECT_FALSE(AddStream(local_stream)); EXPECT_TRUE(RemoveStream(local_stream)); - EXPECT_EQ(0u, mock_peer_connection_->local_streams()->count()); + EXPECT_EQ(0u, mock_peer_connection_->GetSenders().size()); StopAllTracks(local_stream); } @@ -827,14 +835,14 @@ TEST_F(RTCPeerConnectionHandlerTest, addStreamWithStoppedAudioAndVideoTrack) { blink::WebMediaStream local_stream( CreateLocalMediaStream(stream_label)); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - local_stream.AudioTracks(audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + local_stream.AudioTracks(); MediaStreamAudioSource* native_audio_source = MediaStreamAudioSource::From(audio_tracks[0].Source()); native_audio_source->StopSource(); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - local_stream.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + local_stream.VideoTracks(); MediaStreamVideoSource* native_video_source = static_cast<MediaStreamVideoSource*>( video_tracks[0].Source().GetExtraData()); @@ -842,12 +850,7 @@ TEST_F(RTCPeerConnectionHandlerTest, addStreamWithStoppedAudioAndVideoTrack) { EXPECT_TRUE(AddStream(local_stream)); EXPECT_EQ(stream_label, mock_peer_connection_->stream_label()); - EXPECT_EQ( - 1u, - mock_peer_connection_->local_streams()->at(0)->GetAudioTracks().size()); - EXPECT_EQ( - 1u, - mock_peer_connection_->local_streams()->at(0)->GetVideoTracks().size()); + EXPECT_EQ(2u, mock_peer_connection_->GetSenders().size()); StopAllTracks(local_stream); } @@ -876,8 +879,8 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) { blink::WebMediaStream local_stream( CreateLocalMediaStream("local_stream")); EXPECT_TRUE(AddStream(local_stream)); - blink::WebVector<blink::WebMediaStreamTrack> tracks; - local_stream.AudioTracks(tracks); + blink::WebVector<blink::WebMediaStreamTrack> tracks = + local_stream.AudioTracks(); ASSERT_LE(1ul, tracks.size()); scoped_refptr<MockRTCStatsRequest> request( @@ -890,45 +893,13 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) { StopAllTracks(local_stream); } -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, DISABLED_GetStatsWithRemoteSelector) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - blink::WebVector<blink::WebMediaStreamTrack> tracks; - webkit_stream.AudioTracks(tracks); - ASSERT_LE(1ul, tracks.size()); - - scoped_refptr<MockRTCStatsRequest> request( - new rtc::RefCountedObject<MockRTCStatsRequest>()); - request->setSelector(tracks[0]); - pc_handler_->getStats(request.get()); - RunMessageLoopsUntilIdle(); - EXPECT_EQ(1, request->result()->report_count()); -} - TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithBadSelector) { // The setup is the same as GetStatsWithLocalSelector, but the stream is not // added to the PeerConnection. blink::WebMediaStream local_stream( CreateLocalMediaStream("local_stream_2")); - blink::WebVector<blink::WebMediaStreamTrack> tracks; - - local_stream.AudioTracks(tracks); + blink::WebVector<blink::WebMediaStreamTrack> tracks = + local_stream.AudioTracks(); blink::WebMediaStreamTrack component = tracks[0]; mock_peer_connection_->SetGetStatsResult(false); @@ -1063,67 +1034,6 @@ TEST_F(RTCPeerConnectionHandlerTest, GetRTCStats) { EXPECT_EQ(defined_stats_count, 1); } -TEST_F(RTCPeerConnectionHandlerTest, OnSignalingChange) { - testing::InSequence sequence; - - webrtc::PeerConnectionInterface::SignalingState new_state = - webrtc::PeerConnectionInterface::kHaveRemoteOffer; - EXPECT_CALL( - *mock_tracker_.get(), - TrackSignalingStateChange( - pc_handler_.get(), - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveRemoteOffer)); - EXPECT_CALL( - *mock_client_.get(), - DidChangeSignalingState( - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveRemoteOffer)); - pc_handler_->observer()->OnSignalingChange(new_state); - - new_state = webrtc::PeerConnectionInterface::kHaveLocalPrAnswer; - EXPECT_CALL( - *mock_tracker_.get(), - TrackSignalingStateChange( - pc_handler_.get(), - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalPrAnswer)); - EXPECT_CALL( - *mock_client_.get(), - DidChangeSignalingState( - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalPrAnswer)); - pc_handler_->observer()->OnSignalingChange(new_state); - - new_state = webrtc::PeerConnectionInterface::kHaveLocalOffer; - EXPECT_CALL( - *mock_tracker_.get(), - TrackSignalingStateChange( - pc_handler_.get(), - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalOffer)); - EXPECT_CALL( - *mock_client_.get(), - DidChangeSignalingState( - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalOffer)); - pc_handler_->observer()->OnSignalingChange(new_state); - - new_state = webrtc::PeerConnectionInterface::kHaveRemotePrAnswer; - EXPECT_CALL(*mock_tracker_.get(), - TrackSignalingStateChange(pc_handler_.get(), - WebRTCPeerConnectionHandlerClient:: - kSignalingStateHaveRemotePrAnswer)); - EXPECT_CALL(*mock_client_.get(), - DidChangeSignalingState(WebRTCPeerConnectionHandlerClient:: - kSignalingStateHaveRemotePrAnswer)); - pc_handler_->observer()->OnSignalingChange(new_state); - - new_state = webrtc::PeerConnectionInterface::kClosed; - EXPECT_CALL(*mock_tracker_.get(), - TrackSignalingStateChange( - pc_handler_.get(), - WebRTCPeerConnectionHandlerClient::kSignalingStateClosed)); - EXPECT_CALL(*mock_client_.get(), - DidChangeSignalingState( - WebRTCPeerConnectionHandlerClient::kSignalingStateClosed)); - pc_handler_->observer()->OnSignalingChange(new_state); -} - TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) { testing::InSequence sequence; @@ -1263,28 +1173,27 @@ TEST_F(RTCPeerConnectionHandlerTest, DISABLED_OnAddAndOnRemoveStream) { AddRemoteMockMediaStream("remote_stream", "video", "audio")); // Grab the added receivers when it's been successfully added to the PC. std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers_added; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) + EXPECT_CALL(*mock_client_.get(), DidAddReceiverPlanBForMock(_)) .WillRepeatedly( Invoke([&receivers_added]( std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { receivers_added.push_back(std::move(*receiver)); })); - EXPECT_CALL(*mock_tracker_.get(), - TrackAddStream(pc_handler_.get(), - testing::Property( - &blink::WebMediaStream::Id, - blink::WebString::FromASCII("remote_stream")), - PeerConnectionTracker::SOURCE_REMOTE)); + EXPECT_CALL( + *mock_tracker_.get(), + TrackAddTransceiver( + pc_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, _, _)) + .Times(2); // Grab the removed receivers when it's been successfully added to the PC. std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers_removed; EXPECT_CALL( *mock_tracker_.get(), - TrackRemoveStream( + TrackRemoveTransceiver( pc_handler_.get(), - testing::Property(&blink::WebMediaStream::Id, - blink::WebString::FromASCII("remote_stream")), - PeerConnectionTracker::SOURCE_REMOTE)); - EXPECT_CALL(*mock_client_.get(), DidRemoveRemoteTrackForMock(_)) + PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, _, _)) + .Times(2); + EXPECT_CALL(*mock_client_.get(), DidRemoveReceiverPlanBForMock(_)) .WillRepeatedly( Invoke([&receivers_removed]( std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { @@ -1303,211 +1212,6 @@ TEST_F(RTCPeerConnectionHandlerTest, DISABLED_OnAddAndOnRemoveStream) { EXPECT_EQ(receivers_added[1]->Id(), receivers_removed[1]->Id()); } -// This test that WebKit is notified about remote track state changes. -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, DISABLED_RemoteTrackState) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - webkit_stream.AudioTracks(audio_tracks); - EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive, - audio_tracks[0].Source().GetReadyState()); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - webkit_stream.VideoTracks(video_tracks); - EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive, - video_tracks[0].Source().GetReadyState()); - - InvokeOnSignalingThread( - base::Bind(&MockWebRtcAudioTrack::SetEnded, - base::Unretained(static_cast<MockWebRtcAudioTrack*>( - remote_stream->GetAudioTracks()[0].get())))); - EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded, - audio_tracks[0].Source().GetReadyState()); - - InvokeOnSignalingThread( - base::Bind(&MockWebRtcVideoTrack::SetEnded, - base::Unretained(static_cast<MockWebRtcVideoTrack*>( - remote_stream->GetVideoTracks()[0].get())))); - EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded, - video_tracks[0].Source().GetReadyState()); -} - -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, - DISABLED_RemoveAndAddAudioTrackFromRemoteStream) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - { - // Test in a small scope so that |audio_tracks| don't hold on to destroyed - // source later. - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - webkit_stream.AudioTracks(audio_tracks); - EXPECT_EQ(1u, audio_tracks.size()); - } - - // Remove the Webrtc audio track from the Webrtc MediaStream. - scoped_refptr<webrtc::AudioTrackInterface> webrtc_track = - remote_stream->GetAudioTracks()[0].get(); - InvokeRemoveTrack(remote_stream, webrtc_track.get()); - - { - blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks1; - webkit_stream.AudioTracks(modified_audio_tracks1); - EXPECT_EQ(0u, modified_audio_tracks1.size()); - } - - blink::WebHeap::CollectGarbageForTesting(); - - // Add the WebRtc audio track again. - InvokeAddTrack(remote_stream, webrtc_track.get()); - blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks2; - webkit_stream.AudioTracks(modified_audio_tracks2); - EXPECT_EQ(1u, modified_audio_tracks2.size()); -} - -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, - DISABLED_RemoveAndAddVideoTrackFromRemoteStream) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - { - // Test in a small scope so that |video_tracks| don't hold on to destroyed - // source later. - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - webkit_stream.VideoTracks(video_tracks); - EXPECT_EQ(1u, video_tracks.size()); - } - - // Remove the Webrtc video track from the Webrtc MediaStream. - scoped_refptr<webrtc::VideoTrackInterface> webrtc_track = - remote_stream->GetVideoTracks()[0].get(); - InvokeRemoveTrack(remote_stream, webrtc_track.get()); - RunMessageLoopsUntilIdle(); - { - blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks1; - webkit_stream.VideoTracks(modified_video_tracks1); - EXPECT_EQ(0u, modified_video_tracks1.size()); - } - - blink::WebHeap::CollectGarbageForTesting(); - - // Add the WebRtc video track again. - InvokeAddTrack(remote_stream, webrtc_track.get()); - RunMessageLoopsUntilIdle(); - blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks2; - webkit_stream.VideoTracks(modified_video_tracks2); - EXPECT_EQ(1u, modified_video_tracks2.size()); -} - -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, - DISABLED_RemoveAndAddTracksFromRemoteStream) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - { - // Test in a small scope so that |audio_tracks| don't hold on to destroyed - // source later. - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - webkit_stream.AudioTracks(audio_tracks); - EXPECT_EQ(1u, audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - webkit_stream.VideoTracks(video_tracks); - EXPECT_EQ(1u, video_tracks.size()); - } - - // Remove the Webrtc tracks from the MediaStream. - auto audio_track = remote_stream->GetAudioTracks()[0]; - InvokeRemoveTrack(remote_stream, audio_track.get()); - auto video_track = remote_stream->GetVideoTracks()[0]; - InvokeRemoveTrack(remote_stream, video_track.get()); - RunMessageLoopsUntilIdle(); - - { - blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks; - webkit_stream.AudioTracks(modified_audio_tracks); - EXPECT_EQ(0u, modified_audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks; - webkit_stream.VideoTracks(modified_video_tracks); - EXPECT_EQ(0u, modified_video_tracks.size()); - } - - blink::WebHeap::CollectGarbageForTesting(); - - // Add the tracks again. - InvokeAddTrack(remote_stream, audio_track.get()); - InvokeAddTrack(remote_stream, video_track.get()); - - blink::WebHeap::CollectGarbageForTesting(); - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - webkit_stream.AudioTracks(audio_tracks); - EXPECT_EQ(1u, audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - webkit_stream.VideoTracks(video_tracks); - EXPECT_EQ(1u, video_tracks.size()); -} - TEST_F(RTCPeerConnectionHandlerTest, OnIceCandidate) { testing::InSequence sequence; EXPECT_CALL(*mock_tracker_.get(), diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc index a988bd10bb5..200b00beb9e 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc @@ -11,6 +11,96 @@ namespace content { +RtpReceiverState::RtpReceiverState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, + std::vector<std::string> stream_id) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + webrtc_receiver_(std::move(webrtc_receiver)), + is_initialized_(false), + track_ref_(std::move(track_ref)), + stream_ids_(std::move(stream_id)) { + DCHECK(main_task_runner_); + DCHECK(signaling_task_runner_); + DCHECK(webrtc_receiver_); + DCHECK(track_ref_); +} + +RtpReceiverState::RtpReceiverState(RtpReceiverState&& other) + : main_task_runner_(other.main_task_runner_), + signaling_task_runner_(other.signaling_task_runner_), + webrtc_receiver_(std::move(other.webrtc_receiver_)), + is_initialized_(other.is_initialized_), + track_ref_(std::move(other.track_ref_)), + stream_ids_(std::move(other.stream_ids_)) { + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; +} + +RtpReceiverState::~RtpReceiverState() { + // It's OK to not be on the main thread if this state has been moved, in which + // case |main_task_runner_| is null. + DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread()); +} + +RtpReceiverState& RtpReceiverState::operator=(RtpReceiverState&& other) { + DCHECK_EQ(main_task_runner_, other.main_task_runner_); + DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_); + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; + webrtc_receiver_ = std::move(other.webrtc_receiver_); + track_ref_ = std::move(other.track_ref_); + stream_ids_ = std::move(other.stream_ids_); + return *this; +} + +bool RtpReceiverState::is_initialized() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return is_initialized_; +} + +void RtpReceiverState::Initialize() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (is_initialized_) + return; + track_ref_->InitializeOnMainThread(); + is_initialized_ = true; +} + +scoped_refptr<base::SingleThreadTaskRunner> RtpReceiverState::main_task_runner() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return main_task_runner_; +} + +scoped_refptr<base::SingleThreadTaskRunner> +RtpReceiverState::signaling_task_runner() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return signaling_task_runner_; +} + +scoped_refptr<webrtc::RtpReceiverInterface> RtpReceiverState::webrtc_receiver() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_receiver_; +} + +const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& +RtpReceiverState::track_ref() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return track_ref_; +} + +const std::vector<std::string>& RtpReceiverState::stream_ids() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return stream_ids_; +} + class RTCRtpReceiver::RTCRtpReceiverInternal : public base::RefCountedThreadSafe< RTCRtpReceiver::RTCRtpReceiverInternal, @@ -18,37 +108,34 @@ class RTCRtpReceiver::RTCRtpReceiverInternal public: RTCRtpReceiverInternal( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - track_adapter, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_refs) + RtpReceiverState state) : native_peer_connection_(std::move(native_peer_connection)), - main_thread_(std::move(main_thread)), - signaling_thread_(std::move(signaling_thread)), - webrtc_receiver_(std::move(webrtc_receiver)), - track_adapter_(std::move(track_adapter)), - stream_adapter_refs_(std::move(stream_adapter_refs)) { - DCHECK(webrtc_receiver_); - DCHECK(track_adapter_); + main_task_runner_(state.main_task_runner()), + signaling_task_runner_(state.signaling_task_runner()), + webrtc_receiver_(state.webrtc_receiver()), + state_(std::move(state)) { + DCHECK(native_peer_connection_); + DCHECK(state_.is_initialized()); } - const blink::WebMediaStreamTrack& Track() const { - return track_adapter_->web_track(); + const RtpReceiverState& state() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return state_; } - blink::WebVector<blink::WebMediaStream> Streams() const { - blink::WebVector<blink::WebMediaStream> web_streams( - stream_adapter_refs_.size()); - for (size_t i = 0; i < stream_adapter_refs_.size(); ++i) - web_streams[i] = stream_adapter_refs_[i]->adapter().web_stream(); - return web_streams; + void set_state(RtpReceiverState state) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(state.main_task_runner() == main_task_runner_); + DCHECK(state.signaling_task_runner() == signaling_task_runner_); + DCHECK(state.webrtc_receiver() == webrtc_receiver_); + DCHECK(state.is_initialized()); + state_ = std::move(state); } blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> GetSources() { + // The webrtc_recever_ is a proxy, so this is a blocking call to the webrtc + // signalling thread. auto webrtc_sources = webrtc_receiver_->GetSources(); blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> sources(webrtc_sources.size()); @@ -60,64 +147,34 @@ class RTCRtpReceiver::RTCRtpReceiverInternal } void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - signaling_thread_->PostTask( + signaling_task_runner_->PostTask( FROM_HERE, base::BindOnce(&RTCRtpReceiverInternal::GetStatsOnSignalingThread, this, std::move(callback))); } - webrtc::RtpReceiverInterface* webrtc_receiver() const { - return webrtc_receiver_.get(); - } - - const webrtc::MediaStreamTrackInterface& webrtc_track() const { - DCHECK(track_adapter_->webrtc_track()); - return *track_adapter_->webrtc_track(); - } - - bool HasStream(const webrtc::MediaStreamInterface* webrtc_stream) const { - for (const auto& stream_adapter : stream_adapter_refs_) { - if (webrtc_stream == stream_adapter->adapter().webrtc_stream().get()) - return true; - } - return false; - } - - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - StreamAdapterRefs() const { - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_copies; - stream_adapter_copies.reserve(stream_adapter_refs_.size()); - for (const auto& stream_adapter : stream_adapter_refs_) { - stream_adapter_copies.push_back(stream_adapter->Copy()); - } - return stream_adapter_copies; - } - private: friend struct RTCRtpReceiver::RTCRtpReceiverInternalTraits; - ~RTCRtpReceiverInternal() { DCHECK(main_thread_->BelongsToCurrentThread()); } + ~RTCRtpReceiverInternal() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + } void GetStatsOnSignalingThread( std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - native_peer_connection_->GetStats(webrtc_receiver_, - RTCStatsCollectorCallbackImpl::Create( - main_thread_, std::move(callback))); + native_peer_connection_->GetStats( + webrtc_receiver_.get(), RTCStatsCollectorCallbackImpl::Create( + main_task_runner_, std::move(callback))); } const scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_; - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_; - const rtc::scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_; - // The track adapter is the glue between blink and webrtc layer tracks. - // Keeping a reference to the adapter ensures it is not disposed, as is - // required as long as the webrtc layer track is in use by the receiver. - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter_; - // Similarly, references needs to be kept to the stream adapters of streams - // associated with the receiver. - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_refs_; + // Task runners and webrtc receiver: Same information as stored in + // |state_| but const and safe to touch on the signaling thread to + // avoid race with set_state(). + const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + const scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_; + RtpReceiverState state_; }; struct RTCRtpReceiver::RTCRtpReceiverInternalTraits { @@ -128,8 +185,8 @@ struct RTCRtpReceiver::RTCRtpReceiverInternalTraits { static void Destruct(const RTCRtpReceiverInternal* receiver) { // RTCRtpReceiverInternal owns AdapterRefs which have to be destroyed on the // main thread, this ensures delete always happens there. - if (!receiver->main_thread_->BelongsToCurrentThread()) { - receiver->main_thread_->PostTask( + if (!receiver->main_task_runner_->BelongsToCurrentThread()) { + receiver->main_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpReceiver::RTCRtpReceiverInternalTraits::Destruct, @@ -147,18 +204,9 @@ uintptr_t RTCRtpReceiver::getId( RTCRtpReceiver::RTCRtpReceiver( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_refs) + RtpReceiverState state) : internal_(new RTCRtpReceiverInternal(std::move(native_peer_connection), - std::move(main_thread), - std::move(signaling_thread), - std::move(webrtc_receiver), - std::move(track_adapter), - std::move(stream_adapter_refs))) {} + std::move(state))) {} RTCRtpReceiver::RTCRtpReceiver(const RTCRtpReceiver& other) : internal_(other.internal_) {} @@ -170,20 +218,32 @@ RTCRtpReceiver& RTCRtpReceiver::operator=(const RTCRtpReceiver& other) { return *this; } -std::unique_ptr<RTCRtpReceiver> RTCRtpReceiver::ShallowCopy() const { +const RtpReceiverState& RTCRtpReceiver::state() const { + return internal_->state(); +} + +void RTCRtpReceiver::set_state(RtpReceiverState state) { + internal_->set_state(std::move(state)); +} + +std::unique_ptr<blink::WebRTCRtpReceiver> RTCRtpReceiver::ShallowCopy() const { return std::make_unique<RTCRtpReceiver>(*this); } uintptr_t RTCRtpReceiver::Id() const { - return getId(internal_->webrtc_receiver()); + return getId(internal_->state().webrtc_receiver().get()); } const blink::WebMediaStreamTrack& RTCRtpReceiver::Track() const { - return internal_->Track(); + return internal_->state().track_ref()->web_track(); } -blink::WebVector<blink::WebMediaStream> RTCRtpReceiver::Streams() const { - return internal_->Streams(); +blink::WebVector<blink::WebString> RTCRtpReceiver::StreamIds() const { + const auto& stream_ids = internal_->state().stream_ids(); + blink::WebVector<blink::WebString> web_stream_ids(stream_ids.size()); + for (size_t i = 0; i < stream_ids.size(); ++i) + web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids[i]); + return web_stream_ids; } blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> @@ -196,22 +256,66 @@ void RTCRtpReceiver::GetStats( internal_->GetStats(std::move(callback)); } -webrtc::RtpReceiverInterface* RTCRtpReceiver::webrtc_receiver() const { - return internal_->webrtc_receiver(); +RTCRtpReceiverOnlyTransceiver::RTCRtpReceiverOnlyTransceiver( + std::unique_ptr<blink::WebRTCRtpReceiver> receiver) + : receiver_(std::move(receiver)) { + DCHECK(receiver_); +} + +RTCRtpReceiverOnlyTransceiver::~RTCRtpReceiverOnlyTransceiver() {} + +blink::WebRTCRtpTransceiverImplementationType +RTCRtpReceiverOnlyTransceiver::ImplementationType() const { + return blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly; +} + +uintptr_t RTCRtpReceiverOnlyTransceiver::Id() const { + NOTIMPLEMENTED(); + return 0u; +} + +blink::WebString RTCRtpReceiverOnlyTransceiver::Mid() const { + NOTIMPLEMENTED(); + return blink::WebString(); +} + +std::unique_ptr<blink::WebRTCRtpSender> RTCRtpReceiverOnlyTransceiver::Sender() + const { + NOTIMPLEMENTED(); + return nullptr; +} + +std::unique_ptr<blink::WebRTCRtpReceiver> +RTCRtpReceiverOnlyTransceiver::Receiver() const { + return receiver_->ShallowCopy(); +} + +bool RTCRtpReceiverOnlyTransceiver::Stopped() const { + NOTIMPLEMENTED(); + return false; +} + +webrtc::RtpTransceiverDirection RTCRtpReceiverOnlyTransceiver::Direction() + const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; } -const webrtc::MediaStreamTrackInterface& RTCRtpReceiver::webrtc_track() const { - return internal_->webrtc_track(); +void RTCRtpReceiverOnlyTransceiver::SetDirection( + webrtc::RtpTransceiverDirection direction) { + NOTIMPLEMENTED(); } -bool RTCRtpReceiver::HasStream( - const webrtc::MediaStreamInterface* webrtc_stream) const { - return internal_->HasStream(webrtc_stream); +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpReceiverOnlyTransceiver::CurrentDirection() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; } -std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> -RTCRtpReceiver::StreamAdapterRefs() const { - return internal_->StreamAdapterRefs(); +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpReceiverOnlyTransceiver::FiredDirection() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; } } // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h index 29420ae5220..1eb373ad13f 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h @@ -9,17 +9,88 @@ #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "content/common/content_export.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_media_stream_track.h" #include "third_party/blink/public/platform/web_rtc_rtp_receiver.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" #include "third_party/webrtc/api/mediastreaminterface.h" #include "third_party/webrtc/api/peerconnectioninterface.h" #include "third_party/webrtc/api/rtpreceiverinterface.h" namespace content { +// This class represents the state of a receiver; a snapshot of what a +// webrtc-layer receiver looked like when it was inspected on the signaling +// thread such that this information can be moved to the main thread in a single +// PostTask. It is used to surface state changes to make the blink-layer +// receiver up-to-date. +// +// Blink objects live on the main thread and webrtc objects live on the +// signaling thread. If multiple asynchronous operations begin execution on the +// main thread they are posted and executed in order on the signaling thread. +// For example, operation A and operation B are called in JavaScript. When A is +// done on the signaling thread, webrtc object states will be updated. A +// callback is posted to the main thread so that blink objects can be updated to +// match the result of operation A. But if callback A tries to inspect the +// webrtc objects from the main thread this requires posting back to the +// signaling thread and waiting, which also includes waiting for the previously +// posted task: operation B. Inspecting the webrtc object like this does not +// guarantee you to get the state of operation A. +// +// As such, all state changes associated with an operation have to be surfaced +// in the same callback. This includes copying any states into a separate object +// so that it can be inspected on the main thread without any additional thread +// hops. +// +// The RtpReceiverState is a snapshot of what the webrtc::RtpReceiverInterface +// looked like when the RtpReceiverState was created on the signaling thread. It +// also takes care of initializing track adapters, such that we have access to a +// blink track corresponding to the webrtc track of the receiver. +// +// Except for initialization logic and operator=(), the RtpReceiverState is +// immutable and only accessible on the main thread. +// +// TODO(hbos): [Onion Soup] When the sender implementation is moved to blink +// this will be part of the blink sender instead of the content sender. +// https://crbug.com/787254 +class CONTENT_EXPORT RtpReceiverState { + public: + RtpReceiverState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, + std::vector<std::string> stream_ids); + RtpReceiverState(RtpReceiverState&&); + RtpReceiverState(const RtpReceiverState&) = delete; + ~RtpReceiverState(); + + // This is intended to be used for moving the object from the signaling thread + // to the main thread and as such has no thread checks. Once moved to the main + // this should only be invoked on the main thread. + RtpReceiverState& operator=(RtpReceiverState&&); + RtpReceiverState& operator=(const RtpReceiverState&) = delete; + + bool is_initialized() const; + void Initialize(); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const; + scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver() const; + const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& + track_ref() const; + const std::vector<std::string>& stream_ids() const; + + private: + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_; + bool is_initialized_; + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref_; + std::vector<std::string> stream_ids_; +}; + // Used to surface |webrtc::RtpReceiverInterface| to blink. Multiple // |RTCRtpReceiver|s could reference the same webrtc receiver; |id| is the value // of the pointer to the webrtc receiver. @@ -30,35 +101,23 @@ class CONTENT_EXPORT RTCRtpReceiver : public blink::WebRTCRtpReceiver { RTCRtpReceiver( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - track_adapter, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_refs); + RtpReceiverState state); RTCRtpReceiver(const RTCRtpReceiver& other); ~RTCRtpReceiver() override; RTCRtpReceiver& operator=(const RTCRtpReceiver& other); - // Creates a shallow copy of the receiver, representing the same underlying - // webrtc receiver as the original. - std::unique_ptr<RTCRtpReceiver> ShallowCopy() const; + const RtpReceiverState& state() const; + void set_state(RtpReceiverState state); + std::unique_ptr<blink::WebRTCRtpReceiver> ShallowCopy() const override; uintptr_t Id() const override; const blink::WebMediaStreamTrack& Track() const override; - blink::WebVector<blink::WebMediaStream> Streams() const override; + blink::WebVector<blink::WebString> StreamIds() const override; blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> GetSources() override; void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override; - webrtc::RtpReceiverInterface* webrtc_receiver() const; - const webrtc::MediaStreamTrackInterface& webrtc_track() const; - bool HasStream(const webrtc::MediaStreamInterface* webrtc_stream) const; - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - StreamAdapterRefs() const; - private: class RTCRtpReceiverInternal; struct RTCRtpReceiverInternalTraits; @@ -66,6 +125,31 @@ class CONTENT_EXPORT RTCRtpReceiver : public blink::WebRTCRtpReceiver { scoped_refptr<RTCRtpReceiverInternal> internal_; }; +class CONTENT_EXPORT RTCRtpReceiverOnlyTransceiver + : public blink::WebRTCRtpTransceiver { + public: + RTCRtpReceiverOnlyTransceiver( + std::unique_ptr<blink::WebRTCRtpReceiver> receiver); + ~RTCRtpReceiverOnlyTransceiver() override; + + blink::WebRTCRtpTransceiverImplementationType ImplementationType() + const override; + uintptr_t Id() const override; + blink::WebString Mid() const override; + std::unique_ptr<blink::WebRTCRtpSender> Sender() const override; + std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override; + bool Stopped() const override; + webrtc::RtpTransceiverDirection Direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection direction) override; + base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() + const override; + base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() + const override; + + private: + std::unique_ptr<blink::WebRTCRtpReceiver> receiver_; +}; + } // namespace content #endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_RECEIVER_H_ diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc index f55c2b22c4c..ebe77e3780c 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc @@ -16,7 +16,6 @@ #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/mock_peer_connection_impl.h" #include "content/renderer/media/webrtc/test/webrtc_stats_report_obtainer.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" @@ -34,10 +33,8 @@ class RTCRtpReceiverTest : public ::testing::Test { void SetUp() override { dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); - stream_map_ = new WebRtcMediaStreamAdapterMap( - dependency_factory_.get(), main_thread_, - new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), - main_thread_)); + track_map_ = new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), + main_thread_); peer_connection_ = new rtc::RefCountedObject<MockPeerConnectionImpl>( dependency_factory_.get(), nullptr); } @@ -63,23 +60,23 @@ class RTCRtpReceiverTest : public ::testing::Test { std::unique_ptr<RTCRtpReceiver> CreateReceiver( scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track) { - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter; + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; base::RunLoop run_loop; dependency_factory_->GetWebRtcSignalingThread()->PostTask( FROM_HERE, base::BindOnce(&RTCRtpReceiverTest::CreateReceiverOnSignalingThread, base::Unretained(this), std::move(webrtc_track), - base::Unretained(&track_adapter), + base::Unretained(&track_ref), base::Unretained(&run_loop))); run_loop.Run(); DCHECK(mock_webrtc_receiver_); - DCHECK(track_adapter); - return std::make_unique<RTCRtpReceiver>( - peer_connection_.get(), main_thread_, - dependency_factory_->GetWebRtcSignalingThread(), - mock_webrtc_receiver_.get(), std::move(track_adapter), - std::vector< - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>>()); + DCHECK(track_ref); + RtpReceiverState state( + main_thread_, dependency_factory_->GetWebRtcSignalingThread(), + mock_webrtc_receiver_.get(), std::move(track_ref), {}); + state.Initialize(); + return std::make_unique<RTCRtpReceiver>(peer_connection_.get(), + std::move(state)); } scoped_refptr<WebRTCStatsReportObtainer> GetStats() { @@ -92,14 +89,11 @@ class RTCRtpReceiverTest : public ::testing::Test { protected: void CreateReceiverOnSignalingThread( scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>* - track_adapter, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>* track_ref, base::RunLoop* run_loop) { mock_webrtc_receiver_ = new rtc::RefCountedObject<webrtc::MockRtpReceiver>(); - *track_adapter = - stream_map_->track_adapter_map()->GetOrCreateRemoteTrackAdapter( - webrtc_track); + *track_ref = track_map_->GetOrCreateRemoteTrackAdapter(webrtc_track); run_loop->Quit(); } @@ -110,7 +104,7 @@ class RTCRtpReceiverTest : public ::testing::Test { std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_; rtc::scoped_refptr<MockPeerConnectionImpl> peer_connection_; rtc::scoped_refptr<webrtc::MockRtpReceiver> mock_webrtc_receiver_; std::unique_ptr<RTCRtpReceiver> receiver_; @@ -122,25 +116,25 @@ TEST_F(RTCRtpReceiverTest, CreateReceiver) { receiver_ = CreateReceiver(webrtc_track); EXPECT_FALSE(receiver_->Track().IsNull()); EXPECT_EQ(receiver_->Track().Id().Utf8(), webrtc_track->id()); - EXPECT_EQ(&receiver_->webrtc_track(), webrtc_track); + EXPECT_EQ(receiver_->state().track_ref()->webrtc_track(), webrtc_track); } TEST_F(RTCRtpReceiverTest, ShallowCopy) { scoped_refptr<MockWebRtcAudioTrack> webrtc_track = MockWebRtcAudioTrack::Create("webrtc_track"); receiver_ = CreateReceiver(webrtc_track); - auto copy = receiver_->ShallowCopy(); - EXPECT_EQ(&receiver_->webrtc_track(), webrtc_track); - auto* webrtc_receiver = receiver_->webrtc_receiver(); + auto copy = std::make_unique<RTCRtpReceiver>(*receiver_); + EXPECT_EQ(receiver_->state().track_ref()->webrtc_track(), webrtc_track); + const auto& webrtc_receiver = receiver_->state().webrtc_receiver(); auto web_track_unique_id = receiver_->Track().UniqueId(); // Copy is identical to original. - EXPECT_EQ(copy->webrtc_receiver(), webrtc_receiver); - EXPECT_EQ(©->webrtc_track(), webrtc_track); + EXPECT_EQ(copy->state().webrtc_receiver(), webrtc_receiver); + EXPECT_EQ(copy->state().track_ref()->webrtc_track(), webrtc_track); EXPECT_EQ(copy->Track().UniqueId(), web_track_unique_id); // Copy keeps the internal state alive. receiver_.reset(); - EXPECT_EQ(copy->webrtc_receiver(), webrtc_receiver); - EXPECT_EQ(©->webrtc_track(), webrtc_track); + EXPECT_EQ(copy->state().webrtc_receiver(), webrtc_receiver); + EXPECT_EQ(copy->state().track_ref()->webrtc_track(), webrtc_track); EXPECT_EQ(copy->Track().UniqueId(), web_track_unique_id); } diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc index 528c8d26a15..a2d16ec7de7 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc @@ -36,6 +36,100 @@ void OnSetParametersCompleted(blink::WebRTCVoidRequest request, } // namespace +RtpSenderState::RtpSenderState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, + std::vector<std::string> stream_ids) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + webrtc_sender_(std::move(webrtc_sender)), + is_initialized_(false), + track_ref_(std::move(track_ref)), + stream_ids_(std::move(stream_ids)) { + DCHECK(main_task_runner_); + DCHECK(signaling_task_runner_); + DCHECK(webrtc_sender_); +} + +RtpSenderState::RtpSenderState(RtpSenderState&& other) + : main_task_runner_(other.main_task_runner_), + signaling_task_runner_(other.signaling_task_runner_), + webrtc_sender_(std::move(other.webrtc_sender_)), + is_initialized_(other.is_initialized_), + track_ref_(std::move(other.track_ref_)), + stream_ids_(std::move(other.stream_ids_)) { + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; +} + +RtpSenderState::~RtpSenderState() { + // It's OK to not be on the main thread if this state has been moved, in which + // case |main_task_runner_| is null. + DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread()); +} + +RtpSenderState& RtpSenderState::operator=(RtpSenderState&& other) { + DCHECK_EQ(main_task_runner_, other.main_task_runner_); + DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_); + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; + webrtc_sender_ = std::move(other.webrtc_sender_); + is_initialized_ = other.is_initialized_; + track_ref_ = std::move(other.track_ref_); + stream_ids_ = std::move(other.stream_ids_); + return *this; +} + +bool RtpSenderState::is_initialized() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return is_initialized_; +} + +void RtpSenderState::Initialize() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (track_ref_) + track_ref_->InitializeOnMainThread(); + is_initialized_ = true; +} + +scoped_refptr<base::SingleThreadTaskRunner> RtpSenderState::main_task_runner() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return main_task_runner_; +} + +scoped_refptr<base::SingleThreadTaskRunner> +RtpSenderState::signaling_task_runner() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return signaling_task_runner_; +} + +scoped_refptr<webrtc::RtpSenderInterface> RtpSenderState::webrtc_sender() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_sender_; +} + +const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& +RtpSenderState::track_ref() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return track_ref_; +} + +void RtpSenderState::set_track_ref( + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(!is_initialized_ || !track_ref || track_ref->is_initialized()); + track_ref_ = std::move(track_ref); +} + +std::vector<std::string> RtpSenderState::stream_ids() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return stream_ids_; +} + class RTCRtpSender::RTCRtpSenderInternal : public base::RefCountedThreadSafe< RTCRtpSender::RTCRtpSenderInternal, @@ -43,86 +137,42 @@ class RTCRtpSender::RTCRtpSenderInternal public: RTCRtpSenderInternal( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - blink::WebMediaStreamTrack web_track, - std::vector<blink::WebMediaStream> web_streams) - : native_peer_connection_(std::move(native_peer_connection)), - main_thread_(std::move(main_thread)), - signaling_thread_(std::move(signaling_thread)), - stream_map_(std::move(stream_map)), - webrtc_sender_(std::move(webrtc_sender)) { - DCHECK(main_thread_); - DCHECK(signaling_thread_); - DCHECK(stream_map_); - DCHECK(webrtc_sender_); - if (!web_track.IsNull()) { - track_ref_ = - stream_map_->track_adapter_map()->GetOrCreateLocalTrackAdapter( - web_track); - } - for (size_t i = 0; i < web_streams.size(); ++i) { - if (!web_streams[i].IsNull()) { - stream_refs_.push_back( - stream_map_->GetOrCreateLocalStreamAdapter(web_streams[i])); - } - } - } - - RTCRtpSenderInternal( - scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs) + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpSenderState state) : native_peer_connection_(std::move(native_peer_connection)), - main_thread_(std::move(main_thread)), - signaling_thread_(std::move(signaling_thread)), - stream_map_(std::move(stream_map)), - webrtc_sender_(std::move(webrtc_sender)), - track_ref_(std::move(track_ref)), - stream_refs_(std::move(stream_refs)) { - DCHECK(main_thread_); - DCHECK(signaling_thread_); - DCHECK(stream_map_); - DCHECK(webrtc_sender_); - } - - webrtc::RtpSenderInterface* webrtc_sender() const { - return webrtc_sender_.get(); + track_map_(std::move(track_map)), + main_task_runner_(state.main_task_runner()), + signaling_task_runner_(state.signaling_task_runner()), + webrtc_sender_(state.webrtc_sender()), + state_(std::move(state)) { + DCHECK(track_map_); + DCHECK(state_.is_initialized()); } - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref() - const { - return track_ref_ ? track_ref_->Copy() : nullptr; + const RtpSenderState& state() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return state_; } - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs() const { - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_ref_copies(stream_refs_.size()); - for (size_t i = 0; i < stream_refs_.size(); ++i) - stream_ref_copies[i] = stream_refs_[i]->Copy(); - return stream_ref_copies; + void set_state(RtpSenderState state) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK_EQ(state.main_task_runner(), main_task_runner_); + DCHECK_EQ(state.signaling_task_runner(), signaling_task_runner_); + DCHECK(state.webrtc_sender() == webrtc_sender_); + DCHECK(state.is_initialized()); + state_ = std::move(state); } void ReplaceTrack(blink::WebMediaStreamTrack with_track, base::OnceCallback<void(bool)> callback) { - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; webrtc::MediaStreamTrackInterface* webrtc_track = nullptr; if (!with_track.IsNull()) { - track_ref = - stream_map_->track_adapter_map()->GetOrCreateLocalTrackAdapter( - with_track); + track_ref = track_map_->GetOrCreateLocalTrackAdapter(with_track); webrtc_track = track_ref->webrtc_track(); } - signaling_thread_->PostTask( + signaling_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::ReplaceTrackOnSignalingThread, @@ -131,14 +181,16 @@ class RTCRtpSender::RTCRtpSenderInternal } std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender() const { - // The webrtc_sender is a proxy, so this is a blocking call to the + // The webrtc_sender() is a proxy, so this is a blocking call to the // webrtc signalling thread. - DCHECK(main_thread_->BelongsToCurrentThread()); - auto dtmf_sender = webrtc_sender()->GetDtmfSender(); + DCHECK(main_task_runner_->BelongsToCurrentThread()); + auto dtmf_sender = webrtc_sender_->GetDtmfSender(); return std::make_unique<RtcDtmfSenderHandler>(dtmf_sender); } std::unique_ptr<webrtc::RtpParameters> GetParameters() { + // The webrtc_sender() is a proxy, so this is a blocking call to the + // webrtc signalling thread. parameters_ = webrtc_sender_->GetParameters(); return std::make_unique<webrtc::RtpParameters>(parameters_); } @@ -146,7 +198,7 @@ class RTCRtpSender::RTCRtpSenderInternal void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters> encodings, webrtc::DegradationPreference degradation_preference, base::OnceCallback<void(webrtc::RTCError)> callback) { - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); webrtc::RtpParameters new_parameters = parameters_; @@ -171,7 +223,7 @@ class RTCRtpSender::RTCRtpSenderInternal encoding.scale_resolution_down_by; } - signaling_thread_->PostTask( + signaling_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::SetParametersOnSignalingThread, @@ -179,7 +231,7 @@ class RTCRtpSender::RTCRtpSenderInternal } void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - signaling_thread_->PostTask( + signaling_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::GetStatsOnSignalingThread, @@ -187,13 +239,14 @@ class RTCRtpSender::RTCRtpSenderInternal } bool RemoveFromPeerConnection(webrtc::PeerConnectionInterface* pc) { - if (!pc->RemoveTrack(webrtc_sender_)) + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (!pc->RemoveTrack(webrtc_sender_.get())) return false; // TODO(hbos): Removing the track should null the sender's track, or we // should do |webrtc_sender_->SetTrack(null)| but that is not allowed on a // stopped sender. In the meantime, there is a discrepancy between layers. // https://crbug.com/webrtc/7945 - track_ref_.reset(); + state_.set_track_ref(nullptr); return true; } @@ -202,7 +255,7 @@ class RTCRtpSender::RTCRtpSenderInternal ~RTCRtpSenderInternal() { // Ensured by destructor traits. - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); } // |webrtc_track| is passed as an argument because |track_ref->webrtc_track()| @@ -211,9 +264,9 @@ class RTCRtpSender::RTCRtpSenderInternal std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, webrtc::MediaStreamTrackInterface* webrtc_track, base::OnceCallback<void(bool)> callback) { - DCHECK(signaling_thread_->BelongsToCurrentThread()); + DCHECK(signaling_task_runner_->BelongsToCurrentThread()); bool result = webrtc_sender_->SetTrack(webrtc_track); - main_thread_->PostTask( + main_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::ReplaceTrackCallback, this, @@ -224,25 +277,25 @@ class RTCRtpSender::RTCRtpSenderInternal bool result, std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, base::OnceCallback<void(bool)> callback) { - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); if (result) - track_ref_ = std::move(track_ref); + state_.set_track_ref(std::move(track_ref)); std::move(callback).Run(result); } void GetStatsOnSignalingThread( std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - native_peer_connection_->GetStats(webrtc_sender_, - RTCStatsCollectorCallbackImpl::Create( - main_thread_, std::move(callback))); + native_peer_connection_->GetStats( + webrtc_sender_.get(), RTCStatsCollectorCallbackImpl::Create( + main_task_runner_, std::move(callback))); } void SetParametersOnSignalingThread( webrtc::RtpParameters parameters, base::OnceCallback<void(webrtc::RTCError)> callback) { - DCHECK(signaling_thread_->BelongsToCurrentThread()); + DCHECK(signaling_task_runner_->BelongsToCurrentThread()); webrtc::RTCError result = webrtc_sender_->SetParameters(parameters); - main_thread_->PostTask( + main_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::SetParametersCallback, this, @@ -252,23 +305,19 @@ class RTCRtpSender::RTCRtpSenderInternal void SetParametersCallback( webrtc::RTCError result, base::OnceCallback<void(webrtc::RTCError)> callback) { - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); std::move(callback).Run(std::move(result)); } const scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_; - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_; - const scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map_; - const rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_; - // The track adapter is the glue between blink and webrtc layer tracks. - // Keeping a reference to the adapter ensures it is not disposed, as is - // required as long as the webrtc layer track is in use by the sender. - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref_; - // Similarly, reference needs to be kept to the stream adapters of the - // sender's associated set of streams. - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs_; + const scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_; + // Task runners and webrtc sender: Same information as stored in + // |state_| but const and safe to touch on the signaling thread to + // avoid race with set_state(). + const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + const scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_; + RtpSenderState state_; webrtc::RtpParameters parameters_; }; @@ -280,8 +329,8 @@ struct RTCRtpSender::RTCRtpSenderInternalTraits { static void Destruct(const RTCRtpSenderInternal* sender) { // RTCRtpSenderInternal owns AdapterRefs which have to be destroyed on the // main thread, this ensures delete always happens there. - if (!sender->main_thread_->BelongsToCurrentThread()) { - sender->main_thread_->PostTask( + if (!sender->main_task_runner_->BelongsToCurrentThread()) { + sender->main_task_runner_->PostTask( FROM_HERE, base::BindOnce(&RTCRtpSender::RTCRtpSenderInternalTraits::Destruct, base::Unretained(sender))); @@ -297,36 +346,11 @@ uintptr_t RTCRtpSender::getId(const webrtc::RtpSenderInterface* webrtc_sender) { RTCRtpSender::RTCRtpSender( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - blink::WebMediaStreamTrack web_track, - std::vector<blink::WebMediaStream> web_streams) - : internal_(new RTCRtpSenderInternal(std::move(native_peer_connection), - std::move(main_thread), - std::move(signaling_thread), - std::move(stream_map), - std::move(webrtc_sender), - std::move(web_track), - std::move(web_streams))) {} - -RTCRtpSender::RTCRtpSender( - scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs) + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpSenderState state) : internal_(new RTCRtpSenderInternal(std::move(native_peer_connection), - std::move(main_thread), - std::move(signaling_thread), - std::move(stream_map), - std::move(webrtc_sender), - std::move(track_ref), - std::move(stream_refs))) {} + std::move(track_map), + std::move(state))) {} RTCRtpSender::RTCRtpSender(const RTCRtpSender& other) : internal_(other.internal_) {} @@ -338,19 +362,35 @@ RTCRtpSender& RTCRtpSender::operator=(const RTCRtpSender& other) { return *this; } -std::unique_ptr<RTCRtpSender> RTCRtpSender::ShallowCopy() const { +const RtpSenderState& RTCRtpSender::state() const { + return internal_->state(); +} + +void RTCRtpSender::set_state(RtpSenderState state) { + internal_->set_state(std::move(state)); +} + +std::unique_ptr<blink::WebRTCRtpSender> RTCRtpSender::ShallowCopy() const { return std::make_unique<RTCRtpSender>(*this); } uintptr_t RTCRtpSender::Id() const { - return getId(internal_->webrtc_sender()); + return getId(internal_->state().webrtc_sender().get()); } blink::WebMediaStreamTrack RTCRtpSender::Track() const { - auto track_ref = internal_->track_ref(); + const auto& track_ref = internal_->state().track_ref(); return track_ref ? track_ref->web_track() : blink::WebMediaStreamTrack(); } +blink::WebVector<blink::WebString> RTCRtpSender::StreamIds() const { + const auto& stream_ids = internal_->state().stream_ids(); + blink::WebVector<blink::WebString> web_stream_ids(stream_ids.size()); + for (size_t i = 0; i < stream_ids.size(); ++i) + web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids[i]); + return web_stream_ids; +} + void RTCRtpSender::ReplaceTrack(blink::WebMediaStreamTrack with_track, blink::WebRTCVoidRequest request) { internal_->ReplaceTrack( @@ -381,20 +421,6 @@ void RTCRtpSender::GetStats( internal_->GetStats(std::move(callback)); } -webrtc::RtpSenderInterface* RTCRtpSender::webrtc_sender() const { - return internal_->webrtc_sender(); -} - -const webrtc::MediaStreamTrackInterface* RTCRtpSender::webrtc_track() const { - auto track_ref = internal_->track_ref(); - return track_ref ? track_ref->webrtc_track() : nullptr; -} - -std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> -RTCRtpSender::stream_refs() const { - return internal_->stream_refs(); -} - void RTCRtpSender::ReplaceTrack(blink::WebMediaStreamTrack with_track, base::OnceCallback<void(bool)> callback) { internal_->ReplaceTrack(std::move(with_track), std::move(callback)); @@ -405,4 +431,65 @@ bool RTCRtpSender::RemoveFromPeerConnection( return internal_->RemoveFromPeerConnection(pc); } +RTCRtpSenderOnlyTransceiver::RTCRtpSenderOnlyTransceiver( + std::unique_ptr<blink::WebRTCRtpSender> sender) + : sender_(std::move(sender)) { + DCHECK(sender_); +} + +RTCRtpSenderOnlyTransceiver::~RTCRtpSenderOnlyTransceiver() {} + +blink::WebRTCRtpTransceiverImplementationType +RTCRtpSenderOnlyTransceiver::ImplementationType() const { + return blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly; +} + +uintptr_t RTCRtpSenderOnlyTransceiver::Id() const { + NOTIMPLEMENTED(); + return 0u; +} + +blink::WebString RTCRtpSenderOnlyTransceiver::Mid() const { + NOTIMPLEMENTED(); + return blink::WebString(); +} + +std::unique_ptr<blink::WebRTCRtpSender> RTCRtpSenderOnlyTransceiver::Sender() + const { + return sender_->ShallowCopy(); +} + +std::unique_ptr<blink::WebRTCRtpReceiver> +RTCRtpSenderOnlyTransceiver::Receiver() const { + NOTIMPLEMENTED(); + return nullptr; +} + +bool RTCRtpSenderOnlyTransceiver::Stopped() const { + NOTIMPLEMENTED(); + return false; +} + +webrtc::RtpTransceiverDirection RTCRtpSenderOnlyTransceiver::Direction() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; +} + +void RTCRtpSenderOnlyTransceiver::SetDirection( + webrtc::RtpTransceiverDirection direction) { + NOTIMPLEMENTED(); +} + +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpSenderOnlyTransceiver::CurrentDirection() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; +} + +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpSenderOnlyTransceiver::FiredDirection() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h index 990b21fb64c..7a96b39e38f 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h @@ -11,10 +11,10 @@ #include "base/callback.h" #include "base/single_thread_task_runner.h" #include "content/common/content_export.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "third_party/blink/public/platform/web_media_stream_track.h" #include "third_party/blink/public/platform/web_rtc_rtp_sender.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" #include "third_party/blink/public/platform/web_rtc_stats.h" #include "third_party/webrtc/api/peerconnectioninterface.h" #include "third_party/webrtc/api/rtpsenderinterface.h" @@ -22,43 +22,108 @@ namespace content { +// This class represents the state of a sender; a snapshot of what a +// webrtc-layer sender looked like when it was inspected on the signaling thread +// such that this information can be moved to the main thread in a single +// PostTask. It is used to surface state changes to make the blink-layer sender +// up-to-date. +// +// Blink objects live on the main thread and webrtc objects live on the +// signaling thread. If multiple asynchronous operations begin execution on the +// main thread they are posted and executed in order on the signaling thread. +// For example, operation A and operation B are called in JavaScript. When A is +// done on the signaling thread, webrtc object states will be updated. A +// callback is posted to the main thread so that blink objects can be updated to +// match the result of operation A. But if callback A tries to inspect the +// webrtc objects from the main thread this requires posting back to the +// signaling thread and waiting, which also includes waiting for the previously +// posted task: operation B. Inspecting the webrtc object like this does not +// guarantee you to get the state of operation A. +// +// As such, all state changes associated with an operation have to be surfaced +// in the same callback. This includes copying any states into a separate object +// so that it can be inspected on the main thread without any additional thread +// hops. +// +// The RtpSenderState is a snapshot of what the webrtc::RtpSenderInterface +// looked like when the RtpSenderState was created on the signaling thread. It +// also takes care of initializing track adapters, such that we have access to a +// blink track corresponding to the webrtc track of the sender. +// +// Except for initialization logic and operator=(), the RtpSenderState is +// immutable and only accessible on the main thread. +// +// TODO(hbos): [Onion Soup] When the sender implementation is moved to blink +// this will be part of the blink sender instead of the content sender. +// https://crbug.com/787254 +class CONTENT_EXPORT RtpSenderState { + public: + RtpSenderState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, + std::vector<std::string> stream_ids); + RtpSenderState(RtpSenderState&&); + RtpSenderState(const RtpSenderState&) = delete; + ~RtpSenderState(); + + // This is intended to be used for moving the object from the signaling thread + // to the main thread and as such has no thread checks. Once moved to the main + // this should only be invoked on the main thread. + RtpSenderState& operator=(RtpSenderState&&); + RtpSenderState& operator=(const RtpSenderState&) = delete; + + bool is_initialized() const; + void Initialize(); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const; + scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender() const; + const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& + track_ref() const; + void set_track_ref( + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref); + std::vector<std::string> stream_ids() const; + + private: + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_; + bool is_initialized_; + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref_; + std::vector<std::string> stream_ids_; +}; + // Used to surface |webrtc::RtpSenderInterface| to blink. Multiple // |RTCRtpSender|s could reference the same webrtc sender; |id| is the value // of the pointer to the webrtc sender. +// TODO(hbos): [Onion Soup] Move all of the implementation inside the blink +// object and remove this class and interface. The blink object is reference +// counted and we can get rid of this "Web"-copyable with "internal" nonsense, +// all the blink object will need is the RtpSenderState. Requires coordination +// with transceivers and receivers since these are tightly coupled. +// https://crbug.com/787254 class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender { public: static uintptr_t getId(const webrtc::RtpSenderInterface* webrtc_sender); RTCRtpSender( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - blink::WebMediaStreamTrack web_track, - std::vector<blink::WebMediaStream> web_streams); - RTCRtpSender( - scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs); + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpSenderState state); RTCRtpSender(const RTCRtpSender& other); ~RTCRtpSender() override; - RTCRtpSender& operator=(const RTCRtpSender& other); - // Creates a shallow copy of the sender, representing the same underlying - // webrtc sender as the original. - // TODO(hbos): Remove in favor of constructor. https://crbug.com/790007 - std::unique_ptr<RTCRtpSender> ShallowCopy() const; + const RtpSenderState& state() const; + void set_state(RtpSenderState state); // blink::WebRTCRtpSender. + std::unique_ptr<blink::WebRTCRtpSender> ShallowCopy() const override; uintptr_t Id() const override; blink::WebMediaStreamTrack Track() const override; + blink::WebVector<blink::WebString> StreamIds() const override; void ReplaceTrack(blink::WebMediaStreamTrack with_track, blink::WebRTCVoidRequest request) override; std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender() @@ -69,10 +134,6 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender { blink::WebRTCVoidRequest) override; void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override; - webrtc::RtpSenderInterface* webrtc_sender() const; - const webrtc::MediaStreamTrackInterface* webrtc_track() const; - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs() const; // The ReplaceTrack() that takes a blink::WebRTCVoidRequest is implemented on // top of this, which returns the result in a callback instead. Allows doing // ReplaceTrack() without having a blink::WebRTCVoidRequest, which can only be @@ -88,6 +149,30 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender { scoped_refptr<RTCRtpSenderInternal> internal_; }; +class CONTENT_EXPORT RTCRtpSenderOnlyTransceiver + : public blink::WebRTCRtpTransceiver { + public: + RTCRtpSenderOnlyTransceiver(std::unique_ptr<blink::WebRTCRtpSender> sender); + ~RTCRtpSenderOnlyTransceiver() override; + + blink::WebRTCRtpTransceiverImplementationType ImplementationType() + const override; + uintptr_t Id() const override; + blink::WebString Mid() const override; + std::unique_ptr<blink::WebRTCRtpSender> Sender() const override; + std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override; + bool Stopped() const override; + webrtc::RtpTransceiverDirection Direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection direction) override; + base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() + const override; + base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() + const override; + + private: + std::unique_ptr<blink::WebRTCRtpSender> sender_; +}; + } // namespace content #endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_SENDER_H_ diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc index eb086d2e0d2..0f3f27f9dad 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc @@ -16,7 +16,6 @@ #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/mock_peer_connection_impl.h" #include "content/renderer/media/webrtc/test/webrtc_stats_report_obtainer.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" @@ -40,10 +39,8 @@ class RTCRtpSenderTest : public ::testing::Test { void SetUp() override { dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); - stream_map_ = new WebRtcMediaStreamAdapterMap( - dependency_factory_.get(), main_thread_, - new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), - main_thread_)); + track_map_ = new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), + main_thread_); peer_connection_ = new rtc::RefCountedObject<MockPeerConnectionImpl>( dependency_factory_.get(), nullptr); mock_webrtc_sender_ = new rtc::RefCountedObject<webrtc::MockRtpSender>(); @@ -84,11 +81,18 @@ class RTCRtpSenderTest : public ::testing::Test { std::unique_ptr<RTCRtpSender> CreateSender( blink::WebMediaStreamTrack web_track) { - return std::make_unique<RTCRtpSender>( - peer_connection_.get(), main_thread_, - dependency_factory_->GetWebRtcSignalingThread(), stream_map_, - mock_webrtc_sender_.get(), std::move(web_track), - std::vector<blink::WebMediaStream>()); + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; + if (!web_track.IsNull()) { + track_ref = track_map_->GetOrCreateLocalTrackAdapter(web_track); + DCHECK(track_ref->is_initialized()); + } + RtpSenderState sender_state(main_thread_, + dependency_factory_->GetWebRtcSignalingThread(), + mock_webrtc_sender_.get(), std::move(track_ref), + std::vector<std::string>()); + sender_state.Initialize(); + return std::make_unique<RTCRtpSender>(peer_connection_.get(), track_map_, + std::move(sender_state)); } // Calls replaceTrack(), which is asynchronous, returning a callback that when @@ -139,7 +143,7 @@ class RTCRtpSenderTest : public ::testing::Test { std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_; rtc::scoped_refptr<MockPeerConnectionImpl> peer_connection_; rtc::scoped_refptr<webrtc::MockRtpSender> mock_webrtc_sender_; std::unique_ptr<RTCRtpSender> sender_; diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc new file mode 100644 index 00000000000..7bdda93416d --- /dev/null +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc @@ -0,0 +1,357 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/webrtc/rtc_rtp_transceiver.h" + +#include "base/logging.h" +#include "base/memory/ref_counted.h" + +namespace content { + +RtpTransceiverState::RtpTransceiverState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver, + base::Optional<RtpSenderState> sender_state, + base::Optional<RtpReceiverState> receiver_state, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction, + base::Optional<webrtc::RtpTransceiverDirection> fired_direction) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + webrtc_transceiver_(std::move(webrtc_transceiver)), + is_initialized_(false), + sender_state_(std::move(sender_state)), + receiver_state_(std::move(receiver_state)), + mid_(std::move(mid)), + stopped_(std::move(stopped)), + direction_(std::move(direction)), + current_direction_(std::move(current_direction)), + fired_direction_(std::move(fired_direction)) { + DCHECK(main_task_runner_); + DCHECK(signaling_task_runner_); + DCHECK(webrtc_transceiver_); +} + +RtpTransceiverState::RtpTransceiverState(RtpTransceiverState&& other) + : main_task_runner_(other.main_task_runner_), + signaling_task_runner_(other.signaling_task_runner_), + webrtc_transceiver_(std::move(other.webrtc_transceiver_)), + is_initialized_(other.is_initialized_), + sender_state_(std::move(other.sender_state_)), + receiver_state_(std::move(other.receiver_state_)), + mid_(std::move(other.mid_)), + stopped_(std::move(other.stopped_)), + direction_(std::move(other.direction_)), + current_direction_(std::move(other.current_direction_)), + fired_direction_(std::move(other.fired_direction_)) { + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; +} + +RtpTransceiverState::~RtpTransceiverState() { + // It's OK to not be on the main thread if this state has been moved, in which + // case |main_task_runner_| is null. + DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread()); +} + +RtpTransceiverState& RtpTransceiverState::operator=( + RtpTransceiverState&& other) { + DCHECK_EQ(main_task_runner_, other.main_task_runner_); + DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_); + // Need to be on main thread for sender/receiver state's destructor that can + // be triggered by replacing . + DCHECK(main_task_runner_->BelongsToCurrentThread()); + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; + webrtc_transceiver_ = std::move(other.webrtc_transceiver_); + is_initialized_ = other.is_initialized_; + sender_state_ = std::move(other.sender_state_); + receiver_state_ = std::move(other.receiver_state_); + mid_ = std::move(other.mid_); + stopped_ = std::move(other.stopped_); + direction_ = std::move(other.direction_); + current_direction_ = std::move(other.current_direction_); + fired_direction_ = std::move(other.fired_direction_); + return *this; +} + +bool RtpTransceiverState::is_initialized() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return is_initialized_; +} + +void RtpTransceiverState::Initialize() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (sender_state_) + sender_state_->Initialize(); + if (receiver_state_) + receiver_state_->Initialize(); + is_initialized_ = true; +} + +scoped_refptr<base::SingleThreadTaskRunner> +RtpTransceiverState::main_task_runner() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return main_task_runner_; +} + +scoped_refptr<base::SingleThreadTaskRunner> +RtpTransceiverState::signaling_task_runner() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return signaling_task_runner_; +} + +scoped_refptr<webrtc::RtpTransceiverInterface> +RtpTransceiverState::webrtc_transceiver() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_transceiver_; +} + +const base::Optional<RtpSenderState>& RtpTransceiverState::sender_state() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return sender_state_; +} + +RtpSenderState RtpTransceiverState::MoveSenderState() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + base::Optional<RtpSenderState> temp(base::nullopt); + sender_state_.swap(temp); + return *std::move(temp); +} + +const base::Optional<RtpReceiverState>& RtpTransceiverState::receiver_state() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return receiver_state_; +} + +RtpReceiverState RtpTransceiverState::MoveReceiverState() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + base::Optional<RtpReceiverState> temp(base::nullopt); + receiver_state_.swap(temp); + return *std::move(temp); +} + +base::Optional<std::string> RtpTransceiverState::mid() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return mid_; +} + +bool RtpTransceiverState::stopped() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return stopped_; +} + +webrtc::RtpTransceiverDirection RtpTransceiverState::direction() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return direction_; +} + +void RtpTransceiverState::set_direction( + webrtc::RtpTransceiverDirection direction) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + direction_ = direction; +} + +base::Optional<webrtc::RtpTransceiverDirection> +RtpTransceiverState::current_direction() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return current_direction_; +} + +base::Optional<webrtc::RtpTransceiverDirection> +RtpTransceiverState::fired_direction() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return fired_direction_; +} + +class RTCRtpTransceiver::RTCRtpTransceiverInternal + : public base::RefCountedThreadSafe< + RTCRtpTransceiver::RTCRtpTransceiverInternal, + RTCRtpTransceiver::RTCRtpTransceiverInternalTraits> { + public: + RTCRtpTransceiverInternal( + scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpTransceiverState state) + : main_task_runner_(state.main_task_runner()), + signaling_task_runner_(state.signaling_task_runner()), + webrtc_transceiver_(state.webrtc_transceiver()), + state_(std::move(state)) { + sender_ = std::make_unique<RTCRtpSender>(native_peer_connection, track_map, + state_.MoveSenderState()); + receiver_ = std::make_unique<RTCRtpReceiver>(native_peer_connection, + state_.MoveReceiverState()); + } + + const RtpTransceiverState& state() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return state_; + } + + void set_state(RtpTransceiverState state) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK_EQ(state.main_task_runner(), main_task_runner_); + DCHECK_EQ(state.signaling_task_runner(), signaling_task_runner_); + DCHECK(state.webrtc_transceiver() == webrtc_transceiver_); + DCHECK(state.is_initialized()); + state_ = std::move(state); + sender_->set_state(state_.MoveSenderState()); + receiver_->set_state(state_.MoveReceiverState()); + } + + RTCRtpSender* content_sender() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return sender_.get(); + } + + RTCRtpReceiver* content_receiver() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return receiver_.get(); + } + + void SetDirection(webrtc::RtpTransceiverDirection direction) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + // This implicitly performs a blocking invoke on the webrtc signaling thread + // due to use of PROXY references for |webrtc_transceiver_|. + webrtc_transceiver_->SetDirection(direction); + state_.set_direction(webrtc_transceiver_->direction()); + } + + private: + friend struct RTCRtpTransceiver::RTCRtpTransceiverInternalTraits; + + ~RTCRtpTransceiverInternal() { + // Ensured by destructor traits. + DCHECK(main_task_runner_->BelongsToCurrentThread()); + } + + // Task runners and webrtc transceiver: Same information as stored in |state_| + // but const and safe to touch on the signaling thread to avoid race with + // set_state(). + const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + const scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver_; + RtpTransceiverState state_; + std::unique_ptr<RTCRtpSender> sender_; + std::unique_ptr<RTCRtpReceiver> receiver_; +}; + +struct RTCRtpTransceiver::RTCRtpTransceiverInternalTraits { + private: + friend class base::RefCountedThreadSafe<RTCRtpTransceiverInternal, + RTCRtpTransceiverInternalTraits>; + + static void Destruct(const RTCRtpTransceiverInternal* transceiver) { + // RTCRtpTransceiverInternal owns AdapterRefs which have to be destroyed on + // the main thread, this ensures delete always happens there. + if (!transceiver->main_task_runner_->BelongsToCurrentThread()) { + transceiver->main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &RTCRtpTransceiver::RTCRtpTransceiverInternalTraits::Destruct, + base::Unretained(transceiver))); + return; + } + delete transceiver; + } +}; + +uintptr_t RTCRtpTransceiver::GetId( + const webrtc::RtpTransceiverInterface* webrtc_transceiver) { + return reinterpret_cast<uintptr_t>(webrtc_transceiver); +} + +RTCRtpTransceiver::RTCRtpTransceiver( + scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpTransceiverState transceiver_state) + : internal_(new RTCRtpTransceiverInternal(std::move(native_peer_connection), + std::move(track_map), + std::move(transceiver_state))) {} + +RTCRtpTransceiver::RTCRtpTransceiver(const RTCRtpTransceiver& other) + : internal_(other.internal_) {} + +RTCRtpTransceiver::~RTCRtpTransceiver() {} + +RTCRtpTransceiver& RTCRtpTransceiver::operator=( + const RTCRtpTransceiver& other) { + internal_ = other.internal_; + return *this; +} + +std::unique_ptr<RTCRtpTransceiver> RTCRtpTransceiver::ShallowCopy() const { + return std::make_unique<RTCRtpTransceiver>(*this); +} + +const RtpTransceiverState& RTCRtpTransceiver::state() const { + return internal_->state(); +} + +RTCRtpSender* RTCRtpTransceiver::content_sender() { + return internal_->content_sender(); +} + +RTCRtpReceiver* RTCRtpTransceiver::content_receiver() { + return internal_->content_receiver(); +} + +void RTCRtpTransceiver::set_state(RtpTransceiverState transceiver_state) { + internal_->set_state(std::move(transceiver_state)); +} + +blink::WebRTCRtpTransceiverImplementationType +RTCRtpTransceiver::ImplementationType() const { + return blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver; +} + +uintptr_t RTCRtpTransceiver::Id() const { + return GetId(internal_->state().webrtc_transceiver().get()); +} + +blink::WebString RTCRtpTransceiver::Mid() const { + const auto& mid = internal_->state().mid(); + return mid ? blink::WebString::FromUTF8(*mid) + : blink::WebString(); // IsNull() +} + +std::unique_ptr<blink::WebRTCRtpSender> RTCRtpTransceiver::Sender() const { + return internal_->content_sender()->ShallowCopy(); +} + +std::unique_ptr<blink::WebRTCRtpReceiver> RTCRtpTransceiver::Receiver() const { + return internal_->content_receiver()->ShallowCopy(); +} + +bool RTCRtpTransceiver::Stopped() const { + return internal_->state().stopped(); +} + +webrtc::RtpTransceiverDirection RTCRtpTransceiver::Direction() const { + return internal_->state().direction(); +} + +void RTCRtpTransceiver::SetDirection( + webrtc::RtpTransceiverDirection direction) { + internal_->SetDirection(direction); +} + +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpTransceiver::CurrentDirection() const { + return internal_->state().current_direction(); +} + +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpTransceiver::FiredDirection() const { + return internal_->state().fired_direction(); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h new file mode 100644 index 00000000000..5eadedf1955 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h @@ -0,0 +1,160 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_TRANSCEIVER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_TRANSCEIVER_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/optional.h" +#include "base/single_thread_task_runner.h" +#include "content/renderer/media/webrtc/rtc_rtp_receiver.h" +#include "content/renderer/media/webrtc/rtc_rtp_sender.h" +#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" +#include "third_party/webrtc/api/rtptransceiverinterface.h" + +namespace content { + +// This class represents the state of a transceiver; a snapshot of what a +// webrtc-layer transceiver looked like when it was inspected on the signaling +// thread such that this information can be moved to the main thread in a single +// PostTask. It is used to surface state changes to make the blink-layer +// transceiver up-to-date. +// +// Blink objects live on the main thread and webrtc objects live on the +// signaling thread. If multiple asynchronous operations begin execution on the +// main thread they are posted and executed in order on the signaling thread. +// For example, operation A and operation B are called in JavaScript. When A is +// done on the signaling thread, webrtc object states will be updated. A +// callback is posted to the main thread so that blink objects can be updated to +// match the result of operation A. But if callback A tries to inspect the +// webrtc objects from the main thread this requires posting back to the +// signaling thread and waiting, which also includes waiting for the previously +// posted task: operation B. Inspecting the webrtc object like this does not +// guarantee you to get the state of operation A. +// +// As such, all state changes associated with an operation have to be surfaced +// in the same callback. This includes copying any states into a separate object +// so that it can be inspected on the main thread without any additional thread +// hops. +// +// The RtpTransceiverState is a snapshot of what the +// webrtc::RtpTransceiverInterface looked like when the RtpTransceiverState was +// created on the signaling thread. It also takes care of initializing sender +// and receiver states, including their track adapters such that we have access +// to a blink track corresponding to the webrtc tracks of the sender and +// receiver. +// +// Except for initialization logic and operator=(), the RtpTransceiverState is +// immutable and only accessible on the main thread. +// +// TODO(hbos): [Onion Soup] When the transceiver implementation is moved to +// blink this will be part of the blink transceiver instead of the content +// transceiver. https://crbug.com/787254 +class CONTENT_EXPORT RtpTransceiverState { + public: + RtpTransceiverState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver, + base::Optional<RtpSenderState> sender_state, + base::Optional<RtpReceiverState> receiver_state, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction, + base::Optional<webrtc::RtpTransceiverDirection> fired_direction); + RtpTransceiverState(RtpTransceiverState&&); + RtpTransceiverState(const RtpTransceiverState&) = delete; + ~RtpTransceiverState(); + + // This is intended to be used for moving the object from the signaling thread + // to the main thread and as such has no thread checks. Once moved to the main + // this should only be invoked on the main thread. + RtpTransceiverState& operator=(RtpTransceiverState&&); + RtpTransceiverState& operator=(const RtpTransceiverState&) = delete; + + bool is_initialized() const; + void Initialize(); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const; + scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver() const; + const base::Optional<RtpSenderState>& sender_state() const; + RtpSenderState MoveSenderState(); + const base::Optional<RtpReceiverState>& receiver_state() const; + RtpReceiverState MoveReceiverState(); + base::Optional<std::string> mid() const; + bool stopped() const; + webrtc::RtpTransceiverDirection direction() const; + void set_direction(webrtc::RtpTransceiverDirection); + base::Optional<webrtc::RtpTransceiverDirection> current_direction() const; + base::Optional<webrtc::RtpTransceiverDirection> fired_direction() const; + + private: + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver_; + bool is_initialized_; + base::Optional<RtpSenderState> sender_state_; + base::Optional<RtpReceiverState> receiver_state_; + base::Optional<std::string> mid_; + bool stopped_; + webrtc::RtpTransceiverDirection direction_; + base::Optional<webrtc::RtpTransceiverDirection> current_direction_; + base::Optional<webrtc::RtpTransceiverDirection> fired_direction_; +}; + +// Used to surface |webrtc::RtpTransceiverInterface| to blink. Multiple +// |RTCRtpTransceiver|s could reference the same webrtc transceiver; |id| is +// unique per webrtc transceiver. +// Its methods are accessed on the main thread, internally also performs +// operations on the signaling thread. +// TODO(hbos): [Onion Soup] Remove the content layer versions of this class and +// rely on webrtc directly from blink. Requires coordination with senders and +// receivers. https://crbug.com/787254 +class CONTENT_EXPORT RTCRtpTransceiver : public blink::WebRTCRtpTransceiver { + public: + static uintptr_t GetId( + const webrtc::RtpTransceiverInterface* webrtc_transceiver); + + RTCRtpTransceiver( + scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpTransceiverState state); + RTCRtpTransceiver(const RTCRtpTransceiver& other); + ~RTCRtpTransceiver() override; + + RTCRtpTransceiver& operator=(const RTCRtpTransceiver& other); + std::unique_ptr<RTCRtpTransceiver> ShallowCopy() const; + + const RtpTransceiverState& state() const; + void set_state(RtpTransceiverState state); + RTCRtpSender* content_sender(); + RTCRtpReceiver* content_receiver(); + + blink::WebRTCRtpTransceiverImplementationType ImplementationType() + const override; + uintptr_t Id() const override; + blink::WebString Mid() const override; + std::unique_ptr<blink::WebRTCRtpSender> Sender() const override; + std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override; + bool Stopped() const override; + webrtc::RtpTransceiverDirection Direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection direction) override; + base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() + const override; + base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() + const override; + + private: + class RTCRtpTransceiverInternal; + struct RTCRtpTransceiverInternalTraits; + + scoped_refptr<RTCRtpTransceiverInternal> internal_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_TRANSCEIVER_H_ diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc new file mode 100644 index 00000000000..3690936bfc8 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc @@ -0,0 +1,363 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/webrtc/rtc_rtp_transceiver.h" + +#include <memory> + +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" +#include "base/optional.h" +#include "base/run_loop.h" +#include "base/single_thread_task_runner.h" +#include "base/synchronization/waitable_event.h" +#include "build/build_config.h" +#include "content/child/child_process.h" +#include "content/renderer/media/stream/media_stream_audio_source.h" +#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" +#include "content/renderer/media/webrtc/mock_peer_connection_impl.h" +#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" +#include "content/renderer/media/webrtc/webrtc_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" +#include "third_party/blink/public/platform/web_media_stream_source.h" +#include "third_party/blink/public/platform/web_string.h" +#include "third_party/blink/public/web/web_heap.h" +#include "third_party/webrtc/api/test/mock_rtpreceiver.h" +#include "third_party/webrtc/api/test/mock_rtpsender.h" + +namespace content { + +class RTCRtpTransceiverTest : public ::testing::Test { + public: + void SetUp() override { + dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); + main_task_runner_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); + track_map_ = new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), + main_task_runner_); + peer_connection_ = new rtc::RefCountedObject<MockPeerConnectionImpl>( + dependency_factory_.get(), nullptr); + } + + void TearDown() override { + // Syncing up with the signaling thread ensures any pending operations on + // that thread are executed. If they post back to the main thread, such as + // the sender or receiver destructor traits, this is allowed to execute + // before the test shuts down the threads. + SyncWithSignalingThread(); + blink::WebHeap::CollectAllGarbageForTesting(); + } + + // Wait for the signaling thread to perform any queued tasks, executing tasks + // posted to the current thread in the meantime while waiting. + void SyncWithSignalingThread() const { + base::RunLoop run_loop; + dependency_factory_->GetWebRtcSignalingThread()->PostTask( + FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); + } + + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const { + return dependency_factory_->GetWebRtcSignalingThread(); + } + + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + CreateLocalTrackAndAdapter(const std::string& id) { + return track_map_->GetOrCreateLocalTrackAdapter(CreateBlinkLocalTrack(id)); + } + + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + CreateRemoteTrackAndAdapter(const std::string& id) { + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track = + MockWebRtcAudioTrack::Create(id).get(); + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; + base::RunLoop run_loop; + signaling_task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &RTCRtpTransceiverTest::CreateRemoteTrackAdapterOnSignalingThread, + base::Unretained(this), std::move(webrtc_track), + base::Unretained(&track_ref), base::Unretained(&run_loop))); + run_loop.Run(); + DCHECK(track_ref); + return track_ref; + } + + rtc::scoped_refptr<FakeRtpSender> CreateWebRtcSender( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::string& stream_id) { + return new rtc::RefCountedObject<FakeRtpSender>( + std::move(track), std::vector<std::string>({stream_id})); + } + + rtc::scoped_refptr<FakeRtpReceiver> CreateWebRtcReceiver( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::string& stream_id) { + rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( + new rtc::RefCountedObject<MockMediaStream>(stream_id)); + return new rtc::RefCountedObject<FakeRtpReceiver>( + track.get(), + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>( + {remote_stream})); + } + + rtc::scoped_refptr<FakeRtpTransceiver> CreateWebRtcTransceiver( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction) { + DCHECK(!sender->track() || + sender->track()->kind() == receiver->track()->kind()); + return new rtc::RefCountedObject<FakeRtpTransceiver>( + receiver->track()->kind() == + webrtc::MediaStreamTrackInterface::kAudioKind + ? cricket::MEDIA_TYPE_AUDIO + : cricket::MEDIA_TYPE_VIDEO, + std::move(sender), std::move(receiver), std::move(mid), stopped, + direction, std::move(current_direction)); + } + + RtpTransceiverState CreateTransceiverState( + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + sender_track_ref, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + receiver_track_ref) { + std::vector<std::string> receiver_stream_ids; + for (const auto& stream : webrtc_transceiver->receiver()->streams()) { + receiver_stream_ids.push_back(stream->id()); + } + return RtpTransceiverState( + main_task_runner_, signaling_task_runner(), webrtc_transceiver.get(), + RtpSenderState(main_task_runner_, signaling_task_runner(), + webrtc_transceiver->sender().get(), + std::move(sender_track_ref), + webrtc_transceiver->sender()->stream_ids()), + RtpReceiverState(main_task_runner_, signaling_task_runner(), + webrtc_transceiver->receiver().get(), + std::move(receiver_track_ref), + std::move(receiver_stream_ids)), + ToBaseOptional(webrtc_transceiver->mid()), + webrtc_transceiver->stopped(), webrtc_transceiver->direction(), + ToBaseOptional(webrtc_transceiver->current_direction()), + ToBaseOptional(webrtc_transceiver->fired_direction())); + } + + protected: + blink::WebMediaStreamTrack CreateBlinkLocalTrack(const std::string& id) { + blink::WebMediaStreamSource web_source; + web_source.Initialize( + blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio, + blink::WebString::FromUTF8("local_audio_track"), false); + MediaStreamAudioSource* audio_source = new MediaStreamAudioSource(true); + // Takes ownership of |audio_source|. + web_source.SetExtraData(audio_source); + + blink::WebMediaStreamTrack web_track; + web_track.Initialize(web_source.Id(), web_source); + audio_source->ConnectToTrack(web_track); + return web_track; + } + + void CreateRemoteTrackAdapterOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>* track_ref, + base::RunLoop* run_loop) { + *track_ref = track_map_->GetOrCreateRemoteTrackAdapter(webrtc_track.get()); + run_loop->Quit(); + } + + private: + base::MessageLoop message_loop_; + + protected: + std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_; + rtc::scoped_refptr<MockPeerConnectionImpl> peer_connection_; +}; + +TEST_F(RTCRtpTransceiverTest, InitializeTransceiverState) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"), + CreateWebRtcReceiver(remote_track_adapter->webrtc_track(), + "remote_stream"), + base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv, + base::nullopt); + RtpTransceiverState transceiver_state = + CreateTransceiverState(webrtc_transceiver, std::move(local_track_adapter), + std::move(remote_track_adapter)); + EXPECT_FALSE(transceiver_state.is_initialized()); + transceiver_state.Initialize(); + + EXPECT_TRUE(transceiver_state.is_initialized()); + // Inspect sender states. + const auto& sender_state = transceiver_state.sender_state(); + EXPECT_TRUE(sender_state); + EXPECT_TRUE(sender_state->is_initialized()); + const auto& webrtc_sender = webrtc_transceiver->sender(); + EXPECT_EQ(sender_state->webrtc_sender().get(), webrtc_sender.get()); + EXPECT_TRUE(sender_state->track_ref()->is_initialized()); + EXPECT_EQ(sender_state->track_ref()->webrtc_track(), + webrtc_sender->track().get()); + EXPECT_EQ(sender_state->stream_ids(), webrtc_sender->stream_ids()); + // Inspect receiver states. + const auto& receiver_state = transceiver_state.receiver_state(); + EXPECT_TRUE(receiver_state); + EXPECT_TRUE(receiver_state->is_initialized()); + const auto& webrtc_receiver = webrtc_transceiver->receiver(); + EXPECT_EQ(receiver_state->webrtc_receiver().get(), webrtc_receiver.get()); + EXPECT_TRUE(receiver_state->track_ref()->is_initialized()); + EXPECT_EQ(receiver_state->track_ref()->webrtc_track(), + webrtc_receiver->track().get()); + std::vector<std::string> receiver_stream_ids; + for (const auto& stream : webrtc_receiver->streams()) { + receiver_stream_ids.push_back(stream->id()); + } + EXPECT_EQ(receiver_state->stream_ids(), receiver_stream_ids); + // Inspect transceiver states. + EXPECT_TRUE( + OptionalEquals(transceiver_state.mid(), webrtc_transceiver->mid())); + EXPECT_EQ(transceiver_state.stopped(), webrtc_transceiver->stopped()); + EXPECT_TRUE(transceiver_state.direction() == webrtc_transceiver->direction()); + EXPECT_TRUE(OptionalEquals(transceiver_state.current_direction(), + webrtc_transceiver->current_direction())); + EXPECT_TRUE(OptionalEquals(transceiver_state.fired_direction(), + webrtc_transceiver->fired_direction())); +} + +TEST_F(RTCRtpTransceiverTest, CreateTranceiver) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"), + CreateWebRtcReceiver(remote_track_adapter->webrtc_track(), + "remote_stream"), + base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv, + base::nullopt); + RtpTransceiverState transceiver_state = + CreateTransceiverState(webrtc_transceiver, std::move(local_track_adapter), + std::move(remote_track_adapter)); + EXPECT_FALSE(transceiver_state.is_initialized()); + transceiver_state.Initialize(); + + RTCRtpTransceiver transceiver(peer_connection_.get(), track_map_, + std::move(transceiver_state)); + EXPECT_TRUE(transceiver.Mid().IsNull()); + EXPECT_TRUE(transceiver.Sender()); + EXPECT_TRUE(transceiver.Receiver()); + EXPECT_FALSE(transceiver.Stopped()); + EXPECT_EQ(transceiver.Direction(), + webrtc::RtpTransceiverDirection::kSendRecv); + EXPECT_FALSE(transceiver.CurrentDirection()); + EXPECT_FALSE(transceiver.FiredDirection()); +} + +TEST_F(RTCRtpTransceiverTest, ModifyTransceiver) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track"); + auto webrtc_sender = + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"); + auto webrtc_receiver = CreateWebRtcReceiver( + remote_track_adapter->webrtc_track(), "remote_stream"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + webrtc_sender, webrtc_receiver, base::nullopt, false, + webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + + // Create initial state. + RtpTransceiverState initial_transceiver_state = + CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(), + remote_track_adapter->Copy()); + EXPECT_FALSE(initial_transceiver_state.is_initialized()); + initial_transceiver_state.Initialize(); + + // Modify the webrtc transceiver and create a new state object for the + // modified state. + *webrtc_transceiver = + *CreateWebRtcTransceiver(webrtc_sender, webrtc_receiver, "MidyMacMidface", + true, webrtc::RtpTransceiverDirection::kInactive, + webrtc::RtpTransceiverDirection::kSendRecv); + RtpTransceiverState modified_transceiver_state = + CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(), + remote_track_adapter->Copy()); + EXPECT_FALSE(modified_transceiver_state.is_initialized()); + modified_transceiver_state.Initialize(); + + // Modifying the webrtc transceiver after the initial state was created should + // not have affected the transceiver state. + RTCRtpTransceiver transceiver(peer_connection_.get(), track_map_, + std::move(initial_transceiver_state)); + EXPECT_TRUE(transceiver.Mid().IsNull()); + EXPECT_TRUE(transceiver.Sender()); + EXPECT_TRUE(transceiver.Receiver()); + EXPECT_FALSE(transceiver.Stopped()); + EXPECT_EQ(transceiver.Direction(), + webrtc::RtpTransceiverDirection::kSendRecv); + EXPECT_FALSE(transceiver.CurrentDirection()); + EXPECT_FALSE(transceiver.FiredDirection()); + + // Setting the state should make the transceiver state up-to-date. + transceiver.set_state(std::move(modified_transceiver_state)); + EXPECT_EQ(transceiver.Mid(), "MidyMacMidface"); + EXPECT_TRUE(transceiver.Sender()); + EXPECT_TRUE(transceiver.Receiver()); + EXPECT_TRUE(transceiver.Stopped()); + EXPECT_EQ(transceiver.Direction(), + webrtc::RtpTransceiverDirection::kInactive); + EXPECT_TRUE(transceiver.CurrentDirection() == + webrtc::RtpTransceiverDirection::kSendRecv); + EXPECT_FALSE(transceiver.FiredDirection()); +} + +TEST_F(RTCRtpTransceiverTest, ShallowCopy) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track"); + auto webrtc_sender = + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"); + auto webrtc_receiver = CreateWebRtcReceiver( + remote_track_adapter->webrtc_track(), "remote_stream"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + webrtc_sender, webrtc_receiver, base::nullopt, false /* stopped */, + webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + + std::unique_ptr<RTCRtpTransceiver> transceiver; + // Create transceiver. + { + RtpTransceiverState transceiver_state = + CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(), + remote_track_adapter->Copy()); + EXPECT_FALSE(transceiver_state.is_initialized()); + transceiver_state.Initialize(); + transceiver.reset(new RTCRtpTransceiver(peer_connection_.get(), track_map_, + std::move(transceiver_state))); + } + DCHECK(transceiver); + EXPECT_FALSE(transceiver->Stopped()); + + std::unique_ptr<RTCRtpTransceiver> shallow_copy = transceiver->ShallowCopy(); + // Modifying the shallow copy should modify the original too since they have a + // shared internal state. + { + // Modify webrtc transceiver to be stopped. + *webrtc_transceiver = *CreateWebRtcTransceiver( + webrtc_sender, webrtc_receiver, base::nullopt, true /* stopped */, + webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + RtpTransceiverState transceiver_state = + CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(), + remote_track_adapter->Copy()); + EXPECT_FALSE(transceiver_state.is_initialized()); + transceiver_state.Initialize(); + // Set the state of the shallow copy. + shallow_copy->set_state(std::move(transceiver_state)); + } + EXPECT_TRUE(shallow_copy->Stopped()); + EXPECT_TRUE(transceiver->Stopped()); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_stats.cc b/chromium/content/renderer/media/webrtc/rtc_stats.cc index 0c7478f8646..a24ef5bc613 100644 --- a/chromium/content/renderer/media/webrtc/rtc_stats.cc +++ b/chromium/content/renderer/media/webrtc/rtc_stats.cc @@ -4,6 +4,7 @@ #include "content/renderer/media/webrtc/rtc_stats.h" +#include <algorithm> #include <set> #include <string> @@ -57,6 +58,22 @@ bool IsWhitelistedStats(const webrtc::RTCStats& stats) { return GetStatsWhitelist()->IsWhitelisted(stats); } +// Filters out any unstandardized members; stats should only be surfaced to JS +// if they're standardized. +std::vector<const webrtc::RTCStatsMemberInterface*> StandardizedMembers( + std::vector<const webrtc::RTCStatsMemberInterface*> stats_members) { + // Note that using "is_standarized" avoids having to maintain a whitelist of + // every single standardized member, as we do at the "stats object" level + // with "RTCStatsWhitelist". + stats_members.erase( + std::remove_if(stats_members.begin(), stats_members.end(), + [](const webrtc::RTCStatsMemberInterface* member) { + return !member->is_standardized(); + }), + stats_members.end()); + return stats_members; +} + } // namespace RTCStatsReport::RTCStatsReport( @@ -105,7 +122,7 @@ RTCStats::RTCStats( const webrtc::RTCStats* stats) : stats_owner_(stats_owner), stats_(stats), - stats_members_(stats->Members()) { + stats_members_(StandardizedMembers(stats->Members())) { DCHECK(stats_owner_); DCHECK(stats_); DCHECK(stats_owner_->Get(stats_->id())); diff --git a/chromium/content/renderer/media/webrtc/rtc_stats.h b/chromium/content/renderer/media/webrtc/rtc_stats.h index 937cb25f3f0..370ab41d587 100644 --- a/chromium/content/renderer/media/webrtc/rtc_stats.h +++ b/chromium/content/renderer/media/webrtc/rtc_stats.h @@ -15,6 +15,9 @@ namespace content { +// Wrapper around a webrtc::RTCStatsReport that also filters out any stats +// objects that aren't whitelisted, and any members that aren't standardized +// (using RTCStatsMemberInterface::is_standardized). class CONTENT_EXPORT RTCStatsReport : public blink::WebRTCStatsReport { public: RTCStatsReport( diff --git a/chromium/content/renderer/media/webrtc/rtc_stats_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_stats_unittest.cc index 379f3bc0918..6cf1d5bd49b 100644 --- a/chromium/content/renderer/media/webrtc/rtc_stats_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_stats_unittest.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> + #include "content/renderer/media/webrtc/rtc_stats.h" #include "testing/gtest/include/gtest/gtest.h" @@ -45,4 +47,47 @@ TEST(RTCStatsTest, OnlyIncludeWhitelistedStats_Iteration) { EXPECT_FALSE(report.Next()); } +// Stats object with both a standard and non-standard member, used for the test +// below. +namespace { +class TestStats : public webrtc::RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + TestStats(const std::string& id, int64_t timestamp_us); + ~TestStats() override = default; + + webrtc::RTCStatsMember<int32_t> standardized; + webrtc::RTCNonStandardStatsMember<int32_t> non_standardized; +}; + +WEBRTC_RTCSTATS_IMPL(TestStats, + webrtc::RTCStats, + "teststats", + &standardized, + &non_standardized); + +TestStats::TestStats(const std::string& id, int64_t timestamp_us) + : RTCStats(id, timestamp_us), + standardized("standardized"), + non_standardized("non_standardized") {} +} // namespace + +// Similar to how only whitelisted stats objects should be surfaced, only +// standardized members of the whitelisted objects should be surfaced. +TEST(RTCStatsTest, OnlyIncludeStandarizedMembers) { + rtc::scoped_refptr<webrtc::RTCStatsReport> webrtc_report = + webrtc::RTCStatsReport::Create(42); + WhitelistStatsForTesting(TestStats::kType); + webrtc_report->AddStats(std::make_unique<TestStats>("id", 0)); + + // TestStats has two members, but the non-standard member should be filtered + // out. + RTCStatsReport report(webrtc_report.get()); + std::unique_ptr<blink::WebRTCStats> stats = report.Next(); + ASSERT_NE(nullptr, stats); + ASSERT_EQ(1u, stats->MembersCount()); + EXPECT_EQ("standardized", stats->GetMember(0)->GetName()); +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc index 050c9f61d84..864cb65f90c 100644 --- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc @@ -70,6 +70,8 @@ class RTCVideoDecoderTest capabilities_.supported_profiles.push_back(supported_profile); supported_profile.profile = media::VP8PROFILE_ANY; capabilities_.supported_profiles.push_back(supported_profile); + supported_profile.profile = media::VP9PROFILE_MIN; + capabilities_.supported_profiles.push_back(supported_profile); EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner()) .WillRepeatedly(Return(vda_task_runner_)); @@ -231,6 +233,24 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) { rtc_decoder_->Decode(input_image, missingFrames, nullptr, 0)); } +TEST_F(RTCVideoDecoderTest, FallBackToSoftwareOnVp9Svc) { + // HW VP9 decoders don't handle more than one spatial layer. See + // https://crbug.com/webrtc/9304, https://crbug.com/webrtc/9518 for details. + // The RTC video decoder triggers software fallback if it receives stream + // with more than one spatial layer. + CreateDecoder(webrtc::kVideoCodecVP9); + Initialize(); + + webrtc::CodecSpecificInfo codec_specific_info; + codec_specific_info.codecType = webrtc::kVideoCodecVP9; + codec_specific_info.codecSpecific.VP9.ss_data_available = true; + codec_specific_info.codecSpecific.VP9.num_spatial_layers = 2; + + webrtc::EncodedImage input_image; + EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE, + rtc_decoder_->Decode(input_image, false, &codec_specific_info, 0)); +} + TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { CreateDecoder(webrtc::kVideoCodecVP8); Initialize(); diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc index bfa722c5fc2..69f49db28bc 100644 --- a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc +++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc @@ -17,7 +17,6 @@ #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" -#include "base/rand_util.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" @@ -115,7 +114,8 @@ class RTCVideoEncoder::Impl public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> { public: Impl(media::GpuVideoAcceleratorFactories* gpu_factories, - webrtc::VideoCodecType video_codec_type); + webrtc::VideoCodecType video_codec_type, + webrtc::VideoContentType video_content_type); // Create the VEA and call Initialize() on it. Called once per instantiation, // and then the instance is bound forevermore to whichever thread made the @@ -163,10 +163,9 @@ class RTCVideoEncoder::Impl void RequireBitstreamBuffers(unsigned int input_count, const gfx::Size& input_coded_size, size_t output_buffer_size) override; - void BitstreamBufferReady(int32_t bitstream_buffer_id, - size_t payload_size, - bool key_frame, - base::TimeDelta timestamp) override; + void BitstreamBufferReady( + int32_t bitstream_buffer_id, + const media::BitstreamBufferMetadata& metadata) override; void NotifyError(media::VideoEncodeAccelerator::Error error) override; private: @@ -206,8 +205,7 @@ class RTCVideoEncoder::Impl // Return an encoded output buffer to WebRTC. void ReturnEncodedImage(const webrtc::EncodedImage& image, - int32_t bitstream_buffer_id, - uint16_t picture_id); + int32_t bitstream_buffer_id); void SetStatus(int32_t status); @@ -262,15 +260,15 @@ class RTCVideoEncoder::Impl // encoder. int output_buffers_free_count_; - // 15 bits running index of the VP8 frames. See VP8 RTP spec for details. - uint16_t picture_id_; - // webrtc::VideoEncoder encode complete callback. webrtc::EncodedImageCallback* encoded_image_callback_; // The video codec type, as reported to WebRTC. const webrtc::VideoCodecType video_codec_type_; + // The content type, as reported to WebRTC (screenshare vs realtime video). + const webrtc::VideoContentType video_content_type_; + // Protect |status_|. |status_| is read or written on |gpu_task_runner_| in // Impl. It can be read in RTCVideoEncoder on other threads. mutable base::Lock status_lock_; @@ -285,7 +283,8 @@ class RTCVideoEncoder::Impl }; RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories, - webrtc::VideoCodecType video_codec_type) + webrtc::VideoCodecType video_codec_type, + webrtc::VideoContentType video_content_type) : gpu_factories_(gpu_factories), async_waiter_(nullptr), async_retval_(nullptr), @@ -295,10 +294,9 @@ RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories, output_buffers_free_count_(0), encoded_image_callback_(nullptr), video_codec_type_(video_codec_type), + video_content_type_(video_content_type), status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) { thread_checker_.DetachFromThread(); - // Picture ID should start on a random number. - picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF)); } void RTCVideoEncoder::Impl::CreateAndInitializeVEA( @@ -505,13 +503,13 @@ void RTCVideoEncoder::Impl::RequireBitstreamBuffers( SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); } -void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, - size_t payload_size, - bool key_frame, - base::TimeDelta timestamp) { +void RTCVideoEncoder::Impl::BitstreamBufferReady( + int32_t bitstream_buffer_id, + const media::BitstreamBufferMetadata& metadata) { DVLOG(3) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id - << ", payload_size=" << payload_size << ", key_frame=" << key_frame - << ", timestamp ms=" << timestamp.InMilliseconds(); + << ", payload_size=" << metadata.payload_size_bytes + << ", key_frame=" << metadata.key_frame + << ", timestamp ms=" << metadata.timestamp.InMilliseconds(); DCHECK(thread_checker_.CalledOnValidThread()); if (bitstream_buffer_id < 0 || @@ -522,7 +520,7 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, } base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id].get(); - if (payload_size > output_buffer->mapped_size()) { + if (metadata.payload_size_bytes > output_buffer->mapped_size()) { LogAndNotifyError(FROM_HERE, "invalid payload_size", media::VideoEncodeAccelerator::kPlatformFailureError); return; @@ -537,7 +535,7 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, // Pop timestamps until we have a match. while (!pending_timestamps_.empty()) { const auto& front_timestamps = pending_timestamps_.front(); - if (front_timestamps.media_timestamp_ == timestamp) { + if (front_timestamps.media_timestamp_ == metadata.timestamp) { rtp_timestamp = front_timestamps.rtp_timestamp; capture_timestamp_ms = front_timestamps.capture_time_ms; pending_timestamps_.pop_front(); @@ -558,19 +556,18 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, } webrtc::EncodedImage image( - reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size, - output_buffer->mapped_size()); + reinterpret_cast<uint8_t*>(output_buffer->memory()), + metadata.payload_size_bytes, output_buffer->mapped_size()); image._encodedWidth = input_visible_size_.width(); image._encodedHeight = input_visible_size_.height(); image._timeStamp = rtp_timestamp.value(); image.capture_time_ms_ = capture_timestamp_ms.value(); image._frameType = - (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); + (metadata.key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); + image.content_type_ = video_content_type_; image._completeFrame = true; - ReturnEncodedImage(image, bitstream_buffer_id, picture_id_); - // Picture ID must wrap after reaching the maximum. - picture_id_ = (picture_id_ + 1) & 0x7FFF; + ReturnEncodedImage(image, bitstream_buffer_id); } void RTCVideoEncoder::Impl::NotifyError( @@ -759,11 +756,9 @@ void RTCVideoEncoder::Impl::RegisterEncodeCompleteCallback( void RTCVideoEncoder::Impl::ReturnEncodedImage( const webrtc::EncodedImage& image, - int32_t bitstream_buffer_id, - uint16_t picture_id) { + int32_t bitstream_buffer_id) { DCHECK(thread_checker_.CalledOnValidThread()); - DVLOG(3) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id - << ", picture_id=" << picture_id; + DVLOG(3) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id; if (!encoded_image_callback_) return; @@ -798,8 +793,6 @@ void RTCVideoEncoder::Impl::ReturnEncodedImage( info.codecType = video_codec_type_; info.codec_name = ImplementationName(); if (video_codec_type_ == webrtc::kVideoCodecVP8) { - info.codecSpecific.VP8.pictureId = picture_id; - info.codecSpecific.VP8.tl0PicIdx = -1; info.codecSpecific.VP8.keyIdx = -1; } @@ -840,7 +833,7 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings, Release(); if (codec_settings->codecType == webrtc::kVideoCodecVP8 && - codec_settings->mode == webrtc::kScreensharing && + codec_settings->mode == webrtc::VideoCodecMode::kScreensharing && codec_settings->VP8().numberOfTemporalLayers > 1) { // This is a VP8 stream with screensharing using temporal layers for // temporal scalability. Since this implementation does not yet implement @@ -854,7 +847,11 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings, } } - impl_ = new Impl(gpu_factories_, ProfileToWebRtcVideoCodecType(profile_)); + impl_ = + new Impl(gpu_factories_, ProfileToWebRtcVideoCodecType(profile_), + (codec_settings->mode == webrtc::VideoCodecMode::kScreensharing) + ? webrtc::VideoContentType::SCREENSHARE + : webrtc::VideoContentType::UNSPECIFIED); base::WaitableEvent initialization_waiter( base::WaitableEvent::ResetPolicy::MANUAL, diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder_factory.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder_factory.cc index 3307c40e0b8..7b89e610a23 100644 --- a/chromium/content/renderer/media/webrtc/rtc_video_encoder_factory.cc +++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder_factory.cc @@ -73,7 +73,7 @@ base::Optional<cricket::VideoCodec> VEAToWebRTCCodec( const int fps = profile.max_framerate_numerator; DCHECK_EQ(1u, profile.max_framerate_denominator); - const rtc::Optional<webrtc::H264::Level> h264_level = + const absl::optional<webrtc::H264::Level> h264_level = webrtc::H264::SupportedLevel(width * height, fps); const webrtc::H264::ProfileLevelId profile_level_id( h264_profile, h264_level.value_or(webrtc::H264::kLevel1)); diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc index d3defba9124..2d142d5aa82 100644 --- a/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc @@ -180,7 +180,9 @@ class RTCVideoEncoderTest void ReturnFrameWithTimeStamp(const scoped_refptr<media::VideoFrame>& frame, bool force_keyframe) { - client_->BitstreamBufferReady(0, 0, force_keyframe, frame->timestamp()); + client_->BitstreamBufferReady( + 0, + media::BitstreamBufferMetadata(0, force_keyframe, frame->timestamp())); } void VerifyTimestamp(uint32_t rtp_timestamp, diff --git a/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.cc b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.cc new file mode 100644 index 00000000000..4792cefac27 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.cc @@ -0,0 +1,225 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/webrtc/transceiver_state_surfacer.h" + +#include "content/renderer/media/webrtc/webrtc_util.h" +#include "third_party/webrtc/api/rtptransceiverinterface.h" + +namespace content { + +TransceiverStateSurfacer::TransceiverStateSurfacer( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + is_initialized_(false), + states_obtained_(false) { + DCHECK(main_task_runner_); + DCHECK(signaling_task_runner_); +} + +TransceiverStateSurfacer::TransceiverStateSurfacer( + TransceiverStateSurfacer&& other) + : main_task_runner_(other.main_task_runner_), + signaling_task_runner_(other.signaling_task_runner_), + is_initialized_(other.is_initialized_), + states_obtained_(other.states_obtained_), + transceiver_states_(std::move(other.transceiver_states_)) { + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; +} + +TransceiverStateSurfacer::~TransceiverStateSurfacer() { + // It's OK to not be on the main thread if this object has been moved, in + // which case |main_task_runner_| is null. + DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread()); +} + +TransceiverStateSurfacer& TransceiverStateSurfacer::operator=( + TransceiverStateSurfacer&& other) { + main_task_runner_ = other.main_task_runner_; + signaling_task_runner_ = other.signaling_task_runner_; + states_obtained_ = other.states_obtained_; + transceiver_states_ = std::move(other.transceiver_states_); + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; + return *this; +} + +void TransceiverStateSurfacer::Initialize( + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + webrtc_transceivers) { + DCHECK(signaling_task_runner_->BelongsToCurrentThread()); + DCHECK(!is_initialized_); + for (auto& webrtc_transceiver : webrtc_transceivers) { + // Create the sender state. + base::Optional<RtpSenderState> sender_state; + auto webrtc_sender = webrtc_transceiver->sender(); + if (webrtc_sender) { + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + sender_track_ref; + if (webrtc_sender->track()) { + // The track adapter for this track must already exist for us to obtain + // it, since this cannot be created from the signaling thread. + // TODO(hbos): Consider either making it possible to create local track + // adapters on the signaling thread for initialization on the main + // thread or wait for Onion Souping to simplify this. + // https://crbug.com/787254 + sender_track_ref = + track_adapter_map->GetLocalTrackAdapter(webrtc_sender->track()); + CHECK(sender_track_ref); + } + sender_state = RtpSenderState( + main_task_runner_, signaling_task_runner_, webrtc_sender.get(), + std::move(sender_track_ref), webrtc_sender->stream_ids()); + } + // Create the receiver state. + base::Optional<RtpReceiverState> receiver_state; + auto webrtc_receiver = webrtc_transceiver->receiver(); + if (webrtc_receiver) { + DCHECK(webrtc_receiver->track()); + auto receiver_track_ref = + track_adapter_map->GetOrCreateRemoteTrackAdapter( + webrtc_receiver->track().get()); + DCHECK(receiver_track_ref); + std::vector<std::string> receiver_stream_ids; + for (auto& stream : webrtc_receiver->streams()) { + receiver_stream_ids.push_back(stream->id()); + } + receiver_state = RtpReceiverState( + main_task_runner_, signaling_task_runner_, webrtc_receiver.get(), + std::move(receiver_track_ref), std::move(receiver_stream_ids)); + } + // Create the transceiver state. + transceiver_states_.push_back(RtpTransceiverState( + main_task_runner_, signaling_task_runner_, webrtc_transceiver.get(), + std::move(sender_state), std::move(receiver_state), + ToBaseOptional(webrtc_transceiver->mid()), + webrtc_transceiver->stopped(), webrtc_transceiver->direction(), + ToBaseOptional(webrtc_transceiver->current_direction()), + ToBaseOptional(webrtc_transceiver->fired_direction()))); + } + is_initialized_ = true; +} + +std::vector<RtpTransceiverState> TransceiverStateSurfacer::ObtainStates() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(is_initialized_); + for (auto& transceiver_state : transceiver_states_) + transceiver_state.Initialize(); + states_obtained_ = true; + return std::move(transceiver_states_); +} + +SurfaceSenderStateOnly::SurfaceSenderStateOnly( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender) + : sender_(std::move(sender)) { + DCHECK(sender_); +} + +SurfaceSenderStateOnly::~SurfaceSenderStateOnly() {} + +cricket::MediaType SurfaceSenderStateOnly::media_type() const { + return sender_->media_type(); +} + +absl::optional<std::string> SurfaceSenderStateOnly::mid() const { + return absl::nullopt; +} + +rtc::scoped_refptr<webrtc::RtpSenderInterface> SurfaceSenderStateOnly::sender() + const { + return sender_; +} + +rtc::scoped_refptr<webrtc::RtpReceiverInterface> +SurfaceSenderStateOnly::receiver() const { + return nullptr; +} + +bool SurfaceSenderStateOnly::stopped() const { + return false; +} + +webrtc::RtpTransceiverDirection SurfaceSenderStateOnly::direction() const { + return webrtc::RtpTransceiverDirection::kSendOnly; +} + +void SurfaceSenderStateOnly::SetDirection( + webrtc::RtpTransceiverDirection new_direction) { + NOTIMPLEMENTED(); +} + +absl::optional<webrtc::RtpTransceiverDirection> +SurfaceSenderStateOnly::current_direction() const { + return absl::nullopt; +} + +void SurfaceSenderStateOnly::Stop() { + NOTIMPLEMENTED(); +} + +void SurfaceSenderStateOnly::SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) { + NOTIMPLEMENTED(); +} + +SurfaceReceiverStateOnly::SurfaceReceiverStateOnly( + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) + : receiver_(std::move(receiver)) { + DCHECK(receiver_); +} + +SurfaceReceiverStateOnly::~SurfaceReceiverStateOnly() {} + +cricket::MediaType SurfaceReceiverStateOnly::media_type() const { + return receiver_->media_type(); +} + +absl::optional<std::string> SurfaceReceiverStateOnly::mid() const { + return absl::nullopt; +} + +rtc::scoped_refptr<webrtc::RtpSenderInterface> +SurfaceReceiverStateOnly::sender() const { + return nullptr; +} + +rtc::scoped_refptr<webrtc::RtpReceiverInterface> +SurfaceReceiverStateOnly::receiver() const { + return receiver_; +} + +bool SurfaceReceiverStateOnly::stopped() const { + return false; +} + +webrtc::RtpTransceiverDirection SurfaceReceiverStateOnly::direction() const { + return webrtc::RtpTransceiverDirection::kRecvOnly; +} + +void SurfaceReceiverStateOnly::SetDirection( + webrtc::RtpTransceiverDirection new_direction) { + NOTIMPLEMENTED(); +} + +absl::optional<webrtc::RtpTransceiverDirection> +SurfaceReceiverStateOnly::current_direction() const { + return absl::nullopt; +} + +void SurfaceReceiverStateOnly::Stop() { + NOTIMPLEMENTED(); +} + +void SurfaceReceiverStateOnly::SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) { + NOTIMPLEMENTED(); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.h b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.h new file mode 100644 index 00000000000..ab7cdfeb695 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.h @@ -0,0 +1,112 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_TRANSCEIVER_STATE_SURFACER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_TRANSCEIVER_STATE_SURFACER_H_ + +#include "content/renderer/media/webrtc/rtc_rtp_transceiver.h" +#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" +#include "third_party/webrtc/api/rtptransceiverinterface.h" +#include "third_party/webrtc/rtc_base/refcount.h" +#include "third_party/webrtc/rtc_base/refcountedobject.h" + +namespace content { + +// Takes care of creating and initializing transceiver states (including sender +// and receiver states). This is usable for both blocking and non-blocking calls +// to the webrtc signaling thread. +// +// The surfacer is initialized on the signaling thread and states are obtained +// on the main thread. It is designed to be initialized and handed off; it is +// not thread safe for concurrent thread usage. +class CONTENT_EXPORT TransceiverStateSurfacer { + public: + TransceiverStateSurfacer( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner); + TransceiverStateSurfacer(TransceiverStateSurfacer&&); + TransceiverStateSurfacer(const TransceiverStateSurfacer&) = delete; + ~TransceiverStateSurfacer(); + + // This is intended to be used for moving the object from the signaling thread + // to the main thread and as such has no thread checks. Once moved to the main + // this should only be invoked on the main thread. + TransceiverStateSurfacer& operator=(TransceiverStateSurfacer&&); + TransceiverStateSurfacer& operator=(const TransceiverStateSurfacer&) = delete; + + bool is_initialized() const { return is_initialized_; } + + // Must be invoked on the signaling thread. + void Initialize( + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers); + + // Must be invoked on the main thread. + std::vector<RtpTransceiverState> ObtainStates(); + + protected: + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + bool is_initialized_; + bool states_obtained_; + std::vector<RtpTransceiverState> transceiver_states_; +}; + +// A dummy implementation of a transceiver used to surface sender state +// information only. It is not thread safe, only designed to be passed on to +// TransceiverStateSurfacer::Initialize(). +class CONTENT_EXPORT SurfaceSenderStateOnly + : public rtc::RefCountedObject<webrtc::RtpTransceiverInterface> { + public: + SurfaceSenderStateOnly(rtc::scoped_refptr<webrtc::RtpSenderInterface> sender); + ~SurfaceSenderStateOnly() override; + + cricket::MediaType media_type() const override; + absl::optional<std::string> mid() const override; + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override; + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override; + bool stopped() const override; + webrtc::RtpTransceiverDirection direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection new_direction) override; + absl::optional<webrtc::RtpTransceiverDirection> current_direction() + const override; + void Stop() override; + void SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) override; + + private: + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender_; +}; + +// A dummy implementation of a transceiver used to surface receiver state +// information only. It is not thread safe, only designed to be passed on to +// TransceiverStateSurfacer::Initialize(). +class CONTENT_EXPORT SurfaceReceiverStateOnly + : public rtc::RefCountedObject<webrtc::RtpTransceiverInterface> { + public: + SurfaceReceiverStateOnly( + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver); + ~SurfaceReceiverStateOnly() override; + + cricket::MediaType media_type() const override; + absl::optional<std::string> mid() const override; + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override; + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override; + bool stopped() const override; + webrtc::RtpTransceiverDirection direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection new_direction) override; + absl::optional<webrtc::RtpTransceiverDirection> current_direction() + const override; + void Stop() override; + void SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) override; + + private: + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_TRANSCEIVER_STATE_SURFACER_H_ diff --git a/chromium/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc new file mode 100644 index 00000000000..7f469865324 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc @@ -0,0 +1,294 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/webrtc/transceiver_state_surfacer.h" + +#include <memory> +#include <tuple> + +#include "base/memory/ref_counted.h" +#include "base/run_loop.h" +#include "base/single_thread_task_runner.h" +#include "base/synchronization/waitable_event.h" +#include "base/test/scoped_task_environment.h" +#include "content/child/child_process.h" +#include "content/renderer/media/stream/media_stream_audio_source.h" +#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" +#include "content/renderer/media/webrtc/mock_peer_connection_impl.h" +#include "content/renderer/media/webrtc/webrtc_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" +#include "third_party/blink/public/platform/web_media_stream_source.h" +#include "third_party/blink/public/platform/web_media_stream_track.h" +#include "third_party/blink/public/platform/web_string.h" +#include "third_party/blink/public/web/web_heap.h" + +namespace content { + +class TransceiverStateSurfacerTest : public ::testing::Test { + public: + void SetUp() override { + dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); + main_task_runner_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); + track_adapter_map_ = new WebRtcMediaStreamTrackAdapterMap( + dependency_factory_.get(), main_task_runner_); + surfacer_.reset(new TransceiverStateSurfacer(main_task_runner_, + signaling_task_runner())); + } + + void TearDown() override { + // Make sure posted tasks get a chance to execute or else the stuff is + // teared down while things are in flight. + base::RunLoop().RunUntilIdle(); + blink::WebHeap::CollectAllGarbageForTesting(); + } + + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const { + return dependency_factory_->GetWebRtcSignalingThread(); + } + + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + CreateLocalTrackAndAdapter(const std::string& id) { + return track_adapter_map_->GetOrCreateLocalTrackAdapter( + CreateBlinkLocalTrack(id)); + } + + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> CreateWebRtcTransceiver( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> local_track, + const std::string& local_stream_id, + const std::string& remote_track_id, + const std::string& remote_stream_id) { + return new rtc::RefCountedObject<FakeRtpTransceiver>( + local_track->kind() == webrtc::MediaStreamTrackInterface::kAudioKind + ? cricket::MEDIA_TYPE_AUDIO + : cricket::MEDIA_TYPE_VIDEO, + CreateWebRtcSender(local_track, local_stream_id), + CreateWebRtcReceiver(remote_track_id, remote_stream_id), base::nullopt, + false, webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + } + + rtc::scoped_refptr<webrtc::RtpSenderInterface> CreateWebRtcSender( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::string& stream_id) { + return new rtc::RefCountedObject<FakeRtpSender>( + std::move(track), std::vector<std::string>({stream_id})); + } + + rtc::scoped_refptr<webrtc::RtpReceiverInterface> CreateWebRtcReceiver( + const std::string& track_id, + const std::string& stream_id) { + rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_track = + MockWebRtcAudioTrack::Create(track_id).get(); + rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( + new rtc::RefCountedObject<MockMediaStream>(stream_id)); + return new rtc::RefCountedObject<FakeRtpReceiver>( + remote_track.get(), + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>( + {remote_stream})); + } + + // Initializes the surfacer on the signaling thread and signals the waitable + // event when done. The WaitableEvent's Wait() blocks the main thread until + // initialization occurs. + std::unique_ptr<base::WaitableEvent> AsyncInitializeSurfacerWithWaitableEvent( + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers) { + std::unique_ptr<base::WaitableEvent> waitable_event(new base::WaitableEvent( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED)); + signaling_task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &TransceiverStateSurfacerTest:: + AsyncInitializeSurfacerWithWaitableEventOnSignalingThread, + base::Unretained(this), std::move(transceivers), + waitable_event.get())); + return waitable_event; + } + + // Initializes the surfacer on the signaling thread and posts back to the main + // thread to execute the callback when done. The RunLoop quits after the + // callback is executed. Use the RunLoop's Run() method to allow the posted + // task (such as the callback) to be executed while waiting. The caller must + // let the loop Run() before destroying it. + std::unique_ptr<base::RunLoop> AsyncInitializeSurfacerWithCallback( + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers, + base::OnceCallback<void()> callback) { + std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop()); + signaling_task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&TransceiverStateSurfacerTest:: + AsyncInitializeSurfacerWithCallbackOnSignalingThread, + base::Unretained(this), std::move(transceivers), + std::move(callback), run_loop.get())); + return run_loop; + } + + void ObtainStatesAndExpectInitialized( + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver) { + auto transceiver_states = surfacer_->ObtainStates(); + EXPECT_EQ(1u, transceiver_states.size()); + auto& transceiver_state = transceiver_states[0]; + EXPECT_EQ(transceiver_state.webrtc_transceiver().get(), + webrtc_transceiver.get()); + // Inspect sender states. + const auto& sender_state = transceiver_state.sender_state(); + EXPECT_TRUE(sender_state); + EXPECT_TRUE(sender_state->is_initialized()); + const auto& webrtc_sender = webrtc_transceiver->sender(); + EXPECT_EQ(sender_state->webrtc_sender().get(), webrtc_sender.get()); + EXPECT_TRUE(sender_state->track_ref()->is_initialized()); + EXPECT_EQ(sender_state->track_ref()->webrtc_track(), + webrtc_sender->track().get()); + EXPECT_EQ(sender_state->stream_ids(), webrtc_sender->stream_ids()); + // Inspect receiver states. + const auto& receiver_state = transceiver_state.receiver_state(); + EXPECT_TRUE(receiver_state); + EXPECT_TRUE(receiver_state->is_initialized()); + const auto& webrtc_receiver = webrtc_transceiver->receiver(); + EXPECT_EQ(receiver_state->webrtc_receiver().get(), webrtc_receiver.get()); + EXPECT_TRUE(receiver_state->track_ref()->is_initialized()); + EXPECT_EQ(receiver_state->track_ref()->webrtc_track(), + webrtc_receiver->track().get()); + std::vector<std::string> receiver_stream_ids; + for (const auto& stream : webrtc_receiver->streams()) { + receiver_stream_ids.push_back(stream->id()); + } + EXPECT_EQ(receiver_state->stream_ids(), receiver_stream_ids); + // Inspect transceiver states. + EXPECT_TRUE( + OptionalEquals(transceiver_state.mid(), webrtc_transceiver->mid())); + EXPECT_EQ(transceiver_state.stopped(), webrtc_transceiver->stopped()); + EXPECT_TRUE(transceiver_state.direction() == + webrtc_transceiver->direction()); + EXPECT_TRUE(OptionalEquals(transceiver_state.current_direction(), + webrtc_transceiver->current_direction())); + } + + private: + blink::WebMediaStreamTrack CreateBlinkLocalTrack(const std::string& id) { + blink::WebMediaStreamSource web_source; + web_source.Initialize( + blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio, + blink::WebString::FromUTF8("local_audio_track"), false); + MediaStreamAudioSource* audio_source = new MediaStreamAudioSource(true); + // Takes ownership of |audio_source|. + web_source.SetExtraData(audio_source); + + blink::WebMediaStreamTrack web_track; + web_track.Initialize(web_source.Id(), web_source); + audio_source->ConnectToTrack(web_track); + return web_track; + } + + void AsyncInitializeSurfacerWithWaitableEventOnSignalingThread( + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers, + base::WaitableEvent* waitable_event) { + DCHECK(signaling_task_runner()->BelongsToCurrentThread()); + surfacer_->Initialize(track_adapter_map_, std::move(transceivers)); + waitable_event->Signal(); + } + + void AsyncInitializeSurfacerWithCallbackOnSignalingThread( + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers, + base::OnceCallback<void()> callback, + base::RunLoop* run_loop) { + DCHECK(signaling_task_runner()->BelongsToCurrentThread()); + surfacer_->Initialize(track_adapter_map_, std::move(transceivers)); + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&TransceiverStateSurfacerTest:: + AsyncInitializeSurfacerWithCallbackOnMainThread, + base::Unretained(this), std::move(callback), run_loop)); + } + + void AsyncInitializeSurfacerWithCallbackOnMainThread( + base::OnceCallback<void()> callback, + base::RunLoop* run_loop) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(surfacer_->is_initialized()); + std::move(callback).Run(); + run_loop->Quit(); + } + + base::test::ScopedTaskEnvironment scoped_task_environment_; + + protected: + std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; + std::unique_ptr<TransceiverStateSurfacer> surfacer_; +}; + +TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverBlockingly) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_transceiver = + CreateWebRtcTransceiver(local_track_adapter->webrtc_track(), + "local_stream", "remote_track", "remote_stream"); + auto waitable_event = + AsyncInitializeSurfacerWithWaitableEvent({webrtc_transceiver}); + waitable_event->Wait(); + ObtainStatesAndExpectInitialized(webrtc_transceiver); +} + +TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverInCallback) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_transceiver = + CreateWebRtcTransceiver(local_track_adapter->webrtc_track(), + "local_stream", "remote_track", "remote_stream"); + auto run_loop = AsyncInitializeSurfacerWithCallback( + {webrtc_transceiver}, + base::BindOnce( + &TransceiverStateSurfacerTest::ObtainStatesAndExpectInitialized, + base::Unretained(this), webrtc_transceiver)); + run_loop->Run(); +} + +TEST_F(TransceiverStateSurfacerTest, SurfaceSenderStateOnly) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_sender = + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"); + auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent( + {new SurfaceSenderStateOnly(webrtc_sender)}); + waitable_event->Wait(); + auto transceiver_states = surfacer_->ObtainStates(); + EXPECT_EQ(1u, transceiver_states.size()); + auto& transceiver_state = transceiver_states[0]; + EXPECT_TRUE(transceiver_state.sender_state()); + EXPECT_TRUE(transceiver_state.sender_state()->is_initialized()); + EXPECT_FALSE(transceiver_state.receiver_state()); + // Expect transceiver members be be missing for optional members and have + // sensible values for non-optional members. + EXPECT_FALSE(transceiver_state.mid()); + EXPECT_FALSE(transceiver_state.stopped()); + EXPECT_EQ(transceiver_state.direction(), + webrtc::RtpTransceiverDirection::kSendOnly); + EXPECT_FALSE(transceiver_state.current_direction()); +} + +TEST_F(TransceiverStateSurfacerTest, SurfaceReceiverStateOnly) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_receiver = CreateWebRtcReceiver("remote_track", "remote_stream"); + auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent( + {new SurfaceReceiverStateOnly(webrtc_receiver)}); + waitable_event->Wait(); + auto transceiver_states = surfacer_->ObtainStates(); + EXPECT_EQ(1u, transceiver_states.size()); + auto& transceiver_state = transceiver_states[0]; + EXPECT_FALSE(transceiver_state.sender_state()); + EXPECT_TRUE(transceiver_state.receiver_state()); + EXPECT_TRUE(transceiver_state.receiver_state()->is_initialized()); + // Expect transceiver members be be missing for optional members and have + // sensible values for non-optional members. + EXPECT_FALSE(transceiver_state.mid()); + EXPECT_FALSE(transceiver_state.stopped()); + EXPECT_EQ(transceiver_state.direction(), + webrtc::RtpTransceiverDirection::kRecvOnly); + EXPECT_FALSE(transceiver_state.current_direction()); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc index b18f49d21f8..c1ea561596d 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc @@ -11,10 +11,11 @@ #include "base/location.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/stream/media_stream_audio_track.h" #include "content/renderer/media/webrtc/peer_connection_remote_audio_source.h" #include "content/renderer/media/webrtc_logging.h" @@ -93,8 +94,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer { void Play() override { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(started_); - if (playing_state_.playing()) + if (!started_ || playing_state_.playing()) return; playing_state_.set_playing(true); on_play_state_changed_.Run(media_stream_, &playing_state_); @@ -102,8 +102,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer { void Pause() override { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(started_); - if (!playing_state_.playing()) + if (!started_ || !playing_state_.playing()) return; playing_state_.set_playing(false); on_play_state_changed_.Run(media_stream_, &playing_state_); @@ -549,7 +548,7 @@ bool WebRtcAudioRenderer::AddPlayingState( DCHECK(state->playing()); // Look up or add the |source| to the map. PlayingStates& array = source_playing_states_[source]; - if (std::find(array.begin(), array.end(), state) != array.end()) + if (base::ContainsValue(array, state)) return false; array.push_back(state); @@ -584,8 +583,8 @@ void WebRtcAudioRenderer::OnPlayStateChanged( const blink::WebMediaStream& media_stream, PlayingState* state) { DCHECK(thread_checker_.CalledOnValidThread()); - blink::WebVector<blink::WebMediaStreamTrack> web_tracks; - media_stream.AudioTracks(web_tracks); + blink::WebVector<blink::WebMediaStreamTrack> web_tracks = + media_stream.AudioTracks(); for (const blink::WebMediaStreamTrack& web_track : web_tracks) { // WebRtcAudioRenderer can only render audio tracks received from a remote diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc index 7e886d27945..e3e2cce259b 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc @@ -13,7 +13,7 @@ #include "base/run_loop.h" #include "build/build_config.h" #include "content/public/renderer/media_stream_audio_renderer.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/webrtc/webrtc_audio_device_impl.h" #include "media/base/audio_capturer_source.h" #include "media/base/mock_audio_renderer_sink.h" diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc index ba37c80ba94..b5a59a0e32e 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc @@ -27,26 +27,26 @@ WebRtcAudioSink::WebRtcAudioSink( } WebRtcAudioSink::~WebRtcAudioSink() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DVLOG(1) << "WebRtcAudioSink::~WebRtcAudioSink()"; } void WebRtcAudioSink::SetAudioProcessor( scoped_refptr<MediaStreamAudioProcessor> processor) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(processor.get()); adapter_->set_processor(std::move(processor)); } void WebRtcAudioSink::SetLevel( scoped_refptr<MediaStreamAudioLevelCalculator::Level> level) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(level.get()); adapter_->set_level(std::move(level)); } void WebRtcAudioSink::OnEnabledChanged(bool enabled) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); adapter_->signaling_task_runner()->PostTask( FROM_HERE, base::BindOnce(base::IgnoreResult(&WebRtcAudioSink::Adapter::set_enabled), @@ -55,17 +55,14 @@ void WebRtcAudioSink::OnEnabledChanged(bool enabled) { void WebRtcAudioSink::OnData(const media::AudioBus& audio_bus, base::TimeTicks estimated_capture_time) { - DCHECK(audio_thread_checker_.CalledOnValidThread()); + // No thread check: OnData might be called on different threads (but not + // concurrently). // The following will result in zero, one, or multiple synchronous calls to // DeliverRebufferedAudio(). fifo_.Push(audio_bus); } void WebRtcAudioSink::OnSetFormat(const media::AudioParameters& params) { - // On a format change, the thread delivering audio might have also changed. - audio_thread_checker_.DetachFromThread(); - DCHECK(audio_thread_checker_.CalledOnValidThread()); - DCHECK(params.IsValid()); params_ = params; // Make sure that our params always reflect a buffer size of 10ms. @@ -78,7 +75,6 @@ void WebRtcAudioSink::OnSetFormat(const media::AudioParameters& params) { void WebRtcAudioSink::DeliverRebufferedAudio(const media::AudioBus& audio_bus, int frame_delay) { - DCHECK(audio_thread_checker_.CalledOnValidThread()); DCHECK(params_.IsValid()); // TODO(miu): Why doesn't a WebRTC sink care about reference time passed to diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h index d330bcd1d2f..fee1d51f999 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h +++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h @@ -8,6 +8,8 @@ #include <stdint.h> #include <memory> +#include <string> +#include <utility> #include <vector> #include "base/macros.h" @@ -166,11 +168,7 @@ class CONTENT_EXPORT WebRtcAudioSink : public MediaStreamAudioSink { // In debug builds, check that WebRtcAudioSink's public methods are all being // called on the main render thread. - base::ThreadChecker thread_checker_; - - // Used to DCHECK that OnSetFormat() and OnData() are called on the same - // thread. - base::ThreadChecker audio_thread_checker_; + THREAD_CHECKER(thread_checker_); DISALLOW_COPY_AND_ASSIGN(WebRtcAudioSink); }; diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc deleted file mode 100644 index 835d6194e24..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" - -#include <utility> - -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread_task_runner_handle.h" -#include "content/renderer/media/stream/media_stream_audio_track.h" -#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h" -#include "third_party/blink/public/platform/web_media_stream_source.h" -#include "third_party/blink/public/platform/web_media_stream_track.h" - -namespace content { - -// static -std::unique_ptr<WebRtcMediaStreamAdapter> -WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - PeerConnectionDependencyFactory* factory, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - const blink::WebMediaStream& web_stream) { - return std::make_unique<LocalWebRtcMediaStreamAdapter>( - factory, std::move(track_adapter_map), web_stream); -} - -// static -std::unique_ptr<WebRtcMediaStreamAdapter> -WebRtcMediaStreamAdapter::CreateRemoteStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream) { - return std::make_unique<RemoteWebRtcMediaStreamAdapter>( - std::move(main_thread), std::move(track_adapter_map), - std::move(webrtc_stream)); -} - -WebRtcMediaStreamAdapter::WebRtcMediaStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream, - const blink::WebMediaStream& web_stream) - : main_thread_(std::move(main_thread)), - track_adapter_map_(std::move(track_adapter_map)), - webrtc_stream_(std::move(webrtc_stream)), - web_stream_(web_stream) { - DCHECK(main_thread_); - DCHECK(track_adapter_map_); -} - -WebRtcMediaStreamAdapter::~WebRtcMediaStreamAdapter() { - DCHECK(main_thread_->BelongsToCurrentThread()); -} - -LocalWebRtcMediaStreamAdapter::LocalWebRtcMediaStreamAdapter( - PeerConnectionDependencyFactory* factory, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - const blink::WebMediaStream& web_stream) - : WebRtcMediaStreamAdapter(base::ThreadTaskRunnerHandle::Get(), - std::move(track_adapter_map), - nullptr, - web_stream), - factory_(factory) { - webrtc_stream_ = factory_->CreateLocalMediaStream(web_stream.Id().Utf8()); - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - web_stream_.AudioTracks(audio_tracks); - for (blink::WebMediaStreamTrack& audio_track : audio_tracks) - TrackAdded(audio_track); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream_.VideoTracks(video_tracks); - for (blink::WebMediaStreamTrack& video_track : video_tracks) - TrackAdded(video_track); - - web_stream_.AddObserver(this); -} - -LocalWebRtcMediaStreamAdapter::~LocalWebRtcMediaStreamAdapter() { - DCHECK(main_thread_->BelongsToCurrentThread()); - web_stream_.RemoveObserver(this); - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - web_stream_.AudioTracks(audio_tracks); - for (blink::WebMediaStreamTrack& audio_track : audio_tracks) - TrackRemoved(audio_track); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream_.VideoTracks(video_tracks); - for (blink::WebMediaStreamTrack& video_track : video_tracks) - TrackRemoved(video_track); -} - -bool LocalWebRtcMediaStreamAdapter::is_initialized() const { - return true; -} - -const scoped_refptr<webrtc::MediaStreamInterface>& -LocalWebRtcMediaStreamAdapter::webrtc_stream() const { - return webrtc_stream_; -} - -const blink::WebMediaStream& LocalWebRtcMediaStreamAdapter::web_stream() const { - return web_stream_; -} - -void LocalWebRtcMediaStreamAdapter::SetTracks( - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs) { - NOTIMPLEMENTED() << "Not supported for local stream adapters."; -} - -void LocalWebRtcMediaStreamAdapter::TrackAdded( - const blink::WebMediaStreamTrack& web_track) { - DCHECK(adapter_refs_.find(web_track.UniqueId()) == adapter_refs_.end()); - bool is_audio_track = - (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio); - if (is_audio_track && !MediaStreamAudioTrack::From(web_track)) { - DLOG(ERROR) << "No native track for blink audio track."; - return; - } - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> adapter_ref = - track_adapter_map_->GetOrCreateLocalTrackAdapter(web_track); - if (is_audio_track) { - webrtc_stream_->AddTrack( - static_cast<webrtc::AudioTrackInterface*>(adapter_ref->webrtc_track())); - } else { - webrtc_stream_->AddTrack( - static_cast<webrtc::VideoTrackInterface*>(adapter_ref->webrtc_track())); - } - adapter_refs_.insert( - std::make_pair(web_track.UniqueId(), std::move(adapter_ref))); -} - -void LocalWebRtcMediaStreamAdapter::TrackRemoved( - const blink::WebMediaStreamTrack& web_track) { - auto it = adapter_refs_.find(web_track.UniqueId()); - if (it == adapter_refs_.end()) { - // This can happen for audio tracks that don't have a source, these would - // never be added in the first place. - return; - } - if (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) { - webrtc_stream_->RemoveTrack( - static_cast<webrtc::AudioTrackInterface*>(it->second->webrtc_track())); - } else { - webrtc_stream_->RemoveTrack( - static_cast<webrtc::VideoTrackInterface*>(it->second->webrtc_track())); - } - adapter_refs_.erase(it); -} - -// static -bool RemoteWebRtcMediaStreamAdapter::RemoteAdapterRefsContainsTrack( - const RemoteAdapterRefs& adapter_refs, - webrtc::MediaStreamTrackInterface* webrtc_track) { - for (const auto& adapter_ref : adapter_refs) { - if (adapter_ref->webrtc_track() == webrtc_track) - return true; - } - return false; -} - -// static -RemoteWebRtcMediaStreamAdapter::RemoteAdapterRefs -RemoteWebRtcMediaStreamAdapter::GetRemoteAdapterRefsFromWebRtcStream( - const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, - webrtc::MediaStreamInterface* webrtc_stream) { - // TODO(hbos): When adapter's |webrtc_track| can be called from any thread so - // can RemoteAdapterRefsContainsTrack and we can DCHECK here that we don't end - // up with duplicate entries. https://crbug.com/756436 - RemoteAdapterRefs adapter_refs; - for (auto& webrtc_audio_track : webrtc_stream->GetAudioTracks()) { - adapter_refs.push_back(track_adapter_map->GetOrCreateRemoteTrackAdapter( - webrtc_audio_track.get())); - } - for (auto& webrtc_video_track : webrtc_stream->GetVideoTracks()) { - adapter_refs.push_back(track_adapter_map->GetOrCreateRemoteTrackAdapter( - webrtc_video_track.get())); - } - return adapter_refs; -} - -RemoteWebRtcMediaStreamAdapter::RemoteWebRtcMediaStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream) - : WebRtcMediaStreamAdapter(std::move(main_thread), - std::move(track_adapter_map), - std::move(webrtc_stream), - // "null" |WebMediaStream| - blink::WebMediaStream()), - is_initialized_(false), - weak_factory_(this) { - CHECK(!main_thread_->BelongsToCurrentThread()); - CHECK(track_adapter_map_); - - RemoteAdapterRefs adapter_refs = GetRemoteAdapterRefsFromWebRtcStream( - track_adapter_map_, webrtc_stream_.get()); - main_thread_->PostTask( - FROM_HERE, - base::BindOnce(&RemoteWebRtcMediaStreamAdapter::InitializeOnMainThread, - weak_factory_.GetWeakPtr(), webrtc_stream_->id(), - std::move(adapter_refs), - webrtc_stream_->GetAudioTracks().size(), - webrtc_stream_->GetVideoTracks().size())); -} - -RemoteWebRtcMediaStreamAdapter::~RemoteWebRtcMediaStreamAdapter() { - DCHECK(main_thread_->BelongsToCurrentThread()); - SetTracks(RemoteAdapterRefs()); -} - -bool RemoteWebRtcMediaStreamAdapter::is_initialized() const { - base::AutoLock scoped_lock(lock_); - return is_initialized_; -} - -const scoped_refptr<webrtc::MediaStreamInterface>& -RemoteWebRtcMediaStreamAdapter::webrtc_stream() const { - base::AutoLock scoped_lock(lock_); - DCHECK(is_initialized_); - return webrtc_stream_; -} - -const blink::WebMediaStream& RemoteWebRtcMediaStreamAdapter::web_stream() - const { - base::AutoLock scoped_lock(lock_); - DCHECK(is_initialized_); - return web_stream_; -} - -void RemoteWebRtcMediaStreamAdapter::InitializeOnMainThread( - const std::string& label, - RemoteAdapterRefs adapter_refs, - size_t audio_track_count, - size_t video_track_count) { - CHECK(main_thread_->BelongsToCurrentThread()); - CHECK_EQ(audio_track_count + video_track_count, adapter_refs.size()); - - adapter_refs_ = std::move(adapter_refs); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks( - audio_track_count); - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks( - video_track_count); - size_t audio_i = 0; - size_t video_i = 0; - for (const auto& adapter_ref : adapter_refs_) { - const blink::WebMediaStreamTrack& web_track = adapter_ref->web_track(); - if (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) - web_audio_tracks[audio_i++] = web_track; - else - web_video_tracks[video_i++] = web_track; - } - - web_stream_.Initialize(blink::WebString::FromUTF8(label), web_audio_tracks, - web_video_tracks); - CHECK(!web_stream_.IsNull()); - - base::AutoLock scoped_lock(lock_); - is_initialized_ = true; -} - -void RemoteWebRtcMediaStreamAdapter::SetTracks( - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs) { - DCHECK(main_thread_->BelongsToCurrentThread()); - - // Find removed tracks. - base::EraseIf( - adapter_refs_, - [this, &track_refs]( - const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& - track_ref) { - bool erase = !RemoteAdapterRefsContainsTrack(track_refs, - track_ref->webrtc_track()); - if (erase) - web_stream_.RemoveTrack(track_ref->web_track()); - return erase; - }); - // Find added tracks. - for (auto& track_ref : track_refs) { - if (!RemoteAdapterRefsContainsTrack(adapter_refs_, - track_ref->webrtc_track())) { - web_stream_.AddTrack(track_ref->web_track()); - adapter_refs_.push_back(std::move(track_ref)); - } - } -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h deleted file mode 100644 index 49c6388ec5a..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_ - -#include <map> -#include <memory> -#include <string> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "content/common/content_export.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" -#include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/webrtc/api/mediastreaminterface.h" - -namespace content { - -class PeerConnectionDependencyFactory; - -// An adapter is the glue between webrtc and blink media streams. Adapters of -// local media streams are created from a blink stream and get a webrtc stream -// correspondent. Adapters of remote media streams are created from a webrtc -// stream and get a blink stream correspondent. The adapter makes sure that when -// the stream it was created from is modified the correspondent is updated to -// reflect the new state. -// The adapters are thread safe but must be constructed on the correct thread -// (local adapters: main thread, remote adapters: webrtc signaling thread) and -// destroyed on the main thread. -class CONTENT_EXPORT WebRtcMediaStreamAdapter { - public: - using TrackAdapterRefs = std::vector< - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>>; - - // Creates an adapter for a local media stream. The adapter is already - // initialized. Invoked on the main thread. - static std::unique_ptr<WebRtcMediaStreamAdapter> CreateLocalStreamAdapter( - PeerConnectionDependencyFactory* factory, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - const blink::WebMediaStream& web_stream); - // Creates an adapter for a remote media stream. Invoked on the webrtc - // signaling thread. The adapter is initialized in a post to the main thread. - static std::unique_ptr<WebRtcMediaStreamAdapter> CreateRemoteStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream); - // Invoke on the main thread. - virtual ~WebRtcMediaStreamAdapter(); - - // Once initialized, |webrtc_stream| and |web_stream| are accessible. An - // initialized adapter remains initialized until destroyed. - virtual bool is_initialized() const = 0; - virtual const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream() - const = 0; - virtual const blink::WebMediaStream& web_stream() const = 0; - bool IsEqual(const blink::WebMediaStream& stream) const { - return (web_stream_.IsNull() && stream.IsNull()) || - (web_stream_.Id() == stream.Id()); - } - - virtual void SetTracks(TrackAdapterRefs track_refs) = 0; - - protected: - WebRtcMediaStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream, - const blink::WebMediaStream& web_stream); - - scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - // The map and owner of all track adapters for the associated peer connection. - // When a track is added or removed from this stream, the map provides us with - // a reference to the corresponding track adapter, creating a new one if - // necessary. - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; - - // If |is_initialized()| both of these need to be set and remain constant. - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_; - blink::WebMediaStream web_stream_; - - DISALLOW_COPY_AND_ASSIGN(WebRtcMediaStreamAdapter); -}; - -// Adapter implementation for a local |blink::WebMediaStream|. Created and -// destroyed on the main thread. -class LocalWebRtcMediaStreamAdapter : public WebRtcMediaStreamAdapter, - blink::WebMediaStreamObserver { - public: - LocalWebRtcMediaStreamAdapter( - PeerConnectionDependencyFactory* factory, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - const blink::WebMediaStream& web_stream); - ~LocalWebRtcMediaStreamAdapter() override; - - // |WebRtcMediaStreamAdapter| implementation. - bool is_initialized() const override; - const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream() - const override; - const blink::WebMediaStream& web_stream() const override; - void SetTracks(TrackAdapterRefs track_refs) override; - - private: - // A map between web track UniqueIDs and references to track adapters. - using LocalAdapterRefMap = - std::map<int, // blink::WebMediaStreamTrack::UniqueId() - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>>; - - // |MediaStreamObserver| implementation. Also used as a helper functions when - // adding/removing all tracks in the constructor/destructor. - void TrackAdded(const blink::WebMediaStreamTrack& web_track) override; - void TrackRemoved(const blink::WebMediaStreamTrack& web_track) override; - - // Pointer to a |PeerConnectionDependencyFactory|, owned by the - // |RenderThread|. It's valid for the lifetime of |RenderThread|. - PeerConnectionDependencyFactory* const factory_; - - // Track adapters belonging to this stream. Keeping adapter references alive - // ensures the adapters are not disposed by the |track_adapter_map_| as long - // as the webrtc layer track is in use by the webrtc layer stream. - LocalAdapterRefMap adapter_refs_; - - DISALLOW_COPY_AND_ASSIGN(LocalWebRtcMediaStreamAdapter); -}; - -// Adapter implementation for a remote |webrtc::MediaStreamInterface|. Created -// on the the webrtc signaling thread, initialized on the main thread where it -// must be destroyed. -class RemoteWebRtcMediaStreamAdapter : public WebRtcMediaStreamAdapter { - public: - RemoteWebRtcMediaStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream); - ~RemoteWebRtcMediaStreamAdapter() override; - - // |WebRtcMediaStreamAdapter| implementation. - bool is_initialized() const override; - const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream() - const override; - const blink::WebMediaStream& web_stream() const override; - void SetTracks(TrackAdapterRefs track_refs) override; - - private: - // Track adapters for the remote webrtc tracks of a stream. - using RemoteAdapterRefs = WebRtcMediaStreamAdapter::TrackAdapterRefs; - - static bool RemoteAdapterRefsContainsTrack( - const RemoteAdapterRefs& adapter_refs, - webrtc::MediaStreamTrackInterface* track); - - // Gets the adapters for the tracks that are members of the webrtc stream. - // Invoke on webrtc signaling thread. New adapters are initialized in a post - // to the main thread after which their |web_track| becomes available. - static RemoteAdapterRefs GetRemoteAdapterRefsFromWebRtcStream( - const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, - webrtc::MediaStreamInterface* webrtc_stream); - - void InitializeOnMainThread(const std::string& label, - RemoteAdapterRefs track_adapter_refs, - size_t audio_track_count, - size_t video_track_count); - - mutable base::Lock lock_; - bool is_initialized_; - // Track adapters belonging to this stream. Keeping adapter references alive - // ensures the adapters are not disposed by the |track_adapter_map_| as long - // as the webrtc layer track is in use by the webrtc layer stream. - RemoteAdapterRefs adapter_refs_; - base::WeakPtrFactory<RemoteWebRtcMediaStreamAdapter> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(RemoteWebRtcMediaStreamAdapter); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc deleted file mode 100644 index b445ce8c893..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" - -namespace content { - -WebRtcMediaStreamAdapterMap::AdapterEntry::AdapterEntry( - std::unique_ptr<WebRtcMediaStreamAdapter> adapter) - : adapter(std::move(adapter)), ref_count(0) { - DCHECK(this->adapter); -} - -WebRtcMediaStreamAdapterMap::AdapterEntry::AdapterEntry(AdapterEntry&& other) - : adapter(other.adapter.release()), ref_count(other.ref_count) {} - -WebRtcMediaStreamAdapterMap::AdapterEntry::~AdapterEntry() { - // |ref_count| is allowed to be non-zero only if this entry has been moved - // which is the case if the |adapter| has already been released. - DCHECK(!ref_count || !adapter); -} - -WebRtcMediaStreamAdapterMap::AdapterRef::AdapterRef( - scoped_refptr<WebRtcMediaStreamAdapterMap> map, - Type type, - AdapterEntry* adapter_entry) - : map_(std::move(map)), type_(type), adapter_entry_(adapter_entry) { - DCHECK(map_); - DCHECK(adapter_entry_); - map_->lock_.AssertAcquired(); - ++adapter_entry_->ref_count; -} - -WebRtcMediaStreamAdapterMap::AdapterRef::~AdapterRef() { - DCHECK(map_->main_thread_->BelongsToCurrentThread()); - std::unique_ptr<WebRtcMediaStreamAdapter> removed_adapter; - { - base::AutoLock scoped_lock(map_->lock_); - --adapter_entry_->ref_count; - if (adapter_entry_->ref_count == 0) { - removed_adapter = std::move(adapter_entry_->adapter); - // "GetOrCreate..." ensures the adapter is initialized and the secondary - // key is set before the last |AdapterRef| is destroyed. We can use either - // the primary or secondary key for removal. - if (type_ == Type::kLocal) { - map_->local_stream_adapters_.EraseByPrimary( - removed_adapter->web_stream().UniqueId()); - } else { - map_->remote_stream_adapters_.EraseByPrimary( - removed_adapter->webrtc_stream().get()); - } - } - } - // Destroy the adapter whilst not holding the lock so that it is safe for - // destructors to use the signaling thread synchronously without any risk of - // deadlock. - removed_adapter.reset(); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::AdapterRef::Copy() const { - base::AutoLock scoped_lock(map_->lock_); - return base::WrapUnique(new AdapterRef(map_, type_, adapter_entry_)); -} - -WebRtcMediaStreamAdapterMap::WebRtcMediaStreamAdapterMap( - PeerConnectionDependencyFactory* const factory, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map) - : factory_(factory), - main_thread_(std::move(main_thread)), - track_adapter_map_(std::move(track_adapter_map)) { - DCHECK(factory_); - DCHECK(main_thread_); - DCHECK(track_adapter_map_); -} - -WebRtcMediaStreamAdapterMap::~WebRtcMediaStreamAdapterMap() { - DCHECK(local_stream_adapters_.empty()); - DCHECK(remote_stream_adapters_.empty()); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetLocalStreamAdapter( - const blink::WebMediaStream& web_stream) { - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - local_stream_adapters_.FindByPrimary(web_stream.UniqueId()); - if (!adapter_entry) - return nullptr; - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry)); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetLocalStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream) { - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - local_stream_adapters_.FindBySecondary(webrtc_stream); - if (!adapter_entry) - return nullptr; - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry)); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetOrCreateLocalStreamAdapter( - const blink::WebMediaStream& web_stream) { - CHECK(main_thread_->BelongsToCurrentThread()); - CHECK(!web_stream.IsNull()); - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - local_stream_adapters_.FindByPrimary(web_stream.UniqueId()); - if (!adapter_entry) { - std::unique_ptr<WebRtcMediaStreamAdapter> adapter; - { - // Make sure we don't hold the lock while calling out to - // CreateLocalStreamAdapter(). The reason is that constructing a local - // stream adapter, will synchronize with WebRTC's signaling thread and - // callbacks on the signaling thread might end up coming back to us - // and we might need the lock then. - base::AutoUnlock scoped_unlock(lock_); - adapter = WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - factory_, track_adapter_map_, web_stream); - } - - adapter_entry = local_stream_adapters_.Insert(web_stream.UniqueId(), - std::move(adapter)); - CHECK(adapter_entry->adapter->is_initialized()); - CHECK(adapter_entry->adapter->webrtc_stream()); - local_stream_adapters_.SetSecondaryKey( - web_stream.UniqueId(), adapter_entry->adapter->webrtc_stream().get()); - } - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry)); -} - -size_t WebRtcMediaStreamAdapterMap::GetLocalStreamCount() const { - base::AutoLock scoped_lock(lock_); - return local_stream_adapters_.PrimarySize(); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetRemoteStreamAdapter( - const blink::WebMediaStream& web_stream) { - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - remote_stream_adapters_.FindBySecondary(web_stream.UniqueId()); - if (!adapter_entry) - return nullptr; - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry)); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetRemoteStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream) { - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - remote_stream_adapters_.FindByPrimary(webrtc_stream); - if (!adapter_entry) - return nullptr; - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry)); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetOrCreateRemoteStreamAdapter( - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream) { - CHECK(!main_thread_->BelongsToCurrentThread()); - CHECK(webrtc_stream); - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - remote_stream_adapters_.FindByPrimary(webrtc_stream.get()); - if (!adapter_entry) { - // Make sure we don't hold the lock while calling out to - // CreateRemoteStreamAdapter(). The reason is that it might synchronize - // with other threads, possibly the main thread, where we might need to grab - // the lock (e.g. inside of GetOrCreateLocalStreamAdapter()). - std::unique_ptr<WebRtcMediaStreamAdapter> adapter; - { - base::AutoUnlock scoped_unlock(lock_); - adapter = WebRtcMediaStreamAdapter::CreateRemoteStreamAdapter( - main_thread_, track_adapter_map_, webrtc_stream.get()); - } - - adapter_entry = - remote_stream_adapters_.Insert(webrtc_stream.get(), std::move(adapter)); - - // The new adapter is initialized in a post to the main thread. As soon as - // it is initialized we map its |webrtc_stream| to the - // |remote_stream_adapters_| entry as its secondary key. This ensures that - // there is at least one |AdapterRef| alive until after the adapter is - // initialized and its secondary key is set. - main_thread_->PostTask( - FROM_HERE, - base::BindOnce( - &WebRtcMediaStreamAdapterMap::OnRemoteStreamAdapterInitialized, - this, - base::WrapUnique(new AdapterRef(this, AdapterRef::Type::kRemote, - adapter_entry)))); - } - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry)); -} - -size_t WebRtcMediaStreamAdapterMap::GetRemoteStreamCount() const { - base::AutoLock scoped_lock(lock_); - return remote_stream_adapters_.PrimarySize(); -} - -void WebRtcMediaStreamAdapterMap::OnRemoteStreamAdapterInitialized( - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref) { - CHECK(main_thread_->BelongsToCurrentThread()); - CHECK(adapter_ref->is_initialized()); - CHECK(!adapter_ref->adapter().web_stream().IsNull()); - { - base::AutoLock scoped_lock(lock_); - remote_stream_adapters_.SetSecondaryKey( - adapter_ref->adapter().webrtc_stream().get(), - adapter_ref->adapter().web_stream().UniqueId()); - } -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h deleted file mode 100644 index 1d9c40b6692..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_ - -#include <map> -#include <memory> - -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "content/common/content_export.h" -#include "content/renderer/media/webrtc/two_keys_adapter_map.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" -#include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/webrtc/api/mediastreaminterface.h" - -namespace content { - -// A map and owner of |WebRtcMediaStreamAdapter|s. Adapters are the glue between -// blink and webrtc layer versions of streams. As long as a stream is in use by -// a peer connection there has to exist an adapter for it. The map takes care of -// creating and disposing stream adapters. Adapters are accessed via -// |AdapterRef|s, when all references to an adapter are destroyed it is -// destroyed and removed from the map. -class CONTENT_EXPORT WebRtcMediaStreamAdapterMap - : public base::RefCountedThreadSafe<WebRtcMediaStreamAdapterMap> { - private: - // The map's entries are reference counted in order to remove the adapter when - // all |AdapterRef|s referencing an entry are destroyed. - // Private section needed here due to |AdapterRef|'s usage of |AdapterEntry|. - struct AdapterEntry { - AdapterEntry(std::unique_ptr<WebRtcMediaStreamAdapter> adapter); - AdapterEntry(AdapterEntry&& other); - ~AdapterEntry(); - - AdapterEntry(const AdapterEntry&) = delete; - AdapterEntry& operator=(const AdapterEntry&) = delete; - - std::unique_ptr<WebRtcMediaStreamAdapter> adapter; - size_t ref_count; - }; - - public: - // Accessor to an adapter to take care of reference counting. When the last - // |AdapterRef| is destroyed, the corresponding adapter is destroyed and - // removed from the map. - class CONTENT_EXPORT AdapterRef { - public: - // Must be invoked on the main thread. If this was the last reference to the - // adapter it will be disposed and removed from the map. - ~AdapterRef(); - - std::unique_ptr<AdapterRef> Copy() const; - bool is_initialized() const { return adapter().is_initialized(); } - const WebRtcMediaStreamAdapter& adapter() const { - return *adapter_entry_->adapter; - } - WebRtcMediaStreamAdapter& adapter() { return *adapter_entry_->adapter; } - - private: - friend class WebRtcMediaStreamAdapterMap; - - enum class Type { kLocal, kRemote }; - - // Increments the |AdapterEntry::ref_count|. Assumes map's |lock_| is held. - AdapterRef(scoped_refptr<WebRtcMediaStreamAdapterMap> map, - Type type, - AdapterEntry* adapter_entry); - - scoped_refptr<WebRtcMediaStreamAdapterMap> map_; - Type type_; - AdapterEntry* adapter_entry_; - }; - - // Must be invoked on the main thread. - WebRtcMediaStreamAdapterMap( - PeerConnectionDependencyFactory* const factory, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map); - - // Gets a new reference to the local stream adapter, or null if no such - // adapter was found. When all references are destroyed the adapter is - // destroyed and removed from the map. This can be called on any thread, but - // references must be destroyed on the main thread. - // The adapter is a associated with a blink and webrtc stream, lookup works by - // either stream. - std::unique_ptr<AdapterRef> GetLocalStreamAdapter( - const blink::WebMediaStream& web_stream); - std::unique_ptr<AdapterRef> GetLocalStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream); - // Invoke on the main thread. Gets a new reference to the local stream adapter - // for the web stream. If no adapter exists for the stream one is created. - // When all references are destroyed the adapter is destroyed and removed from - // the map. References must be destroyed on the main thread. - std::unique_ptr<AdapterRef> GetOrCreateLocalStreamAdapter( - const blink::WebMediaStream& web_stream); - size_t GetLocalStreamCount() const; - - // Gets a new reference to the remote stream adapter by ID, or null if no such - // adapter was found. When all references are destroyed the adapter is - // destroyed and removed from the map. This can be called on any thread, but - // references must be destroyed on the main thread. The adapter is a - // associated with a blink and webrtc stream, lookup works by either stream. - // First variety: If an adapter exists it will already be initialized, if one - // does not exist null is returned. - std::unique_ptr<AdapterRef> GetRemoteStreamAdapter( - const blink::WebMediaStream& web_stream); - // Second variety: If an adapter exists it may or may not be initialized, see - // |AdapterRef::is_initialized|. If an adapter does not exist null is - // returned. - std::unique_ptr<AdapterRef> GetRemoteStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream); - // Invoke on the webrtc signaling thread. Gets a new reference to the remote - // stream adapter for the webrtc stream. If no adapter exists for the stream - // one is created and initialization completes on the main thread in a post. - // When all references are destroyed the adapter is destroyed and removed from - // the map. References must be destroyed on the main thread. - std::unique_ptr<AdapterRef> GetOrCreateRemoteStreamAdapter( - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream); - size_t GetRemoteStreamCount() const; - - const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map() - const { - return track_adapter_map_; - } - - private: - friend class base::RefCountedThreadSafe<WebRtcMediaStreamAdapterMap>; - - // "(blink::WebMediaStream, webrtc::MediaStreamInterface) -> AdapterEntry" - // maps. The primary key is based on the object used to create the adapter. - // Local streams are created from |blink::WebMediaStream|s, remote streams are - // created from |webrtc::MediaStreamInterface|s. - // The adapter keeps the |webrtc::MediaStreamInterface| alive with ref - // counting making it safe to use a raw pointer for key. - using LocalStreamAdapterMap = - TwoKeysAdapterMap<int, // blink::WebMediaStream::UniqueId() - webrtc::MediaStreamInterface*, - AdapterEntry>; - using RemoteStreamAdapterMap = - TwoKeysAdapterMap<webrtc::MediaStreamInterface*, - int, // blink::WebMediaStream::UniqueId() - AdapterEntry>; - - // Invoke on the main thread. - virtual ~WebRtcMediaStreamAdapterMap(); - - void OnRemoteStreamAdapterInitialized( - std::unique_ptr<AdapterRef> adapter_ref); - - // Pointer to a |PeerConnectionDependencyFactory| owned by the |RenderThread|. - // It's valid for the lifetime of |RenderThread|. - PeerConnectionDependencyFactory* const factory_; - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - // Takes care of creating and owning track adapters, used by stream adapters. - const scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; - - mutable base::Lock lock_; - LocalStreamAdapterMap local_stream_adapters_; - RemoteStreamAdapterMap remote_stream_adapters_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc deleted file mode 100644 index 87f0032a8bd..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" - -#include <memory> -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/scoped_task_environment.h" -#include "content/child/child_process.h" -#include "content/renderer/media/mock_audio_device_factory.h" -#include "content/renderer/media/stream/media_stream_video_source.h" -#include "content/renderer/media/stream/media_stream_video_track.h" -#include "content/renderer/media/stream/mock_media_stream_video_source.h" -#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" -#include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/blink/public/platform/web_media_stream_source.h" -#include "third_party/blink/public/platform/web_media_stream_track.h" -#include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/public/web/web_heap.h" - -using ::testing::_; - -namespace content { - -class WebRtcMediaStreamAdapterMapTest : public ::testing::Test { - public: - void SetUp() override { - dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); - main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); - map_ = new WebRtcMediaStreamAdapterMap( - dependency_factory_.get(), main_thread_, - new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), - main_thread_)); - } - - void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); } - - blink::WebMediaStream CreateLocalStream(const std::string& id) { - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks( - static_cast<size_t>(1)); - blink::WebMediaStreamSource video_source; - video_source.Initialize("video_source", - blink::WebMediaStreamSource::kTypeVideo, - "video_source", false /* remote */); - MediaStreamVideoSource* native_source = new MockMediaStreamVideoSource(); - video_source.SetExtraData(native_source); - web_video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack( - native_source, MediaStreamVideoSource::ConstraintsCallback(), true); - - blink::WebMediaStream web_stream; - web_stream.Initialize(blink::WebString::FromUTF8(id), - blink::WebVector<blink::WebMediaStreamTrack>(), - web_video_tracks); - return web_stream; - } - - scoped_refptr<webrtc::MediaStreamInterface> CreateRemoteStream( - const std::string& id) { - scoped_refptr<webrtc::MediaStreamInterface> stream( - new rtc::RefCountedObject<MockMediaStream>(id)); - stream->AddTrack(MockWebRtcAudioTrack::Create("remote_audio_track").get()); - stream->AddTrack(MockWebRtcVideoTrack::Create("remote_video_track").get()); - return stream; - } - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> - GetOrCreateRemoteStreamAdapter(webrtc::MediaStreamInterface* webrtc_stream) { - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref; - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(&WebRtcMediaStreamAdapterMapTest:: - GetOrCreateRemoteStreamAdapterOnSignalingThread, - base::Unretained(this), base::Unretained(webrtc_stream), - base::Unretained(&adapter_ref))); - RunMessageLoopsUntilIdle(); - DCHECK(adapter_ref); - return adapter_ref; - } - - protected: - void GetOrCreateRemoteStreamAdapterOnSignalingThread( - webrtc::MediaStreamInterface* webrtc_stream, - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>* adapter_ref) { - *adapter_ref = map_->GetOrCreateRemoteStreamAdapter(webrtc_stream); - EXPECT_TRUE(*adapter_ref); - } - - // Runs message loops on the webrtc signaling thread and the main thread until - // idle. - void RunMessageLoopsUntilIdle() { - base::WaitableEvent waitable_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, base::BindOnce(&WebRtcMediaStreamAdapterMapTest::SignalEvent, - base::Unretained(this), &waitable_event)); - waitable_event.Wait(); - base::RunLoop().RunUntilIdle(); - } - - void SignalEvent(base::WaitableEvent* waitable_event) { - waitable_event->Signal(); - } - - // Message loop and child processes is needed for task queues and threading to - // work, as is necessary to create tracks and adapters. - base::test::ScopedTaskEnvironment scoped_task_environment_; - ChildProcess child_process_; - - std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; - scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<WebRtcMediaStreamAdapterMap> map_; -}; - -TEST_F(WebRtcMediaStreamAdapterMapTest, AddAndRemoveLocalStreamAdapter) { - blink::WebMediaStream local_web_stream = CreateLocalStream("local_stream"); - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref = - map_->GetOrCreateLocalStreamAdapter(local_web_stream); - EXPECT_TRUE(adapter_ref); - EXPECT_TRUE(adapter_ref->adapter().IsEqual(local_web_stream)); - EXPECT_EQ(1u, map_->GetLocalStreamCount()); - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 = - map_->GetLocalStreamAdapter(local_web_stream); - EXPECT_TRUE(adapter_ref2); - EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter()); - EXPECT_EQ(1u, map_->GetLocalStreamCount()); - - adapter_ref.reset(); - EXPECT_EQ(1u, map_->GetLocalStreamCount()); - adapter_ref2.reset(); - EXPECT_EQ(0u, map_->GetLocalStreamCount()); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, LookUpLocalAdapterByWebRtcStream) { - blink::WebMediaStream local_web_stream = CreateLocalStream("local_stream"); - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref = - map_->GetOrCreateLocalStreamAdapter(local_web_stream); - EXPECT_TRUE(adapter_ref); - EXPECT_TRUE(adapter_ref->adapter().IsEqual(local_web_stream)); - EXPECT_EQ(1u, map_->GetLocalStreamCount()); - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 = - map_->GetLocalStreamAdapter(adapter_ref->adapter().web_stream()); - EXPECT_TRUE(adapter_ref2); - EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter()); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, GetLocalStreamAdapterInvalidID) { - blink::WebMediaStream local_web_stream = CreateLocalStream("missing"); - EXPECT_FALSE(map_->GetLocalStreamAdapter(local_web_stream)); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, AddAndRemoveRemoteStreamAdapter) { - scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream = - CreateRemoteStream("remote_stream"); - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref = - GetOrCreateRemoteStreamAdapter(remote_webrtc_stream.get()); - EXPECT_EQ(remote_webrtc_stream, adapter_ref->adapter().webrtc_stream()); - EXPECT_EQ(1u, map_->GetRemoteStreamCount()); - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 = - map_->GetRemoteStreamAdapter(remote_webrtc_stream.get()); - EXPECT_TRUE(adapter_ref2); - EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter()); - EXPECT_EQ(1u, map_->GetRemoteStreamCount()); - - adapter_ref.reset(); - EXPECT_EQ(1u, map_->GetRemoteStreamCount()); - adapter_ref2.reset(); - EXPECT_EQ(0u, map_->GetRemoteStreamCount()); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, LookUpRemoteAdapterByWebStream) { - scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream = - CreateRemoteStream("remote_stream"); - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref = - GetOrCreateRemoteStreamAdapter(remote_webrtc_stream.get()); - EXPECT_EQ(remote_webrtc_stream, adapter_ref->adapter().webrtc_stream()); - EXPECT_EQ(1u, map_->GetRemoteStreamCount()); - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 = - map_->GetRemoteStreamAdapter( - adapter_ref->adapter().webrtc_stream().get()); - EXPECT_TRUE(adapter_ref2); - EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter()); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, GetRemoteStreamAdapterInvalidID) { - scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream = - CreateRemoteStream("missing"); - EXPECT_FALSE(map_->GetRemoteStreamAdapter(remote_webrtc_stream.get())); -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc deleted file mode 100644 index ec8ffdca628..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" - -#include <stddef.h> - -#include <memory> -#include <string> -#include <utility> - -#include "base/run_loop.h" -#include "base/strings/stringprintf.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" -#include "content/child/child_process.h" -#include "content/renderer/media/mock_audio_device_factory.h" -#include "content/renderer/media/stream/media_stream_video_source.h" -#include "content/renderer/media/stream/media_stream_video_track.h" -#include "content/renderer/media/stream/mock_constraint_factory.h" -#include "content/renderer/media/stream/mock_media_stream_video_source.h" -#include "content/renderer/media/stream/processed_local_audio_source.h" -#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" -#include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/blink/public/platform/web_media_stream_source.h" -#include "third_party/blink/public/platform/web_media_stream_track.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/public/web/web_heap.h" - -using ::testing::_; - -namespace content { - -class WebRtcMediaStreamAdapterTest : public ::testing::Test { - public: - void SetUp() override { - dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); - track_adapter_map_ = new WebRtcMediaStreamTrackAdapterMap( - dependency_factory_.get(), - blink::scheduler::GetSingleThreadTaskRunnerForTesting()); - } - - void TearDown() override { - track_adapter_map_ = nullptr; - blink::WebHeap::CollectAllGarbageForTesting(); - } - - protected: - // The ScopedTaskEnvironment prevents the ChildProcess from leaking a - // TaskScheduler. - base::test::ScopedTaskEnvironment scoped_task_environment_; - ChildProcess child_process_; - std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; -}; - -class LocalWebRtcMediaStreamAdapterTest : public WebRtcMediaStreamAdapterTest { - public: - blink::WebMediaStream CreateWebMediaStream( - const std::string& audio_track_id, - const std::string& video_track_id) { - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks( - static_cast<size_t>(1u)); - blink::WebMediaStreamSource audio_source; - audio_source.Initialize(blink::WebString::FromUTF8(audio_track_id), - blink::WebMediaStreamSource::kTypeAudio, - blink::WebString::FromUTF8(audio_track_id), - false /* remote */); - ProcessedLocalAudioSource* const source = new ProcessedLocalAudioSource( - -1 /* consumer_render_frame_id is N/A for non-browser tests */, - MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "mock_audio_device_id", - "Mock audio device", - media::AudioParameters::kAudioCDSampleRate, - media::CHANNEL_LAYOUT_STEREO, - media::AudioParameters::kAudioCDSampleRate / 50), - false /* hotword_enabled */, false /* disable_local_echo */, - AudioProcessingProperties(), - base::Bind(&LocalWebRtcMediaStreamAdapterTest::OnAudioSourceStarted), - dependency_factory_.get()); - source->SetAllowInvalidRenderFrameIdForTesting(true); - audio_source.SetExtraData(source); // Takes ownership. - audio_tracks[0].Initialize(blink::WebString::FromUTF8(audio_track_id), - audio_source); - EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), - Initialize(_, _)); - EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), - SetAutomaticGainControl(true)); - EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), Start()); - EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), Stop()); - CHECK(source->ConnectToTrack(audio_tracks[0])); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks( - static_cast<size_t>(1u)); - MediaStreamSource::SourceStoppedCallback dummy_callback; - blink::WebMediaStreamSource video_source; - video_source.Initialize(blink::WebString::FromUTF8(video_track_id), - blink::WebMediaStreamSource::kTypeVideo, - blink::WebString::FromUTF8(video_track_id), - false /* remote */); - MediaStreamVideoSource* native_source = new MockMediaStreamVideoSource(); - video_source.SetExtraData(native_source); - video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack( - blink::WebString::FromUTF8(video_track_id), native_source, - MediaStreamVideoSource::ConstraintsCallback(), true); - - blink::WebMediaStream stream_desc; - stream_desc.Initialize("stream_id", audio_tracks, video_tracks); - return stream_desc; - } - - private: - static void OnAudioSourceStarted(MediaStreamSource* source, - MediaStreamRequestResult result, - const blink::WebString& result_name) {} - - MockAudioDeviceFactory mock_audio_device_factory_; -}; - -class RemoteWebRtcMediaStreamAdapterTest : public WebRtcMediaStreamAdapterTest { - public: - scoped_refptr<webrtc::MediaStreamInterface> CreateWebRtcMediaStream( - const std::string& audio_track_id, - const std::string& video_track_id) { - scoped_refptr<webrtc::MediaStreamInterface> stream( - new rtc::RefCountedObject<MockMediaStream>("remote_stream")); - stream->AddTrack(MockWebRtcAudioTrack::Create(audio_track_id).get()); - stream->AddTrack(MockWebRtcVideoTrack::Create(video_track_id).get()); - return stream; - } - - std::unique_ptr<WebRtcMediaStreamAdapter> CreateRemoteStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream) { - std::unique_ptr<WebRtcMediaStreamAdapter> adapter; - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce( - &RemoteWebRtcMediaStreamAdapterTest:: - CreateRemoteStreamAdapterOnSignalingThread, - base::Unretained(this), - base::Unretained( - blink::scheduler::GetSingleThreadTaskRunnerForTesting().get()), - base::Unretained(webrtc_stream), base::Unretained(&adapter))); - RunMessageLoopsUntilIdle(); - DCHECK(adapter); - return adapter; - } - - // Adds the track and gets the adapters for the stream's resulting tracks. - template <typename TrackType> - WebRtcMediaStreamAdapter::TrackAdapterRefs AddTrack( - webrtc::MediaStreamInterface* webrtc_stream, - TrackType* webrtc_track) { - typedef bool (webrtc::MediaStreamInterface::*AddTrack)(TrackType*); - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, base::BindOnce(base::IgnoreResult<AddTrack>( - &webrtc::MediaStreamInterface::AddTrack), - base::Unretained(webrtc_stream), - base::Unretained(webrtc_track))); - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs; - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(&RemoteWebRtcMediaStreamAdapterTest:: - GetStreamTrackRefsOnSignalingThread, - base::Unretained(this), base::Unretained(webrtc_stream), - base::Unretained(&track_refs))); - RunMessageLoopsUntilIdle(); - return track_refs; - } - - // Removes the track and gets the adapters for the stream's resulting tracks. - template <typename TrackType> - WebRtcMediaStreamAdapter::TrackAdapterRefs RemoveTrack( - webrtc::MediaStreamInterface* webrtc_stream, - TrackType* webrtc_track) { - typedef bool (webrtc::MediaStreamInterface::*RemoveTrack)(TrackType*); - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(base::IgnoreResult<RemoveTrack>( - &webrtc::MediaStreamInterface::RemoveTrack), - base::Unretained(webrtc_stream), - base::Unretained(webrtc_track))); - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs; - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(&RemoteWebRtcMediaStreamAdapterTest:: - GetStreamTrackRefsOnSignalingThread, - base::Unretained(this), base::Unretained(webrtc_stream), - base::Unretained(&track_refs))); - RunMessageLoopsUntilIdle(); - return track_refs; - } - - private: - void CreateRemoteStreamAdapterOnSignalingThread( - base::SingleThreadTaskRunner* main_thread, - webrtc::MediaStreamInterface* webrtc_stream, - std::unique_ptr<WebRtcMediaStreamAdapter>* adapter) { - *adapter = WebRtcMediaStreamAdapter::CreateRemoteStreamAdapter( - main_thread, track_adapter_map_, webrtc_stream); - EXPECT_FALSE((*adapter)->is_initialized()); - } - - void GetStreamTrackRefsOnSignalingThread( - webrtc::MediaStreamInterface* webrtc_stream, - WebRtcMediaStreamAdapter::TrackAdapterRefs* out_track_refs) { - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs; - for (auto& audio_track : webrtc_stream->GetAudioTracks()) { - track_refs.push_back( - track_adapter_map_->GetOrCreateRemoteTrackAdapter(audio_track.get())); - } - for (auto& video_track : webrtc_stream->GetVideoTracks()) { - track_refs.push_back( - track_adapter_map_->GetOrCreateRemoteTrackAdapter(video_track.get())); - } - *out_track_refs = std::move(track_refs); - } - - // Runs message loops on the webrtc signaling thread and the main thread until - // idle. - void RunMessageLoopsUntilIdle() { - base::WaitableEvent waitable_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(&RemoteWebRtcMediaStreamAdapterTest::SignalEvent, - base::Unretained(this), &waitable_event)); - // TODO(hbos): Use base::RunLoop instead of WaitableEvent. - waitable_event.Wait(); - base::RunLoop().RunUntilIdle(); - } - - void SignalEvent(base::WaitableEvent* waitable_event) { - waitable_event->Signal(); - } -}; - -TEST_F(LocalWebRtcMediaStreamAdapterTest, CreateStreamAdapter) { - blink::WebMediaStream web_stream = - CreateWebMediaStream("audio_track_id", "video_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - dependency_factory_.get(), track_adapter_map_, web_stream); - EXPECT_TRUE(adapter->IsEqual(web_stream)); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetAudioTracks().size()); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetVideoTracks().size()); - EXPECT_EQ(web_stream.Id().Utf8(), adapter->webrtc_stream()->id()); -} - -TEST_F(LocalWebRtcMediaStreamAdapterTest, - CreateStreamAdapterWithSharedTrackIds) { - blink::WebMediaStream web_stream = - CreateWebMediaStream("shared_track_id", "shared_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - dependency_factory_.get(), track_adapter_map_, web_stream); - EXPECT_TRUE(adapter->IsEqual(web_stream)); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetAudioTracks().size()); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetVideoTracks().size()); - EXPECT_EQ(web_stream.Id().Utf8(), adapter->webrtc_stream()->id()); -} - -// It should not crash if |MediaStream| is created in blink with an unknown -// audio source. This can happen if a |MediaStream| is created with remote audio -// track. -TEST_F(LocalWebRtcMediaStreamAdapterTest, - AdapterForWebStreamWithoutAudioSource) { - // Create a blink MediaStream description. - blink::WebMediaStreamSource audio_source; - audio_source.Initialize("audio source", - blink::WebMediaStreamSource::kTypeAudio, "something", - false /* remote */); - // Without |audio_source.SetExtraData()| it is possible to initialize tracks - // and streams but the source is a dummy. - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks( - static_cast<size_t>(1)); - audio_tracks[0].Initialize(audio_source.Id(), audio_source); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks( - static_cast<size_t>(0)); - - blink::WebMediaStream web_stream; - web_stream.Initialize("stream_id", audio_tracks, video_tracks); - - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - dependency_factory_.get(), track_adapter_map_, web_stream); - EXPECT_TRUE(adapter->IsEqual(web_stream)); - EXPECT_EQ(0u, adapter->webrtc_stream()->GetAudioTracks().size()); - EXPECT_EQ(0u, adapter->webrtc_stream()->GetVideoTracks().size()); - EXPECT_EQ(web_stream.Id().Utf8(), adapter->webrtc_stream()->id()); -} - -TEST_F(LocalWebRtcMediaStreamAdapterTest, RemoveAndAddTrack) { - blink::WebMediaStream web_stream = - CreateWebMediaStream("audio_track_id", "video_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - dependency_factory_.get(), track_adapter_map_, web_stream); - EXPECT_TRUE(adapter->IsEqual(web_stream)); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetAudioTracks().size()); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetVideoTracks().size()); - EXPECT_EQ(web_stream.Id().Utf8(), adapter->webrtc_stream()->id()); - - // Modify the web layer stream, make sure the webrtc layer stream is updated. - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - web_stream.AudioTracks(audio_tracks); - - web_stream.RemoveTrack(audio_tracks[0]); - EXPECT_TRUE(adapter->webrtc_stream()->GetAudioTracks().empty()); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream.VideoTracks(video_tracks); - - web_stream.RemoveTrack(video_tracks[0]); - EXPECT_TRUE(adapter->webrtc_stream()->GetVideoTracks().empty()); - - web_stream.AddTrack(audio_tracks[0]); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetAudioTracks().size()); - - web_stream.AddTrack(video_tracks[0]); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetVideoTracks().size()); -} - -TEST_F(RemoteWebRtcMediaStreamAdapterTest, CreateStreamAdapter) { - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream = - CreateWebRtcMediaStream("audio_track_id", "video_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - CreateRemoteStreamAdapter(webrtc_stream.get()); - EXPECT_TRUE(adapter->is_initialized()); - EXPECT_EQ(webrtc_stream, adapter->webrtc_stream()); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(1u, web_audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(1u, web_video_tracks.size()); -} - -TEST_F(RemoteWebRtcMediaStreamAdapterTest, - CreateStreamAdapterWithSharedTrackIds) { - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream = - CreateWebRtcMediaStream("shared_track_id", "shared_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - CreateRemoteStreamAdapter(webrtc_stream.get()); - EXPECT_TRUE(adapter->is_initialized()); - EXPECT_EQ(webrtc_stream, adapter->webrtc_stream()); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(1u, web_audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(1u, web_video_tracks.size()); -} - -TEST_F(RemoteWebRtcMediaStreamAdapterTest, RemoveAndAddTrack) { - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream = - CreateWebRtcMediaStream("audio_track_id", "video_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - CreateRemoteStreamAdapter(webrtc_stream.get()); - EXPECT_TRUE(adapter->is_initialized()); - EXPECT_EQ(webrtc_stream, adapter->webrtc_stream()); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(1u, web_audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(1u, web_video_tracks.size()); - - // Modify the webrtc layer stream, make sure the web layer stream is updated. - rtc::scoped_refptr<webrtc::AudioTrackInterface> webrtc_audio_track = - webrtc_stream->GetAudioTracks()[0]; - adapter->SetTracks( - RemoveTrack(webrtc_stream.get(), webrtc_audio_track.get())); - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(0u, web_audio_tracks.size()); - - rtc::scoped_refptr<webrtc::VideoTrackInterface> webrtc_video_track = - webrtc_stream->GetVideoTracks()[0]; - adapter->SetTracks( - RemoveTrack(webrtc_stream.get(), webrtc_video_track.get())); - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(0u, web_video_tracks.size()); - - adapter->SetTracks(AddTrack(webrtc_stream.get(), webrtc_audio_track.get())); - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(1u, web_audio_tracks.size()); - - adapter->SetTracks(AddTrack(webrtc_stream.get(), webrtc_video_track.get())); - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(1u, web_video_tracks.size()); -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc index e03d1719ee0..a20adaaae7b 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.cc @@ -63,22 +63,24 @@ WebRtcMediaStreamTrackAdapter::WebRtcMediaStreamTrackAdapter( remote_track_can_complete_initialization_( base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED), - is_initialized_(false) { + is_initialized_(false), + is_disposed_(false) { DCHECK(factory_); DCHECK(main_thread_); } WebRtcMediaStreamTrackAdapter::~WebRtcMediaStreamTrackAdapter() { DCHECK(!remote_track_can_complete_initialization_.IsSignaled()); - DCHECK(!is_initialized_); + DCHECK(is_disposed_); } void WebRtcMediaStreamTrackAdapter::Dispose() { DCHECK(main_thread_->BelongsToCurrentThread()); - if (!is_initialized_) + DCHECK(is_initialized_); + if (is_disposed_) return; remote_track_can_complete_initialization_.Reset(); - is_initialized_ = false; + is_disposed_ = true; if (web_track_.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) { if (local_track_audio_sink_) @@ -99,10 +101,19 @@ bool WebRtcMediaStreamTrackAdapter::is_initialized() const { return is_initialized_; } +void WebRtcMediaStreamTrackAdapter::InitializeOnMainThread() { + DCHECK(main_thread_->BelongsToCurrentThread()); + if (is_initialized_) + return; + // TODO(hbos): Only ever initialize explicitly, + // remove EnsureTrackIsInitialized(). https://crbug.com/857458 + EnsureTrackIsInitialized(); +} + const blink::WebMediaStreamTrack& WebRtcMediaStreamTrackAdapter::web_track() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!web_track_.IsNull()); EnsureTrackIsInitialized(); + DCHECK(!web_track_.IsNull()); return web_track_; } @@ -231,6 +242,7 @@ void WebRtcMediaStreamTrackAdapter:: } void WebRtcMediaStreamTrackAdapter::EnsureTrackIsInitialized() { + DCHECK(main_thread_->BelongsToCurrentThread()); if (is_initialized_) return; @@ -242,7 +254,6 @@ void WebRtcMediaStreamTrackAdapter::EnsureTrackIsInitialized() { void WebRtcMediaStreamTrackAdapter::DisposeLocalAudioTrack() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); DCHECK(local_track_audio_sink_); DCHECK_EQ(web_track_.Source().GetType(), blink::WebMediaStreamSource::kTypeAudio); @@ -256,7 +267,6 @@ void WebRtcMediaStreamTrackAdapter::DisposeLocalAudioTrack() { void WebRtcMediaStreamTrackAdapter::DisposeLocalVideoTrack() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); DCHECK(local_track_video_sink_); DCHECK_EQ(web_track_.Source().GetType(), blink::WebMediaStreamSource::kTypeVideo); @@ -267,7 +277,6 @@ void WebRtcMediaStreamTrackAdapter::DisposeLocalVideoTrack() { void WebRtcMediaStreamTrackAdapter::DisposeRemoteAudioTrack() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); DCHECK(remote_audio_track_adapter_); DCHECK_EQ(web_track_.Source().GetType(), blink::WebMediaStreamSource::kTypeAudio); @@ -280,7 +289,6 @@ void WebRtcMediaStreamTrackAdapter::DisposeRemoteAudioTrack() { void WebRtcMediaStreamTrackAdapter::DisposeRemoteVideoTrack() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); DCHECK(remote_video_track_adapter_); DCHECK_EQ(web_track_.Source().GetType(), blink::WebMediaStreamSource::kTypeVideo); @@ -300,7 +308,7 @@ void WebRtcMediaStreamTrackAdapter:: void WebRtcMediaStreamTrackAdapter::FinalizeRemoteTrackDisposingOnMainThread() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); + DCHECK(is_disposed_); remote_audio_track_adapter_ = nullptr; remote_video_track_adapter_ = nullptr; webrtc_track_ = nullptr; diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h index 722738c3950..8be75b5b895 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h @@ -53,6 +53,7 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapter void Dispose(); bool is_initialized() const; + void InitializeOnMainThread(); // These methods must be called on the main thread. // TODO(hbos): Allow these methods to be called on any thread and make them // const. https://crbug.com/756436 @@ -116,6 +117,7 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapter // completed on the main thread. base::WaitableEvent remote_track_can_complete_initialization_; bool is_initialized_; + bool is_disposed_; blink::WebMediaStreamTrack web_track_; scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_; // If the track is local, a sink is added to the local webrtc track that is diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.cc index 28d6c1713a4..de3f036beff 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.cc @@ -59,6 +59,17 @@ WebRtcMediaStreamTrackAdapterMap::AdapterRef::Copy() const { return base::WrapUnique(new AdapterRef(map_, type_, adapter_)); } +void WebRtcMediaStreamTrackAdapterMap::AdapterRef::InitializeOnMainThread() { + adapter_->InitializeOnMainThread(); + if (type_ == WebRtcMediaStreamTrackAdapterMap::AdapterRef::Type::kRemote) { + base::AutoLock scoped_lock(map_->lock_); + if (!map_->remote_track_adapters_.FindBySecondary(web_track().UniqueId())) { + map_->remote_track_adapters_.SetSecondaryKey(webrtc_track(), + web_track().UniqueId()); + } + } +} + WebRtcMediaStreamTrackAdapterMap::WebRtcMediaStreamTrackAdapterMap( PeerConnectionDependencyFactory* const factory, scoped_refptr<base::SingleThreadTaskRunner> main_thread) @@ -182,13 +193,13 @@ WebRtcMediaStreamTrackAdapterMap::GetOrCreateRemoteTrackAdapter( // entry as its secondary key. This ensures that there is at least one // |AdapterRef| alive until after the adapter is initialized and its secondary // key is set. + auto adapter_ref = base::WrapUnique( + new AdapterRef(this, AdapterRef::Type::kRemote, new_adapter)); main_thread_->PostTask( FROM_HERE, base::BindOnce( - &WebRtcMediaStreamTrackAdapterMap::OnRemoteTrackAdapterInitialized, - this, - base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kRemote, new_adapter)))); + &WebRtcMediaStreamTrackAdapterMap::AdapterRef::InitializeOnMainThread, + std::move(adapter_ref))); return base::WrapUnique( new AdapterRef(this, AdapterRef::Type::kRemote, new_adapter)); } @@ -198,14 +209,4 @@ size_t WebRtcMediaStreamTrackAdapterMap::GetRemoteTrackCount() const { return remote_track_adapters_.PrimarySize(); } -void WebRtcMediaStreamTrackAdapterMap::OnRemoteTrackAdapterInitialized( - std::unique_ptr<AdapterRef> adapter_ref) { - DCHECK(adapter_ref->is_initialized()); - { - base::AutoLock scoped_lock(lock_); - remote_track_adapters_.SetSecondaryKey(adapter_ref->webrtc_track(), - adapter_ref->web_track().UniqueId()); - } -} - } // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h index c7ef9ed9b92..8c9cbf17c0d 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h @@ -38,6 +38,7 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapterMap std::unique_ptr<AdapterRef> Copy() const; bool is_initialized() const { return adapter_->is_initialized(); } + void InitializeOnMainThread(); const blink::WebMediaStreamTrack& web_track() const { return adapter_->web_track(); } @@ -137,8 +138,6 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapterMap // Invoke on the main thread. virtual ~WebRtcMediaStreamTrackAdapterMap(); - void OnRemoteTrackAdapterInitialized(std::unique_ptr<AdapterRef> adapter_ref); - // Pointer to a |PeerConnectionDependencyFactory| owned by the |RenderThread|. // It's valid for the lifetime of |RenderThread|. PeerConnectionDependencyFactory* const factory_; diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc index 8c5fd3e426f..a141ce50156 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc @@ -53,8 +53,8 @@ class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test { } std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - GetOrCreateRemoteTrackAdapter( - webrtc::MediaStreamTrackInterface* webrtc_track) { + GetOrCreateRemoteTrackAdapter(webrtc::MediaStreamTrackInterface* webrtc_track, + bool wait_for_initialization = true) { DCHECK(main_thread_->BelongsToCurrentThread()); std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> adapter; signaling_thread()->PostTask( @@ -63,7 +63,13 @@ class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test { GetOrCreateRemoteTrackAdapterOnSignalingThread, base::Unretained(this), base::Unretained(webrtc_track), &adapter)); - RunMessageLoopsUntilIdle(); + RunMessageLoopsUntilIdle(wait_for_initialization); + DCHECK(adapter); + if (wait_for_initialization) { + DCHECK(adapter->is_initialized()); + } else { + DCHECK(!adapter->is_initialized()); + } return adapter; } @@ -76,7 +82,7 @@ class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test { // Runs message loops on the webrtc signaling thread and the main thread until // idle. - void RunMessageLoopsUntilIdle() { + void RunMessageLoopsUntilIdle(bool run_loop_on_main_thread = true) { DCHECK(main_thread_->BelongsToCurrentThread()); base::WaitableEvent waitable_event( base::WaitableEvent::ResetPolicy::MANUAL, @@ -86,7 +92,8 @@ class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test { RunMessageLoopUntilIdleOnSignalingThread, base::Unretained(this), &waitable_event)); waitable_event.Wait(); - base::RunLoop().RunUntilIdle(); + if (run_loop_on_main_thread) + base::RunLoop().RunUntilIdle(); } void RunMessageLoopUntilIdleOnSignalingThread( @@ -168,6 +175,29 @@ TEST_F(WebRtcMediaStreamTrackAdapterMapTest, AddAndRemoveRemoteTrackAdapter) { } TEST_F(WebRtcMediaStreamTrackAdapterMapTest, + InitializeRemoteTrackAdapterExplicitly) { + scoped_refptr<MockWebRtcAudioTrack> webrtc_track = + MockWebRtcAudioTrack::Create("remote_track"); + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> adapter_ref = + GetOrCreateRemoteTrackAdapter(webrtc_track.get(), false); + EXPECT_FALSE(adapter_ref->is_initialized()); + adapter_ref->InitializeOnMainThread(); + EXPECT_TRUE(adapter_ref->is_initialized()); + + EXPECT_EQ(1u, map_->GetRemoteTrackCount()); + // Ensure the implicit initialization's posted task is run after it is already + // initialized. + RunMessageLoopsUntilIdle(); + // Destroying all references to the adapter should remove it from the map and + // dispose it. + adapter_ref.reset(); + EXPECT_EQ(0u, map_->GetRemoteTrackCount()); + EXPECT_EQ(nullptr, map_->GetRemoteTrackAdapter(webrtc_track.get())); + // Allow the disposing of track to occur. + RunMessageLoopsUntilIdle(); +} + +TEST_F(WebRtcMediaStreamTrackAdapterMapTest, LocalAndRemoteTrackAdaptersWithSameID) { // Local and remote tracks should be able to use the same id without conflict. const char* id = "id"; diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc index 7ca513bc07f..74f586d44b1 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc @@ -37,7 +37,6 @@ class WebRtcMediaStreamTrackAdapterTest : public ::testing::Test { if (track_adapter_) { EXPECT_TRUE(track_adapter_->is_initialized()); track_adapter_->Dispose(); - EXPECT_FALSE(track_adapter_->is_initialized()); track_adapter_ = nullptr; RunMessageLoopsUntilIdle(); } @@ -80,9 +79,9 @@ class WebRtcMediaStreamTrackAdapterTest : public ::testing::Test { dependency_factory_.get(), main_thread_, webrtc_track); } - // Runs message loops on the webrtc signaling thread and the main thread until - // idle. - void RunMessageLoopsUntilIdle() { + // Runs message loops on the webrtc signaling thread and optionally the main + // thread until idle. + void RunMessageLoopsUntilIdle(bool run_loop_on_main_thread = true) { base::WaitableEvent waitable_event( base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED); @@ -91,7 +90,8 @@ class WebRtcMediaStreamTrackAdapterTest : public ::testing::Test { RunMessageLoopUntilIdleOnSignalingThread, base::Unretained(this), &waitable_event)); waitable_event.Wait(); - base::RunLoop().RunUntilIdle(); + if (run_loop_on_main_thread) + base::RunLoop().RunUntilIdle(); } void RunMessageLoopUntilIdleOnSignalingThread( @@ -157,6 +157,7 @@ TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteAudioTrack) { base::BindOnce( &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter, base::Unretained(this), base::Unretained(webrtc_track.get()))); + // The adapter is initialized implicitly in a PostTask, allow it to run. RunMessageLoopsUntilIdle(); DCHECK(track_adapter_); EXPECT_TRUE(track_adapter_->is_initialized()); @@ -181,6 +182,7 @@ TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteVideoTrack) { base::BindOnce( &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter, base::Unretained(this), base::Unretained(webrtc_track.get()))); + // The adapter is initialized implicitly in a PostTask, allow it to run. RunMessageLoopsUntilIdle(); DCHECK(track_adapter_); EXPECT_TRUE(track_adapter_->is_initialized()); @@ -197,4 +199,33 @@ TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteVideoTrack) { track_adapter_->GetRemoteVideoTrackAdapterForTesting()->initialized()); } +TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteTrackExplicitlyInitialized) { + scoped_refptr<MockWebRtcAudioTrack> webrtc_track = + MockWebRtcAudioTrack::Create("remote_audio_track"); + dependency_factory_->GetWebRtcSignalingThread()->PostTask( + FROM_HERE, + base::BindOnce( + &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter, + base::Unretained(this), base::Unretained(webrtc_track.get()))); + // Wait for the CreateRemoteTrackAdapter() call, but don't run the main thread + // loop that would have implicitly initialized the adapter. + RunMessageLoopsUntilIdle(false); + DCHECK(track_adapter_); + EXPECT_FALSE(track_adapter_->is_initialized()); + // Explicitly initialize before the main thread loop has a chance to run. + track_adapter_->InitializeOnMainThread(); + EXPECT_TRUE(track_adapter_->is_initialized()); + EXPECT_TRUE(!track_adapter_->web_track().IsNull()); + EXPECT_EQ(track_adapter_->web_track().Source().GetType(), + blink::WebMediaStreamSource::kTypeAudio); + EXPECT_TRUE(track_adapter_->webrtc_track()); + EXPECT_EQ(track_adapter_->webrtc_track()->kind(), + webrtc::MediaStreamTrackInterface::kAudioKind); + EXPECT_EQ(track_adapter_->webrtc_track()->id().c_str(), + track_adapter_->web_track().Id()); + EXPECT_TRUE(track_adapter_->GetRemoteAudioTrackAdapterForTesting()); + EXPECT_TRUE( + track_adapter_->GetRemoteAudioTrackAdapterForTesting()->initialized()); +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.cc b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.cc new file mode 100644 index 00000000000..f36ef07ad97 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/webrtc/webrtc_set_description_observer.h" + +#include "base/logging.h" + +namespace content { + +WebRtcSetDescriptionObserver::States::States() + : signaling_state( + webrtc::PeerConnectionInterface::SignalingState::kClosed) {} + +WebRtcSetDescriptionObserver::States::States(States&& other) + : signaling_state(other.signaling_state), + transceiver_states(std::move(other.transceiver_states)) {} + +WebRtcSetDescriptionObserver::States::~States() = default; + +WebRtcSetDescriptionObserver::States& WebRtcSetDescriptionObserver::States:: +operator=(States&& other) { + signaling_state = other.signaling_state; + transceiver_states = std::move(other.transceiver_states); + return *this; +} + +WebRtcSetDescriptionObserver::WebRtcSetDescriptionObserver() = default; + +WebRtcSetDescriptionObserver::~WebRtcSetDescriptionObserver() = default; + +WebRtcSetDescriptionObserverHandlerImpl:: + WebRtcSetDescriptionObserverHandlerImpl( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + pc_(std::move(pc)), + track_adapter_map_(std::move(track_adapter_map)), + observer_(std::move(observer)), + surface_receivers_only_(surface_receivers_only) {} + +WebRtcSetDescriptionObserverHandlerImpl:: + ~WebRtcSetDescriptionObserverHandlerImpl() = default; + +void WebRtcSetDescriptionObserverHandlerImpl::OnSetDescriptionComplete( + webrtc::RTCError error) { + CHECK(signaling_task_runner_->BelongsToCurrentThread()); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + receiver_only_transceivers; + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (surface_receivers_only_) { + for (const auto& receiver : pc_->GetReceivers()) { + transceivers.push_back(new SurfaceReceiverStateOnly(receiver)); + } + } else { + transceivers = pc_->GetTransceivers(); + } + TransceiverStateSurfacer transceiver_state_surfacer(main_task_runner_, + signaling_task_runner_); + transceiver_state_surfacer.Initialize(track_adapter_map_, + std::move(transceivers)); + main_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&WebRtcSetDescriptionObserverHandlerImpl:: + OnSetDescriptionCompleteOnMainThread, + this, std::move(error), pc_->signaling_state(), + std::move(transceiver_state_surfacer))); +} + +void WebRtcSetDescriptionObserverHandlerImpl:: + OnSetDescriptionCompleteOnMainThread( + webrtc::RTCError error, + webrtc::PeerConnectionInterface::SignalingState signaling_state, + TransceiverStateSurfacer transceiver_state_surfacer) { + CHECK(main_task_runner_->BelongsToCurrentThread()); + WebRtcSetDescriptionObserver::States states; + states.signaling_state = signaling_state; + states.transceiver_states = transceiver_state_surfacer.ObtainStates(); + observer_->OnSetDescriptionComplete(std::move(error), std::move(states)); +} + +scoped_refptr<WebRtcSetLocalDescriptionObserverHandler> +WebRtcSetLocalDescriptionObserverHandler::Create( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) { + return new rtc::RefCountedObject<WebRtcSetLocalDescriptionObserverHandler>( + std::move(main_task_runner), std::move(signaling_task_runner), + std::move(pc), std::move(track_adapter_map), std::move(observer), + surface_receivers_only); +} + +WebRtcSetLocalDescriptionObserverHandler:: + WebRtcSetLocalDescriptionObserverHandler( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) + : handler_impl_(new WebRtcSetDescriptionObserverHandlerImpl( + std::move(main_task_runner), + std::move(signaling_task_runner), + std::move(pc), + std::move(track_adapter_map), + std::move(observer), + surface_receivers_only)) {} + +WebRtcSetLocalDescriptionObserverHandler:: + ~WebRtcSetLocalDescriptionObserverHandler() = default; + +void WebRtcSetLocalDescriptionObserverHandler::OnSuccess() { + handler_impl_->OnSetDescriptionComplete(webrtc::RTCError::OK()); +} + +void WebRtcSetLocalDescriptionObserverHandler::OnFailure( + webrtc::RTCError error) { + handler_impl_->OnSetDescriptionComplete(std::move(error)); +} + +scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> +WebRtcSetRemoteDescriptionObserverHandler::Create( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) { + return new rtc::RefCountedObject<WebRtcSetRemoteDescriptionObserverHandler>( + std::move(main_task_runner), std::move(signaling_task_runner), + std::move(pc), std::move(track_adapter_map), std::move(observer), + surface_receivers_only); +} + +WebRtcSetRemoteDescriptionObserverHandler:: + WebRtcSetRemoteDescriptionObserverHandler( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) + : handler_impl_(new WebRtcSetDescriptionObserverHandlerImpl( + std::move(main_task_runner), + std::move(signaling_task_runner), + std::move(pc), + std::move(track_adapter_map), + std::move(observer), + surface_receivers_only)) {} + +WebRtcSetRemoteDescriptionObserverHandler:: + ~WebRtcSetRemoteDescriptionObserverHandler() = default; + +void WebRtcSetRemoteDescriptionObserverHandler::OnSetRemoteDescriptionComplete( + webrtc::RTCError error) { + handler_impl_->OnSetDescriptionComplete(std::move(error)); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.h b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.h new file mode 100644 index 00000000000..41e84950259 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.h @@ -0,0 +1,186 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_DESCRIPTION_OBSERVER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_DESCRIPTION_OBSERVER_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "content/common/content_export.h" +#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h" +#include "content/renderer/media/webrtc/rtc_rtp_receiver.h" +#include "content/renderer/media/webrtc/rtc_rtp_sender.h" +#include "content/renderer/media/webrtc/rtc_rtp_transceiver.h" +#include "content/renderer/media/webrtc/transceiver_state_surfacer.h" +#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" +#include "third_party/webrtc/api/jsep.h" +#include "third_party/webrtc/api/peerconnectioninterface.h" +#include "third_party/webrtc/api/rtcerror.h" +#include "third_party/webrtc/api/rtpreceiverinterface.h" +#include "third_party/webrtc/api/setremotedescriptionobserverinterface.h" +#include "third_party/webrtc/rtc_base/refcount.h" +#include "third_party/webrtc/rtc_base/refcountedobject.h" +#include "third_party/webrtc/rtc_base/scoped_ref_ptr.h" + +namespace content { + +// The content layer correspondent of the setLocalDescription() observer +// (webrtc::SetSessionDescriptionObserver) and setRemoteDescription() observer +// (webrtc::SetRemoteDescriptionObserverInterface). The implementation should +// process the state changes of the Set[Local/Remote]Description() by inspecting +// the updated States. +class CONTENT_EXPORT WebRtcSetDescriptionObserver + : public base::RefCountedThreadSafe<WebRtcSetDescriptionObserver> { + public: + // The states as they were when the operation finished on the webrtc signaling + // thread. Note that other operations may have occurred while jumping back to + // the main thread, but these must be handled separately. + struct CONTENT_EXPORT States { + States(); + States(States&& other); + ~States(); + + States& operator=(States&& other); + + webrtc::PeerConnectionInterface::SignalingState signaling_state; + std::vector<RtpTransceiverState> transceiver_states; + + DISALLOW_COPY_AND_ASSIGN(States); + }; + + WebRtcSetDescriptionObserver(); + + // Invoked in a PostTask() on the main thread after the SetLocalDescription() + // or SetRemoteDescription() operation completed on the webrtc signaling + // thread. + virtual void OnSetDescriptionComplete(webrtc::RTCError error, + States states) = 0; + + protected: + friend class base::RefCountedThreadSafe<WebRtcSetDescriptionObserver>; + virtual ~WebRtcSetDescriptionObserver(); + + DISALLOW_COPY_AND_ASSIGN(WebRtcSetDescriptionObserver); +}; + +// Takes care of surfacing WebRtcSetDescriptionObserver::State information from +// the webrtc signaling thread to the main thread. With the state information +// obtained, invokes |observer_|'s +// WebRtcSetDescriptionObserver::OnSetDescriptionComplete() on the main thread. +// +// This implements the behavior +// of both WebRtcSetLocalDescriptionObserverHandler and +// WebRtcSetRemoteDescriptionObserverHandler, but these are put in different +// classes because local and remote description observers have different +// interfaces in webrtc. +class CONTENT_EXPORT WebRtcSetDescriptionObserverHandlerImpl + : public base::RefCountedThreadSafe< + WebRtcSetDescriptionObserverHandlerImpl> { + public: + WebRtcSetDescriptionObserverHandlerImpl( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + + // Must be called on the webrtc signaling thread internally by the handler + // when the Set[Local/Remote]Description() operation finishes. + void OnSetDescriptionComplete(webrtc::RTCError error); + + private: + friend class base::RefCountedThreadSafe< + WebRtcSetDescriptionObserverHandlerImpl>; + virtual ~WebRtcSetDescriptionObserverHandlerImpl(); + + void OnSetDescriptionCompleteOnMainThread( + webrtc::RTCError error, + webrtc::PeerConnectionInterface::SignalingState signaling_state, + TransceiverStateSurfacer transceiver_state_surfacer); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + scoped_refptr<webrtc::PeerConnectionInterface> pc_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; + scoped_refptr<WebRtcSetDescriptionObserver> observer_; + bool surface_receivers_only_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcSetDescriptionObserverHandlerImpl); +}; + +// An implementation of webrtc::SetSessionDescriptionObserver for performing the +// operations of WebRtcSetDescriptionObserverHandlerImpl. +class CONTENT_EXPORT WebRtcSetLocalDescriptionObserverHandler + : public webrtc::SetSessionDescriptionObserver { + public: + static scoped_refptr<WebRtcSetLocalDescriptionObserverHandler> Create( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + + // webrtc::SetSessionDescriptionObserver implementation. Implementation calls + // WebRtcSetDescriptionObserverHandlerImpl::OnSetDescriptionComplete(). + void OnSuccess() override; + void OnFailure(webrtc::RTCError error) override; + + protected: + WebRtcSetLocalDescriptionObserverHandler( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + ~WebRtcSetLocalDescriptionObserverHandler() override; + + scoped_refptr<WebRtcSetDescriptionObserverHandlerImpl> handler_impl_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcSetLocalDescriptionObserverHandler); +}; + +// An implementation of webrtc::SetRemoteDescriptionObserverInterface for +// performing the operations of WebRtcSetDescriptionObserverHandlerImpl. +class CONTENT_EXPORT WebRtcSetRemoteDescriptionObserverHandler + : public webrtc::SetRemoteDescriptionObserverInterface { + public: + static scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> Create( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + + // webrtc::SetRemoteDescriptionObserverInterface implementation. + // Implementation calls + // WebRtcSetDescriptionObserverHandlerImpl::OnSetDescriptionComplete(). + void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override; + + protected: + WebRtcSetRemoteDescriptionObserverHandler( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + ~WebRtcSetRemoteDescriptionObserverHandler() override; + + scoped_refptr<WebRtcSetDescriptionObserverHandlerImpl> handler_impl_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcSetRemoteDescriptionObserverHandler); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_DESCRIPTION_OBSERVER_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc index 5b861458a11..c2f7dc786b0 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/webrtc/webrtc_set_remote_description_observer.h" +#include "content/renderer/media/webrtc/webrtc_set_description_observer.h" #include <memory> #include <utility> @@ -16,7 +16,6 @@ #include "content/child/child_process.h" #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/mock_peer_connection_impl.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" @@ -29,35 +28,41 @@ using ::testing::Return; namespace content { -class WebRtcSetRemoteDescriptionObserverForTest - : public WebRtcSetRemoteDescriptionObserver { +class WebRtcSetDescriptionObserverForTest + : public WebRtcSetDescriptionObserver { public: - bool called() const { return states_or_error_.has_value(); } - bool result() const { return states_or_error_->ok(); } + bool called() const { return called_; } - const WebRtcSetRemoteDescriptionObserver::States& states() const { - DCHECK(called() && result()); - return states_or_error_->value(); + const WebRtcSetDescriptionObserver::States& states() const { + DCHECK(called_); + return states_; } const webrtc::RTCError& error() const { - DCHECK(called() && !result()); - return states_or_error_->error(); + DCHECK(called_); + return error_; } - // WebRtcSetRemoteDescriptionObserver implementation. - void OnSetRemoteDescriptionComplete( - webrtc::RTCErrorOr<States> states_or_error) override { - states_or_error_ = std::move(states_or_error); + // WebRtcSetDescriptionObserver implementation. + void OnSetDescriptionComplete( + webrtc::RTCError error, + WebRtcSetDescriptionObserver::States states) override { + called_ = true; + error_ = std::move(error); + states_ = std::move(states); } private: - ~WebRtcSetRemoteDescriptionObserverForTest() override {} + ~WebRtcSetDescriptionObserverForTest() override {} - base::Optional<webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States>> - states_or_error_; - WebRtcSetRemoteDescriptionObserver::States states_; + bool called_ = false; + webrtc::RTCError error_; + WebRtcSetDescriptionObserver::States states_; }; +// TODO(hbos): This only tests WebRtcSetRemoteDescriptionObserverHandler, +// parameterize the test to make it also test +// WebRtcSetLocalDescriptionObserverHandler and with "surface_receivers_only" as +// both true and false. https://crbug.com/865006 class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test { public: void SetUp() override { @@ -66,14 +71,13 @@ class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test { new cricket::FakeMediaEngine()))); dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); - scoped_refptr<WebRtcMediaStreamAdapterMap> map = - new WebRtcMediaStreamAdapterMap( - dependency_factory_.get(), main_thread_, - new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), - main_thread_)); - observer_ = new WebRtcSetRemoteDescriptionObserverForTest(); + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> map = + new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), + main_thread_); + observer_ = new WebRtcSetDescriptionObserverForTest(); observer_handler_ = WebRtcSetRemoteDescriptionObserverHandler::Create( - main_thread_, pc_, map, observer_); + main_thread_, dependency_factory_->GetWebRtcSignalingThread(), pc_, map, + observer_, true /* surface_receivers_only*/); } void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); } @@ -106,7 +110,7 @@ class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test { scoped_refptr<webrtc::MockPeerConnection> pc_; std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<WebRtcSetRemoteDescriptionObserverForTest> observer_; + scoped_refptr<WebRtcSetDescriptionObserverForTest> observer_; scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> observer_handler_; std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> receivers_; @@ -124,28 +128,65 @@ TEST_F(WebRtcSetRemoteDescriptionObserverHandlerTest, OnSuccess) { {added_stream.get()}))); receivers_.push_back(added_receiver.get()); + EXPECT_CALL(*pc_, signaling_state()) + .WillRepeatedly(Return(webrtc::PeerConnectionInterface::kStable)); EXPECT_CALL(*pc_, GetReceivers()).WillRepeatedly(Return(receivers_)); InvokeOnSetRemoteDescriptionComplete(webrtc::RTCError::OK()); EXPECT_TRUE(observer_->called()); - EXPECT_TRUE(observer_->result()); - - EXPECT_EQ(1u, observer_->states().receiver_states.size()); - const WebRtcReceiverState& receiver_state = - observer_->states().receiver_states[0]; - EXPECT_EQ(added_receiver, receiver_state.receiver); - EXPECT_EQ(added_track, receiver_state.track_ref->webrtc_track()); - EXPECT_EQ(1u, receiver_state.stream_refs.size()); - EXPECT_EQ(added_stream, - receiver_state.stream_refs[0]->adapter().webrtc_stream()); + EXPECT_TRUE(observer_->error().ok()); + + EXPECT_EQ(webrtc::PeerConnectionInterface::kStable, + observer_->states().signaling_state); + + EXPECT_EQ(1u, observer_->states().transceiver_states.size()); + const RtpTransceiverState& transceiver_state = + observer_->states().transceiver_states[0]; + EXPECT_FALSE(transceiver_state.sender_state()); + EXPECT_TRUE(transceiver_state.receiver_state()); + const RtpReceiverState& receiver_state = *transceiver_state.receiver_state(); + EXPECT_EQ(added_receiver, receiver_state.webrtc_receiver()); + EXPECT_EQ(added_track, receiver_state.track_ref()->webrtc_track()); + EXPECT_EQ(1u, receiver_state.stream_ids().size()); + EXPECT_EQ(added_stream->id(), receiver_state.stream_ids()[0]); } TEST_F(WebRtcSetRemoteDescriptionObserverHandlerTest, OnFailure) { - webrtc::RTCError error(webrtc::RTCErrorType::INVALID_PARAMETER, "Oh noes!"); - InvokeOnSetRemoteDescriptionComplete(std::move(error)); + scoped_refptr<MockWebRtcAudioTrack> added_track = + MockWebRtcAudioTrack::Create("added_track"); + scoped_refptr<webrtc::MediaStreamInterface> added_stream( + new rtc::RefCountedObject<MockMediaStream>("added_stream")); + scoped_refptr<webrtc::RtpReceiverInterface> added_receiver( + new rtc::RefCountedObject<FakeRtpReceiver>( + added_track.get(), + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>( + {added_stream.get()}))); + + receivers_.push_back(added_receiver.get()); + EXPECT_CALL(*pc_, signaling_state()) + .WillRepeatedly(Return(webrtc::PeerConnectionInterface::kStable)); + EXPECT_CALL(*pc_, GetReceivers()).WillRepeatedly(Return(receivers_)); + + InvokeOnSetRemoteDescriptionComplete( + webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER, "Oh noes!")); EXPECT_TRUE(observer_->called()); - EXPECT_FALSE(observer_->result()); + EXPECT_FALSE(observer_->error().ok()); EXPECT_EQ(std::string("Oh noes!"), observer_->error().message()); + + // Verify states were surfaced even though we got an error. + EXPECT_EQ(webrtc::PeerConnectionInterface::kStable, + observer_->states().signaling_state); + + EXPECT_EQ(1u, observer_->states().transceiver_states.size()); + const RtpTransceiverState& transceiver_state = + observer_->states().transceiver_states[0]; + EXPECT_FALSE(transceiver_state.sender_state()); + EXPECT_TRUE(transceiver_state.receiver_state()); + const RtpReceiverState& receiver_state = *transceiver_state.receiver_state(); + EXPECT_EQ(added_receiver, receiver_state.webrtc_receiver()); + EXPECT_EQ(added_track, receiver_state.track_ref()->webrtc_track()); + EXPECT_EQ(1u, receiver_state.stream_ids().size()); + EXPECT_EQ(added_stream->id(), receiver_state.stream_ids()[0]); } } // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.cc b/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.cc deleted file mode 100644 index 0ebb644548b..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.cc +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_set_remote_description_observer.h" - -#include "base/logging.h" - -namespace content { - -WebRtcReceiverState::WebRtcReceiverState( - scoped_refptr<webrtc::RtpReceiverInterface> receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs) - : receiver(std::move(receiver)), - track_ref(std::move(track_ref)), - stream_refs(std::move(stream_refs)) {} - -WebRtcReceiverState::WebRtcReceiverState(WebRtcReceiverState&& other) = default; - -WebRtcReceiverState& WebRtcReceiverState::operator=( - WebRtcReceiverState&& other) = default; - -WebRtcReceiverState::~WebRtcReceiverState() {} - -WebRtcSetRemoteDescriptionObserver::States::States() {} - -WebRtcSetRemoteDescriptionObserver::States::States(States&& other) - : receiver_states(std::move(other.receiver_states)) {} - -WebRtcSetRemoteDescriptionObserver::States::~States() {} - -WebRtcSetRemoteDescriptionObserver::States& -WebRtcSetRemoteDescriptionObserver::States::operator=(States&& other) { - receiver_states = std::move(other.receiver_states); - return *this; -} - -void WebRtcSetRemoteDescriptionObserver::States::CheckInvariants() const { - // Invariants: - // - All receiver states have a stream ref - // - All receiver states refer to streams that are non-null. - for (auto& receiver_state : receiver_states) { - for (auto& stream_ref : receiver_state.stream_refs) { - CHECK(stream_ref); - CHECK(!stream_ref->adapter().web_stream().IsNull()); - } - } -} - -WebRtcSetRemoteDescriptionObserver::WebRtcSetRemoteDescriptionObserver() {} - -WebRtcSetRemoteDescriptionObserver::~WebRtcSetRemoteDescriptionObserver() {} - -scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> -WebRtcSetRemoteDescriptionObserverHandler::Create( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<webrtc::PeerConnectionInterface> pc, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map, - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer) { - return new rtc::RefCountedObject<WebRtcSetRemoteDescriptionObserverHandler>( - std::move(main_thread), std::move(pc), std::move(stream_adapter_map), - std::move(observer)); -} - -WebRtcSetRemoteDescriptionObserverHandler:: - WebRtcSetRemoteDescriptionObserverHandler( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<webrtc::PeerConnectionInterface> pc, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map, - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer) - : main_thread_(std::move(main_thread)), - pc_(std::move(pc)), - stream_adapter_map_(std::move(stream_adapter_map)), - observer_(std::move(observer)) {} - -WebRtcSetRemoteDescriptionObserverHandler:: - ~WebRtcSetRemoteDescriptionObserverHandler() {} - -void WebRtcSetRemoteDescriptionObserverHandler::OnSetRemoteDescriptionComplete( - webrtc::RTCError error) { - CHECK(!main_thread_->BelongsToCurrentThread()); - - webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States> - states_or_error; - if (error.ok()) { - WebRtcSetRemoteDescriptionObserver::States states; - for (const auto& webrtc_receiver : pc_->GetReceivers()) { - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref = - track_adapter_map()->GetOrCreateRemoteTrackAdapter( - webrtc_receiver->track().get()); - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs; - for (const auto& stream : webrtc_receiver->streams()) { - stream_refs.push_back( - stream_adapter_map_->GetOrCreateRemoteStreamAdapter(stream.get())); - } - states.receiver_states.push_back(WebRtcReceiverState( - webrtc_receiver.get(), std::move(track_ref), std::move(stream_refs))); - } - states_or_error = std::move(states); - } else { - states_or_error = std::move(error); - } - main_thread_->PostTask( - FROM_HERE, base::BindOnce(&WebRtcSetRemoteDescriptionObserverHandler:: - OnSetRemoteDescriptionCompleteOnMainThread, - this, std::move(states_or_error))); -} - -void WebRtcSetRemoteDescriptionObserverHandler:: - OnSetRemoteDescriptionCompleteOnMainThread( - webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States> - states_or_error) { - CHECK(main_thread_->BelongsToCurrentThread()); - observer_->OnSetRemoteDescriptionComplete(std::move(states_or_error)); -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.h b/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.h deleted file mode 100644 index 1102c415990..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_REMOTE_DESCRIPTION_OBSERVER_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_REMOTE_DESCRIPTION_OBSERVER_H_ - -#include <vector> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_refptr.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "content/common/content_export.h" -#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h" -#include "third_party/webrtc/api/rtcerror.h" -#include "third_party/webrtc/api/rtpreceiverinterface.h" -#include "third_party/webrtc/api/setremotedescriptionobserverinterface.h" -#include "third_party/webrtc/rtc_base/refcount.h" -#include "third_party/webrtc/rtc_base/refcountedobject.h" -#include "third_party/webrtc/rtc_base/scoped_ref_ptr.h" - -namespace content { - -// Describes an instance of a receiver at the time the SRD call was completed. -// Because webrtc and content operate on different threads, webrtc objects may -// have been modified by the time we synchronize the receivers on the main -// thread, and members of this class should be inspected rather than members of -// |receiver|. -struct CONTENT_EXPORT WebRtcReceiverState { - WebRtcReceiverState( - scoped_refptr<webrtc::RtpReceiverInterface> receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs); - WebRtcReceiverState(WebRtcReceiverState&& other); - ~WebRtcReceiverState(); - - WebRtcReceiverState& operator=(WebRtcReceiverState&& other); - - scoped_refptr<webrtc::RtpReceiverInterface> receiver; - // The receiver's track when the SRD occurred. - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; - // The receiver's associated set of streams when the SRD occurred. - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs; - - DISALLOW_COPY_AND_ASSIGN(WebRtcReceiverState); -}; - -// The content layer correspondent of -// webrtc::SetRemoteDescriptionObserverInterface. It's an interface with -// callbacks for handling the result of SetRemoteDescription on the main thread. -// The implementation should process the state changes of the -// SetRemoteDescription by inspecting the updated States. -class CONTENT_EXPORT WebRtcSetRemoteDescriptionObserver - : public base::RefCountedThreadSafe<WebRtcSetRemoteDescriptionObserver> { - public: - // The relevant peer connection states as they were when the - // SetRemoteDescription call completed. This is used instead of inspecting the - // PeerConnection and other webrtc objects directly because they may have been - // modified before we reach the main thread. - struct CONTENT_EXPORT States { - States(); - States(States&& other); - ~States(); - - States& operator=(States&& other); - - // The receivers at the time of the event. - std::vector<WebRtcReceiverState> receiver_states; - // Check that the invariants for this structure hold. - void CheckInvariants() const; - - DISALLOW_COPY_AND_ASSIGN(States); - }; - - WebRtcSetRemoteDescriptionObserver(); - - // Invoked asynchronously on the main thread after the SetRemoteDescription - // completed on the webrtc signaling thread. - virtual void OnSetRemoteDescriptionComplete( - webrtc::RTCErrorOr<States> states_or_error) = 0; - - protected: - friend class base::RefCountedThreadSafe<WebRtcSetRemoteDescriptionObserver>; - virtual ~WebRtcSetRemoteDescriptionObserver(); - - DISALLOW_COPY_AND_ASSIGN(WebRtcSetRemoteDescriptionObserver); -}; - -// The glue between webrtc and content layer observers listening to -// SetRemoteDescription. This observer listens on the webrtc signaling thread -// for the result of SetRemoteDescription, copies any relevant webrtc peer -// connection states such that they can be processed on the main thread, and -// invokes the WebRtcSetRemoteDescriptionObserver on the main thread with the -// state changes. -class CONTENT_EXPORT WebRtcSetRemoteDescriptionObserverHandler - : public webrtc::SetRemoteDescriptionObserverInterface { - public: - static scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> Create( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<webrtc::PeerConnectionInterface> pc, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map, - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer); - - // webrtc::SetRemoteDescriptionObserverInterface implementation. - void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override; - - protected: - WebRtcSetRemoteDescriptionObserverHandler( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<webrtc::PeerConnectionInterface> pc, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map, - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer); - ~WebRtcSetRemoteDescriptionObserverHandler() override; - - private: - void OnSetRemoteDescriptionCompleteOnMainThread( - webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States> - states_or_error); - - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map() const { - return stream_adapter_map_->track_adapter_map(); - } - - scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<webrtc::PeerConnectionInterface> pc_; - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map_; - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer_; - - DISALLOW_COPY_AND_ASSIGN(WebRtcSetRemoteDescriptionObserverHandler); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_REMOTE_DESCRIPTION_OBSERVER_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_util.h b/chromium/content/renderer/media/webrtc/webrtc_util.h new file mode 100644 index 00000000000..425c0ec9373 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/webrtc_util.h @@ -0,0 +1,35 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_UTIL_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_UTIL_H_ + +#include "base/optional.h" + +namespace content { + +template <typename OptionalT> +base::Optional<typename OptionalT::value_type> ToBaseOptional( + const OptionalT& optional) { + return optional ? base::make_optional(*optional) : base::nullopt; +} + +template <typename OptionalT> +absl::optional<typename OptionalT::value_type> ToAbslOptional( + const OptionalT& optional) { + return optional ? absl::make_optional(*optional) : absl::nullopt; +} + +template <typename OptionalT1, typename OptionalT2> +bool OptionalEquals(const OptionalT1& lhs, const OptionalT2& rhs) { + if (!lhs) + return !rhs; + if (!rhs) + return false; + return *lhs == *rhs; +} + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_UTIL_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc index 95357d45e98..57ae21ee241 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc @@ -209,7 +209,9 @@ bool WebRtcVideoCapturerAdapter::ShouldAdaptResolution() const { return true; } if (content_hint_ == - blink::WebMediaStreamTrack::ContentHintType::kVideoDetail) { + blink::WebMediaStreamTrack::ContentHintType::kVideoDetail || + content_hint_ == + blink::WebMediaStreamTrack::ContentHintType::kVideoText) { return false; } // Screencast does not adapt by default. diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc index e076b3de238..ce1208152d4 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc @@ -117,44 +117,4 @@ TEST_F(WebRtcVideoCapturerAdapterTest, Scale720To640360) { TestSourceCropFrame(1280, 720, 1280, 720, 640, 360); } -TEST_F(WebRtcVideoCapturerAdapterTest, - NonScreencastAdapterDoesNotAdaptContentHintDetail) { - // Non-screenshare adapter should not adapt frames when detail is set. - TestContentHintResolutionAdaptation( - false, blink::WebMediaStreamTrack::ContentHintType::kNone, true, - blink::WebMediaStreamTrack::ContentHintType::kVideoDetail, false); -} - -TEST_F(WebRtcVideoCapturerAdapterTest, - NonScreencastAdapterAdaptsContentHintFluid) { - // Non-screenshare adapter should still adapt frames when motion is set. - TestContentHintResolutionAdaptation( - false, blink::WebMediaStreamTrack::ContentHintType::kNone, true, - blink::WebMediaStreamTrack::ContentHintType::kVideoMotion, true); -} - -TEST_F(WebRtcVideoCapturerAdapterTest, - ScreencastAdapterAdaptsContentHintFluid) { - // Screenshare adapter should adapt frames when motion is set. - TestContentHintResolutionAdaptation( - true, blink::WebMediaStreamTrack::ContentHintType::kNone, false, - blink::WebMediaStreamTrack::ContentHintType::kVideoMotion, true); -} - -TEST_F(WebRtcVideoCapturerAdapterTest, - ScreencastAdapterDoesNotAdaptContentHintDetailed) { - // Screenshare adapter should still not adapt frames when detail is set. - TestContentHintResolutionAdaptation( - true, blink::WebMediaStreamTrack::ContentHintType::kNone, false, - blink::WebMediaStreamTrack::ContentHintType::kVideoDetail, false); -} - -TEST_F(WebRtcVideoCapturerAdapterTest, RespectsConstructionTimeContentHint) { - // Non-screenshare adapter constructed with detail content hint should not - // adapt before SetContentHint is run. - TestContentHintResolutionAdaptation( - false, blink::WebMediaStreamTrack::ContentHintType::kVideoDetail, false, - blink::WebMediaStreamTrack::ContentHintType::kVideoMotion, true); -} - } // namespace content |