Index: content/renderer/media/peer_connection_handler_jsep.cc |
diff --git a/content/renderer/media/peer_connection_handler_jsep.cc b/content/renderer/media/peer_connection_handler_jsep.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..183dfc92267f0ee671eca0ff0b2087eab64e3fd8 |
--- /dev/null |
+++ b/content/renderer/media/peer_connection_handler_jsep.cc |
@@ -0,0 +1,374 @@ |
+// Copyright (c) 2012 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/peer_connection_handler_jsep.h" |
+ |
+#include <utility> |
+#include <vector> |
+ |
+#include "base/bind.h" |
+#include "base/logging.h" |
+#include "base/string_number_conversions.h" |
+#include "base/utf_string_conversions.h" |
+#include "content/renderer/media/media_stream_dependency_factory.h" |
+#include "content/renderer/media/media_stream_impl.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebIceCandidate.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebIceOptions.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebJSEPPeerConnectionHandlerClient.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaHints.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamDescriptor.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamSource.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSessionDescription.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" |
+ |
+PeerConnectionHandlerJsep::PeerConnectionHandlerJsep( |
+ WebKit::WebJSEPPeerConnectionHandlerClient* client, |
+ MediaStreamImpl* msi, |
+ MediaStreamDependencyFactory* dependency_factory) |
+ : PeerConnectionHandlerBase(msi, dependency_factory), |
+ client_(client) { |
+} |
+ |
+PeerConnectionHandlerJsep::~PeerConnectionHandlerJsep() { |
+} |
+ |
+void PeerConnectionHandlerJsep::initialize( |
+ const WebKit::WebString& server_configuration, |
+ const WebKit::WebString& username) { |
+ native_peer_connection_ = dependency_factory_->CreatePeerConnection( |
+ UTF16ToUTF8(server_configuration), |
+ this); |
+ CHECK(native_peer_connection_); |
+} |
+ |
+WebKit::WebSessionDescription PeerConnectionHandlerJsep::createOffer( |
+ const WebKit::WebMediaHints& hints) { |
+ WebKit::WebSessionDescription offer; |
+ |
+ webrtc::MediaHints native_hints(hints.audio(), hints.video()); |
+ webrtc::SessionDescriptionInterface* native_offer = |
+ native_peer_connection_->CreateOffer(native_hints); |
+ if (!native_offer) |
+ return offer; |
+ |
+ offer = CreateWebKitSessionDescription(native_offer); |
+ delete native_offer; |
+ return offer; |
+} |
+ |
+WebKit::WebSessionDescription PeerConnectionHandlerJsep::createAnswer( |
+ const WebKit::WebString& offer, |
+ const WebKit::WebMediaHints& hints) { |
+ WebKit::WebSessionDescription answer; |
+ |
+ webrtc::MediaHints native_hints(hints.audio(), hints.video()); |
+ webrtc::SessionDescriptionInterface* native_offer = |
+ webrtc::CreateSessionDescription(UTF16ToUTF8(offer)); |
+ if (!native_offer) |
+ return answer; |
+ |
+ webrtc::SessionDescriptionInterface* native_answer = |
+ native_peer_connection_->CreateAnswer(native_hints, native_offer); |
+ delete native_offer; |
+ if (!native_answer) |
+ return answer; |
+ |
+ answer = CreateWebKitSessionDescription(native_answer); |
+ delete native_answer; |
+ return answer; |
+} |
+ |
+bool PeerConnectionHandlerJsep::setLocalDescription( |
+ Action action, |
+ const WebKit::WebSessionDescription& description) { |
+ webrtc::PeerConnectionInterface::Action native_action; |
+ if (!GetNativeAction(action, &native_action)) |
+ return false; |
+ |
+ webrtc::SessionDescriptionInterface* native_desc = |
+ CreateNativeSessionDescription(description); |
+ if (!native_desc) |
+ return false; |
+ |
+ return native_peer_connection_->SetLocalDescription(native_action, |
+ native_desc); |
+} |
+ |
+bool PeerConnectionHandlerJsep::setRemoteDescription( |
+ Action action, |
+ const WebKit::WebSessionDescription& description) { |
+ webrtc::PeerConnectionInterface::Action native_action; |
+ if (!GetNativeAction(action, &native_action)) |
+ return false; |
+ |
+ webrtc::SessionDescriptionInterface* native_desc = |
+ CreateNativeSessionDescription(description); |
+ if (!native_desc) |
+ return false; |
+ |
+ return native_peer_connection_->SetRemoteDescription(native_action, |
+ native_desc); |
+} |
+ |
+WebKit::WebSessionDescription PeerConnectionHandlerJsep::localDescription() { |
+ const webrtc::SessionDescriptionInterface* native_desc = |
+ native_peer_connection_->local_description(); |
+ WebKit::WebSessionDescription description = |
+ CreateWebKitSessionDescription(native_desc); |
+ delete native_desc; |
+ return description; |
+} |
+ |
+WebKit::WebSessionDescription PeerConnectionHandlerJsep::remoteDescription() { |
+ const webrtc::SessionDescriptionInterface* native_desc = |
+ native_peer_connection_->remote_description(); |
+ WebKit::WebSessionDescription description = |
+ CreateWebKitSessionDescription(native_desc); |
+ delete native_desc; |
+ return description; |
+} |
+ |
+bool PeerConnectionHandlerJsep::startIce(const WebKit::WebIceOptions& options) { |
+ webrtc::PeerConnectionInterface::IceOptions native_options; |
+ switch (options.useCandidates()) { |
+ case WebKit::WebIceOptions::ALL: |
+ native_options = webrtc::PeerConnectionInterface::kUseAll; |
+ break; |
+ case WebKit::WebIceOptions::NO_RELAY: |
+ native_options = webrtc::PeerConnectionInterface::kNoRelay; |
+ break; |
+ case WebKit::WebIceOptions::ONLY_RELAY: |
+ native_options = webrtc::PeerConnectionInterface::kOnlyRelay; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ return false; |
+ } |
+ native_peer_connection_->StartIce(native_options); |
+ return true; |
+} |
+ |
+bool PeerConnectionHandlerJsep::processIceMessage( |
+ const WebKit::WebIceCandidate& candidate) { |
+ webrtc::IceCandidateInterface* native_candidate = |
+ webrtc::CreateIceCandidate(UTF16ToUTF8(candidate.label()), |
+ UTF16ToUTF8(candidate.candidateLine())); |
+ if (!native_candidate) |
+ return false; |
+ |
+ bool return_value = |
+ native_peer_connection_->ProcessIceMessage(native_candidate); |
+ delete native_candidate; |
+ return return_value; |
+} |
+ |
+void PeerConnectionHandlerJsep::addStream( |
+ const WebKit::WebMediaStreamDescriptor& stream) { |
+ AddStream(stream); |
+ native_peer_connection_->CommitStreamChanges(); |
+} |
+ |
+void PeerConnectionHandlerJsep::removeStream( |
+ const WebKit::WebMediaStreamDescriptor& stream) { |
+ RemoveStream(stream); |
+ native_peer_connection_->CommitStreamChanges(); |
+} |
+ |
+void PeerConnectionHandlerJsep::stop() { |
+ // TODO(ronghuawu): There's an issue with signaling messages being sent during |
+ // close. We need to investigate further. Not calling Close() on native |
+ // PeerConnection is OK for now. |
+ native_peer_connection_ = NULL; |
+ media_stream_impl_->ClosePeerConnection(); |
+} |
+ |
+void PeerConnectionHandlerJsep::OnError() { |
+ // TODO(grunell): Implement. |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void PeerConnectionHandlerJsep::OnMessage(const std::string& msg) { |
+ // TODO(grunell): Implement. |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void PeerConnectionHandlerJsep::OnSignalingMessage(const std::string& msg) { |
+ // Not used by JSEP PeerConnection. |
+ NOTREACHED(); |
+} |
+ |
+void PeerConnectionHandlerJsep::OnStateChange(StateType state_changed) { |
+ switch (state_changed) { |
+ case kReadyState: |
+ WebKit::WebJSEPPeerConnectionHandlerClient::ReadyState ready_state; |
+ switch (native_peer_connection_->ready_state()) { |
+ case webrtc::PeerConnectionInterface::kNew: |
+ ready_state = WebKit::WebJSEPPeerConnectionHandlerClient::NEW; |
+ break; |
+ case webrtc::PeerConnectionInterface::kNegotiating: |
+ ready_state = WebKit::WebJSEPPeerConnectionHandlerClient::NEGOTIATING; |
+ break; |
+ case webrtc::PeerConnectionInterface::kActive: |
+ ready_state = WebKit::WebJSEPPeerConnectionHandlerClient::ACTIVE; |
+ break; |
+ case webrtc::PeerConnectionInterface::kClosing: |
+ // Not used by JSEP. |
+ NOTREACHED(); |
+ return; |
+ case webrtc::PeerConnectionInterface::kClosed: |
+ ready_state = WebKit::WebJSEPPeerConnectionHandlerClient::CLOSED; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ return; |
+ } |
+ client_->didChangeReadyState(ready_state); |
+ break; |
+ case kIceState: |
+ // TODO(grunell): Implement when available in native PeerConnection. |
+ NOTIMPLEMENTED(); |
+ break; |
+ case kSdpState: |
+ // Not used by JSEP. |
+ NOTREACHED(); |
+ return; |
+ default: |
+ NOTREACHED(); |
+ return; |
+ } |
+} |
+ |
+void PeerConnectionHandlerJsep::OnAddStream( |
+ webrtc::MediaStreamInterface* stream) { |
+ if (!stream) |
+ return; |
+ |
+ if (!message_loop_proxy_->BelongsToCurrentThread()) { |
+ message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
+ &PeerConnectionHandlerJsep::OnAddStreamCallback, |
+ base::Unretained(this), |
tommi (sloooow) - chröme
2012/03/15 12:31:52
is there no chance that the PeerConnectionHandlerJ
Henrik Grunell
2012/03/23 12:50:45
Actually, we are guaranteed to be called on the co
|
+ stream)); |
+ } else { |
+ OnAddStreamCallback(stream); |
+ } |
+} |
+ |
+void PeerConnectionHandlerJsep::OnRemoveStream( |
+ webrtc::MediaStreamInterface* stream) { |
+ if (!stream) |
+ return; |
+ |
+ if (!message_loop_proxy_->BelongsToCurrentThread()) { |
+ message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
+ &PeerConnectionHandlerJsep::OnRemoveStreamCallback, |
+ base::Unretained(this), |
+ stream)); |
+ } else { |
+ OnRemoveStreamCallback(stream); |
+ } |
+} |
+ |
+void PeerConnectionHandlerJsep::OnIceCandidate( |
+ const webrtc::IceCandidateInterface* candidate) { |
+ WebKit::WebIceCandidate web_candidate; |
+ |
+ std::string label = candidate->label(); |
+ std::string sdp; |
+ if (!candidate->ToString(&sdp)) { |
+ LOG(ERROR) << "Could not get SDP string"; |
+ return; |
+ } |
+ |
+ web_candidate.initialize(UTF8ToUTF16(label), UTF8ToUTF16(sdp)); |
+ |
+ // moreToFollow parameter isn't supported in native PeerConnection, so we |
+ // always use true here, and then false in OnIceComplete(). |
+ client_->didGenerateIceCandidate(web_candidate, true); |
+} |
+ |
+void PeerConnectionHandlerJsep::OnIceComplete() { |
+ // moreToFollow parameter isn't supported in native PeerConnection, so we |
+ // send an empty WebIseCandidate with moreToFollow=false. |
+ WebKit::WebIceCandidate web_candidate; |
+ client_->didGenerateIceCandidate(web_candidate, false); |
+} |
+ |
+webrtc::SessionDescriptionInterface* |
+PeerConnectionHandlerJsep::CreateNativeSessionDescription( |
+ const WebKit::WebSessionDescription& description) { |
+ std::string initial_sdp = UTF16ToUTF8(description.initialSdp()); |
+ webrtc::SessionDescriptionInterface* native_desc = |
+ webrtc::CreateSessionDescription(initial_sdp); |
+ if (!native_desc) |
+ return NULL; |
+ |
+ for (size_t i = 0; i < description.numberOfAddedCandidates(); ++i) { |
+ WebKit::WebIceCandidate candidate = description.candidate(i); |
+ webrtc::IceCandidateInterface* native_candidate = |
+ webrtc::CreateIceCandidate(UTF16ToUTF8(candidate.label()), |
+ UTF16ToUTF8(candidate.candidateLine())); |
+ native_desc->AddCandidate(native_candidate); |
+ } |
+ |
+ return native_desc; |
+} |
+ |
+WebKit::WebSessionDescription |
+PeerConnectionHandlerJsep::CreateWebKitSessionDescription( |
+ const webrtc::SessionDescriptionInterface* native_desc) { |
+ WebKit::WebSessionDescription description; |
+ if (!native_desc) |
+ return description; |
+ |
+ std::string sdp; |
+ if (!native_desc->ToString(&sdp)) |
+ return description; |
+ |
+ description.initialize(UTF8ToUTF16(sdp)); |
+ return description; |
+} |
+ |
+bool PeerConnectionHandlerJsep::GetNativeAction( |
+ const Action action, |
+ webrtc::PeerConnectionInterface::Action* native_action) { |
+ switch (action) { |
+ case SDP_OFFER: |
+ *native_action = webrtc::PeerConnectionInterface::kOffer; |
+ break; |
+ case SDP_PRANSWER: |
+ DVLOG(1) << "Action PRANSWER not supported yet"; |
+ return false; |
+ case SDP_ANSWER: |
+ *native_action = webrtc::PeerConnectionInterface::kAnswer; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+void PeerConnectionHandlerJsep::OnAddStreamCallback( |
+ webrtc::MediaStreamInterface* stream) { |
+ DCHECK(remote_streams_.find(stream) == remote_streams_.end()); |
+ WebKit::WebMediaStreamDescriptor descriptor = |
+ CreateWebKitStreamDescriptor(stream); |
+ remote_streams_.insert( |
+ std::pair<webrtc::MediaStreamInterface*, |
+ WebKit::WebMediaStreamDescriptor>(stream, descriptor)); |
+ client_->didAddRemoteStream(descriptor); |
+} |
+ |
+void PeerConnectionHandlerJsep::OnRemoveStreamCallback( |
+ webrtc::MediaStreamInterface* stream) { |
+ RemoteStreamMap::iterator it = remote_streams_.find(stream); |
+ if (it == remote_streams_.end()) { |
+ NOTREACHED() << "Stream not found"; |
+ return; |
+ } |
+ WebKit::WebMediaStreamDescriptor descriptor = it->second; |
+ DCHECK(!descriptor.isNull()); |
+ remote_streams_.erase(it); |
+ client_->didRemoveRemoteStream(descriptor); |
+} |