OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/renderer/media/rtc_peer_connection_handler.h" |
| 6 |
| 7 #include <string> |
| 8 #include <utility> |
| 9 |
| 10 #include "base/logging.h" |
| 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/utf_string_conversions.h" |
| 13 #include "content/renderer/media/media_stream_dependency_factory.h" |
| 14 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaConstraints
.h" |
| 15 #include "third_party/WebKit/Source/Platform/chromium/public/WebRTCConfiguration
.h" |
| 16 #include "third_party/WebKit/Source/Platform/chromium/public/WebRTCICECandidateD
escriptor.h" |
| 17 #include "third_party/WebKit/Source/Platform/chromium/public/WebRTCPeerConnectio
nHandlerClient.h" |
| 18 #include "third_party/WebKit/Source/Platform/chromium/public/WebRTCSessionDescri
ptionDescriptor.h" |
| 19 #include "third_party/WebKit/Source/Platform/chromium/public/WebRTCSessionDescri
ptionRequest.h" |
| 20 #include "third_party/WebKit/Source/Platform/chromium/public/WebRTCVoidRequest.h
" |
| 21 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h" |
| 22 |
| 23 // Converter functions from libjingle types to WebKit types. |
| 24 |
| 25 static WebKit::WebRTCPeerConnectionHandlerClient::ICEState |
| 26 GetWebKitIceState(webrtc::PeerConnectionInterface::IceState ice_state) { |
| 27 switch (ice_state) { |
| 28 case webrtc::PeerConnectionInterface::kIceNew: |
| 29 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateNew; |
| 30 case webrtc::PeerConnectionInterface::kIceGathering: |
| 31 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateGathering; |
| 32 case webrtc::PeerConnectionInterface::kIceWaiting: |
| 33 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateWaiting; |
| 34 case webrtc::PeerConnectionInterface::kIceChecking: |
| 35 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateChecking; |
| 36 case webrtc::PeerConnectionInterface::kIceConnected: |
| 37 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateConnected; |
| 38 case webrtc::PeerConnectionInterface::kIceCompleted: |
| 39 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateCompleted; |
| 40 case webrtc::PeerConnectionInterface::kIceFailed: |
| 41 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateFailed; |
| 42 case webrtc::PeerConnectionInterface::kIceClosed: |
| 43 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateClosed; |
| 44 default: |
| 45 NOTREACHED(); |
| 46 return WebKit::WebRTCPeerConnectionHandlerClient::ICEStateClosed; |
| 47 } |
| 48 NOTREACHED(); |
| 49 } |
| 50 |
| 51 static WebKit::WebRTCPeerConnectionHandlerClient::ReadyState |
| 52 GetWebKitReadyState( |
| 53 webrtc::PeerConnectionInterface::ReadyState ready_state) { |
| 54 switch (ready_state) { |
| 55 case webrtc::PeerConnectionInterface::kNew: |
| 56 return WebKit::WebRTCPeerConnectionHandlerClient::ReadyStateNew; |
| 57 case webrtc::PeerConnectionInterface::kOpening: |
| 58 return WebKit::WebRTCPeerConnectionHandlerClient::ReadyStateOpening; |
| 59 case webrtc::PeerConnectionInterface::kActive: |
| 60 return WebKit::WebRTCPeerConnectionHandlerClient::ReadyStateActive; |
| 61 case webrtc::PeerConnectionInterface::kClosing: |
| 62 return WebKit::WebRTCPeerConnectionHandlerClient::ReadyStateClosing; |
| 63 case webrtc::PeerConnectionInterface::kClosed: |
| 64 return WebKit::WebRTCPeerConnectionHandlerClient::ReadyStateClosed; |
| 65 default: |
| 66 NOTREACHED(); |
| 67 return WebKit::WebRTCPeerConnectionHandlerClient::ReadyStateClosed; |
| 68 } |
| 69 NOTREACHED(); |
| 70 } |
| 71 |
| 72 static WebKit::WebRTCSessionDescriptionDescriptor |
| 73 CreateWebKitSessionDescription( |
| 74 const webrtc::SessionDescriptionInterface* native_desc) { |
| 75 WebKit::WebRTCSessionDescriptionDescriptor description; |
| 76 if (!native_desc) { |
| 77 LOG(ERROR) << "Native session description is null."; |
| 78 return description; |
| 79 } |
| 80 |
| 81 std::string sdp; |
| 82 if (!native_desc->ToString(&sdp)) { |
| 83 LOG(ERROR) << "Failed to get SDP string of native session description."; |
| 84 return description; |
| 85 } |
| 86 |
| 87 description.initialize(UTF8ToUTF16(native_desc->type()), UTF8ToUTF16(sdp)); |
| 88 return description; |
| 89 } |
| 90 |
| 91 // Converter functions from WebKit types to libjingle types. |
| 92 |
| 93 static void GetNativeIceServers( |
| 94 const WebKit::WebRTCConfiguration& server_configuration, |
| 95 webrtc::JsepInterface::IceServers* servers) { |
| 96 if (server_configuration.isNull() || !servers) |
| 97 return; |
| 98 for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) { |
| 99 webrtc::JsepInterface::IceServer server; |
| 100 const WebKit::WebRTCICEServer& webkit_server = |
| 101 server_configuration.server(i); |
| 102 server.password = UTF16ToUTF8(webkit_server.credential()); |
| 103 server.uri = webkit_server.uri().spec(); |
| 104 servers->push_back(server); |
| 105 } |
| 106 } |
| 107 |
| 108 // Class mapping responses from calls to libjingle CreateOffer/Answer and |
| 109 // the WebKit::WebRTCSessionDescriptionRequest. |
| 110 class CreateSessionDescriptionRequest |
| 111 : public webrtc::CreateSessionDescriptionObserver { |
| 112 public: |
| 113 explicit CreateSessionDescriptionRequest( |
| 114 const WebKit::WebRTCSessionDescriptionRequest& request) |
| 115 : webkit_request_(request) {} |
| 116 |
| 117 virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE { |
| 118 webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc)); |
| 119 } |
| 120 virtual void OnFailure(const std::string& error) OVERRIDE { |
| 121 webkit_request_.requestFailed(UTF8ToUTF16(error)); |
| 122 } |
| 123 |
| 124 protected: |
| 125 virtual ~CreateSessionDescriptionRequest() {} |
| 126 |
| 127 private: |
| 128 WebKit::WebRTCSessionDescriptionRequest webkit_request_; |
| 129 }; |
| 130 |
| 131 // Class mapping responses from calls to libjingle |
| 132 // SetLocalDescription/SetRemoteDescription and a WebKit::WebRTCVoidRequest. |
| 133 class SetSessionDescriptionRequest |
| 134 : public webrtc::SetSessionDescriptionObserver { |
| 135 public: |
| 136 explicit SetSessionDescriptionRequest( |
| 137 const WebKit::WebRTCVoidRequest& request) |
| 138 : webkit_request_(request) {} |
| 139 |
| 140 virtual void OnSuccess() OVERRIDE { |
| 141 webkit_request_.requestSucceeded(); |
| 142 } |
| 143 virtual void OnFailure(const std::string& error) OVERRIDE { |
| 144 webkit_request_.requestFailed(UTF8ToUTF16(error)); |
| 145 } |
| 146 |
| 147 protected: |
| 148 virtual ~SetSessionDescriptionRequest() {} |
| 149 |
| 150 private: |
| 151 WebKit::WebRTCVoidRequest webkit_request_; |
| 152 }; |
| 153 |
| 154 // TODO(perkj): Implement MediaConstraints when WebKit have done so. |
| 155 class RTCMediaConstraints : public webrtc::MediaConstraintsInterface { |
| 156 public: |
| 157 explicit RTCMediaConstraints( |
| 158 const WebKit::WebMediaConstraints& /*constraints*/) { |
| 159 } |
| 160 ~RTCMediaConstraints() {} |
| 161 }; |
| 162 |
| 163 RTCPeerConnectionHandler::RTCPeerConnectionHandler( |
| 164 WebKit::WebRTCPeerConnectionHandlerClient* client, |
| 165 MediaStreamDependencyFactory* dependency_factory) |
| 166 : PeerConnectionHandlerBase(dependency_factory), |
| 167 client_(client) { |
| 168 } |
| 169 |
| 170 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() { |
| 171 } |
| 172 |
| 173 bool RTCPeerConnectionHandler::initialize( |
| 174 const WebKit::WebRTCConfiguration& server_configuration, |
| 175 const WebKit::WebMediaConstraints& options ) { |
| 176 webrtc::JsepInterface::IceServers servers; |
| 177 GetNativeIceServers(server_configuration, &servers); |
| 178 |
| 179 RTCMediaConstraints constraints(options); |
| 180 native_peer_connection_ = |
| 181 dependency_factory_->CreatePeerConnection( |
| 182 servers, &constraints, this); |
| 183 if (!native_peer_connection_) { |
| 184 LOG(ERROR) << "Failed to initialize native PeerConnection."; |
| 185 return false; |
| 186 } |
| 187 return true; |
| 188 } |
| 189 |
| 190 void RTCPeerConnectionHandler::createOffer( |
| 191 const WebKit::WebRTCSessionDescriptionRequest& request, |
| 192 const WebKit::WebMediaConstraints& options) { |
| 193 talk_base::scoped_refptr<CreateSessionDescriptionRequest> description_request( |
| 194 new talk_base::RefCountedObject<CreateSessionDescriptionRequest>( |
| 195 request)); |
| 196 RTCMediaConstraints constraints(options); |
| 197 native_peer_connection_->CreateOffer( |
| 198 description_request.get(), &constraints); |
| 199 } |
| 200 |
| 201 void RTCPeerConnectionHandler::createAnswer( |
| 202 const WebKit::WebRTCSessionDescriptionRequest& request, |
| 203 const WebKit::WebMediaConstraints& options) { |
| 204 talk_base::scoped_refptr<CreateSessionDescriptionRequest> description_request( |
| 205 new talk_base::RefCountedObject<CreateSessionDescriptionRequest>( |
| 206 request)); |
| 207 RTCMediaConstraints constraints(options); |
| 208 native_peer_connection_->CreateAnswer(description_request.get(), |
| 209 &constraints); |
| 210 } |
| 211 |
| 212 void RTCPeerConnectionHandler::setLocalDescription( |
| 213 const WebKit::WebRTCVoidRequest& request, |
| 214 const WebKit::WebRTCSessionDescriptionDescriptor& description) { |
| 215 webrtc::SessionDescriptionInterface* native_desc = |
| 216 CreateNativeSessionDescription(description); |
| 217 if (!native_desc) { |
| 218 const char kReason[] = "Failed to parse SessionDescription."; |
| 219 LOG(ERROR) << kReason; |
| 220 WebKit::WebString reason(kReason); |
| 221 request.requestFailed(reason); |
| 222 return; |
| 223 } |
| 224 talk_base::scoped_refptr<SetSessionDescriptionRequest> set_request( |
| 225 new talk_base::RefCountedObject<SetSessionDescriptionRequest>(request)); |
| 226 native_peer_connection_->SetLocalDescription(set_request.get(), native_desc); |
| 227 } |
| 228 |
| 229 void RTCPeerConnectionHandler::setRemoteDescription( |
| 230 const WebKit::WebRTCVoidRequest& request, |
| 231 const WebKit::WebRTCSessionDescriptionDescriptor& description) { |
| 232 webrtc::SessionDescriptionInterface* native_desc = |
| 233 CreateNativeSessionDescription(description); |
| 234 if (!native_desc) { |
| 235 const char kReason[] = "Failed to parse SessionDescription."; |
| 236 LOG(ERROR) << kReason; |
| 237 WebKit::WebString reason(kReason); |
| 238 request.requestFailed(reason); |
| 239 return; |
| 240 } |
| 241 talk_base::scoped_refptr<SetSessionDescriptionRequest> set_request( |
| 242 new talk_base::RefCountedObject<SetSessionDescriptionRequest>(request)); |
| 243 native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc); |
| 244 } |
| 245 |
| 246 WebKit::WebRTCSessionDescriptionDescriptor |
| 247 RTCPeerConnectionHandler::localDescription() { |
| 248 const webrtc::SessionDescriptionInterface* native_desc = |
| 249 native_peer_connection_->local_description(); |
| 250 WebKit::WebRTCSessionDescriptionDescriptor description = |
| 251 CreateWebKitSessionDescription(native_desc); |
| 252 return description; |
| 253 } |
| 254 |
| 255 WebKit::WebRTCSessionDescriptionDescriptor |
| 256 RTCPeerConnectionHandler::remoteDescription() { |
| 257 const webrtc::SessionDescriptionInterface* native_desc = |
| 258 native_peer_connection_->remote_description(); |
| 259 WebKit::WebRTCSessionDescriptionDescriptor description = |
| 260 CreateWebKitSessionDescription(native_desc); |
| 261 return description; |
| 262 } |
| 263 |
| 264 bool RTCPeerConnectionHandler::updateICE( |
| 265 const WebKit::WebRTCConfiguration& server_configuration, |
| 266 const WebKit::WebMediaConstraints& options) { |
| 267 webrtc::JsepInterface::IceServers servers; |
| 268 GetNativeIceServers(server_configuration, &servers); |
| 269 RTCMediaConstraints constraints(options); |
| 270 return native_peer_connection_->UpdateIce(servers, |
| 271 &constraints); |
| 272 } |
| 273 |
| 274 bool RTCPeerConnectionHandler::addICECandidate( |
| 275 const WebKit::WebRTCICECandidateDescriptor& candidate) { |
| 276 scoped_ptr<webrtc::IceCandidateInterface> native_candidate( |
| 277 dependency_factory_->CreateIceCandidate( |
| 278 UTF16ToUTF8(candidate.sdpMid()), |
| 279 candidate.sdpMLineIndex(), |
| 280 UTF16ToUTF8(candidate.candidate()))); |
| 281 if (!native_candidate.get()) { |
| 282 LOG(ERROR) << "Could not create native ICE candidate."; |
| 283 return false; |
| 284 } |
| 285 |
| 286 bool return_value = |
| 287 native_peer_connection_->AddIceCandidate(native_candidate.get()); |
| 288 if (!return_value) |
| 289 LOG(ERROR) << "Error processing ICE candidate."; |
| 290 return return_value; |
| 291 } |
| 292 |
| 293 bool RTCPeerConnectionHandler::addStream( |
| 294 const WebKit::WebMediaStreamDescriptor& stream, |
| 295 const WebKit::WebMediaConstraints& options) { |
| 296 RTCMediaConstraints constraints(options); |
| 297 return AddStream(stream, &constraints); |
| 298 } |
| 299 |
| 300 void RTCPeerConnectionHandler::removeStream( |
| 301 const WebKit::WebMediaStreamDescriptor& stream) { |
| 302 RemoveStream(stream); |
| 303 } |
| 304 |
| 305 void RTCPeerConnectionHandler::stop() { |
| 306 DVLOG(1) << "RTCPeerConnectionHandler::stop"; |
| 307 native_peer_connection_ = NULL; |
| 308 } |
| 309 |
| 310 void RTCPeerConnectionHandler::OnError() { |
| 311 // TODO(perkj): Implement. |
| 312 NOTIMPLEMENTED(); |
| 313 } |
| 314 |
| 315 void RTCPeerConnectionHandler::OnStateChange(StateType state_changed) { |
| 316 switch (state_changed) { |
| 317 case kReadyState: { |
| 318 WebKit::WebRTCPeerConnectionHandlerClient::ReadyState ready_state = |
| 319 GetWebKitReadyState(native_peer_connection_->ready_state()); |
| 320 client_->didChangeReadyState(ready_state); |
| 321 break; |
| 322 } |
| 323 case kIceState: { |
| 324 WebKit::WebRTCPeerConnectionHandlerClient::ICEState ice_state = |
| 325 GetWebKitIceState(native_peer_connection_->ice_state()); |
| 326 client_->didChangeICEState(ice_state); |
| 327 break; |
| 328 } |
| 329 default: |
| 330 NOTREACHED(); |
| 331 break; |
| 332 } |
| 333 } |
| 334 |
| 335 void RTCPeerConnectionHandler::OnAddStream( |
| 336 webrtc::MediaStreamInterface* stream) { |
| 337 if (!stream) { |
| 338 LOG(ERROR) << "OnAddStream: stream is null"; |
| 339 return; |
| 340 } |
| 341 |
| 342 DCHECK(remote_streams_.find(stream) == remote_streams_.end()); |
| 343 WebKit::WebMediaStreamDescriptor descriptor = |
| 344 CreateWebKitStreamDescriptor(stream); |
| 345 remote_streams_.insert( |
| 346 std::pair<webrtc::MediaStreamInterface*, |
| 347 WebKit::WebMediaStreamDescriptor>(stream, descriptor)); |
| 348 client_->didAddRemoteStream(descriptor); |
| 349 } |
| 350 |
| 351 void RTCPeerConnectionHandler::OnRemoveStream( |
| 352 webrtc::MediaStreamInterface* stream) { |
| 353 if (!stream) { |
| 354 LOG(ERROR) << "OnRemoveStream: stream is null"; |
| 355 return; |
| 356 } |
| 357 |
| 358 RemoteStreamMap::iterator it = remote_streams_.find(stream); |
| 359 if (it == remote_streams_.end()) { |
| 360 NOTREACHED() << "Stream not found"; |
| 361 return; |
| 362 } |
| 363 WebKit::WebMediaStreamDescriptor descriptor = it->second; |
| 364 DCHECK(!descriptor.isNull()); |
| 365 remote_streams_.erase(it); |
| 366 client_->didRemoveRemoteStream(descriptor); |
| 367 } |
| 368 |
| 369 void RTCPeerConnectionHandler::OnIceCandidate( |
| 370 const webrtc::IceCandidateInterface* candidate) { |
| 371 std::string sdp; |
| 372 if (!candidate->ToString(&sdp)) { |
| 373 LOG(ERROR) << "OnIceCandidate: Could not get SDP string."; |
| 374 return; |
| 375 } |
| 376 WebKit::WebRTCICECandidateDescriptor web_candidate; |
| 377 web_candidate.initialize(UTF8ToUTF16(sdp), |
| 378 UTF8ToUTF16(candidate->sdp_mid()), |
| 379 candidate->sdp_mline_index()); |
| 380 client_->didGenerateICECandidate(web_candidate); |
| 381 } |
| 382 |
| 383 void RTCPeerConnectionHandler::OnIceComplete() { |
| 384 // Generates a NULL ice candidate object. |
| 385 WebKit::WebRTCICECandidateDescriptor web_candidate; |
| 386 client_->didGenerateICECandidate(web_candidate); |
| 387 } |
| 388 |
| 389 void RTCPeerConnectionHandler::OnRenegotiationNeeded() { |
| 390 client_->doRenegotiate(); |
| 391 } |
| 392 |
| 393 webrtc::SessionDescriptionInterface* |
| 394 RTCPeerConnectionHandler::CreateNativeSessionDescription( |
| 395 const WebKit::WebRTCSessionDescriptionDescriptor& description) { |
| 396 std::string sdp = UTF16ToUTF8(description.sdp()); |
| 397 std::string type = UTF16ToUTF8(description.type()); |
| 398 webrtc::SessionDescriptionInterface* native_desc = |
| 399 dependency_factory_->CreateSessionDescription(type, sdp); |
| 400 if (!native_desc) { |
| 401 LOG(ERROR) << "Failed to create native session description. Type: " |
| 402 << type << " SDP: " << sdp; |
| 403 return NULL; |
| 404 } |
| 405 |
| 406 return native_desc; |
| 407 } |
OLD | NEW |