Commit 4979aac4 authored by Henrik Boström's avatar Henrik Boström Committed by Commit Bot

RTCPeerConnectionHandler: Keep track of senders.

https://chromium-review.googlesource.com/c/566806 showed that the
WebRtcRtpBrowserTest.AddAndRemoveTracks* tests would reliably crash
if the garbage collector was invoked between addTrack and getSenders.
Tracks that were added using addTrack would have their track adapters
(glue between blink and webrtc) kept alive only by the blink layer
sender holding on to a reference, since these were not kept alive by
any "local streams" holding a reference.

The blink::RTCPeerConnection now holds a strong reference to senders
and receivers to prevent GC while in-use, with TODOs to remove ones
no longer used when addStream/removeStream is implemented using
addTrack/removeTrack.

Furthermore the content::RTCPeerConnectionHandler holds on to the
content layer representation of senders so that their associated set
of streams are not forgotten between addTrack and getSenders.

Having the handler keep track of senders is good practice, this gets
rid of the assumption that blink layer senders have to be kept alive.
A TODO was added to do the same for receivers (not yet required because
blink layer receivers are kept alive).

With this change, the AddAndRemoveTracks* tests pass and are
re-enabled.

Bug: 740650
Change-Id: Iec3a39a994bef31904f2969d791125867ec1e398
Reviewed-on: https://chromium-review.googlesource.com/567184Reviewed-by: default avatarHenrik Boström <hbos@chromium.org>
Reviewed-by: default avatarTaylor Brandstetter <deadbeef@chromium.org>
Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Commit-Queue: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#487430}
parent b77a8e2b
...@@ -69,8 +69,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest, GetReceivers) { ...@@ -69,8 +69,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest, GetReceivers) {
VerifyRtpReceivers(right_tab_, 6); VerifyRtpReceivers(right_tab_, 6);
} }
IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest, IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest, AddAndRemoveTracksWithoutStream) {
DISABLED_AddAndRemoveTracksWithoutStream) {
StartServerAndOpenTabs(); StartServerAndOpenTabs();
SetupPeerconnectionWithoutLocalStream(left_tab_); SetupPeerconnectionWithoutLocalStream(left_tab_);
...@@ -151,7 +150,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest, ...@@ -151,7 +150,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest,
} }
IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest, IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest,
DISABLED_AddAndRemoveTracksWithSharedStream) { AddAndRemoveTracksWithSharedStream) {
StartServerAndOpenTabs(); StartServerAndOpenTabs();
SetupPeerconnectionWithoutLocalStream(left_tab_); SetupPeerconnectionWithoutLocalStream(left_tab_);
...@@ -232,7 +231,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest, ...@@ -232,7 +231,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest,
} }
IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest, IN_PROC_BROWSER_TEST_F(WebRtcRtpBrowserTest,
DISABLED_AddAndRemoveTracksWithIndividualStreams) { AddAndRemoveTracksWithIndividualStreams) {
StartServerAndOpenTabs(); StartServerAndOpenTabs();
SetupPeerconnectionWithoutLocalStream(left_tab_); SetupPeerconnectionWithoutLocalStream(left_tab_);
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include "content/renderer/media/rtc_dtmf_sender_handler.h" #include "content/renderer/media/rtc_dtmf_sender_handler.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/rtc_rtp_receiver.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_stats.h" #include "content/renderer/media/webrtc/rtc_stats.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" #include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
#include "content/renderer/media/webrtc_audio_device_impl.h" #include "content/renderer/media/webrtc_audio_device_impl.h"
...@@ -1586,6 +1585,10 @@ void RTCPeerConnectionHandler::RemoveStream( ...@@ -1586,6 +1585,10 @@ void RTCPeerConnectionHandler::RemoveStream(
PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter(); PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
webrtc_stream.get()); webrtc_stream.get());
// Make sure |rtp_senders_| is up-to-date. When |AddStream| and |RemoveStream|
// is implemented using |AddTrack| and |RemoveTrack|, add and remove
// |rtp_senders_| there. https://crbug.com/738929
GetSenders();
} }
void RTCPeerConnectionHandler::GetStats( void RTCPeerConnectionHandler::GetStats(
...@@ -1650,18 +1653,42 @@ RTCPeerConnectionHandler::GetSenders() { ...@@ -1650,18 +1653,42 @@ RTCPeerConnectionHandler::GetSenders() {
blink::WebVector<std::unique_ptr<blink::WebRTCRtpSender>> web_senders( blink::WebVector<std::unique_ptr<blink::WebRTCRtpSender>> web_senders(
webrtc_senders.size()); webrtc_senders.size());
for (size_t i = 0; i < web_senders.size(); ++i) { for (size_t i = 0; i < web_senders.size(); ++i) {
uintptr_t id = RTCRtpSender::getId(webrtc_senders[i]);
auto it = rtp_senders_.find(id);
if (it == rtp_senders_.end()) {
rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track = rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track =
webrtc_senders[i]->track(); webrtc_senders[i]->track();
std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter; std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
track_adapter;
if (webrtc_track) { if (webrtc_track) {
track_adapter = track_adapter =
track_adapter_map_->GetLocalTrackAdapter(webrtc_track->id()); track_adapter_map_->GetLocalTrackAdapter(webrtc_track->id());
DCHECK(track_adapter); DCHECK(track_adapter);
} }
// Create a reference to the sender. Multiple |RTCRtpSender|s can reference it = rtp_senders_
// the same webrtc track, see |id|. .insert(std::make_pair(
web_senders[i] = base::MakeUnique<RTCRtpSender>(webrtc_senders[i].get(), id, base::MakeUnique<RTCRtpSender>(
std::move(track_adapter)); webrtc_senders[i].get(), std::move(track_adapter))))
.first;
}
web_senders[i] = it->second->ShallowCopy();
}
// TODO(hbos): When |AddStream| and |RemoveStream| are implemented using
// |AddTrack| and |RemoveTrack|, add and remove |rtp_senders_| there instead
// of figuring out which ones are no longer used here.
// https://crbug.com/738929
for (auto it = rtp_senders_.begin(); it != rtp_senders_.end();) {
bool sender_exists = false;
for (auto webrtc_sender : webrtc_senders) {
if (RTCRtpSender::getId(webrtc_sender) == it->first) {
sender_exists = true;
break;
}
}
if (!sender_exists)
it = rtp_senders_.erase(it);
else
++it;
} }
return web_senders; return web_senders;
} }
...@@ -1720,9 +1747,16 @@ std::unique_ptr<blink::WebRTCRtpSender> RTCPeerConnectionHandler::AddTrack( ...@@ -1720,9 +1747,16 @@ std::unique_ptr<blink::WebRTCRtpSender> RTCPeerConnectionHandler::AddTrack(
webrtc_streams); webrtc_streams);
if (!webrtc_sender) if (!webrtc_sender)
return nullptr; return nullptr;
return base::MakeUnique<RTCRtpSender>(std::move(webrtc_sender), DCHECK(rtp_senders_.find(RTCRtpSender::getId(webrtc_sender)) ==
rtp_senders_.end());
auto it = rtp_senders_
.insert(std::make_pair(
RTCRtpSender::getId(webrtc_sender),
base::MakeUnique<RTCRtpSender>(std::move(webrtc_sender),
std::move(track_adapter), std::move(track_adapter),
std::move(stream_adapters)); std::move(stream_adapters))))
.first;
return it->second->ShallowCopy();
} }
bool RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) { bool RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) {
...@@ -1732,6 +1766,10 @@ bool RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) { ...@@ -1732,6 +1766,10 @@ bool RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) {
return false; return false;
} }
sender->OnRemoved(); sender->OnRemoved();
// Make sure |rtp_senders_| is up-to-date. When |AddStream| and |RemoveStream|
// is implemented using |AddTrack| and |RemoveTrack|, add and remove
// |rtp_senders_| there. https://crbug.com/738929
GetSenders();
return true; return true;
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/renderer/media/webrtc/media_stream_track_metrics.h" #include "content/renderer/media/webrtc/media_stream_track_metrics.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/webrtc_media_stream_adapter_map.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h"
#include "ipc/ipc_platform_file.h" #include "ipc/ipc_platform_file.h"
...@@ -284,6 +285,16 @@ class CONTENT_EXPORT RTCPeerConnectionHandler ...@@ -284,6 +285,16 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// peer connection using |AddStream| and |RemoveStream|. // peer connection using |AddStream| and |RemoveStream|.
std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>>
local_streams_; local_streams_;
// Maps |RTCRtpSender::getId|s of |webrtc::RtpSenderInterface| to the
// corresponding content layer sender. This is needed to retain the senders'
// associated set of streams for senders created by |AddTrack|.
std::map<uintptr_t, std::unique_ptr<RTCRtpSender>> rtp_senders_;
// We don't need an "rtp_receivers_" map as long as the blink layer receivers
// are not GC'd (protecting the relevant adapters from destruction). These can
// be constructed anew on every |GetReceivers| call.
// TODO(hbos): When receivers can be created separately from remote streams we
// should add an "rtp_receivers_" map too to get rid of the requirement for
// the blink layer to keep a receiver reference. https://crbug.com/741619
base::WeakPtr<PeerConnectionTracker> peer_connection_tracker_; base::WeakPtr<PeerConnectionTracker> peer_connection_tracker_;
......
...@@ -54,6 +54,17 @@ RTCRtpSender::RTCRtpSender( ...@@ -54,6 +54,17 @@ RTCRtpSender::RTCRtpSender(
RTCRtpSender::~RTCRtpSender() {} RTCRtpSender::~RTCRtpSender() {}
std::unique_ptr<RTCRtpSender> RTCRtpSender::ShallowCopy() const {
std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>>
stream_adapter_copies(stream_adapters_.size());
for (size_t i = 0; i < stream_adapters_.size(); ++i) {
stream_adapter_copies[i] = stream_adapters_[i]->Copy();
}
return base::MakeUnique<RTCRtpSender>(webrtc_rtp_sender_,
track_adapter_->Copy(),
std::move(stream_adapter_copies));
}
uintptr_t RTCRtpSender::Id() const { uintptr_t RTCRtpSender::Id() const {
return getId(webrtc_rtp_sender_.get()); return getId(webrtc_rtp_sender_.get());
} }
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
namespace content { namespace content {
// Used to surface |webrtc::RtpSenderInterface| to blink. Multiple // Used to surface |webrtc::RtpSenderInterface| to blink. Multiple
// |RTCRtpSender|s could reference the same webrtc receiver; |id| is the value // |RTCRtpSender|s could reference the same webrtc sender; |id| is the value
// of the pointer to the webrtc sender. // of the pointer to the webrtc sender.
class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender { class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender {
public: public:
...@@ -36,6 +36,10 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender { ...@@ -36,6 +36,10 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender {
stream_adapters); stream_adapters);
~RTCRtpSender() override; ~RTCRtpSender() override;
// Creates a shallow copy of the sender, representing the same underlying
// webrtc sender as the original.
std::unique_ptr<RTCRtpSender> ShallowCopy() const;
uintptr_t Id() const override; uintptr_t Id() const override;
const blink::WebMediaStreamTrack* Track() const override; const blink::WebMediaStreamTrack* Track() const override;
......
...@@ -39,6 +39,11 @@ WebRtcMediaStreamAdapterMap::AdapterRef::~AdapterRef() { ...@@ -39,6 +39,11 @@ WebRtcMediaStreamAdapterMap::AdapterRef::~AdapterRef() {
} }
} }
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
WebRtcMediaStreamAdapterMap::AdapterRef::Copy() const {
return base::WrapUnique(new AdapterRef(map_, it_));
}
WebRtcMediaStreamAdapterMap::WebRtcMediaStreamAdapterMap( WebRtcMediaStreamAdapterMap::WebRtcMediaStreamAdapterMap(
PeerConnectionDependencyFactory* const factory, PeerConnectionDependencyFactory* const factory,
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map) scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map)
......
...@@ -48,6 +48,7 @@ class CONTENT_EXPORT WebRtcMediaStreamAdapterMap ...@@ -48,6 +48,7 @@ class CONTENT_EXPORT WebRtcMediaStreamAdapterMap
// adapter it will be disposed and removed from the map. // adapter it will be disposed and removed from the map.
~AdapterRef(); ~AdapterRef();
std::unique_ptr<AdapterRef> Copy() const;
const WebRtcMediaStreamAdapter& adapter() const { const WebRtcMediaStreamAdapter& adapter() const {
return *it_->second.adapter; return *it_->second.adapter;
} }
......
...@@ -54,6 +54,12 @@ WebRtcMediaStreamTrackAdapterMap::AdapterRef::~AdapterRef() { ...@@ -54,6 +54,12 @@ WebRtcMediaStreamTrackAdapterMap::AdapterRef::~AdapterRef() {
} }
} }
std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
WebRtcMediaStreamTrackAdapterMap::AdapterRef::Copy() const {
base::AutoLock scoped_lock(map_->lock_);
return base::WrapUnique(new AdapterRef(map_, type_, it_));
}
WebRtcMediaStreamTrackAdapterMap::WebRtcMediaStreamTrackAdapterMap( WebRtcMediaStreamTrackAdapterMap::WebRtcMediaStreamTrackAdapterMap(
PeerConnectionDependencyFactory* const factory) PeerConnectionDependencyFactory* const factory)
: factory_(factory), main_thread_(base::ThreadTaskRunnerHandle::Get()) { : factory_(factory), main_thread_(base::ThreadTaskRunnerHandle::Get()) {
......
...@@ -50,6 +50,7 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapterMap ...@@ -50,6 +50,7 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapterMap
// adapter it will be disposed and removed from the map. // adapter it will be disposed and removed from the map.
~AdapterRef(); ~AdapterRef();
std::unique_ptr<AdapterRef> Copy() const;
bool is_initialized() const { return adapter_->is_initialized(); } bool is_initialized() const { return adapter_->is_initialized(); }
const blink::WebMediaStreamTrack& web_track() const { const blink::WebMediaStreamTrack& web_track() const {
return adapter_->web_track(); return adapter_->web_track();
......
...@@ -1110,7 +1110,10 @@ void RTCPeerConnection::addStream(ScriptState* script_state, ...@@ -1110,7 +1110,10 @@ void RTCPeerConnection::addStream(ScriptState* script_state,
if (!valid) if (!valid)
exception_state.ThrowDOMException(kSyntaxError, exception_state.ThrowDOMException(kSyntaxError,
"Unable to add the provided stream."); "Unable to add the provided stream.");
// Ensure |rtp_senders_| is up-to-date. // Ensure |rtp_senders_| is up-to-date so that |addTrack| knows if a sender
// already exists for a track. When |addStream| and |removeStream| are
// are implemented using |addTrack| and |removeTrack| we can simply add and
// remove senders there instead. https://crbug.com/738929
getSenders(); getSenders();
} }
...@@ -1137,10 +1140,16 @@ void RTCPeerConnection::removeStream(MediaStream* stream, ...@@ -1137,10 +1140,16 @@ void RTCPeerConnection::removeStream(MediaStream* stream,
} }
MediaStreamVector RTCPeerConnection::getLocalStreams() const { MediaStreamVector RTCPeerConnection::getLocalStreams() const {
// TODO(hbos): We should define this as "the streams of all senders" instead
// of a set that we add to and subtract from on |addStream| and
// |removeStream|. https://crbug.com/738918
return local_streams_; return local_streams_;
} }
MediaStreamVector RTCPeerConnection::getRemoteStreams() const { MediaStreamVector RTCPeerConnection::getRemoteStreams() const {
// TODO(hbos): We should define this as "the streams of all receivers" instead
// of a set that we add to and subtract from on a remote stream being added or
// removed. https://crbug.com/741618
return remote_streams_; return remote_streams_;
} }
...@@ -1305,6 +1314,9 @@ void RTCPeerConnection::removeTrack(RTCRtpSender* sender, ...@@ -1305,6 +1314,9 @@ void RTCPeerConnection::removeTrack(RTCRtpSender* sender,
// being nulled. // being nulled.
DCHECK(!sender->web_rtp_sender()->Track()); DCHECK(!sender->web_rtp_sender()->Track());
sender->SetTrack(nullptr); sender->SetTrack(nullptr);
// TODO(hbos): When |addStream| and |removeStream| are implemented using
// |addTrack| and |removeTrack|, we should remove |sender| from |rtp_senders_|
// here. https://crbug.com/738929
} }
RTCDataChannel* RTCPeerConnection::createDataChannel( RTCDataChannel* RTCPeerConnection::createDataChannel(
...@@ -1481,6 +1493,9 @@ void RTCPeerConnection::DidRemoveRemoteStream( ...@@ -1481,6 +1493,9 @@ void RTCPeerConnection::DidRemoveRemoteStream(
DCHECK(pos != kNotFound); DCHECK(pos != kNotFound);
remote_streams_.erase(pos); remote_streams_.erase(pos);
stream->UnregisterObserver(this); stream->UnregisterObserver(this);
// TODO(hbos): When we listen to receivers/tracks being added and removed
// instead of streams we should remove the receiver(s) from |rtp_receivers_|
// here. https://crbug.com/741619
ScheduleDispatchEvent( ScheduleDispatchEvent(
MediaStreamEvent::Create(EventTypeNames::removestream, stream)); MediaStreamEvent::Create(EventTypeNames::removestream, stream));
......
...@@ -247,7 +247,7 @@ class MODULES_EXPORT RTCPeerConnection final ...@@ -247,7 +247,7 @@ class MODULES_EXPORT RTCPeerConnection final
void ScheduleDispatchEvent(Event*); void ScheduleDispatchEvent(Event*);
void ScheduleDispatchEvent(Event*, std::unique_ptr<BoolFunction>); void ScheduleDispatchEvent(Event*, std::unique_ptr<BoolFunction>);
void DispatchScheduledEvent(); void DispatchScheduledEvent();
MediaStreamTrack* GetTrack(const WebMediaStreamTrack& web_track) const; MediaStreamTrack* GetTrack(const WebMediaStreamTrack&) const;
void ChangeSignalingState(WebRTCPeerConnectionHandlerClient::SignalingState); void ChangeSignalingState(WebRTCPeerConnectionHandlerClient::SignalingState);
void ChangeIceGatheringState( void ChangeIceGatheringState(
...@@ -276,8 +276,8 @@ class MODULES_EXPORT RTCPeerConnection final ...@@ -276,8 +276,8 @@ class MODULES_EXPORT RTCPeerConnection final
// |rtp_receivers_|. // |rtp_receivers_|.
HeapHashMap<WeakMember<MediaStreamComponent>, WeakMember<MediaStreamTrack>> HeapHashMap<WeakMember<MediaStreamComponent>, WeakMember<MediaStreamTrack>>
tracks_; tracks_;
HeapHashMap<uintptr_t, WeakMember<RTCRtpSender>> rtp_senders_; HeapHashMap<uintptr_t, Member<RTCRtpSender>> rtp_senders_;
HeapHashMap<uintptr_t, WeakMember<RTCRtpReceiver>> rtp_receivers_; HeapHashMap<uintptr_t, Member<RTCRtpReceiver>> rtp_receivers_;
std::unique_ptr<WebRTCPeerConnectionHandler> peer_handler_; std::unique_ptr<WebRTCPeerConnectionHandler> peer_handler_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment