Chromium Code Reviews| Index: content/renderer/media/rtc_peer_connection_handler.cc |
| diff --git a/content/renderer/media/rtc_peer_connection_handler.cc b/content/renderer/media/rtc_peer_connection_handler.cc |
| index 844e250113fe187285b26de5eeddfe1670e00b24..91b65339180b1501e656021e2dc0fd13306f6114 100644 |
| --- a/content/renderer/media/rtc_peer_connection_handler.cc |
| +++ b/content/renderer/media/rtc_peer_connection_handler.cc |
| @@ -117,24 +117,111 @@ GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) { |
| } |
| } |
| +static blink::WebRTCSessionDescription CreateWebKitSessionDescription( |
| + const std::string& sdp, const std::string& type) { |
| + blink::WebRTCSessionDescription description; |
| + description.initialize(base::UTF8ToUTF16(type), base::UTF8ToUTF16(sdp)); |
| + return description; |
| +} |
| + |
| static blink::WebRTCSessionDescription |
| CreateWebKitSessionDescription( |
| const webrtc::SessionDescriptionInterface* native_desc) { |
| - blink::WebRTCSessionDescription description; |
| if (!native_desc) { |
| LOG(ERROR) << "Native session description is null."; |
| - return description; |
| + return blink::WebRTCSessionDescription(); |
| } |
| std::string sdp; |
| if (!native_desc->ToString(&sdp)) { |
| LOG(ERROR) << "Failed to get SDP string of native session description."; |
| - return description; |
| + return blink::WebRTCSessionDescription(); |
| } |
| - description.initialize(base::UTF8ToUTF16(native_desc->type()), |
| - base::UTF8ToUTF16(sdp)); |
| - return description; |
| + return CreateWebKitSessionDescription(sdp, native_desc->type()); |
| +} |
| + |
| +void RunClosureWithTrace(const base::Closure& closure, |
|
perkj_chrome
2014/11/05 10:31:02
static to be consistent with above. Or move all to
tommi (sloooow) - chröme
2014/11/05 10:50:38
Done. Moved all into an anonymous namespace. Had
|
| + const char* trace_event_name) { |
| + TRACE_EVENT0("webrtc", trace_event_name); |
| + closure.Run(); |
| +} |
| + |
| +void RunSynchronousClosure(const base::Closure& closure, |
| + const char* trace_event_name, |
| + base::WaitableEvent* event) { |
| + { |
| + TRACE_EVENT0("webrtc", trace_event_name); |
| + closure.Run(); |
| + } |
| + event->Signal(); |
| +} |
| + |
| +template<typename ResultType> |
| +void RunSynchronousClosureWithResult( |
|
perkj_chrome
2014/11/05 10:31:02
unused
tommi (sloooow) - chröme
2014/11/05 10:50:39
Done.
|
| + const base::Callback<ResultType()>& closure, |
| + const char* trace_event_name, |
| + base::WaitableEvent* event, |
| + ResultType* result) { |
| + { |
| + TRACE_EVENT0("webrtc", trace_event_name); |
| + *result = closure.Run(); |
| + } |
| + event->Signal(); |
| +} |
| + |
| +void RunSynchronousClosureOnThread( |
|
perkj_chrome
2014/11/05 10:31:01
unused
tommi (sloooow) - chröme
2014/11/05 10:50:39
Done.
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& thread, |
| + const base::Closure& closure, |
| + const char* trace_event_name) { |
| + if (thread->BelongsToCurrentThread()) { |
| + TRACE_EVENT0("webrtc", trace_event_name); |
| + closure.Run(); |
| + } else { |
| + base::WaitableEvent event(false, false); |
| + thread->PostTask(FROM_HERE, |
| + base::Bind(&RunSynchronousClosure, closure, |
| + base::Unretained(trace_event_name), |
| + base::Unretained(&event))); |
| + event.Wait(); |
| + } |
| +} |
| + |
| +template<typename ResultType> |
| +ResultType RunSynchronousClosureOnThreadWithResultT( |
|
perkj_chrome
2014/11/05 10:31:01
unused?
tommi (sloooow) - chröme
2014/11/05 10:50:38
Done.
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& thread, |
| + const base::Callback<ResultType()>& closure, |
| + const char* trace_event_name) { |
| + ResultType ret = ResultType(); |
| + if (!thread.get() || thread->BelongsToCurrentThread()) { |
| + TRACE_EVENT0("webrtc", trace_event_name); |
| + ret = closure.Run(); |
| + } else { |
| + base::WaitableEvent event(false, false); |
| + thread->PostTask(FROM_HERE, |
| + base::Bind(&RunSynchronousClosureWithResult<ResultType>, closure, |
| + base::Unretained(trace_event_name), base::Unretained(&event), |
| + base::Unretained(&ret))); |
| + event.Wait(); |
| + } |
| + |
| + return ret; |
| +} |
| + |
| +static void GetSessionDescription( |
|
perkj_chrome
2014/11/05 10:31:02
suggest naming GetSdpAndTypeFromSessionDescription
tommi (sloooow) - chröme
2014/11/05 10:50:39
Done.
|
| + const webrtc::SessionDescriptionInterface* session_description, |
| + std::string* sdp, std::string* type) { |
| + if (session_description) { |
| + session_description->ToString(sdp); |
| + *type = session_description->type(); |
| + } |
| +} |
| + |
| +void GetDescription( |
| + const base::Callback<const webrtc::SessionDescriptionInterface*()>& |
| + description, |
|
perkj_chrome
2014/11/05 10:31:02
Can we rename |description| to something that indi
tommi (sloooow) - chröme
2014/11/05 10:50:39
Renamed to description_callback
|
| + std::string* sdp, std::string* type) { |
| + GetSessionDescription(description.Run(), sdp, type); |
|
perkj_chrome
2014/11/05 10:31:02
Can you please join GetSessionDescription and GetD
tommi (sloooow) - chröme
2014/11/05 10:50:39
Done.
|
| } |
| // Converter functions from WebKit types to libjingle types. |
| @@ -310,7 +397,7 @@ class StatsResponse : public webrtc::StatsObserver { |
| void OnComplete(const StatsReports& reports) override { |
| DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
| TRACE_EVENT0("webrtc", "StatsResponse::OnComplete"); |
| - // TODO(tommi): Get rid of these string copies some how. |
| + // TODO(tommi): Get rid of these string copies somehow. |
| // We can't use webkit objects directly since they use a single threaded |
| // heap allocator. |
| scoped_ptr<std::vector<StatsReportCopyable>> report_copies( |
| @@ -617,12 +704,10 @@ class RTCPeerConnectionHandler::Observer |
| RTCPeerConnectionHandler::RTCPeerConnectionHandler( |
| blink::WebRTCPeerConnectionHandlerClient* client, |
| - PeerConnectionDependencyFactory* dependency_factory, |
| - const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread) |
| + PeerConnectionDependencyFactory* dependency_factory) |
| : client_(client), |
| dependency_factory_(dependency_factory), |
| frame_(NULL), |
| - signaling_thread_(signaling_thread), |
| num_data_channels_created_(0), |
| num_local_candidates_ipv4_(0), |
| num_local_candidates_ipv6_(0), |
| @@ -750,6 +835,7 @@ void RTCPeerConnectionHandler::createOffer( |
| weak_factory_.GetWeakPtr(), peer_connection_tracker_, |
| PeerConnectionTracker::ACTION_CREATE_OFFER)); |
| + // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply. |
| RTCMediaConstraints constraints(options); |
| native_peer_connection_->CreateOffer(description_request.get(), &constraints); |
| @@ -769,6 +855,7 @@ void RTCPeerConnectionHandler::createOffer( |
| weak_factory_.GetWeakPtr(), peer_connection_tracker_, |
| PeerConnectionTracker::ACTION_CREATE_OFFER)); |
| + // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply. |
| RTCMediaConstraints constraints; |
| ConvertOfferOptionsToConstraints(options, &constraints); |
| native_peer_connection_->CreateOffer(description_request.get(), &constraints); |
| @@ -787,6 +874,7 @@ void RTCPeerConnectionHandler::createAnswer( |
| base::ThreadTaskRunnerHandle::Get(), request, |
| weak_factory_.GetWeakPtr(), peer_connection_tracker_, |
| PeerConnectionTracker::ACTION_CREATE_ANSWER)); |
| + // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply. |
| RTCMediaConstraints constraints(options); |
| native_peer_connection_->CreateAnswer(description_request.get(), |
| &constraints); |
| @@ -830,8 +918,12 @@ void RTCPeerConnectionHandler::setLocalDescription( |
| weak_factory_.GetWeakPtr(), peer_connection_tracker_, |
| PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION)); |
| - // TODO(tommi): Run this on the signaling thread. |
| - native_peer_connection_->SetLocalDescription(set_request.get(), native_desc); |
| + signaling_thread()->PostTask(FROM_HERE, |
| + base::Bind(&RunClosureWithTrace, |
| + base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription, |
| + native_peer_connection_, set_request, |
| + base::Unretained(native_desc)), |
| + "SetLocalDescription")); |
| } |
| void RTCPeerConnectionHandler::setRemoteDescription( |
| @@ -867,30 +959,52 @@ void RTCPeerConnectionHandler::setRemoteDescription( |
| base::ThreadTaskRunnerHandle::Get(), request, |
| weak_factory_.GetWeakPtr(), peer_connection_tracker_, |
| PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION)); |
| - // TODO(tommi): Run this on the signaling thread. |
| - native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc); |
| + signaling_thread()->PostTask(FROM_HERE, |
| + base::Bind(&RunClosureWithTrace, |
| + base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription, |
| + native_peer_connection_, set_request, |
| + base::Unretained(native_desc)), |
| + "SetRemoteDescription")); |
| } |
| blink::WebRTCSessionDescription |
| RTCPeerConnectionHandler::localDescription() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription"); |
| - const webrtc::SessionDescriptionInterface* native_desc = |
| - native_peer_connection_->local_description(); |
| - blink::WebRTCSessionDescription description = |
| - CreateWebKitSessionDescription(native_desc); |
| - return description; |
| + |
| + // 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 |
| + // it directly here. Instead, we access the object completely on the signaling |
| + // thread. |
| + std::string sdp, type; |
| + base::Callback<const webrtc::SessionDescriptionInterface*()> description = |
|
perkj_chrome
2014/11/05 10:31:02
name get_description_cb?
tommi (sloooow) - chröme
2014/11/05 10:50:39
Done. changed to description_cb (since the functio
|
| + base::Bind(&webrtc::PeerConnectionInterface::local_description, |
| + native_peer_connection_); |
| + RunSynchronousClosureOnThread( |
| + base::Bind(&GetDescription, description, base::Unretained(&sdp), |
| + base::Unretained(&type)), |
| + "localDescription"); |
| + |
| + return CreateWebKitSessionDescription(sdp, type); |
| } |
| blink::WebRTCSessionDescription |
| RTCPeerConnectionHandler::remoteDescription() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription"); |
| - const webrtc::SessionDescriptionInterface* native_desc = |
| - native_peer_connection_->remote_description(); |
| - blink::WebRTCSessionDescription description = |
| - CreateWebKitSessionDescription(native_desc); |
| - return description; |
| + // 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 |
| + // it directly here. Instead, we access the object completely on the signaling |
| + // thread. |
| + std::string sdp, type; |
| + auto desc = base::Bind(&webrtc::PeerConnectionInterface::remote_description, |
|
perkj_chrome
2014/11/05 10:31:02
please use base::Callback<const webrtc::SessionDes
tommi (sloooow) - chröme
2014/11/05 10:50:39
Done.
|
| + native_peer_connection_); |
|
perkj_chrome
2014/11/05 10:31:02
nit: indentation
tommi (sloooow) - chröme
2014/11/05 10:50:39
Done.
|
| + RunSynchronousClosureOnThread( |
| + base::Bind(&GetDescription, desc, base::Unretained(&sdp), |
| + base::Unretained(&type)), |
| + "remoteDescription"); |
| + |
| + return CreateWebKitSessionDescription(sdp, type); |
| } |
| bool RTCPeerConnectionHandler::updateICE( |
| @@ -915,6 +1029,9 @@ bool RTCPeerConnectionHandler::addICECandidate( |
| TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate"); |
| // Libjingle currently does not accept callbacks for addICECandidate. |
| // For that reason we are going to call callbacks from here. |
| + |
| + // TODO(tommi): Instead of calling addICECandidate here, we can do a |
| + // PostTaskAndReply kind of a thing. |
| bool result = addICECandidate(candidate); |
| base::MessageLoop::current()->PostTask( |
| FROM_HERE, |
| @@ -1014,6 +1131,7 @@ void RTCPeerConnectionHandler::removeStream( |
| } |
| } |
| DCHECK(webrtc_stream.get()); |
| + // TODO(tommi): Make this async (PostTaskAndReply). |
| native_peer_connection_->RemoveStream(webrtc_stream.get()); |
| if (peer_connection_tracker_) { |
| @@ -1061,7 +1179,7 @@ void RTCPeerConnectionHandler::GetStats( |
| const std::string& track_id, |
| blink::WebMediaStreamSource::Type track_type) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - signaling_thread_->PostTask(FROM_HERE, |
| + signaling_thread()->PostTask(FROM_HERE, |
| base::Bind(&GetStatsOnSignalingThread, native_peer_connection_, level, |
| make_scoped_refptr(observer), track_id, track_type)); |
| } |
| @@ -1120,9 +1238,10 @@ blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender( |
| return nullptr; |
| } |
| - webrtc::AudioTrackInterface* audio_track = native_track->GetAudioAdapter(); |
| + scoped_refptr<webrtc::AudioTrackInterface> audio_track = |
| + native_track->GetAudioAdapter(); |
| rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender( |
| - native_peer_connection_->CreateDtmfSender(audio_track)); |
| + native_peer_connection_->CreateDtmfSender(audio_track.get())); |
| if (!sender) { |
| DLOG(ERROR) << "Could not create native DTMF sender."; |
| return nullptr; |
| @@ -1137,9 +1256,14 @@ void RTCPeerConnectionHandler::stop() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DVLOG(1) << "RTCPeerConnectionHandler::stop"; |
| + if (!client_) |
| + return; // Already stopped. |
| + |
| if (peer_connection_tracker_) |
| peer_connection_tracker_->TrackStop(this); |
| + |
| native_peer_connection_->Close(); |
| + |
| // The client_ pointer is not considered valid after this point and no further |
| // callbacks must be made. |
| client_ = nullptr; |
| @@ -1339,4 +1463,36 @@ RTCPeerConnectionHandler::CreateNativeSessionDescription( |
| return native_desc; |
| } |
| +scoped_refptr<base::SingleThreadTaskRunner> |
| +RTCPeerConnectionHandler::signaling_thread() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return dependency_factory_->GetWebRtcSignalingThread(); |
| +} |
| + |
| +void RTCPeerConnectionHandler::RunSynchronousClosureOnThread( |
|
perkj_chrome
2014/11/05 10:31:01
Name RunSynchronousClosureOnSignalingThread?
tommi (sloooow) - chröme
2014/11/05 10:50:39
Done.
|
| + const base::Closure& closure, |
| + const char* trace_event_name) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread()); |
| + if (!thread.get() || thread->BelongsToCurrentThread()) { |
| + TRACE_EVENT0("webrtc", trace_event_name); |
| + closure.Run(); |
| + } else { |
| + base::WaitableEvent event(false, false); |
| + thread->PostTask(FROM_HERE, |
| + base::Bind(&RunSynchronousClosure, closure, |
| + base::Unretained(trace_event_name), |
| + base::Unretained(&event))); |
| + event.Wait(); |
| + } |
| +} |
| + |
| +bool RTCPeerConnectionHandler::RunSynchronousClosureOnThreadWithResult( |
|
perkj_chrome
2014/11/05 10:31:01
unused?
tommi (sloooow) - chröme
2014/11/05 10:50:38
Removed
|
| + const base::Callback<bool()>& closure, |
| + const char* trace_event_name) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return RunSynchronousClosureOnThreadWithResultT<bool>(signaling_thread(), |
| + closure, trace_event_name); |
| +} |
| + |
| } // namespace content |